poshlostios/sys/terminal.js

187 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const CHAR_SIZE = [10, 22]
const CURSOR_OFFSET = [10, 10]
var terminal = document.getElementById("terminal")
var terminal_text = ""
var last_stdin_length = 0
function getTerminalSize() {
return [
Math.round((window.innerWidth - CURSOR_OFFSET[0] * 2) / CHAR_SIZE[0]),
Math.round((window.innerHeight - CURSOR_OFFSET[1] * 2) / CHAR_SIZE[1])
]
}
function writeTerminalAtCursor(content) {
let cursor_index = getCursorIndex()
terminal_text = terminal_text.slice(0, cursor_index) + content + terminal_text.slice(cursor_index)
setCursor(cursor_pos[0]+1, cursor_pos[1])
last_stdin_length += 1
updateTerminalWOCursor()
}
function writeTerminal(content) {
terminal_text += content
last_stdin_length = 0
updateTerminal()
}
function replaceTerminal(content) {
terminal_text = content
updateTerminal()
}
function trimTerminal(length) {
terminal_text = terminal_text.substring(0, terminal_text.length-length)
updateTerminal()
}
function getStrippedTerminal() {
return stripColors(getTerminal())
}
function getTerminal() {
return terminal_text
}
function setTerminal(content) {
terminal_text = content
}
function clearTerminal() {
terminal_text = ""
updateTerminal()
}
function updateTerminalWOCursor() {
terminal.innerHTML = convertColorCodes(stripHtml(terminal_text))
}
function updateTerminal() {
let stripped_terminal = getStrippedTerminal()
setCursor(
stripped_terminal.split("\n").reverse()[0].length,
stripped_terminal.split("\n").length-1
)
updateTerminalWOCursor()
}
var cursor = document.getElementById("cursor")
var cursor_pos = [0, 0]
function getCursorIndex() {
let lines = terminal_text.split("\n");
let index = 0;
for (let y = 0; y < lines.length; y++) {
let line = lines[y];
let strippedLine = stripColors(line);
let length = strippedLine.length;
if (y == cursor_pos[1]) {
let visiblePos = cursor_pos[0];
let realPos = 0;
let visibleCount = 0;
// Синхронизируем позиции между оригинальным и очищенным текстом
for (let i = 0; i < line.length; i++) {
if (visibleCount === visiblePos) {
return index + realPos;
}
if (line[i] === "\n") {
index++;
continue;
}
if (!line.substring(i).match(/^\$#([0-9a-fA-F]{6})|^\$[A-Z_]+--|^\$reset/)) {
visibleCount++;
}
realPos++;
}
return index + realPos; // На случай, если курсор в конце строки
}
index += line.length + 1; // +1 за \n
}
return index;
}
function getCursor() {
return cursor_pos
}
function setCursor(x, y) {
cursor_pos = [x, y]
updateCursor()
}
function updateCursor() {
cursor.style["top"] = cursor_pos[1] * CHAR_SIZE[1] + CURSOR_OFFSET[1] + "px"
cursor.style["left"] = cursor_pos[0] * CHAR_SIZE[0] + CURSOR_OFFSET[0] + "px"
cursor.scrollIntoView({behavior: "smooth", inline: "end"})
}
function stripColors(input) {
return input.replace(/\$#([0-9a-fA-F]{6})/g, "")
.replace(/\$([A-Z_]+)--/g, "")
.replace(/\$reset/g, "")
}
function makeColorCodesPrintable(input) {
return input.replace(/\$#([0-9a-fA-F]{6})/g, "$$##$1")
.replace(/\$([A-Z_]+)--/g, "$$#$1--")
.replace(/\$reset/g, "$$#reset")
}
function convertColorCodes(input) {
return input.replace(/\$#([0-9a-fA-F]{6})/g, '<span style="color: #$1">')
.replace(/\$##([0-9a-fA-F]{6})/g, '$$#$1')
.replace(/\$([A-Z_]+)--/g, '<span style="color: var(--$1)">')
.replace(/\$#([A-Z_]+)--/g, '$$$1--')
.replace(/\$reset/g, '</span>')
.replace(/\$#reset/g, '$$reset');
}
function stripHtml(html) {
let tmp = document.createElement("DIV");
tmp.innerText = html;
return tmp.innerHTML;
}
document.onkeydown = (e) => {
let key = e.key;
if (!disable_stdin) {
if (key == "Enter") {
stdin += "\n"
if (!silent_stdin) {
writeTerminal("\n")
}
} else if (key.length == 1) {
if (e.ctrlKey && key == "v") return
stdin += key
if (!silent_stdin) {
writeTerminalAtCursor(key)
}
} else {
stdin += "\r"+(e.ctrlKey ? "1" : "0")+(e.altKey ? "1" : "0")+(e.shiftKey ? "1" : "0")+e.key+"\r"
}
}
}
var clipboard_collect = document.getElementById("clipboard-collect")
setInterval(() => {
clipboard_collect.focus()
});
clipboard_collect.onpaste = (e) => {
let paste = (e.clipboardData || window.clipboardData).getData("text");
if (paste != null) {
stdin += paste.replace("\r", "")
writeTerminal(paste)
}
}