feat: add some utilities
This commit is contained in:
10
src/program/Clear.ts
Normal file
10
src/program/Clear.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import type { SimpleStream } from '../utils/SimpleStream'
|
||||||
|
import { Program } from './Program'
|
||||||
|
|
||||||
|
export class Clear extends Program {
|
||||||
|
async Exec(_: SimpleStream<string>, stdout: SimpleStream<string>, __: string[]): Promise<number> {
|
||||||
|
stdout.emit('\f')
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/program/Eval.ts
Normal file
17
src/program/Eval.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import type { SimpleStream } from '../utils/SimpleStream'
|
||||||
|
import { Program } from './Program'
|
||||||
|
|
||||||
|
export class Eval extends Program {
|
||||||
|
async Exec(_: SimpleStream<string>, stdout: SimpleStream<string>, args: string[]): Promise<number> {
|
||||||
|
const javascript = args.slice(1).join(' ')
|
||||||
|
|
||||||
|
try {
|
||||||
|
eval(javascript)
|
||||||
|
} catch (e) {
|
||||||
|
stdout.emit(`${String(e)}\n`)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/program/Loadprg.ts
Normal file
29
src/program/Loadprg.ts
Normal file
@@ -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<string>, stdout: SimpleStream<string>, args: string[]): Promise<number> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/program/Lsprg.ts
Normal file
19
src/program/Lsprg.ts
Normal file
@@ -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<string>, stdout: SimpleStream<string>, __: string[]): Promise<number> {
|
||||||
|
for (const program in this.wush.GetPrograms())
|
||||||
|
stdout.emit(`${program}\n`)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/program/Program.ts
Normal file
5
src/program/Program.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import type { SimpleStream } from "../utils/SimpleStream";
|
||||||
|
|
||||||
|
export abstract class Program {
|
||||||
|
abstract Exec(stdin: SimpleStream<string>, stdout: SimpleStream<string>, args: string[]): Promise<number>
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import type { SimpleStream } from '../utils/SimpleStream'
|
|
||||||
|
|
||||||
export const ClearExec = async (stdin: SimpleStream<string>, stdout: SimpleStream<string>): Promise<number> => {
|
|
||||||
stdout.emit("\f")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
@@ -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 = {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// a representation of ascii control codes
|
|
||||||
export const ControlCode = {
|
|
||||||
FormFeed: 12,
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
// Web-Uno Shell
|
// Web-Uno Shell
|
||||||
// the best name I could come up with lmao
|
// 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 { Terminal } from '../terminal/Terminal'
|
||||||
import { EventBroadcaster } from '../utils/EventBroadcaster'
|
import { EventBroadcaster } from '../utils/EventBroadcaster'
|
||||||
import { SimpleStream } from '../utils/SimpleStream'
|
import { SimpleStream } from '../utils/SimpleStream'
|
||||||
import { ControlCode } from './ControlCode'
|
|
||||||
import { Shell } from './Shell'
|
import { Shell } from './Shell'
|
||||||
|
|
||||||
export class Wush extends Shell {
|
export class Wush extends Shell {
|
||||||
@@ -23,6 +26,8 @@ export class Wush extends Shell {
|
|||||||
readonly stdin: SimpleStream<string>
|
readonly stdin: SimpleStream<string>
|
||||||
readonly stdout: SimpleStream<string>
|
readonly stdout: SimpleStream<string>
|
||||||
|
|
||||||
|
private programs: { [name: string]: Program } = {}
|
||||||
|
|
||||||
constructor(broadcaster: EventBroadcaster, terminal: Terminal) {
|
constructor(broadcaster: EventBroadcaster, terminal: Terminal) {
|
||||||
super(broadcaster, terminal)
|
super(broadcaster, terminal)
|
||||||
|
|
||||||
@@ -36,10 +41,28 @@ export class Wush extends Shell {
|
|||||||
this.HandleKeyInput(key, isCharacter),
|
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.stdout.on(data => this.WriteEscapedString(data))
|
||||||
this.Prompt()
|
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() {
|
Prompt() {
|
||||||
this.terminal.Write(`hi [${this.execExitCode}] -> `)
|
this.terminal.Write(`hi [${this.execExitCode}] -> `)
|
||||||
}
|
}
|
||||||
@@ -53,6 +76,8 @@ export class Wush extends Shell {
|
|||||||
buf.forEach((char, i) => {
|
buf.forEach((char, i) => {
|
||||||
if (this.ProcessControlCode(char)) {
|
if (this.ProcessControlCode(char)) {
|
||||||
buf.splice(i, 1)
|
buf.splice(i, 1)
|
||||||
|
} else {
|
||||||
|
this.terminal.Write(char)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -90,16 +115,19 @@ export class Wush extends Shell {
|
|||||||
|
|
||||||
this.execExitCode = -1
|
this.execExitCode = -1
|
||||||
|
|
||||||
if (args[0] === 'clear') {
|
if (this.programs[args[0]] instanceof Program) {
|
||||||
ClearExec(this.stdin, this.stdout)
|
this.programs[args[0]].Exec(this.stdin, this.stdout, args)
|
||||||
.then(code => {
|
.then(code => {
|
||||||
this.execExitCode = code != -1 ? code : -2
|
this.execExitCode = code != -1 ? code : -2
|
||||||
})
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.WriteEscapedString("lol")
|
||||||
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
// check if the exec actually exited with an exit code
|
// 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
|
// and if not, set it to -2 to indicate that it didn't exit with a valid code
|
||||||
if (this.execExitCode != -1)
|
if (this.execExitCode === -1)
|
||||||
this.execExitCode == -2
|
this.execExitCode = -2
|
||||||
|
|
||||||
// this.terminal.Write(`The program exited with exit code ${this.execExitCode}.`)
|
// this.terminal.Write(`The program exited with exit code ${this.execExitCode}.`)
|
||||||
this.Prompt()
|
this.Prompt()
|
||||||
@@ -109,7 +137,7 @@ export class Wush extends Shell {
|
|||||||
|
|
||||||
// don't print anything if there are no arguments
|
// don't print anything if there are no arguments
|
||||||
if (args[0].length !== 0) {
|
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 })
|
this.terminal.MoveCursor(0, 1, { x: true, y: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,6 +150,9 @@ export class Wush extends Shell {
|
|||||||
case '\f':
|
case '\f':
|
||||||
this.terminal.NewPage()
|
this.terminal.NewPage()
|
||||||
return true
|
return true
|
||||||
|
case '\n':
|
||||||
|
this.terminal.MoveCursor(0, 1, { x: true, y: false })
|
||||||
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#terminal {
|
#terminal {
|
||||||
background: colors.$terminal-background;
|
background: colors.$terminal-background;
|
||||||
color: colors.$terminal-white;
|
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 {
|
::-moz-selection {
|
||||||
background: colors.$terminal-white;
|
background: colors.$terminal-white;
|
||||||
|
|||||||
Reference in New Issue
Block a user