fs functions wip, set_working_dir needs to work

This commit is contained in:
2025-02-07 02:45:36 -05:00
parent acf460772c
commit ee7b2168d9
11 changed files with 153 additions and 96 deletions

View File

@ -2,6 +2,7 @@ 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>
export default function rgb(s: string, Ru8: number, Gu8: number, Bu8: number) {
return <span style={{color: `rgb(${Ru8},${Gu8},${Bu8})`}}>{s}</span>
@ -11,5 +12,6 @@ export {
red,
green,
blue,
cyan
cyan,
bold
}

View File

@ -1,26 +0,0 @@
import { working_dir } from "../fs"
type args = string[]
function ls(args: args) {
console.log(args)
}
function pwd(args: args) {
}
function cat(args: args) {
}
interface commands_list {
[index: string]: (args: args) => void
}
const commands: commands_list = {
["ls"]: ls,
["pwd"]: pwd,
["cat"]: cat,
}
export default commands

View File

@ -0,0 +1,48 @@
import type { JSX } from "react"
import { Entry } from "../fs/fs"
import { blue } from "../color"
import { set_working_dir } from "../fs/fn"
type args = string[]
type command = JSX.Element | undefined
function parse_ls(entries: JSX.Element[]) {
return <div className="horizontal-display">
</div>
}
function cd(args: args): command {
set_working_dir(args[1])
}
function ls(args: args): command {
// if (args[1] === undefined) {
// for (const dir_name in working_dir) {
// }
// return <p>{`${working_dir}`}</p>
// }
}
function pwd(args: args): command {
const tree: string[] = []
return <p>{`${tree.join("/")}`}</p>
}
function cat(args: args): command {
return
}
interface commands_list {
[index: string]: (args: args) => command
}
const commands: commands_list = {
["cd"]: cd,
["ls"]: ls,
["pwd"]: pwd,
["cat"]: cat,
}
export default commands

View File

@ -1,14 +1,10 @@
import type { JSX } from "react";
import type { Root } from "react-dom/client";
import { type newElement } from "../../terminal/exec";
import commands from "./list";
type Renderer<T> = React.Dispatch<React.SetStateAction<T>>
import { bold } from "../color";
function trim(stdin: string): string {
const trimmed_str: string[] = []
stdin.split(" ").forEach(s => { if (s != "") { trimmed_str.push(s) } })
stdin.split(" ").forEach(s => { if (s !== "") { trimmed_str.push(s) } })
return trimmed_str.join(" ")
}
@ -16,26 +12,26 @@ function to_args(trimmed_str: string): string[] {
return trimmed_str.split(" ")
}
function valid_command(args: string[]): boolean {
function valid_command(args: string[]): JSX.Element | undefined {
for (const command_in_list in commands) {
const command = args[0]
if (command === command_in_list) {
commands[command_in_list](args)
return true
return commands[command_in_list](args)
}
}
return false
return
}
function unknown_command(name: string) {
return <p>{`sh: Unknown command: ${name}`}</p>
function unknown_command(cmd_name: string) {
return <p>{"shell: Unknown command: "}{bold(cmd_name)}</p>
}
export default function run(stdin: string) {
const args = to_args(trim(stdin))
const command = valid_command(args)
if (args[0] !== "" && !valid_command(args)) {
if (args[0] !== "" && !command) {
return unknown_command(args[0])
}
return <></>
return command ? command : <></>
}

View File

@ -33,14 +33,14 @@ function new_prompt(): JSX.Element {
return display_prompt()
}
function keyboard_events(terminal_window: HTMLElement, new_element_f: newElement) {
function keyboard_events(terminal_window: HTMLElement, new_elements_f: newElement) {
const terminal_event = (keyboard_event: KeyboardEvent) => {
if (keyboard_event.key === Key.Enter) {
const current_prompt = get_current_prompt()
if (current_prompt) {
const prompt = new_prompt()
const output = run(current_prompt.value)
new_element_f([output, prompt])
new_elements_f([output, prompt])
terminal_window.removeEventListener("keydown", terminal_event)
}
} else if (keyboard_event.key === Key.ArrowUp) {

View File

@ -1,46 +0,0 @@
let working_dir = "user"
const enum EntryType {
Directory,
File
}
const enum Permissions {
r,
w,
rw
}
type File = string
type Entry<T> = {
readonly inner: T,
readonly type: EntryType,
readonly permissions: Permissions
}
function Entry<T = File>(inner: T, permissions: Permissions): Entry<T> {
const type = typeof inner == "object" ? EntryType.Directory : EntryType.File
return {
inner: inner,
type: type,
permissions: permissions
}
}
const user = {
["about_me.txt"]: Entry("", Permissions.rw),
["services.txt"]: Entry("", Permissions.rw)
}
const home = {
["user"]: Entry(user, Permissions.rw)
}
const root = {
["bin"]: Entry({}, Permissions.r),
["home"]: Entry(home, Permissions.r)
}
const fs = {
["/"]: Entry(root, Permissions.r)
}
export {
fs,
working_dir
}

View File

@ -0,0 +1,35 @@
import { fs } from "./fs"
let working_dir = ["/", "home", "user"]
function get_working_dir_name_full(): string {
const w_dir_clone = [...working_dir]
const root = w_dir_clone.shift()
if (root) {
return root+w_dir_clone.join("/")
}
return "shift-error"
}
function get_working_dir_name(): string {
return working_dir[working_dir.length-1]
}
function set_working_dir(name: string) {
let new_dir;
const w_dir_clone = [...working_dir]
w_dir_clone.push(name)
w_dir_clone.map(p => p !== "/" ? p+"/" : p).forEach(f => {
for (let i = 0; i<fs.length; i++) {
if (fs[i].name === f) {
}
}
})
}
export {
get_working_dir_name_full,
get_working_dir_name,
set_working_dir
}

View File

@ -0,0 +1,47 @@
const enum EntryType {
Directory,
File
}
const enum Permissions {
r,
w,
rw
}
const user = [
Entry("about_me.txt", "about me inside", Permissions.rw),
Entry("services.txt", "services inside", Permissions.rw),
]
const home = [
Entry("user", user, Permissions.rw)
]
const root = [
Entry("home", home, Permissions.r),
Entry("bin", {}, Permissions.r),
]
const fs = [
Entry("/", root, Permissions.r)
]
type File = string
interface Entry<T = File> {
readonly inner: T,
readonly name: string,
readonly type: EntryType,
readonly permissions: Permissions
}
function Entry<T = File>(name: string, inner: T, permissions: Permissions): Entry<T> {
return {
type: typeof inner == "object" ? EntryType.Directory : EntryType.File,
inner: inner,
name: name,
permissions: permissions
}
}
export {
fs,
EntryType,
Permissions,
Entry
}

View File

@ -1,4 +1,4 @@
import { working_dir } from "./fs"
import { get_working_dir_name_full } from "./fs/fn"
import { cyan, green } from "./color"
const userAgent = navigator.userAgent
@ -9,13 +9,14 @@ if (browser_name_fallible) {
browser_name = browser_name_fallible[0] === "Firefox" ? "gecko" : "chromium"
}
function GetWorkingDir() {
return working_dir === "user" ? "~" : working_dir
function working_dir() {
const name = get_working_dir_name_full()
return name === "user" ? "~" : name
}
export default function Display() {
const user = cyan("user")
const dir = green(GetWorkingDir())
const dir = green(working_dir())
return <p>{user}@{browser_name} {dir}{"> "}</p>
}

View File

@ -20,9 +20,9 @@ type newElement = (elements: JSX.Element[]) => void
export default function Shell() {
if (terminal_window) {
const [renderedElements, renderElement] = useState([display_prompt()])
const new_element_f = (elements: JSX.Element[]) => renderElement([...renderedElements, ...elements])
const new_elements_f = (elements: JSX.Element[]) => renderElement([...renderedElements, ...elements])
keyboard_events(terminal_window, new_element_f)
keyboard_events(terminal_window, new_elements_f)
return renderedElements.map((element, k) => <React.Fragment key={k}>{element}</React.Fragment>)
}

View File

@ -8,7 +8,7 @@
"dist"
],
"compilerOptions": {
"noImplicitAny": true,
"noImplicitAny": true,
"jsx": "react-jsx",
"jsxImportSource": "react"
}