From 983cf59476f5260ce156784afe959245efcf8983 Mon Sep 17 00:00:00 2001 From: binekrasik Date: Thu, 26 Mar 2026 22:33:04 +0100 Subject: [PATCH] feat: add some utilities --- src/program/Clear.ts | 10 +++++++++ src/program/Eval.ts | 17 +++++++++++++++ src/program/Loadprg.ts | 29 ++++++++++++++++++++++++++ src/program/Lsprg.ts | 19 +++++++++++++++++ src/program/Program.ts | 5 +++++ src/program/clear.ts | 7 ------- src/program/stdlibwsh.ts | 8 ------- src/shell/ControlCode.ts | 4 ---- src/shell/Wush.ts | 45 +++++++++++++++++++++++++++++++++------- src/styles/terminal.scss | 2 +- 10 files changed, 119 insertions(+), 27 deletions(-) create mode 100644 src/program/Clear.ts create mode 100644 src/program/Eval.ts create mode 100644 src/program/Loadprg.ts create mode 100644 src/program/Lsprg.ts create mode 100644 src/program/Program.ts delete mode 100644 src/program/clear.ts delete mode 100644 src/program/stdlibwsh.ts delete mode 100644 src/shell/ControlCode.ts diff --git a/src/program/Clear.ts b/src/program/Clear.ts new file mode 100644 index 0000000..f33dfb8 --- /dev/null +++ b/src/program/Clear.ts @@ -0,0 +1,10 @@ +import type { SimpleStream } from '../utils/SimpleStream' +import { Program } from './Program' + +export class Clear extends Program { + async Exec(_: SimpleStream, stdout: SimpleStream, __: string[]): Promise { + stdout.emit('\f') + + return 0 + } +} diff --git a/src/program/Eval.ts b/src/program/Eval.ts new file mode 100644 index 0000000..ec3af0a --- /dev/null +++ b/src/program/Eval.ts @@ -0,0 +1,17 @@ +import type { SimpleStream } from '../utils/SimpleStream' +import { Program } from './Program' + +export class Eval extends Program { + async Exec(_: SimpleStream, stdout: SimpleStream, args: string[]): Promise { + const javascript = args.slice(1).join(' ') + + try { + eval(javascript) + } catch (e) { + stdout.emit(`${String(e)}\n`) + return 1 + } + + return 0 + } +} diff --git a/src/program/Loadprg.ts b/src/program/Loadprg.ts new file mode 100644 index 0000000..2d7423e --- /dev/null +++ b/src/program/Loadprg.ts @@ -0,0 +1,29 @@ +import type { Wush } from '../shell/Wush' +import type { SimpleStream } from '../utils/SimpleStream' +import { Program } from './Program' + +export class Loadprg extends Program { + // private wush: Wush + + constructor(_: Wush) { + super() + // this.wush = wush + } + + async Exec(_: SimpleStream, stdout: SimpleStream, args: string[]): Promise { + stdout.emit('Not implemented yet.\n') + return 0 + + const javascript = args.slice(1).join(' ') + + try { + eval(javascript) + } catch (e) { + stdout.emit(`${String(e)}\n`) + stdout.emit(`${String((e as Error).stack)}\n`) + return 1 + } + + return 0 + } +} diff --git a/src/program/Lsprg.ts b/src/program/Lsprg.ts new file mode 100644 index 0000000..308a1da --- /dev/null +++ b/src/program/Lsprg.ts @@ -0,0 +1,19 @@ +import type { Wush } from '../shell/Wush' +import type { SimpleStream } from '../utils/SimpleStream' +import { Program } from './Program' + +export class Lsprg extends Program { + private wush: Wush + + constructor(wush: Wush) { + super() + this.wush = wush + } + + async Exec(_: SimpleStream, stdout: SimpleStream, __: string[]): Promise { + for (const program in this.wush.GetPrograms()) + stdout.emit(`${program}\n`) + + return 0 + } +} diff --git a/src/program/Program.ts b/src/program/Program.ts new file mode 100644 index 0000000..eecd91c --- /dev/null +++ b/src/program/Program.ts @@ -0,0 +1,5 @@ +import type { SimpleStream } from "../utils/SimpleStream"; + +export abstract class Program { + abstract Exec(stdin: SimpleStream, stdout: SimpleStream, args: string[]): Promise +} diff --git a/src/program/clear.ts b/src/program/clear.ts deleted file mode 100644 index f3b3ac7..0000000 --- a/src/program/clear.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { SimpleStream } from '../utils/SimpleStream' - -export const ClearExec = async (stdin: SimpleStream, stdout: SimpleStream): Promise => { - stdout.emit("\f") - - return 0 -} diff --git a/src/program/stdlibwsh.ts b/src/program/stdlibwsh.ts deleted file mode 100644 index 87809e4..0000000 --- a/src/program/stdlibwsh.ts +++ /dev/null @@ -1,8 +0,0 @@ -// stdlibwsh - (st)andard (lib)rary (w)eb (sh)ell -// - céčkoismy at their peak - -import type { SimpleStream } from '../utils/SimpleStream' - -export const io = { - -} diff --git a/src/shell/ControlCode.ts b/src/shell/ControlCode.ts deleted file mode 100644 index 9fdad98..0000000 --- a/src/shell/ControlCode.ts +++ /dev/null @@ -1,4 +0,0 @@ -// a representation of ascii control codes -export const ControlCode = { - FormFeed: 12, -} diff --git a/src/shell/Wush.ts b/src/shell/Wush.ts index e153bc9..3d3adbb 100644 --- a/src/shell/Wush.ts +++ b/src/shell/Wush.ts @@ -1,11 +1,14 @@ // Web-Uno Shell // the best name I could come up with lmao -import { ClearExec } from '../program/clear' +import { Clear } from '../program/Clear' +import { Eval } from '../program/Eval' +import { Loadprg } from '../program/Loadprg' +import { Lsprg } from '../program/Lsprg' +import { Program } from '../program/Program' import { Terminal } from '../terminal/Terminal' import { EventBroadcaster } from '../utils/EventBroadcaster' import { SimpleStream } from '../utils/SimpleStream' -import { ControlCode } from './ControlCode' import { Shell } from './Shell' export class Wush extends Shell { @@ -23,6 +26,8 @@ export class Wush extends Shell { readonly stdin: SimpleStream readonly stdout: SimpleStream + private programs: { [name: string]: Program } = {} + constructor(broadcaster: EventBroadcaster, terminal: Terminal) { super(broadcaster, terminal) @@ -36,10 +41,28 @@ export class Wush extends Shell { this.HandleKeyInput(key, isCharacter), ) + // load core programs + this.programs['clear'] = new Clear() + this.programs['eval'] = new Eval() + this.programs['loadprg'] = new Loadprg(this) + this.programs['lsprg'] = new Lsprg(this) + this.stdout.on(data => this.WriteEscapedString(data)) this.Prompt() } + GetPrograms(): { [name: string]: Program } { + return this.programs + } + + LoadProgram(program: Program, name: string) { + this.programs[name] = program + } + + UnloadProgram(name: string) { + delete this.programs[name] + } + Prompt() { this.terminal.Write(`hi [${this.execExitCode}] -> `) } @@ -53,6 +76,8 @@ export class Wush extends Shell { buf.forEach((char, i) => { if (this.ProcessControlCode(char)) { buf.splice(i, 1) + } else { + this.terminal.Write(char) } }) } @@ -90,16 +115,19 @@ export class Wush extends Shell { this.execExitCode = -1 - if (args[0] === 'clear') { - ClearExec(this.stdin, this.stdout) + if (this.programs[args[0]] instanceof Program) { + this.programs[args[0]].Exec(this.stdin, this.stdout, args) .then(code => { this.execExitCode = code != -1 ? code : -2 }) + .catch(() => { + this.WriteEscapedString("lol") + }) .finally(() => { // check if the exec actually exited with an exit code // and if not, set it to -2 to indicate that it didn't exit with a valid code - if (this.execExitCode != -1) - this.execExitCode == -2 + if (this.execExitCode === -1) + this.execExitCode = -2 // this.terminal.Write(`The program exited with exit code ${this.execExitCode}.`) this.Prompt() @@ -109,7 +137,7 @@ export class Wush extends Shell { // don't print anything if there are no arguments if (args[0].length !== 0) { - this.terminal.Write(`Program ${args[0]} was not found.`) + this.terminal.Write(`wush: unknown command: ${args[0]}.`) this.terminal.MoveCursor(0, 1, { x: true, y: false }) } @@ -122,6 +150,9 @@ export class Wush extends Shell { case '\f': this.terminal.NewPage() return true + case '\n': + this.terminal.MoveCursor(0, 1, { x: true, y: false }) + return true default: return false } diff --git a/src/styles/terminal.scss b/src/styles/terminal.scss index dbf5d71..f269f9f 100644 --- a/src/styles/terminal.scss +++ b/src/styles/terminal.scss @@ -5,7 +5,7 @@ #terminal { background: colors.$terminal-background; color: colors.$terminal-white; - font-family: "JetBrains Mono", "Cascadia Mono", "Consolas", monospace; + font-family: "CaskaydiaCove", "CaskaydiaCove Nerd Font", "JetBrains Mono", "JetBrains Mono Nerd", monospace; ::-moz-selection { background: colors.$terminal-white;