diff --git a/css/base.css b/css/base.css index 8fb2401..49fb404 100644 --- a/css/base.css +++ b/css/base.css @@ -86,6 +86,15 @@ nav { margin: 0 auto; } +.emoji { + --emoji-size: 1.1em; + height: var(--emoji-size); + width: var(--emoji-size); + object-fit: contain; + position: relative; + top: 0.2em; +} + .cursor { color: var(--crust); background-color: var(--text); diff --git a/img/emoji/neodog_bite_neocat.png b/img/emoji/neodog_bite_neocat.png new file mode 100644 index 0000000..5c83d5c Binary files /dev/null and b/img/emoji/neodog_bite_neocat.png differ diff --git a/index.html b/index.html index a81b0ae..1cff433 100644 --- a/index.html +++ b/index.html @@ -47,10 +47,6 @@ @@ -59,7 +55,7 @@ this page instead - My cat + my cat - - diff --git a/js/index.js b/js/index.js index 77d0f7d..af603a2 100644 --- a/js/index.js +++ b/js/index.js @@ -53,6 +53,74 @@ function edgeMoveEvent(x, y, pos, windowID) { w.element.querySelector(".window").style.width = `${w.width}px`; w.element.querySelector(".window").style.height = `${w.height}px`; } +function mouseMoveEvent(windowID, x, y) { + let w = WINDOWS[windowID]; + w.posX = Math.max(0, Math.min(innerWidth - w.width - _windowPaddingX, x - w.vars.mouseOffsetX)); + w.posY = Math.max(0, Math.min(innerHeight - w.height - _windowPaddingY, y - w.vars.mouseOffsetY)); + w.element.style.left = `${w.posX}px`; + w.element.style.top = `${w.posY}px`; +} +function syncInputs(windowID) { + let windowInput = WINDOWS[windowID].element.querySelector("input.window-input"); + let windowVisualText = WINDOWS[windowID].element.querySelector("[data-type-area]"); + let w = WINDOWS[windowID].element.querySelector(".window"); + if (!windowVisualText) { + return; + } + setTimeout(function () { + let text = windowInput.value; + let cursor = windowInput.selectionStart; + if (cursor == text.length) { + windowVisualText.innerHTML = `${escapeHTML(text)} `; + } + else { + windowVisualText.innerHTML = `${escapeHTML(text.slice(0, cursor))}${escapeHTML(text[cursor])}${escapeHTML(text.slice(cursor + 1))}`; + } + }, 1); + w.scrollTop = w.scrollHeight; +} +function setCursor(windowID) { + let windowInput = WINDOWS[windowID].element.querySelector("input.window-input"); + setTimeout(() => { + windowInput.setSelectionRange(windowInput.value.length, windowInput.value.length); + syncInputs(windowID); + }, 1); +} +function toggleFullscreen(windowID) { + let w = WINDOWS[windowID]; + if (w.fullscreen) { + w.posX = Math.max(0, Math.min(innerWidth - w.vars.oldWidth - _windowPaddingX, w.vars.oldPosX)); + w.posY = Math.max(0, Math.min(innerHeight - w.vars.oldHeight - _windowPaddingY, w.vars.oldPosY)); + w.width = Math.max(w.minWidth, Math.min(w.vars.oldWidth, innerWidth - _windowPaddingX)); + w.height = Math.max(w.minHeight, Math.min(w.vars.oldHeight, innerHeight - _windowPaddingY)); + w.fullscreen = false; + delete w.vars.oldPosX; + delete w.vars.oldPosY; + delete w.vars.oldWidth; + delete w.vars.oldHeight; + w.element.style.left = `${w.posX}px`; + w.element.style.top = `${w.posY}px`; + w.element.style.width = `${w.width + _windowPaddingX - 2}px`; + w.element.querySelector(".window").style.width = `${w.width}px`; + w.element.querySelector(".window").style.height = `${w.height}px`; + } + else { + w.vars.oldPosX = w.posX; + w.vars.oldPosY = w.posY; + w.vars.oldWidth = w.width; + w.vars.oldHeight = w.height; + w.fullscreen = true; + w.posX = 0; + w.posY = 0; + w.width = innerWidth; + w.height = innerHeight; + w.element.style.left = "0px"; + w.element.style.top = "0px"; + w.element.style.width = `${w.width}px`; + w.element.querySelector(".window").style.width = `${w.width - _windowPaddingX}px`; + w.element.querySelector(".window").style.height = `${w.height - _windowPaddingY}px`; + } +} function createWindow(config) { if (document.getElementById(config.id)) { incrementZIndex(config.id); @@ -90,30 +158,8 @@ function createWindow(config) { wI = document.createElement("input"); wI.classList.add("window-input"); wI.id = `${config.id}__input`; - function syncInputs() { - setTimeout(function () { - let text = wI.value; - let cursor = wI.selectionStart; - let el = wC.querySelector("[data-type-area]"); - if (!el) { - return; - } - if (cursor == text.length) { - el.innerHTML = `${escapeHTML(text)} `; - } - else { - el.innerHTML = `${escapeHTML(text.slice(0, cursor))}${escapeHTML(text[cursor])}${escapeHTML(text.slice(cursor + 1))}`; - } - }, 1); - } - function setCursor() { - setTimeout(() => { - wI.setSelectionRange(wI.value.length, wI.value.length); - syncInputs(); - }, 0); - } wI.oninput = (event) => { - syncInputs(); + syncInputs(config.id); w.scrollTop = w.scrollHeight; }; wI.onkeydown = (event) => { @@ -122,12 +168,88 @@ function createWindow(config) { w.scrollTop = w.scrollHeight; wI.value = ""; } + else if (event.key == "Tab") { + event.preventDefault(); + let val = wI.value.trim(); + let possibilities = []; + let parent; + if (!val) { + return; + } + if (val.split(" ").length == 1 && wI.value[wI.value.length - 1] != " ") { + possibilities = Object.keys(_internal_commands).filter((cmd) => (cmd.startsWith(val) && !cmd.startsWith("_"))); + } + else if (_internal_commands[val.split(" ")[0]] && _internal_commands[val.split(" ")[0]].autocomplete) { + let ac = _internal_commands[val.split(" ")[0]].autocomplete; + let path = val.split(" ").slice(1).join(" ").trim(); + let sw = path.split("/")[path.split("/").length - 1]; + if (typeof ac == "object") { + possibilities = ac; + } + else { + if (path) { + if (path[path.length - 1] == "/") { + parent = _internal_getFile(_internal_sanitizePath(_internal_joinPaths(windowInformation[config.id].PWD, path))); + } + else { + parent = _internal_getFile(_internal_sanitizePath(_internal_joinPaths(windowInformation[config.id].PWD, path + "/.."))); + } + } + else { + parent = _internal_getFile(windowInformation[config.id].PWD); + } + if (parent && parent.type == "directory") { + let f = parent.files; + possibilities = Object.keys(f); + if (ac == "dir") { + possibilities = possibilities.filter((file) => (f[file] && f[file].type == "directory")); + } + } + else { + parent = null; + } + } + possibilities = possibilities.filter((v) => v.startsWith(sw)); + } + if (possibilities.length == 1) { + if (val.split(" ").length == 1 && wI.value[wI.value.length - 1] != " ") { + wI.value = possibilities[0] + " "; + } + else if (_internal_commands[val.split(" ")[0]] && _internal_commands[val.split(" ")[0]].autocomplete) { + let path = val; + if (val[val.length - 1] == "/") { + path += possibilities[0]; + } + else { + let p = path.split("/"); + if (p.length == 1) { + p = p[0].split(" ", 2); + if (p.length == 1) { + p.push(""); + } + p.pop(); + path = p.join(" ") + " " + possibilities[0]; + } + else { + p.pop(); + path = p.join("/") + "/" + possibilities[0]; + } + } + wI.value = path + (parent && parent.type == "directory" && parent.files[possibilities[0]].type == "directory" ? "/" : " "); + } + syncInputs(config.id); + } + else if (possibilities) { + addWindowCommand(config.id, possibilities.join(" ")); + syncInputs(config.id); + } + } else { - syncInputs(); + syncInputs(config.id); } }; - wI.onfocus = setCursor; - wI.onclick = setCursor; + wI.onfocus = () => { setCursor(config.id); }; + wI.onclick = () => { setCursor(config.id); }; wC = document.createElement("label"); wC.htmlFor = `${config.id}__input`; } @@ -146,6 +268,7 @@ function createWindow(config) { let el = document.createElement("div"); el.classList.add("edge", pos); el.addEventListener("mousedown", function (e) { + incrementZIndex(config.id); e.preventDefault(); WINDOWS[config.id].vars.mouseOffsetX = e.clientX - WINDOWS[config.id].posX; WINDOWS[config.id].vars.mouseOffsetY = e.clientY - WINDOWS[config.id].posY; @@ -182,12 +305,9 @@ function createWindow(config) { zIndex: globalIncrement, vars: {} }; - function mouseMoveEvent(x, y) { - WINDOWS[config.id].posX = Math.max(0, Math.min(innerWidth - WINDOWS[config.id].width - _windowPaddingX, x - WINDOWS[config.id].vars.mouseOffsetX)); - WINDOWS[config.id].posY = Math.max(0, Math.min(innerHeight - WINDOWS[config.id].height - _windowPaddingY, y - WINDOWS[config.id].vars.mouseOffsetY)); - wC.style.left = `${WINDOWS[config.id].posX}px`; - wC.style.top = `${WINDOWS[config.id].posY}px`; - } + windowInformation[config.id] = { + PWD: HOME_DIR + }; wC.addEventListener("focus", function () { incrementZIndex(config.id); }); for (const link of wC.querySelectorAll("a")) { link.addEventListener("focus", function () { incrementZIndex(config.id); }); @@ -199,7 +319,7 @@ function createWindow(config) { WINDOWS[config.id].vars.mouseOffsetX = e.clientX - WINDOWS[config.id].posX; WINDOWS[config.id].vars.mouseOffsetY = e.clientY - WINDOWS[config.id].posY; MOUSE_MOVE_PROCESSING[config.id] = { - callback: mouseMoveEvent, + callback: (x, y) => { mouseMoveEvent(config.id, x, y); }, mouseUp: true }; }); @@ -212,41 +332,8 @@ function createWindow(config) { config.onDestroy(); } }); - wH.querySelector(".fullscreen").addEventListener("click", function () { - let window = WINDOWS[config.id]; - if (window.fullscreen) { - window.posX = Math.max(0, Math.min(innerWidth - window.vars.oldWidth - _windowPaddingX, window.vars.oldPosX)); - window.posY = Math.max(0, Math.min(innerHeight - window.vars.oldHeight - _windowPaddingY, window.vars.oldPosY)); - window.width = Math.max(window.minWidth, Math.min(window.vars.oldWidth, innerWidth - _windowPaddingX)); - window.height = Math.max(window.minHeight, Math.min(window.vars.oldHeight, innerHeight - _windowPaddingY)); - window.fullscreen = false; - delete window.vars.oldPosX; - delete window.vars.oldPosY; - delete window.vars.oldWidth; - delete window.vars.oldHeight; - wC.style.left = `${window.posX}px`; - wC.style.top = `${window.posY}px`; - wC.style.width = `${window.width + _windowPaddingX - 2}px`; - w.style.width = `${window.width}px`; - w.style.height = `${window.height}px`; - } - else { - window.vars.oldPosX = window.posX; - window.vars.oldPosY = window.posY; - window.vars.oldWidth = window.width; - window.vars.oldHeight = window.height; - window.fullscreen = true; - window.posX = 0; - window.posY = 0; - window.width = innerWidth; - window.height = innerHeight; - wC.style.left = "0px"; - wC.style.top = "0px"; - wC.style.width = `${window.width}px`; - w.style.width = `${window.width - _windowPaddingX}px`; - w.style.height = `${window.height - _windowPaddingY}px`; - } - }); + wH.querySelector(".fullscreen").addEventListener("click", () => (toggleFullscreen(config.id))); + wH.addEventListener("dblclick", () => (toggleFullscreen(config.id))); globalIncrement++; } function windowPreset(template, dontDisableTyping = false) { diff --git a/js/shell.js b/js/shell.js index 40c667f..63899cd 100644 --- a/js/shell.js +++ b/js/shell.js @@ -209,19 +209,21 @@ function _internal_neofetch(args, windowID) { return _internal_neofetchOutputs[args]; } const _internal_commands = { - cat: cat, - cd: cd, - clear: clear, - help: help, - ls: ls, - exit: exit, - _internal_set_ps1: _internal_set_ps1, - _internal_neofetch: _internal_neofetch + cat: { callback: cat, autocomplete: "file" }, + cd: { callback: cd, autocomplete: "dir" }, + clear: { callback: clear, autocomplete: null }, + help: { callback: help, autocomplete: null }, + ls: { callback: ls, autocomplete: "file" }, + exit: { callback: exit, autocomplete: null }, + _internal_set_ps1: { callback: _internal_set_ps1, autocomplete: null }, + _internal_neofetch: { callback: _internal_neofetch, autocomplete: null }, + spin: { callback: (args, windowID) => { createBlob(); return ""; }, autocomplete: null }, }; const _internal_defaultFiles = { - about: `
hi there! i'm trinkey!
+ about: `
hi there!
+
i'm trinkey, but you can call me katie too! (trinkey is more of a username)
--------------------
-
i'm a silly little kitty cat who lives in the usa (sadly).
+
i'm a silly little cat who lives in the usa (new york time zone).
i'm trans (she/it, they/them is also fine).
i'm not actively in a relationship, however i'm also not looking to get into one either.
--------------------
@@ -236,6 +238,7 @@ const _internal_defaultFiles = {
- signal - @trinkey.01
- email - trinkey [at] proton [dot] me
- youtube - @trinkey (inactive)
+
- discord - @trinkey_ (mostly inactive)
- gpg key (1D6E 5D28 BDD4 D7FA 96B8 8799 2B33 C6C6 14F2 591A)
`, projects: `
projects - the things i made
- smiggins (website) - a social media platform i made
@@ -247,23 +250,28 @@ const _internal_defaultFiles = { buttons: `
my button: (click to copy html)
trinkey's 88x31. image of her cat on the right with the word 'trinkey' taking up the rest of the button.
--------------------
-
cool people:
notfire.cc - a non-spinning demigirl blobcat angled slightly with a black border to the left of "Micro" + a non-spinning demigirl blobcat angled slightly with a black border to the left of "Micro" kopper's button Sneexy unnick Autumn Town Café the text 'red is purple' on a purple background doskel + velzie
`, testimonials: `
"warning: this user is trinkey"
- bread

"This user is only slightly crazy once was I. 10/10 would recommend"
- subroutine

"the f slur but repeated 36 times"
-
- corn fields seventy four
`, +
- corn fields seventy four

+
"silly cute kitn"
+
- niko

+
"very bitable neodog_bite_neocat
+
- strongsand
+ `, webrings: `
catppuccin webring @@ -301,6 +309,7 @@ const _internal_defaultFiles = {
the outpost frontend for fedi made by kopper

smiggins.trinkey.com:
official jerimiah smiggins instance, that being my own social media platform

+
there's also a qna for me at *trinkey.com/qna

(asterisk (*) means i haven't written the code for it)

` }; const _internal_neofetchOutputs = { @@ -343,25 +352,28 @@ const _internal_neofetchOutputs = { '-MMMMMMMMMMMMM-' \`\`-:::::-\`\`` }; -const helpText = `
 -=== tSh help ===-
+const helpText = ` +
 -=== tSh help ===-
--------------------
-= cat =-
-
Displays the contents of a file.
+
displays the contents of a file
-= cd =-
-
Changes the working directory.
+
changes the working directory
-= clear =-
-
Clears the terminal output.
+
clears the terminal output
-= help =-
-
Shows this help menu.
+
shows this help menu
-= ls =-
-
Lists all files in a directory.
+
lists all files in a directory
  -l - displays more information about each file
  -a - displays all files
  -A - displays all files except implied . and ..
  -r - reverses the order of the files
  -R - recurse through all subdirectories
+
-= spin =-
+
creates a new window with a spinning blobcat wireframe
-= exit =-
-
Closes the terminal.
`; +
closes the terminal window
`; const HOME_DIR = "/home/trinkey"; let FILESYSTEM = { home: { @@ -393,22 +405,16 @@ let FILESYSTEM = { cd: { type: "file", name: "cd", content: "
function cd(directory: string): void { ... }
" }, clear: { type: "file", name: "clear", content: "
function clear(): void { ... }
" }, help: { type: "file", name: "help", content: "
function help(): string { ... }
" }, - ls: { type: "file", name: "ls", content: "
function ls(directory: string): string { ... }
" }, - neofetch: { type: "file", name: "neofetch", content: "
function neofetch(): string { ... }
" } + ls: { type: "file", name: "ls", content: "
function ls(directory?: string): string { ... }
" } } }, ".secret-file": { type: "file", name: ".secret-file", content: "
meow :3
" } }; let windowInformation = {}; function commandManager(windowID, command) { - if (!windowInformation[windowID]) { - windowInformation[windowID] = { - PWD: HOME_DIR - }; - } let out; if (_internal_commands[command.split(" ")[0]]) { - out = _internal_commands[command.split(" ")[0]](command.split(" ").slice(1).join(" ").trim(), windowID); + out = _internal_commands[command.split(" ")[0]].callback(command.split(" ").slice(1).join(" ").trim(), windowID); } else if (command == "") { out = ""; @@ -416,8 +422,11 @@ function commandManager(windowID, command) { else { out = `
Unknown command '${escapeHTML(command.split(" ")[0])}'.
Type 'help' for a list of commands
`; } + addWindowCommand(windowID, out); +} +function addWindowCommand(windowID, value) { let el = document.createElement("div"); - el.innerHTML = out; + el.innerHTML = value; WINDOWS[windowID].element.querySelector(".window").append(el); let dTE = WINDOWS[windowID].element.querySelector("[data-type-area]"); if (dTE) { diff --git a/no-js.html b/no-js.html index 2a49288..53fc24f 100644 --- a/no-js.html +++ b/no-js.html @@ -61,10 +61,9 @@
html:
<a href="https://trinkey.com/" target="_blank"><img src="https://trinkey.com/img/88x31.png" alt="trinkey's 88x31. image of her cat on the right with the word trinkey name taking up the rest of the button." title="trinkey's 88x31. image of her cat on the right with the word trinkey name taking up the rest of the button."></a>
--------------------
-

cool people:

notfire.cc - a non-spinning demigirl blobcat angled slightly with a black border to the left of "Micro" + a non-spinning demigirl blobcat angled slightly with a black border to the left of "Micro" kopper's button Sneexy unnick @@ -119,6 +118,7 @@
the outpost frontend for fedi made by kopper

smiggins.trinkey.com:
official jerimiah smiggins instance, that being my own social media platform

+
there's also a qna for me at *trinkey.com/qna

(asterisk (*) means i haven't written the code for it)
diff --git a/ts/index.ts b/ts/index.ts index cd9bb60..5ffc06e 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -68,6 +68,79 @@ function edgeMoveEvent(x: number, y: number, pos: "top" | "bottom" | "left" | "r (w.element.querySelector(".window") as HTMLElement).style.height = `${w.height}px`; } +function mouseMoveEvent(windowID: string, x: number, y: number): void { + let w: _winConf = WINDOWS[windowID]; + w.posX = Math.max(0, Math.min(innerWidth - w.width - _windowPaddingX, x - w.vars.mouseOffsetX)); + w.posY = Math.max(0, Math.min(innerHeight - w.height - _windowPaddingY, y - w.vars.mouseOffsetY)); + w.element.style.left = `${w.posX}px`; + w.element.style.top = `${w.posY}px`; +} + +function syncInputs(windowID: string): void { + let windowInput: HTMLInputElement = WINDOWS[windowID].element.querySelector("input.window-input"); + let windowVisualText: HTMLDivElement = WINDOWS[windowID].element.querySelector("[data-type-area]"); + let w: HTMLDivElement = WINDOWS[windowID].element.querySelector(".window"); + + if (!windowVisualText) { return; } + + setTimeout(function(): void { + let text: string = windowInput.value; + let cursor: number = windowInput.selectionStart; + + if (cursor == text.length) { + windowVisualText.innerHTML = `${escapeHTML(text)} `; + } else { + windowVisualText.innerHTML = `${escapeHTML(text.slice(0, cursor))}${escapeHTML(text[cursor])}${escapeHTML(text.slice(cursor + 1))}`; + } + }, 1); + + w.scrollTop = w.scrollHeight; +} + +function setCursor(windowID: string): void { + let windowInput: HTMLInputElement = WINDOWS[windowID].element.querySelector("input.window-input"); + + setTimeout((): void => { + windowInput.setSelectionRange(windowInput.value.length, windowInput.value.length); + syncInputs(windowID); + }, 1); +} + +function toggleFullscreen(windowID: string): void { + let w: _winConf = WINDOWS[windowID]; + if (w.fullscreen) { + w.posX = Math.max(0, Math.min(innerWidth - w.vars.oldWidth - _windowPaddingX, w.vars.oldPosX)); // window.vars.oldPosX; + w.posY = Math.max(0, Math.min(innerHeight - w.vars.oldHeight - _windowPaddingY, w.vars.oldPosY)); // window.vars.oldPosY; + w.width = Math.max(w.minWidth, Math.min(w.vars.oldWidth, innerWidth - _windowPaddingX)); // window.vars.oldWidth; + w.height = Math.max(w.minHeight, Math.min(w.vars.oldHeight, innerHeight - _windowPaddingY)); // window.vars.oldHeight; + w.fullscreen = false; + delete w.vars.oldPosX; + delete w.vars.oldPosY; + delete w.vars.oldWidth; + delete w.vars.oldHeight; + w.element.style.left = `${w.posX}px`; + w.element.style.top = `${w.posY}px`; + w.element.style.width = `${w.width + _windowPaddingX - 2}px`; + (w.element.querySelector(".window") as HTMLElement).style.width = `${w.width}px`; + (w.element.querySelector(".window") as HTMLElement).style.height = `${w.height}px`; + } else { + w.vars.oldPosX = w.posX; + w.vars.oldPosY = w.posY; + w.vars.oldWidth = w.width; + w.vars.oldHeight = w.height; + w.fullscreen = true; + w.posX = 0; + w.posY = 0; + w.width = innerWidth; + w.height = innerHeight; + w.element.style.left = "0px"; + w.element.style.top = "0px"; + w.element.style.width = `${w.width}px`; + (w.element.querySelector(".window") as HTMLElement).style.width = `${w.width - _windowPaddingX}px`; + (w.element.querySelector(".window") as HTMLElement).style.height = `${w.height - _windowPaddingY}px`; + } +} + function createWindow(config: _winInitConf): void { if (document.getElementById(config.id)) { incrementZIndex(config.id); @@ -114,31 +187,8 @@ function createWindow(config: _winInitConf): void { wI.classList.add("window-input"); wI.id = `${config.id}__input`; - function syncInputs(): void { - setTimeout(function(): void { - let text: string = wI.value; - let cursor: number = wI.selectionStart; - let el: HTMLElement = wC.querySelector("[data-type-area]"); - - if (!el) { return; } - - if (cursor == text.length) { - el.innerHTML = `${escapeHTML(text)} `; - } else { - el.innerHTML = `${escapeHTML(text.slice(0, cursor))}${escapeHTML(text[cursor])}${escapeHTML(text.slice(cursor + 1))}`; - } - }, 1); - } - - function setCursor(): void { - setTimeout((): void => { - wI.setSelectionRange(wI.value.length, wI.value.length); - syncInputs(); - }, 0); - } - wI.oninput = (event: KeyboardEvent): void => { - syncInputs(); + syncInputs(config.id); w.scrollTop = w.scrollHeight; }; @@ -147,13 +197,91 @@ function createWindow(config: _winInitConf): void { commandManager(config.id, wI.value.trim()); w.scrollTop = w.scrollHeight; wI.value = ""; + } else if (event.key == "Tab") { + event.preventDefault(); + + let val: string = wI.value.trim(); + let possibilities: string[] = []; + let parent: _file | null; + + if (!val) { return; } + + if (val.split(" ").length == 1 && wI.value[wI.value.length - 1] != " ") { + possibilities = Object.keys(_internal_commands).filter((cmd: string): boolean => (cmd.startsWith(val) && !cmd.startsWith("_"))); + } else if (_internal_commands[val.split(" ")[0]] && _internal_commands[val.split(" ")[0]].autocomplete) { + let ac: "dir" | "file" | string[] = _internal_commands[val.split(" ")[0]].autocomplete; + let path: string = val.split(" ").slice(1).join(" ").trim(); + let sw: string = path.split("/")[path.split("/").length - 1]; + + if (typeof ac == "object") { + possibilities = ac; + } else { + if (path) { + if (path[path.length - 1] == "/") { + parent = _internal_getFile(_internal_sanitizePath(_internal_joinPaths(windowInformation[config.id].PWD, path))); + } else { + parent = _internal_getFile(_internal_sanitizePath(_internal_joinPaths(windowInformation[config.id].PWD, path + "/.."))); + } + } else { + parent = _internal_getFile(windowInformation[config.id].PWD); + } + + if (parent && parent.type == "directory") { + let f: _files = parent.files; + possibilities = Object.keys(f); + + if (ac == "dir") { + possibilities = possibilities.filter((file: string): boolean => (f[file] && f[file].type == "directory")); + } + } else { + parent = null; + } + } + + possibilities = possibilities.filter((v: string): boolean => v.startsWith(sw)); + } + + if (possibilities.length == 1) { + if (val.split(" ").length == 1 && wI.value[wI.value.length - 1] != " ") { + wI.value = possibilities[0] + " "; + } else if (_internal_commands[val.split(" ")[0]] && _internal_commands[val.split(" ")[0]].autocomplete) { + let path: string = val; + + if (val[val.length - 1] == "/") { + path += possibilities[0]; + } else { + let p: string[] = path.split("/"); + + if (p.length == 1) { + p = p[0].split(" ", 2); + + if (p.length == 1) { + p.push(""); + } + + p.pop(); + path = p.join(" ") + " " + possibilities[0]; + } else { + p.pop(); + path = p.join("/") + "/" + possibilities[0]; + } + } + + wI.value = path + (parent && parent.type == "directory" && parent.files[possibilities[0]].type == "directory" ? "/" : " "); + } + + syncInputs(config.id); + } else if (possibilities) { + addWindowCommand(config.id, possibilities.join(" ")); + syncInputs(config.id); + } } else { - syncInputs(); + syncInputs(config.id); } }; - wI.onfocus = setCursor; - wI.onclick = setCursor; + wI.onfocus = (): void => { setCursor(config.id); }; + wI.onclick = (): void => { setCursor(config.id); }; wC = document.createElement("label"); wC.htmlFor = `${config.id}__input`; @@ -174,6 +302,7 @@ function createWindow(config: _winInitConf): void { let el: HTMLDivElement = document.createElement("div"); el.classList.add("edge", pos); el.addEventListener("mousedown", function(e: MouseEvent): void { + incrementZIndex(config.id); e.preventDefault(); WINDOWS[config.id].vars.mouseOffsetX = e.clientX - WINDOWS[config.id].posX; @@ -215,12 +344,9 @@ function createWindow(config: _winInitConf): void { vars: {} }; - function mouseMoveEvent(x: number, y: number): void { - WINDOWS[config.id].posX = Math.max(0, Math.min(innerWidth - WINDOWS[config.id].width - _windowPaddingX, x - WINDOWS[config.id].vars.mouseOffsetX)); - WINDOWS[config.id].posY = Math.max(0, Math.min(innerHeight - WINDOWS[config.id].height - _windowPaddingY, y - WINDOWS[config.id].vars.mouseOffsetY)); - wC.style.left = `${WINDOWS[config.id].posX}px`; - wC.style.top = `${WINDOWS[config.id].posY}px`; - } + windowInformation[config.id] = { + PWD: HOME_DIR + }; // wC.addEventListener("mousedown", function(): void { incrementZIndex(config.id); }); wC.addEventListener("focus", function(): void { incrementZIndex(config.id); }); @@ -237,7 +363,7 @@ function createWindow(config: _winInitConf): void { WINDOWS[config.id].vars.mouseOffsetX = e.clientX - WINDOWS[config.id].posX; WINDOWS[config.id].vars.mouseOffsetY = e.clientY - WINDOWS[config.id].posY; MOUSE_MOVE_PROCESSING[config.id] = { - callback: mouseMoveEvent, + callback: (x: number, y: number): void => { mouseMoveEvent(config.id, x, y); }, mouseUp: true }; }); @@ -253,40 +379,8 @@ function createWindow(config: _winInitConf): void { } }); - wH.querySelector(".fullscreen").addEventListener("click", function(): void { - let window: _winConf = WINDOWS[config.id]; - if (window.fullscreen) { - window.posX = Math.max(0, Math.min(innerWidth - window.vars.oldWidth - _windowPaddingX, window.vars.oldPosX)); // window.vars.oldPosX; - window.posY = Math.max(0, Math.min(innerHeight - window.vars.oldHeight - _windowPaddingY, window.vars.oldPosY)); // window.vars.oldPosY; - window.width = Math.max(window.minWidth, Math.min(window.vars.oldWidth, innerWidth - _windowPaddingX)); // window.vars.oldWidth; - window.height = Math.max(window.minHeight, Math.min(window.vars.oldHeight, innerHeight - _windowPaddingY)); // window.vars.oldHeight; - window.fullscreen = false; - delete window.vars.oldPosX; - delete window.vars.oldPosY; - delete window.vars.oldWidth; - delete window.vars.oldHeight; - wC.style.left = `${window.posX}px`; - wC.style.top = `${window.posY}px`; - wC.style.width = `${window.width + _windowPaddingX - 2}px`; - w.style.width = `${window.width}px`; - w.style.height = `${window.height}px`; - } else { - window.vars.oldPosX = window.posX; - window.vars.oldPosY = window.posY; - window.vars.oldWidth = window.width; - window.vars.oldHeight = window.height; - window.fullscreen = true; - window.posX = 0; - window.posY = 0; - window.width = innerWidth; - window.height = innerHeight; - wC.style.left = "0px"; - wC.style.top = "0px"; - wC.style.width = `${window.width}px`; - w.style.width = `${window.width - _windowPaddingX}px`; - w.style.height = `${window.height - _windowPaddingY}px`; - } - }); + wH.querySelector(".fullscreen").addEventListener("click", (): void => (toggleFullscreen(config.id))); + wH.addEventListener("dblclick", (): void => (toggleFullscreen(config.id))); globalIncrement++; } diff --git a/ts/shell.ts b/ts/shell.ts index a21b0e7..79dd37f 100644 --- a/ts/shell.ts +++ b/ts/shell.ts @@ -251,23 +251,30 @@ function _internal_neofetch(args: string, windowID: string): string { return _internal_neofetchOutputs[args]; } -const _internal_commands: { [key: string]: (args: string, windowID: string) => string } = { - cat: cat, - cd: cd, - clear: clear, - help: help, // NEEDS UPDATING - ls: ls, - exit: exit, - _internal_set_ps1: _internal_set_ps1, - _internal_neofetch: _internal_neofetch +const _internal_commands: { + [key: string]: { + callback: (args: string, windowID: string) => string, + autocomplete: "dir" | "file" | null | string[] + } +} = { + cat: { callback: cat, autocomplete: "file" }, + cd: { callback: cd, autocomplete: "dir" }, + clear: { callback: clear, autocomplete: null }, + help: { callback: help, autocomplete: null }, + ls: { callback: ls, autocomplete: "file" }, + exit: { callback: exit, autocomplete: null }, + _internal_set_ps1: { callback: _internal_set_ps1, autocomplete: null }, + _internal_neofetch: { callback: _internal_neofetch, autocomplete: null }, + spin: { callback: (args: string, windowID: string): string => { createBlob(); return ""; }, autocomplete: null }, }; // -= Variables + Other =- // const _internal_defaultFiles: StringDict = { - about: `
hi there! i'm trinkey!
+ about: `
hi there!
+
i'm trinkey, but you can call me katie too! (trinkey is more of a username)
--------------------
-
i'm a silly little kitty cat who lives in the usa (sadly).
-
i'm trans (she/is, they/them is also fine).
+
i'm a silly little cat who lives in the usa (new york time zone).
+
i'm trans (she/it, they/them is also fine).
i'm not actively in a relationship, however i'm also not looking to get into one either.
--------------------
i like to code stuff (mostly websites)! some of my programs can be found in projects section. i know a few languages, those being python, javascript/typescript, html/css (if you count those), and a little bit of java.
@@ -281,6 +288,7 @@ const _internal_defaultFiles: StringDict = {
- signal - @trinkey.01
- email - trinkey [at] proton [dot] me
- youtube - @trinkey (inactive)
+
- discord - @trinkey_ (mostly inactive)
- gpg key (1D6E 5D28 BDD4 D7FA 96B8 8799 2B33 C6C6 14F2 591A)
`, projects: `
projects - the things i made
- smiggins (website) - a social media platform i made
@@ -292,23 +300,28 @@ const _internal_defaultFiles: StringDict = { buttons: `
my button: (click to copy html)
trinkey's 88x31. image of her cat on the right with the word 'trinkey' taking up the rest of the button.
--------------------
-
cool people:
notfire.cc - a non-spinning demigirl blobcat angled slightly with a black border to the left of "Micro" + a non-spinning demigirl blobcat angled slightly with a black border to the left of "Micro" kopper's button Sneexy unnick Autumn Town Café the text 'red is purple' on a purple background doskel + velzie
`, testimonials: `
"warning: this user is trinkey"
- bread

"This user is only slightly crazy once was I. 10/10 would recommend"
- subroutine

"the f slur but repeated 36 times"
-
- corn fields seventy four
`, +
- corn fields seventy four

+
"silly cute kitn"
+
- niko

+
"very bitable neodog_bite_neocat
+
- strongsand
+ `, webrings: `
catppuccin webring @@ -346,6 +359,7 @@ const _internal_defaultFiles: StringDict = {
the outpost frontend for fedi made by kopper

smiggins.trinkey.com:
official jerimiah smiggins instance, that being my own social media platform

+
there's also a qna for me at *trinkey.com/qna

(asterisk (*) means i haven't written the code for it)

` }; @@ -390,25 +404,28 @@ const _internal_neofetchOutputs: StringDict = { \`\`-:::::-\`\`` }; -const helpText: string = `
 -=== tSh help ===-
+const helpText: string = ` +
 -=== tSh help ===-
--------------------
-= cat =-
-
Displays the contents of a file.
+
displays the contents of a file
-= cd =-
-
Changes the working directory.
+
changes the working directory
-= clear =-
-
Clears the terminal output.
+
clears the terminal output
-= help =-
-
Shows this help menu.
+
shows this help menu
-= ls =-
-
Lists all files in a directory.
+
lists all files in a directory
  -l - displays more information about each file
  -a - displays all files
  -A - displays all files except implied . and ..
  -r - reverses the order of the files
  -R - recurse through all subdirectories
+
-= spin =-
+
creates a new window with a spinning blobcat wireframe
-= exit =-
-
Closes the terminal.
`; +
closes the terminal window
`; const HOME_DIR: string = "/home/trinkey"; @@ -438,12 +455,11 @@ let FILESYSTEM: _files = { type: "directory", name: "bin", files: { - cat: { type: "file", name: "cat", content: "
function cat(file: string): string { ... }
" }, - cd: { type: "file", name: "cd", content: "
function cd(directory: string): void { ... }
" }, - clear: { type: "file", name: "clear", content: "
function clear(): void { ... }
" }, - help: { type: "file", name: "help", content: "
function help(): string { ... }
" }, - ls: { type: "file", name: "ls", content: "
function ls(directory: string): string { ... }
" }, - neofetch: { type: "file", name: "neofetch", content: "
function neofetch(): string { ... }
" } + cat: { type: "file", name: "cat", content: "
function cat(file: string): string { ... }
" }, + cd: { type: "file", name: "cd", content: "
function cd(directory: string): void { ... }
" }, + clear: { type: "file", name: "clear", content: "
function clear(): void { ... }
" }, + help: { type: "file", name: "help", content: "
function help(): string { ... }
" }, + ls: { type: "file", name: "ls", content: "
function ls(directory?: string): string { ... }
" } } }, ".secret-file": { type: "file", name: ".secret-file", content: "
meow :3
" } @@ -452,23 +468,21 @@ let FILESYSTEM: _files = { let windowInformation: { [key: string]: _tShWinInfo } = {}; function commandManager(windowID: string, command: string): void { - if (!windowInformation[windowID]) { - windowInformation[windowID] = { - PWD: HOME_DIR - }; - } - let out: string; if (_internal_commands[command.split(" ")[0]]) { - out = _internal_commands[command.split(" ")[0]](command.split(" ").slice(1).join(" ").trim(), windowID); + out = _internal_commands[command.split(" ")[0]].callback(command.split(" ").slice(1).join(" ").trim(), windowID); } else if (command == "") { out = "" } else { out = `
Unknown command '${escapeHTML(command.split(" ")[0])}'.
Type 'help' for a list of commands
`; } + addWindowCommand(windowID, out); +} + +function addWindowCommand(windowID: string, value: string): void { let el: HTMLDivElement = document.createElement("div"); - el.innerHTML = out; + el.innerHTML = value; WINDOWS[windowID].element.querySelector(".window").append(el); let dTE: HTMLElement = WINDOWS[windowID].element.querySelector("[data-type-area]");