Files
website/src/components/CommandLine.astro

130 lines
3.0 KiB
Plaintext

<div id="command-line" class="w-full flex flex-row bg-base">
<input
id="command-line-input"
type="text"
size="1"
class="bg-base focus:outline-none active:outline-none cursor-default caret-transparent m-0"
/>
<div id="caret" aria-hidden="true" class="bg-text inline-block">&nbsp;</div>
<p id="status-text" class="absolute w-full h-full bg-base hidden italic"></p>
</div>
<script>
const cmds: Record<string, () => void> = {
q: () => {
const cmdEvent = new CustomEvent("closebuffer");
window.dispatchEvent(cmdEvent);
},
"help iccf": () => {
const cmdEvent = new CustomEvent("openiccf");
window.dispatchEvent(cmdEvent);
},
};
const container = document.getElementById("command-line") as HTMLDivElement;
const commandLineInput = document.getElementById(
"command-line-input",
) as HTMLInputElement;
const caret = document.getElementById("caret") as HTMLDivElement;
const statusText = document.getElementById(
"status-text",
) as HTMLParagraphElement;
const allowedCharRegex = /[\w\d\s!@#$%^&*()-_+=|\\~`{[}\]:;"'<,>.?/]/;
let isInCmdMode = false;
commandLineInput.value = "";
caret.style.display = "none";
function enableCmdMode() {
caret.style.display = "block";
statusText.classList.add("hidden");
commandLineInput.value = ":";
commandLineInput.style.width = "1ch";
isInCmdMode = true;
const event = new Event("cmdmodeenabled");
container.dispatchEvent(event);
}
function disableCmdMode({ clear } = { clear: true }) {
caret.style.display = "none";
isInCmdMode = false;
if (clear) {
commandLineInput.value = "";
commandLineInput.style.width = "0ch";
}
const event = new Event("cmdmodedisabled");
container.dispatchEvent(event);
}
function appendChar(event: KeyboardEvent) {
commandLineInput.value += event.key;
commandLineInput.style.width = `${commandLineInput.value.length}ch`;
}
function deleteChar() {
commandLineInput.value = commandLineInput.value.substring(
0,
commandLineInput.value.length - 1,
);
commandLineInput.style.width = `${commandLineInput.value.length}ch`;
}
function executeCommand() {
disableCmdMode({ clear: false });
const command = commandLineInput.value.substring(1);
const fn = cmds[command];
if (fn) {
fn();
} else {
statusText.innerHTML = `E492: Not an editor command: ${command}`;
statusText.classList.remove("hidden");
statusText.classList.add("text-red");
}
}
document.addEventListener("keydown", (event) => {
switch (event.key) {
case ":":
if (!isInCmdMode) {
enableCmdMode();
} else {
appendChar(event);
}
break;
case "Escape":
if (isInCmdMode) {
event.preventDefault();
disableCmdMode();
}
break;
case "Backspace":
if (!isInCmdMode) break;
if (commandLineInput.value === ":") {
disableCmdMode();
} else {
deleteChar();
}
break;
case "Enter":
executeCommand();
break;
default:
if (
event.key.length === 1 &&
allowedCharRegex.test(event.key) &&
isInCmdMode
) {
appendChar(event);
}
break;
}
});
</script>