1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
---
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 class="flex flex-col">
<p>$ ls -lah -t --color=auto ~/blogs</p>
<p>"/home/kyren/blogs": No such file or directory (os error 2)</p>
<p> </p>
<p>ls -lah -t --color=auto ~/blogs</p>
<p>ls -lah -t --color=auto ~/blogs</p>
</div>
</TerminalBorder>
<TerminalBorder header="Shell" extra="font-['JetBrains_Mono'] w-full">
<span class="pr-2">$</span>
<p id="terminal" 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] || " ";
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] || " ";
selectedText = text.substring(selectionEnd, cursorPos - 1);
afterCursor = text.substring(cursorPos);
beforeCursor = text.substring(0, oCursorPos);
}
return {
beforeCursor,
afterCursor,
cursorChar,
selectedText,
swapped,
};
}
const terminal = document.getElementById("terminal")!!;
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) {
terminal.innerHTML = `${beforeCursor}${visual}${cursor}${afterCursor}`;
} else {
terminal.innerHTML = `${beforeCursor}${cursor}${visual}${afterCursor}`;
}
}
input.addEventListener("keydown", function (event) {
if (event.key === "Enter") {
event.preventDefault();
// const inputText = input.value;
input.value = "";
updateShell();
}
});
setInterval(updateShell, 50);
</script>
|