Files
github-website/src/pages/shell.astro
2025-02-03 14:31:26 +02:00

169 lines
5.0 KiB
Plaintext

---
import Terminal from "@layouts/Terminal.astro";
import TerminalBorder from "@components/TerminalBorder.astro";
---
<Terminal path="/bin/bash">
<TerminalBorder header="Bash" extra="h-[62%] mt-[0.625vw] mb-[1.5625vw]">
<div id="output" class="flex flex-col"></div>
</TerminalBorder>
<TerminalBorder header="Shell" extra="font-['JetBrains_Mono']">
<pre>$ </pre>
<p id="input" contenteditable="true" spellcheck="false">
npm run buil<span>d</span>after
</p>
<input class="absolute opacity-0 w-0 h-0 p-0 m-0" autofocus />
</TerminalBorder>
</Terminal>
<script>
var prevCursor = -1;
var prevSelectionEnd = -1;
var swapped = false;
function getCursorText(inputElement) {
const text = inputElement.value;
const oCursorPos = inputElement.selectionStart;
const oSelectionEnd = inputElement.selectionEnd;
var cursorPos = oCursorPos;
var selectionEnd = oSelectionEnd;
if (
prevCursor != -1 &&
oCursorPos != oSelectionEnd &&
(prevSelectionEnd != oSelectionEnd ||
(prevSelectionEnd == oSelectionEnd &&
prevCursor == oCursorPos &&
swapped))
) {
cursorPos = oSelectionEnd;
selectionEnd = oCursorPos;
prevSelectionEnd = oSelectionEnd;
swapped = true;
} else {
swapped = false;
}
prevCursor = oCursorPos;
var beforeCursor = text.substring(0, cursorPos);
var afterCursor = text.substring(cursorPos + 1);
var cursorChar = text[cursorPos] || "&nbsp;";
var selectedText = "";
if (selectionEnd > cursorPos) {
selectedText = text.substring(cursorPos + 1, selectionEnd);
afterCursor = text.substring(oSelectionEnd);
beforeCursor = text.substring(0, cursorPos);
} else if (selectionEnd < cursorPos) {
cursorChar = text[cursorPos - 1] || "&nbsp;";
selectedText = text.substring(selectionEnd, cursorPos - 1);
afterCursor = text.substring(cursorPos);
beforeCursor = text.substring(0, oCursorPos);
}
return {
beforeCursor,
afterCursor,
cursorChar,
selectedText,
swapped,
};
}
const output = document.getElementById("output")!!;
const fakeInput = document.getElementById("input")!!;
const input = document.querySelector("input")!!;
const cursorStyle =
"background-color: var(--text); color: var(--background);";
const visualStyle =
"background-color: var(--primary); color: var(--background);";
function updateShell() {
var { beforeCursor, afterCursor, cursorChar, selectedText, swapped } =
getCursorText(input);
input.focus();
const cursor = `<span style="${cursorStyle}">${cursorChar}</span>`;
const visual = `<span style="${visualStyle}">${selectedText}</span>`;
if (swapped) {
fakeInput.innerHTML = `${beforeCursor}${visual}${cursor}${afterCursor}`;
} else {
fakeInput.innerHTML = `${beforeCursor}${cursor}${visual}${afterCursor}`;
}
if (input.value.length >= 97) {
input.value = "";
updateShell();
write("segmentation fault (core dumped)");
updateTerminal();
}
}
var maxLines = 15;
var terminal: string[] = ["Coming soon!"];
function write(line: string) {
const maxChars = 98;
while (line.length > maxChars) {
terminal.push(line.slice(0, maxChars));
line = line.slice(maxChars);
}
terminal.push(line);
while (terminal.length > maxLines) {
terminal.shift();
}
}
function updateTerminal() {
var text = "";
for (let i = 0; i < terminal.length; i++) {
text += `<p>${terminal[i] == "" ? "&nbsp;" : terminal[i]}</p>`;
}
output.innerHTML = text;
}
function runCommand(cmd: string) {
write(`$ ${cmd}`);
console.log(`$ ${cmd}`);
console.log(terminal);
switch (cmd) {
case "":
break;
case "clear":
terminal = [];
break;
case "test":
write('testing "trying to get more info"...');
write('test "trying to get more info" failed');
write("executed 1 test, 0 succeeded, 1 failed");
break;
case "thing":
break;
case "thing":
break;
default:
write(`${cmd}: command not found`);
break;
}
updateTerminal();
}
input.addEventListener("keydown", function (event) {
if (event.key === "Enter") {
event.preventDefault();
runCommand(input.value);
input.value = "";
updateShell();
}
});
setInterval(updateShell, 50);
</script>