From bb7e2a4ae3bfa34eb9f340c9bf2f389e196c8725 Mon Sep 17 00:00:00 2001 From: rhpidfyre Date: Tue, 4 Feb 2025 23:55:09 -0500 Subject: [PATCH] the prompt now displays and repeats on enter --- bun.lock | 12 +++-- package.json | 2 +- src/components/button.astro | 2 +- src/components/react/fs.ts | 1 + src/components/react/shell/events.tsx | 54 +++++++++++++++++++ src/components/react/shell/prompt.tsx | 18 +++++-- src/components/react/terminal.tsx | 33 ------------ .../{term_events.ts => terminal/events.ts} | 0 src/components/react/terminal/exec.tsx | 21 ++++++++ src/pages/index.astro | 4 +- 10 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 src/components/react/shell/events.tsx delete mode 100644 src/components/react/terminal.tsx rename src/components/react/{term_events.ts => terminal/events.ts} (100%) create mode 100644 src/components/react/terminal/exec.tsx diff --git a/bun.lock b/bun.lock index 35918fa..e3cfe7b 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ "@astrojs/compiler": ["@astrojs/compiler@2.10.3", "", {}, "sha512-bL/O7YBxsFt55YHU021oL+xz+B/9HvGNId3F9xURN16aeqDK9juHGktdkCSXz+U4nqFACq6ZFvWomOzhV+zfPw=="], - "@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.5.0", "", {}, "sha512-CgB5ZaZO1PFG+rbjF3HnA7G6gIBjJ070xb7bUjeu5Gqqufma+t6fpuRWMXnK2iEO3zVyX7e/xplPlqtFKy/lvw=="], + "@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.5.1", "", {}, "sha512-M7rAge1n2+aOSxNvKUFa0u/KFn0W+sZy7EW91KOSERotm2Ti8qs+1K0xx3zbOxtAVrmJb5/J98eohVvvEqtNkw=="], "@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.1.0", "", { "dependencies": { "@astrojs/prism": "3.2.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", "shiki": "^1.29.1", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-emZNNSTPGgPc3V399Cazpp5+snogjaF04ocOSQn9vy3Kw/eIC4vTQjXOrWDEoSEy+AwPDZX9bQ4wd3bxhpmGgQ=="], @@ -304,7 +304,7 @@ "array-iterate": ["array-iterate@2.0.1", "", {}, "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg=="], - "astro": ["astro@5.2.3", "", { "dependencies": { "@astrojs/compiler": "^2.10.3", "@astrojs/internal-helpers": "0.5.0", "@astrojs/markdown-remark": "6.1.0", "@astrojs/telemetry": "3.2.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "@types/cookie": "^0.6.0", "acorn": "^8.14.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.1.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^0.7.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.24.2", "estree-walker": "^3.0.3", "fast-glob": "^3.3.3", "flattie": "^1.1.1", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "micromatch": "^4.0.8", "mrmime": "^2.0.0", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "preferred-pm": "^4.1.0", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.0", "shiki": "^1.29.2", "tinyexec": "^0.3.2", "tsconfck": "^3.1.4", "ultrahtml": "^1.5.3", "unist-util-visit": "^5.0.0", "unstorage": "^1.14.4", "vfile": "^6.0.3", "vite": "^6.0.11", "vitefu": "^1.0.5", "which-pm": "^3.0.0", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.0", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.1", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-04AceE/gVihtO3V28Ss0+tPPgLHGoulXrm1E7fUVPYyQu7y6w8+oXfYyzh1lpy+uEYiebjH7AFlJoz73anBmZA=="], + "astro": ["astro@5.2.5", "", { "dependencies": { "@astrojs/compiler": "^2.10.3", "@astrojs/internal-helpers": "0.5.1", "@astrojs/markdown-remark": "6.1.0", "@astrojs/telemetry": "3.2.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "@types/cookie": "^0.6.0", "acorn": "^8.14.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.1.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^0.7.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.24.2", "estree-walker": "^3.0.3", "fast-glob": "^3.3.3", "flattie": "^1.1.1", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "micromatch": "^4.0.8", "mrmime": "^2.0.0", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "preferred-pm": "^4.1.1", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^1.29.2", "tinyexec": "^0.3.2", "tsconfck": "^3.1.4", "ultrahtml": "^1.5.3", "unist-util-visit": "^5.0.0", "unstorage": "^1.14.4", "vfile": "^6.0.3", "vite": "^6.0.11", "vitefu": "^1.0.5", "which-pm": "^3.0.1", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.0", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.1", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-AYXyYkc+c5xbKTm48FyQA91y81nXyNPAaoyafR0LUugE4lAwuvIUcXDBfMzmbuP1lGRvsE33G2oypv6gbGaPFg=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], @@ -664,7 +664,7 @@ "postcss": ["postcss@8.5.1", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ=="], - "preferred-pm": ["preferred-pm@4.1.0", "", { "dependencies": { "find-up-simple": "^1.0.0", "find-yarn-workspace-root2": "1.2.16", "which-pm": "^3.0.0" } }, "sha512-cNKMVcSvE3hZBRukdRsvPtlUaM2fYLFbIvBz620XaDA5SjHsCRsAjNE2baI90Hh7QvJIjCHJYnpPtyqJ1/kOjQ=="], + "preferred-pm": ["preferred-pm@4.1.1", "", { "dependencies": { "find-up-simple": "^1.0.0", "find-yarn-workspace-root2": "1.2.16", "which-pm": "^3.0.1" } }, "sha512-rU+ZAv1Ur9jAUZtGPebQVQPzdGhNzaEiQ7VL9+cjsAWPHFYOccNXPNiev1CCDSOg/2j7UujM7ojNhpkuILEVNQ=="], "prismjs": ["prismjs@1.29.0", "", {}, "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q=="], @@ -728,7 +728,7 @@ "scss": ["scss@0.2.4", "", { "dependencies": { "ometa": "0.2.2" } }, "sha512-4u8V87F+Q/upVhUmhPnB4C1R11xojkRkWjExL2v0CX2EXTg18VrKd+9JWoeyCp2VEMdSpJsyAvVU+rVjogh51A=="], - "semver": ["semver@7.7.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ=="], + "semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], "sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], @@ -814,7 +814,7 @@ "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="], - "which-pm": ["which-pm@3.0.0", "", { "dependencies": { "load-yaml-file": "^0.2.0" } }, "sha512-ysVYmw6+ZBhx3+ZkcPwRuJi38ZOTLJJ33PSHaitLxSKUMsh0LkKd0nC69zZCwt5D+AYUcMK2hhw4yWny20vSGg=="], + "which-pm": ["which-pm@3.0.1", "", { "dependencies": { "load-yaml-file": "^0.2.0" } }, "sha512-v2JrMq0waAI4ju1xU5x3blsxBBMgdgZve580iYMN5frDaLGjbA24fok7wKCsya8KLVO19Ju4XDc5+zTZCJkQfg=="], "which-pm-runs": ["which-pm-runs@1.1.0", "", {}, "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="], @@ -864,6 +864,8 @@ "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + "sharp/semver": ["semver@7.7.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ=="], + "unstorage/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], diff --git a/package.json b/package.json index 9cd3075..117b1a7 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@astrojs/react": "^4.2.0", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", - "astro": "^5.2.3", + "astro": "^5.2.5", "react": "^19.0.0", "react-dom": "^19.0.0", "sass": "^1.83.4", diff --git a/src/components/button.astro b/src/components/button.astro index abd28de..1327a52 100644 --- a/src/components/button.astro +++ b/src/components/button.astro @@ -16,6 +16,6 @@ const {href, display, color = "transparent"} = Astro.props height: 100%; padding: 0 20px 0 20px; - &:hover { background-color: var(--hf-button-hover-color) } + &:hover { background-color: var(--hf-button-hover-color) !important } } \ No newline at end of file diff --git a/src/components/react/fs.ts b/src/components/react/fs.ts index af41466..c2f8d43 100644 --- a/src/components/react/fs.ts +++ b/src/components/react/fs.ts @@ -4,6 +4,7 @@ const enum EntryType { Directory, File } + type File = string type Entry = { readonly inner: T, diff --git a/src/components/react/shell/events.tsx b/src/components/react/shell/events.tsx new file mode 100644 index 0000000..d548913 --- /dev/null +++ b/src/components/react/shell/events.tsx @@ -0,0 +1,54 @@ +import { useState } from "react" +import type { JSX } from "react/jsx-dev-runtime" + +import Display from "./prompt" + +type SetStateAction = React.Dispatch> +const enum Key { + Enter = "Enter", + ArrowUp = "ArrowUp", + ArrowDown = "ArrowDown", + Tab = "Tab" +} + +function DisplayPrompt() { + return <> + + + +} + +function Prompt([existingPrompts, setPrompt]: [JSX.Element[], SetStateAction]) { + const shell_prompts = document.getElementsByClassName("shell-ps1") + Array.from(shell_prompts).forEach((shellps1) => { + (shellps1 as HTMLInputElement).disabled = true + }) + setPrompt([...existingPrompts, DisplayPrompt()]) +} + +function keyboard_stream(terminal_window: HTMLElement, existingPrompts: JSX.Element[], setPrompt: SetStateAction) { + terminal_window.addEventListener("keydown", keyboard_event => { + if (keyboard_event.key === Key.Enter) { + Prompt([existingPrompts, setPrompt]) + } else if (keyboard_event.key === Key.ArrowUp) { + + } else if (keyboard_event.key === Key.ArrowDown) { + + } else if (keyboard_event.key === Key.Tab) { + + } + }) +} + +function Events() { + const terminal_window = document.querySelector("main") + if (terminal_window) { + const [existingPrompts, setPrompt] = useState([DisplayPrompt()]) + + keyboard_stream(terminal_window, existingPrompts, setPrompt) + return existingPrompts + } + return +} + +export default Events \ No newline at end of file diff --git a/src/components/react/shell/prompt.tsx b/src/components/react/shell/prompt.tsx index c2a2709..58b5780 100644 --- a/src/components/react/shell/prompt.tsx +++ b/src/components/react/shell/prompt.tsx @@ -1,10 +1,18 @@ import { working_dir } from "../fs" -import rgb, { cyan, green } from "./color" +import { cyan, green } from "./color" -const GetWorkingDir = () => working_dir === "user" ? "~" : working_dir +const userAgent = navigator.userAgent +const browser_name_fallible = userAgent.match(/Firefox.\d+[\d.\d]+|Chrome.\d+[\d.\d]+/gm)?.map(f => f.split("/")[0]) +const browser_name = browser_name_fallible ? browser_name_fallible[0].toLowerCase() : "unknown" -export default function Prompt() { +function GetWorkingDir() { + return working_dir === "user" ? "~" : working_dir +} + +export default function Display() { const user = cyan("user") const dir = green(GetWorkingDir()) - return

{user}@host {dir}{"> "}

-} \ No newline at end of file + return

{user}@{browser_name} {dir}{"> "}

+} + +export { userAgent } \ No newline at end of file diff --git a/src/components/react/terminal.tsx b/src/components/react/terminal.tsx deleted file mode 100644 index 065754e..0000000 --- a/src/components/react/terminal.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import type { JSX } from "react/jsx-dev-runtime" -import { TermEvents } from "./term_events" -import { createRoot } from "react-dom/client" -import { useState } from "react" - -import Prompt from "./shell/prompt" - -const active_shell_prompt = ShellPrompt() - -function ShellEvents() { - const shell_input = document.querySelector("main") - if (shell_input) { - const [prompts, newPrompt] = useState([]) - shell_input.addEventListener("keydown", (keyboard_event) => { - if (keyboard_event.key == "Enter") { - - } - }) - } -} - -function ShellPrompt() { - return
- - -
-} - -export default function Shell() { - TermEvents() - ShellEvents() - return active_shell_prompt -} \ No newline at end of file diff --git a/src/components/react/term_events.ts b/src/components/react/terminal/events.ts similarity index 100% rename from src/components/react/term_events.ts rename to src/components/react/terminal/events.ts diff --git a/src/components/react/terminal/exec.tsx b/src/components/react/terminal/exec.tsx new file mode 100644 index 0000000..504d04c --- /dev/null +++ b/src/components/react/terminal/exec.tsx @@ -0,0 +1,21 @@ +import { TermEvents } from "./events" +import { red } from "../shell/color" + +import Events from "../shell/events" + +function Panic(message: string) { + return <> +

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

+

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

+

{red(message)}

+

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

+ +} + +export default function Shell() { + const existingPrompts = Events() + if (existingPrompts) { + return existingPrompts.map((ps1, k) =>
{ps1}
) + } + return Panic("The
element is missing") +} \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro index 1fed8a2..358a4a9 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,7 +1,7 @@ --- import Webpage from '../layouts/Webpage.astro'; import Motd from '../components/terminal/motd.astro'; -import Terminal from '../components/react/terminal'; +import Terminal from '../components/react/terminal/exec'; --- @@ -31,5 +31,7 @@ import Terminal from '../components/react/terminal'; width: 90%; /* Pester me when this gets undrafted */ caret-shape: block; + + &:disabled { color: white } } \ No newline at end of file