diff --git a/src/components/client/elements/create.ts b/src/components/client/elements/create.ts new file mode 100644 index 0000000..0c70b66 --- /dev/null +++ b/src/components/client/elements/create.ts @@ -0,0 +1,9 @@ +function create(element: T, className?: string): HTMLElementTagNameMap[T] { + const new_element = document.createElement(element) + if (className) { + new_element.className = className + } + return new_element +} + +export default create \ No newline at end of file diff --git a/src/components/client/elements/prompt.ts b/src/components/client/elements/prompt.ts new file mode 100644 index 0000000..e0e8029 --- /dev/null +++ b/src/components/client/elements/prompt.ts @@ -0,0 +1,66 @@ +import { cyan, green } from "../shell/color" +import { get_working_dir_name } from "../shell/fs/fn" + +import create from "./create" + +const userAgent = navigator.userAgent +const browser_name_fallible = userAgent.match(/Firefox.\d+[\d.\d]+|Chrome.\d+[\d.\d]+/gm)?.map(f => f.split("/")[0]) +let browser_name = "unknown" +if (browser_name_fallible) { + browser_name = browser_name_fallible[0] === "Firefox" ? "gecko" : "chromium" +} + +interface Ps1Prompt { + readonly body: HTMLDivElement, + readonly input: HTMLInputElement +} +interface Inputs { + old?: HTMLInputElement, + new?: HTMLInputElement +} +let inputs: Inputs = { + old: undefined, + new: undefined +} + +function ps1_element(user: HTMLSpanElement, dir: HTMLSpanElement) { + const display = create("p") + display.appendChild(user) + display.append(`@${browser_name}`) + display.appendChild(dir) + display.append("> ") + return display +} + +function working_dir() { + const dir_name = get_working_dir_name() + return dir_name === "user" ? "~" : dir_name +} + +function working_dir_element() { + const user = cyan("user") + const dir = green(" "+working_dir()) + return ps1_element(user, dir) +} + +export default function prompt(): Ps1Prompt { + const prompt_div = create("div", "shell-prompt") + const ps1 = working_dir_element() + const input = create("input", "shell-ps1") + input.type = "text" + input.spellcheck = false + + inputs.old = inputs.new + if (inputs.old) { + inputs.old.disabled = true + } + inputs.new = input + + prompt_div.appendChild(ps1) + prompt_div.appendChild(input) + + return { + body: prompt_div, + input: input + } +} \ No newline at end of file diff --git a/src/components/client/shell/color.ts b/src/components/client/shell/color.ts index 2af5d0b..a186897 100644 --- a/src/components/client/shell/color.ts +++ b/src/components/client/shell/color.ts @@ -1,13 +1,28 @@ +import create from "../elements/create" +const enum Colors { + red = "red", + green = "green", + blue = "blue", + cyan = "cyan", + bold = "bold" +} +function newcolor(inner: string, color?: Colors) { + const span = create("span", color) + span.innerText = inner + return span +} -const red = (s: string) => {s} -const green = (s: string) => {s} -const blue = (s: string) => {s} -const cyan = (s: string) => {s} -const bold = (s: string) => {s} +const red = (s: string) => newcolor(s, Colors.red ) +const green = (s: string) => newcolor(s, Colors.green) +const blue = (s: string) => newcolor(s, Colors.blue) +const cyan = (s: string) => newcolor(s, Colors.cyan) +const bold = (s: string) => newcolor(s, Colors.bold) export default function rgb(s: string, Ru8: number, Gu8: number, Bu8: number) { - return {s} + const rgb_span = newcolor(s) + rgb_span.style.color = `rgb(${Ru8},${Gu8},${Bu8})` + return rgb_span } export { diff --git a/src/components/client/shell/events.ts b/src/components/client/shell/events.ts index b1f4b5a..0e66c52 100644 --- a/src/components/client/shell/events.ts +++ b/src/components/client/shell/events.ts @@ -1,9 +1,6 @@ import Display from "./prompt" import run from "./command/run" -import { type newElement } from "../terminal/exec"; -import type { JSX } from "react"; - const enum Key { Enter = "Enter", ArrowUp = "ArrowUp", @@ -11,28 +8,6 @@ const enum Key { Tab = "Tab" } -function display_prompt() { - return
- - -
-} - -function get_current_prompt(): HTMLInputElement | undefined { - const shell_input = document.getElementsByClassName("shell-ps1") - - return shell_input[shell_input.length-1] as HTMLInputElement -} - -function new_prompt(): JSX.Element { - const shell_prompts = document.getElementsByClassName("shell-ps1") - - Array.from(shell_prompts).forEach(shellps1 => { - (shellps1 as HTMLInputElement).disabled = true - }) - return display_prompt() -} - function keyboard_events(terminal_window: HTMLElement, new_elements_f: newElement) { const terminal_event = (keyboard_event: KeyboardEvent) => { if (keyboard_event.key === Key.Enter) { @@ -57,6 +32,4 @@ function keyboard_events(terminal_window: HTMLElement, new_elements_f: newElemen export { keyboard_events, - display_prompt, - get_current_prompt } \ No newline at end of file diff --git a/src/components/client/terminal.ts b/src/components/client/terminal.ts new file mode 100644 index 0000000..10812e5 --- /dev/null +++ b/src/components/client/terminal.ts @@ -0,0 +1,42 @@ +// import { red } from "../shell/color" +// import { display_prompt, keyboard_events } from "../shell/events" + +import prompt from "./elements/prompt" +// import run from "./shell/command/run" + +const terminal_window = document.querySelector("main") + +const enum Key { + Enter = "Enter", + ArrowUp = "ArrowUp", + ArrowDown = "ArrowDown", + Tab = "Tab" +} + +function spawnps1(terminal_window_safe: HTMLElement) { + const ps1prompt = prompt() + terminal_window_safe.appendChild(ps1prompt.body) + input_processor(ps1prompt.input) +} + +type InputClosure = (key_event: KeyboardEvent) => void +function key_enter(ps1input: HTMLInputElement, key_event: KeyboardEvent, input_closure: InputClosure) { + key_event.preventDefault() + // run(ps1input.value) + ps1input.removeEventListener("keydown", input_closure) +} + +function input_processor(ps1input: HTMLInputElement) { + const input_closure = (key_event: KeyboardEvent) => { + if (key_event.key === Key.Enter) { + key_enter(ps1input, key_event, input_closure) + } + } + ps1input.addEventListener("keydown", input_closure) +} + +if (terminal_window) { + spawnps1(terminal_window) +} else { + +} \ No newline at end of file diff --git a/src/components/client/terminal/contextMenu.ts b/src/components/client/terminal/contextMenu.ts deleted file mode 100644 index 623775a..0000000 --- a/src/components/client/terminal/contextMenu.ts +++ /dev/null @@ -1,30 +0,0 @@ -const terminal_window = document.querySelector("main") - -interface PromptPosition { - x: number, - y: number, -} - -interface PromptContext extends PromptPosition { - enabled: boolean, -} - -function Menu(pos: PromptPosition) { - console.log(pos.x, pos.y) -} - -export default function ContextMenu() { - if (terminal_window) { - useEffect(() => { - const [contextMenu, newContextMenu] = useState(false) - const [_, toggleRightClick] = useState({enabled: false, x: 0, y: 0}) - - terminal_window.addEventListener("contextmenu", (menuEvent) => { - menuEvent.preventDefault() - toggleRightClick({enabled: true, x: menuEvent.pageX, y: menuEvent.pageY}) - Menu({x: menuEvent.pageX, y: menuEvent.pageY}) - }) - }) - - } -} \ No newline at end of file diff --git a/src/components/client/terminal/exec.ts b/src/components/client/terminal/exec.ts deleted file mode 100644 index 2eb4c26..0000000 --- a/src/components/client/terminal/exec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { red } from "../shell/color" -import { display_prompt, keyboard_events } from "../shell/events" - -const terminal_window = document.getElementById("interactive-area") - -// function panic(message: string) { -// return <> -//

{red("=================================================")}

-//

{red("An unexpected JavaScript error occured:")}

-//

{red(message)}

-//

{red("=================================================")}

-// -// } - -// function ps1(terminal_window_safe: HTMLElement): JSX.Element[] { -// const [renderedElements, renderElement] = useState([display_prompt()]) -// const new_elements_f = (elements: JSX.Element[]) => renderElement([...renderedElements, ...elements]) - -// keyboard_events(terminal_window_safe, new_elements_f) - -// return renderedElements -// } - -// export default function Shell() { -// if (terminal_window) { -// return ps1(terminal_window).map((element, k) => {element}) -// } -// return panic("The
element is missing") -// } - -// export { -// panic, -// type newElement, -// } \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro index 594e4d4..4e81bda 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -6,7 +6,7 @@ import Motd from '../components/terminal/motd.astro';
- +