11 Commits

Author SHA1 Message Date
596a21f49d move terminal.ts and keys.ts into the emulator folder 2025-02-26 16:48:51 -05:00
e09891482e not necessary 2025-02-26 14:24:25 -05:00
f7e678190d move rfwfs into rt 2025-02-26 14:18:05 -05:00
22df34ed43 binary searching for files WIP 2025-02-26 02:03:07 -05:00
2ea415a20e fs is now named rfwfs
rhpidfyre's web file system
2025-02-26 00:53:55 -05:00
d59ea8d8a7 search.ts -> index.ts 2025-02-25 23:24:10 -05:00
4f3df58ff4 move the fs tree into tree.ts out of core.ts 2025-02-25 21:13:08 -05:00
db31f20d24 binary_nsort for no automatic sorting 2025-02-25 19:03:10 -05:00
9de5ddcfbf update deps 2025-02-25 18:32:16 -05:00
474345a204 search module for fs 2025-02-25 18:32:08 -05:00
d1fc53206c fs.ts -> core.ts, fn.ts -> library.ts 2025-02-23 23:20:35 -05:00
13 changed files with 198 additions and 112 deletions

View File

@ -9,9 +9,9 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"devDependencies": { "devDependencies": {
"sass": "^1.85.0", "sass": "^1.85.1",
"typescript": "^5.7.3", "typescript": "^5.7.3",
"vite": "^6.1.1", "vite": "^6.2.0",
"vite-plugin-html": "^3.2.2" "vite-plugin-html": "^3.2.2"
} }
} }

View File

@ -1,5 +1,5 @@
<!doctype html> <!doctype html>
<html lang="en"> <html>
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width"/> <meta name="viewport" content="width=device-width"/>
@ -56,6 +56,6 @@
</style> </style>
</noscript> </noscript>
</footer> </footer>
<script type="module" src="./rt/terminal.ts"></script> <script type="module" src="./rt/emulator/terminal.ts"></script>
</body> </body>
</html> </html>

View File

@ -1,5 +1,5 @@
import { cyan, green } from "../shell/color" import { cyan, green } from "../shell/color"
import { get_working_dir_name } from "../shell/fs/fn" import { get_working_dir_name } from "../rfwfs/library"
import create from "./create" import create from "./create"

View File

@ -1,5 +1,5 @@
import run from "./shell/command/command" import run from "../shell/command/command"
import history from "./shell/history" import history from "../shell/history"
type InputClosure = (key_event: KeyboardEvent) => void type InputClosure = (key_event: KeyboardEvent) => void
interface EnterArgs { interface EnterArgs {

View File

@ -1,5 +1,5 @@
import history from "./shell/history" import history from "../shell/history"
import prompt from "./elements/prompt" import prompt from "../elements/prompt"
import keys from "./keys" import keys from "./keys"
const term_win_unsafe = document.querySelector("main") const term_win_unsafe = document.querySelector("main")

View File

@ -8,24 +8,9 @@ const enum Permissions {
rw rw
} }
type FsList = FsEntry[]
type FsEntry = Entry<{}> type FsEntry = Entry<{}>
type FsDirectory = Entry<FsEntry[]> type FsDirectory = Entry<FsList>
const user = [
Entry("about_me.txt", "about me inside", Permissions.rw),
Entry("services.txt", "services inside", Permissions.rw),
Entry("hi", [], 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 type File = string
interface Entry<T = File> { interface Entry<T = File> {
@ -44,9 +29,9 @@ function Entry<T = File>(name: string, inner: T, permissions: Permissions): Entr
} }
export { export {
fs,
type FsDirectory, type FsDirectory,
type FsEntry, type FsEntry,
type FsList,
EntryType, EntryType,
Permissions, Permissions,
Entry Entry

78
src/rt/rfwfs/index.ts Normal file
View File

@ -0,0 +1,78 @@
import { type FsList, type FsEntry } from "./core"
interface SearchResult<T> {
item: T,
binary_index: number
}
interface Search {
binary_fs: (cloned_list: FsList, file_name: string) => SearchResult<FsEntry> | undefined,
binary_nsort: <T>(list: T[], find: T, start: number, end: number) => SearchResult<T> | undefined,
binary: <T>(list: T[], find: T) => SearchResult<T> | undefined,
linear: <T>(list: T[], find: T) => SearchResult<T> | undefined,
}
function wrap_result<T>(item: T, binary_index: number): SearchResult<T> {
return { item: item, binary_index: binary_index }
}
const search = {} as Search
search.binary = function(list, find) {
list.sort()
let start = 0
let end = list.length-1
while (start<=end) {
const median = (start+end)>>1
if (list[median] === find) {
return wrap_result(list[median], median)
} else if (list[median]<find) {
start = median+1
} else {
end = median-1
}
}
return
}
search.binary_nsort = function(list, find, start = 0, end = list.length-1) {
if (start>end) { return }
const median = (start+end)>>1
if (list[median] === find) {
return wrap_result(list[median], median)
}
if (list[median]>find) {
return this.binary_nsort(list, find, start, median-1)
} else {
return this.binary_nsort(list, find, median+1, end)
}
}
search.binary_fs = function(cloned_list, file_name) {
cloned_list.sort((a,z) => a.name.localeCompare(z.name))
let start = 0
let end = cloned_list.length-1
while (start<=end) {
const median = (start+end)>>1
const median_name = cloned_list[median].name
if (median_name === file_name) {
return wrap_result(cloned_list[median], median)
} else if (median_name<file_name) {
start = median+1
} else {
end = median-1
}
}
return
}
search.linear = function(list, find) {
for (let ind = 0; ind<list.length; ind++) {
if (list[ind] === find) {
return wrap_result(list[ind], ind)
}
}
return
}
export default search

85
src/rt/rfwfs/library.ts Normal file
View File

@ -0,0 +1,85 @@
import { type FsDirectory, type FsEntry } from "./core"
import fstree from "./tree"
import index from "./index"
let cached_dir = fstree[0] //start at root
let working_path = ["/", "home", "user"]
const clone_working_path = () => [...working_path]
function get_working_dir_name() {
return working_path[working_path.length-1]
}
function get_working_dir_name_full(): string {
const w_dir_clone = clone_working_path()
const root = w_dir_clone.shift()
if (root) {
return root+w_dir_clone.join("/")
}
return "shift-error"
}
const enum SetDirStatus {
Valid,
NotFound,
NotADirectory,
Invalid
}
interface FsIterEntry {
readonly entry: FsDirectory | null,
readonly status: SetDirStatus
}
function find_fs_dir(working_dir_path_clone: string[], find_dir_name: string): FsIterEntry {
let cached_dir_clone = cached_dir.inner
for (let path_i = 0; path_i<working_dir_path_clone.length; path_i++) {
if (cached_dir_clone) {
let cached_dir_file_names: string[] = []
cached_dir_clone.forEach((file, file_i) => cached_dir_file_names.push(file.name))
const search_result = index.binary(cached_dir_clone, fstree[0])
if (working_dir_path_clone[path_i] === find_dir_name) {
cached_dir_clone = cached_dir_clone
if (path_i === working_dir_path_clone.length) {
const search_result = index.binary(cached_dir_file_names, find_dir_name)
if (search_result) {
}
} else {
continue
}
}
}
return { entry: null, status: SetDirStatus.Invalid }
}
return { entry: null, status: SetDirStatus.NotFound }
}
function set_working_dir(name: string): SetDirStatus {
if (name === ".") { return SetDirStatus.Valid }
const w_dir_clone = clone_working_path()
if (name === "..") {
w_dir_clone.pop()
} else {
w_dir_clone.push(name)
}
}
function get_working_dir_entries(): FsEntry[] {
}
export {
get_working_dir_name,
get_working_dir_name_full,
get_working_dir_entries,
set_working_dir,
SetDirStatus
}

19
src/rt/rfwfs/tree.ts Normal file
View File

@ -0,0 +1,19 @@
import { Entry, Permissions } from "./core"
const user = [
Entry("about_me.txt", "about me inside", Permissions.rw),
Entry("services.txt", "services inside", Permissions.rw),
Entry("hi", [], Permissions.rw)
]
const home = [
Entry("user", user, Permissions.rw)
]
const root = [
Entry("home", home, Permissions.r),
Entry("bin", {}, Permissions.r),
]
const fstree = [
Entry("/", root, Permissions.r)
]
export default fstree

View File

@ -1,4 +1,4 @@
import { set_working_dir, SetDirStatus } from "../../fs/fn" import { set_working_dir, SetDirStatus } from "../../../rfwfs/library"
import type { Args, Term } from "../list" import type { Args, Term } from "../list"
import stdout from "../../../elements/stdout" import stdout from "../../../elements/stdout"

View File

@ -1,7 +1,7 @@
import type { Args, Term } from "../list"; import type { Args, Term } from "../list";
import { blue } from "../../color"; import { blue } from "../../color";
import { get_working_dir_entries } from "../../fs/fn"; import { get_working_dir_entries } from "../../../rfwfs/library";
import { EntryType, FsEntry } from "../../fs/fs"; import { EntryType, FsEntry } from "../../../rfwfs/core";
import stdout, { stdout_horizontal_elements } from "../../../elements/stdout"; import stdout, { stdout_horizontal_elements } from "../../../elements/stdout";
import create from "../../../elements/create"; import create from "../../../elements/create";

View File

@ -1,4 +1,4 @@
import { get_working_dir_name_full } from "../../fs/fn"; import { get_working_dir_name_full } from "../../../rfwfs/library";
import type { Args, Term } from "../list"; import type { Args, Term } from "../list";
import stdout from "../../../elements/stdout"; import stdout from "../../../elements/stdout";

View File

@ -1,81 +0,0 @@
import { EntryType, fs, type FsDirectory, type FsEntry } from "./fs"
let working_dir = ["/", "home", "user"]
function get_working_dir_name() {
return working_dir[working_dir.length-1]
}
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"
}
const enum SetDirStatus {
Valid,
NotFound,
NotADirectory
}
interface FsIterEntry {
readonly entry: FsDirectory | null,
readonly status: SetDirStatus
}
function iter_fs_to_goal(w_dir_clone: string[]): FsIterEntry {
let next_iter = fs[0]
for (const w_dir of w_dir_clone) {
if (w_dir === "/") { continue }
if (next_iter && next_iter.inner) {
const found = next_iter.inner.find(entry => entry.name === w_dir)
if (!found) {
return { entry: null, status: SetDirStatus.NotFound }
}
if (found.type !== EntryType.Directory) {
return { entry: null, status: SetDirStatus.NotADirectory }
}
if (found.name === w_dir_clone[w_dir_clone.length-1]) {
return { entry: next_iter, status: SetDirStatus.Valid }
} else {
next_iter = found.inner as FsDirectory
}
}
}
return { entry: null, status: SetDirStatus.NotFound }
}
function set_working_dir(name: string): SetDirStatus {
if (name === ".") { return SetDirStatus.Valid }
const w_dir_clone = [...working_dir]
if (name === "..") { w_dir_clone.pop() } else { w_dir_clone.push(name) }
const iter_status = iter_fs_to_goal(w_dir_clone)
if (iter_status.status === SetDirStatus.Valid) {
working_dir = w_dir_clone
}
return iter_status.status
}
function get_working_dir_entries(): FsEntry[] {
const entries: FsEntry[] = []
const w_dir_clone = [...working_dir]
const iter_status = iter_fs_to_goal(w_dir_clone)
if (iter_status.entry && iter_status.entry.inner) {
iter_status.entry.inner.forEach(dir => entries.push(dir))
}
return entries
}
export {
get_working_dir_name,
get_working_dir_name_full,
get_working_dir_entries,
set_working_dir,
SetDirStatus
}