the ps1 prompt displays properly

This commit is contained in:
2025-02-17 15:02:06 -05:00
parent 84e7089140
commit 375427b16e
8 changed files with 139 additions and 98 deletions

View File

@ -0,0 +1,9 @@
function create<T extends keyof HTMLElementTagNameMap>(element: T, className?: string): HTMLElementTagNameMap[T] {
const new_element = document.createElement(element)
if (className) {
new_element.className = className
}
return new_element
}
export default create

View File

@ -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
}
}

View File

@ -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) => <span className="red">{s}</span>
const green = (s: string) => <span className="green">{s}</span>
const blue = (s: string) => <span className="blue">{s}</span>
const cyan = (s: string) => <span className="cyan">{s}</span>
const bold = (s: string) => <span className="bold">{s}</span>
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 <span style={{color: `rgb(${Ru8},${Gu8},${Bu8})`}}>{s}</span>
const rgb_span = newcolor(s)
rgb_span.style.color = `rgb(${Ru8},${Gu8},${Bu8})`
return rgb_span
}
export {

View File

@ -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 <div className="shell-prompt">
<Display/>
<input className="shell-ps1" type="text" spellCheck={false}/>
</div>
}
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
}

View File

@ -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 {
}

View File

@ -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})
})
})
}
}

View File

@ -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 <>
// <p>{red("=================================================")}</p>
// <p>{red("An unexpected JavaScript error occured:")}</p>
// <p>{red(message)}</p>
// <p>{red("=================================================")}</p>
// </>
// }
// 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) => <React.Fragment key={k}>{element}</React.Fragment>)
// }
// return panic("The <main> element is missing")
// }
// export {
// panic,
// type newElement,
// }