progress, dont really know what to put in here...

This commit is contained in:
2025-12-08 06:57:38 +01:00
committed by Kamil Olszewski
parent 8a06d7cb93
commit a109c7115e
10 changed files with 1908 additions and 1942 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
32aac83d-ce2b-4def-977c-dcdcb6f514eg
32aac83d-ce2b-4def-977c-dcdcb6f514ed

View File

@@ -19,7 +19,7 @@ export type TimeStamps = {
mTime: Date;
cTime: Date;
aTime: Date;
}
};
// TODO: Finish this
// TODO: Change into a type instead of an enum for performance (low priority)
@@ -103,13 +103,14 @@ export class Bash {
if (command.root) {
if (this.hasSudoPerms(this.user.uid)) {
let out: Result = command.method.call(this, args);
this.appendNewResult(this.getPwd(), out, this.user.history[0]);
this.appendNewResult(this.getCwd(), out, this.user.history[0]);
}
this.throwError(result);
}
let out: Result = command.method.call(this, args);
this.appendNewResult(this.getPwd(), out.data?.data, this.user.history[0]);
console.log(out);
this.appendNewResult(this.getCwd(), out.data?.data, this.user.history[0]);
}
throwError(result: Result): void {
@@ -135,6 +136,7 @@ export class Bash {
output: output,
cmd: cmd
};
console.log(data);
this._terminal.PrintOutput(data);
}

View File

@@ -27,6 +27,7 @@ export const cmd_cd = function (this: Bash, args: CommandArgs): Result {
this.getFs().pwd = this.getFs().cwd;
targetNode = this.getFs().resolvePath(path); // Conversion from STRING path to TREENODE
console.log(targetNode, path, 'CD OUTPUT');
if (targetNode === null) return result;
if (targetNode.type !== Type.Directory) return result;
@@ -34,7 +35,6 @@ export const cmd_cd = function (this: Bash, args: CommandArgs): Result {
this.getFs().cwd = targetNode.inode; // CD was successfull, change current dir to the verified target dir
result.exitCode = ExitCode.SUCCESS;
console.log(this.getCwd());
return result;
};

View File

@@ -71,27 +71,26 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
const f_a: boolean = flagInfo.has('a') || flagInfo.has('f');
const f_h: boolean = flagInfo.has('h');
const f_U: boolean = flagInfo.has('U');
const f_f: boolean = flagInfo.has('f');
if (flagInfo.has('l') || flagInfo.has('g') || flagInfo.has('o')) {
const w: HTMLElement = document.createElement('div');
for (const node of nodes) {
const elem: HTMLElement = document.createElement('div');
let children: TreeNode[] = [];
const children: TreeNode[] = node.children.map((child) => this.getFs().getNodeByINode(child));
const rows: string[] = [];
if (!flagInfo.has('U') && !flagInfo.has('f')) {
if (!f_U && !f_f) {
//TODO: Add sort by option later on
children: TreeNode[] = Sort.nodeArraySort.call(this, node.children, flagInfo.has('r'));
console.log('had U or f');
Sort.nodeArraySort.call(this, children, flagInfo.has('r'));
}
const sizes = node.children.map((child) => (this.getFs().getNodeByINode(child).size));
const sizes = children.map((child) => child.size);
const maxSizeWidth = Math.max(...sizes.map((size) => size));
for (let i = 0; i < node.children.length; i++) {
const child: TreeNode = children[i];
for (const child of children) {
if (child.name.startsWith('.') && !(f_a || flagInfo.has('A'))) continue;
const cols: LsEntry = {
@@ -118,18 +117,17 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
let parent: LsEntry = {
...current,
name: '..'
}
if(node.parent) {
};
if (node.parent) {
const parentNode: TreeNode = this.getFs().getNodeByINode(node.parent);
parent = {
perms: formatPermission(parentNode),
children: formatChildren(parentNode),
owners: formatOwners.call(this, parentNode, flagInfo),
size: formatSize.call(this, f_h, parentNode, maxSizeWidth),
modt: formatModtime(parentNode),
name: '..'
}
children: formatChildren(parentNode),
owners: formatOwners.call(this, parentNode, flagInfo),
size: formatSize.call(this, f_h, parentNode, maxSizeWidth),
modt: formatModtime(parentNode),
name: '..'
};
}
if (flagInfo.has('r')) {
@@ -179,19 +177,16 @@ function formatOwners(this: Bash, node: TreeNode, flag: any): string {
const group: string = this.getGroupByGid(node.group).groupname;
if (flag.has('G') || flag.has('o')) {
if (flag.has('n'))
return `${node.owner}`;
if (flag.has('n')) return `${node.owner}`;
return `${owner}`;
}
if (flag.has('g')) {
if (flag.has('n'))
return `${node.group}`;
if (flag.has('n')) return `${node.group}`;
return `${group}`;
}
if (flag.has('n'))
return `${node.owner} ${node.group}`;
if (flag.has('n')) return `${node.owner} ${node.group}`;
return `${owner} ${group}`;
}
@@ -201,6 +196,9 @@ function formatPermission(node: TreeNode): string {
}
function formatChildren(node: TreeNode): string {
if (node.type !== Type.Directory) return ' 0';
if (!node.children) throw new Error('children array is null on this node');
const c = node.children.length.toString();
return c.length > 1 ? c : ` ${c}`;
}

View File

@@ -1,6 +1,4 @@
import type { readonly } from 'svelte/store';
import type { Permission, TimeStamps, User } from './bash';
import { Stack } from '../stack';
export enum Type {
Directory = 16384,
@@ -57,22 +55,16 @@ export class VirtualFS {
}
private _iNodeToPathString(inode: number): string {
let components: Stack<string> = new Stack<string>();
let currentNode = this.FsTable.get(inode);
let path: string = '';
if (!currentNode) throw new Error('iNode does not exist,');
components.push(currentNode.name);
const currentNode = this.FsTable.get(inode);
if (!currentNode)
throw new Error('could not find the node in the fs table - inodetopathstring');
if (!currentNode.parent) {
for (let i = 0; i < components.size(); i++) {
path += components.pop() + '/';
}
} else {
this._iNodeToPathString(currentNode.parent);
return '/';
}
return path;
const parentPath: string = this._iNodeToPathString(currentNode.parent);
return parentPath === '/' ? `/${currentNode.name}` : `${parentPath}/${currentNode.name}`;
}
//TODO: Make all backend methods NOT throw errors. Just return null, and let more closely connected with bash functions call throwError() so user can see the error.
@@ -82,6 +74,8 @@ export class VirtualFS {
const normalizedPath = path.replace(/^\/+|\/+$/g, '');
const pathComponents = normalizedPath.split('/').filter((component) => component.length > 0);
console.log(path, 'pathstringtoinode');
if (pathComponents.length === 0) return this.rootINode;
let currentNode = this.FsTable.get(this.rootINode);
@@ -96,6 +90,8 @@ export class VirtualFS {
currentNode = nextNode;
}
console.log(path, currentNode.inode);
return currentNode.inode;
}
@@ -119,7 +115,9 @@ export class VirtualFS {
}
formatPath(path: string): string {
console.log(path, 'formatPath');
const prefix = this._iNodeToPathString(this.home);
if (path.startsWith(prefix)) {
return path.replace(prefix, '~');
} else return path;
@@ -127,18 +125,20 @@ export class VirtualFS {
resolvePath(path: string): TreeNode {
if (path === '/') return this.getNodeByINode(this.rootINode);
let parsedPath: string = path;
if (!this._isAbsolutePath(path)) {
const trail: string = this._iNodeToPathString(this.cwd);
path = trail + path;
} else if (path.startsWith('~')) {
parsedPath = `${trail}/${path}`;
console.log(parsedPath);
}
if (path.startsWith('~')) {
const trail: string = this._iNodeToPathString(this.home);
path = trail + path;
parsedPath = `${trail}/${path.replace('~', '')}`;
console.log(parsedPath);
}
console.log(path);
const INode: number = this._pathStringToINode(path);
const INode: number = this._pathStringToINode(parsedPath);
const Node: TreeNode = this.getNodeByINode(INode);
return Node;

View File

@@ -1,7 +1,7 @@
import type { TreeNode } from "./fs";
import type { Bash } from "./bash";
import type { TreeNode } from './fs';
import type { Bash } from './bash';
export enum SortBy {
export enum SortNodeBy {
NAME,
INODE,
SIZE,
@@ -9,17 +9,21 @@ export enum SortBy {
TYPE,
MTIME = 'mTime',
ATIME = 'aTime',
CTIME = 'cTime',
CTIME = 'cTime'
}
export class Sort {
public static nodeArraySort(this: Bash, nodes: TreeNode[] | number[], reverse: boolean = false, sortBy: SortBy = SortBy.NAME): TreeNode[] {
if(nodes.length === 0) throw new Error('Tried to sort an empty node array!');
public static nodeArraySort(
this: Bash,
nodes: TreeNode[] | number[],
reverse: boolean = false,
sortBy: SortNodeBy = SortNodeBy.NAME
): TreeNode[] {
if (nodes.length === 0) throw new Error('Tried to sort an empty node array!');
const parsedNodes: TreeNode[] = [];
if(typeof nodes[0] === 'number') {
for(const inode of nodes as number[]) {
if (typeof nodes[0] === 'number') {
for (const inode of nodes as number[]) {
const node = this.getFs().getNodeByINode(inode);
parsedNodes.push(node);
}
@@ -33,26 +37,37 @@ export class Sort {
}
}
private static nodeQSort(array: TreeNode[], reverse: boolean, sortBy: SortBy, start: number, end: number) {
if(end <= start) return;
private static nodeQSort(
array: TreeNode[],
reverse: boolean,
sortBy: SortNodeBy,
start: number,
end: number
) {
if (end <= start) return;
let pivot: number = this.nodePartition(array, reverse, sortBy, start, end);
this.nodeQSort(array, reverse, sortBy, start, pivot - 1);
this.nodeQSort(array, reverse, sortBy, pivot + 1, end);
}
private static nodePartition(part: TreeNode[], reverse: boolean, sortBy: SortBy, start: number, end: number): number {
private static nodePartition(
part: TreeNode[],
reverse: boolean,
sortBy: SortNodeBy,
start: number,
end: number
): number {
let pivot: TreeNode = part[end];
let i: number = start - 1;
for (let j = start; j <= end; j++) {
if(this.nodeCompareElements(part[j], pivot, sortBy, reverse) < 0) {
if (this.nodeCompareElements(part[j], pivot, sortBy, reverse) < 0) {
i++;
let temp = part[i];
part[i] = part[j];
part[j] = temp;
}
}
}
i++;
let temp = part[i];
@@ -62,12 +77,17 @@ export class Sort {
return i;
}
private static nodeCompareElements(a: TreeNode, b: TreeNode, sortBy: SortBy, reverse: boolean): number {
switch(sortBy) {
case SortBy.NAME: {
private static nodeCompareElements(
a: TreeNode,
b: TreeNode,
sortBy: SortNodeBy,
reverse: boolean
): number {
switch (sortBy) {
case SortNodeBy.NAME: {
const minLength = Math.min(a.name.length, b.name.length);
for(let i = 0; i < minLength; i++) {
for (let i = 0; i < minLength; i++) {
const charCodeA = a.name.charCodeAt(i);
const charCodeB = b.name.charCodeAt(i);
@@ -77,25 +97,25 @@ export class Sort {
}
return reverse ? b.name.length - a.name.length : a.name.length - b.name.length;
}
case SortBy.MTIME:
case SortBy.ATIME:
case SortBy.CTIME: {
// The sortBy serves as the lookup key in the timestamps object.
case SortNodeBy.MTIME:
case SortNodeBy.ATIME:
case SortNodeBy.CTIME: {
// The sortBy serves as the lookup key in the timestamps object.
// It works because the times in SortBy enum have assigned values matching the names of the keys in the TreeNode object
const timeA: number = a.timestamps[sortBy].getTime();
const timeB: number = b.timestamps[sortBy].getTime();
return reverse ? timeA - timeB : timeB - timeA;
}
case SortBy.SIZE: {
case SortNodeBy.SIZE: {
return reverse ? a.size - b.size : b.size - a.size;
}
case SortBy.EXTENSION: {
case SortNodeBy.EXTENSION: {
const extA: string = a.name.split('.').pop() ?? '';
const extB: string = b.name.split('.').pop() ?? '';
const minLength = Math.min(extA.length, extB.length);
for(let i = 0; i < minLength; i++) {
for (let i = 0; i < minLength; i++) {
const charCodeA = extA.charCodeAt(i);
const charCodeB = extB.charCodeAt(i);
@@ -105,14 +125,14 @@ export class Sort {
}
return reverse ? extB.length - extA.length : extA.length - extB.length;
}
case SortBy.INODE: {
case SortNodeBy.INODE: {
return reverse ? b.inode - a.inode : a.inode - b.inode;
}
case SortBy.TYPE: {
case SortNodeBy.TYPE: {
return reverse ? b.type - a.type : a.type - b.type;
}
default:
throw new Error(`Sorting basis outside of the declared scope. - `);
}
}
}
}

View File

@@ -9,10 +9,10 @@ export function isInitializing(): boolean {
}
function jsonToNodeTable(data: any, parent?: number): Map<number, TreeNode> {
const FsTable: Map<number, TreeNode> = new Map<number, TreeNode>;
const FsTable: Map<number, TreeNode> = new Map<number, TreeNode>();
const entryList = Object.entries(data);
for(let i = 0; i < entryList.length; i++) {
for (let i = 0; i < entryList.length; i++) {
const object: any = entryList[i][1];
const node: TreeNode = {
inode: object.Inode,
@@ -48,7 +48,7 @@ function jsonToNodeTable(data: any, parent?: number): Map<number, TreeNode> {
cTime: new Date(object.TimeStamps.CTime),
aTime: new Date(object.TimeStamps.ATime)
},
parent: object.parent
parent: object.Parent
};
FsTable.set(object.Inode, node);

View File

@@ -85,7 +85,7 @@ export class Terminal {
executeCommand(input: string): void {
this.bash.updateHistory(input);
const parsed: ParsedInput = this._parseInput(input);
console.log(parsed);
console.log(parsed, 'executeCommand output');
this.bash.executeCommand(parsed.command, parsed.args);
}
@@ -99,6 +99,7 @@ export class Terminal {
getCwd(): string {
const fs: VirtualFS = this.bash.getFs();
console.log(fs.getPathByInode(this.bash.getCwd()));
return fs.formatPath(fs.getPathByInode(this.bash.getCwd()));
}

View File

@@ -19,6 +19,7 @@
switch (e.key) {
case 'Enter': {
terminal.executeCommand(inputValue);
updateTerminal();
break;
}
case 'ArrowRight': {