Compare commits
4 Commits
8830b130ad
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 97296843df | |||
| 1faab39849 | |||
| 0ad0e362d6 | |||
| 7fbf3593fb |
@@ -33,7 +33,7 @@
|
|||||||
},
|
},
|
||||||
"Interactible": false,
|
"Interactible": false,
|
||||||
"Func": null,
|
"Func": null,
|
||||||
"Parent": null
|
"Parent": 1
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"Inode": 2,
|
"Inode": 2,
|
||||||
|
|||||||
15
src/lib/stores/bash/commands/clear.ts
Normal file
15
src/lib/stores/bash/commands/clear.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { ExitCode, type Bash } from "../bash";
|
||||||
|
import type { CommandArgs, ICommand, Result } from "../static";
|
||||||
|
|
||||||
|
export const cmd_clear = function(this: Bash, args: CommandArgs): Result {
|
||||||
|
let result: Result = { exitCode: ExitCode.ERROR, path: this.getCwd() };
|
||||||
|
result.exitCode = ExitCode.SUCCESS;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const clear: ICommand = {
|
||||||
|
method: cmd_clear,
|
||||||
|
flags: [] as string[],
|
||||||
|
help: 'PATH TO HELP.md',
|
||||||
|
root: false
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Bash, ExitCode, type Permission, type TimeStamps } from '../bash';
|
import { Bash, ExitCode, type Permission, type TimeStamps } from '../bash';
|
||||||
import { Type, type NodePerms, type TreeNode } from '../fs';
|
import { Type, VirtualFS, type NodePerms, type TreeNode } from '../fs';
|
||||||
import { Sort, SortNodeBy } from '../sort';
|
import { Sort, SortNodeBy } from '../sort';
|
||||||
import type { CommandArgs, ICommand, Result, resultData } from '../static';
|
import type { CommandArgs, ICommand, Result, resultData } from '../static';
|
||||||
|
|
||||||
@@ -38,6 +38,7 @@ const months: readonly string[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const cmd_ls = function (this: Bash, args: CommandArgs): Result {
|
export const cmd_ls = function (this: Bash, args: CommandArgs): Result {
|
||||||
|
const Fs = this.getFs();
|
||||||
const resultData: resultData = { cmd: 'ls', data: null, args: args };
|
const resultData: resultData = { cmd: 'ls', data: null, args: args };
|
||||||
const result: Result = { exitCode: ExitCode.ERROR, path: this.getCwd(), data: resultData };
|
const result: Result = { exitCode: ExitCode.ERROR, path: this.getCwd(), data: resultData };
|
||||||
const nodes: TreeNode[] = [];
|
const nodes: TreeNode[] = [];
|
||||||
@@ -55,10 +56,10 @@ export const cmd_ls = function (this: Bash, args: CommandArgs): Result {
|
|||||||
this.throwError(result); //No such flag/s
|
this.throwError(result); //No such flag/s
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.args.length === 0) nodes.push(this.getFs().getNodeByINode(this.getFs().cwd));
|
if (args.args.length === 0) nodes.push(Fs.getNodeByINode(Fs.cwd));
|
||||||
|
|
||||||
for (let i = 0; i < args.args.length; i++) {
|
for (let i = 0; i < args.args.length; i++) {
|
||||||
const node = this.getFs().resolvePath(args.args[i]);
|
const node = Fs.resolvePath(args.args[i]);
|
||||||
if (node === null) this.throwError(result); //no such path (i think this will never occur as backed methods have error cases implemented - which is wrong)
|
if (node === null) this.throwError(result); //no such path (i think this will never occur as backed methods have error cases implemented - which is wrong)
|
||||||
|
|
||||||
nodes.push(node);
|
nodes.push(node);
|
||||||
@@ -71,16 +72,19 @@ export const cmd_ls = function (this: Bash, args: CommandArgs): Result {
|
|||||||
|
|
||||||
function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
||||||
const dummysonoerror: HTMLElement = document.createElement('div');
|
const dummysonoerror: HTMLElement = document.createElement('div');
|
||||||
|
const Fs: VirtualFS = this.getFs();
|
||||||
|
|
||||||
|
|
||||||
const flagInfo = checkFlags(args.flags);
|
const flagInfo = checkFlags(args.flags);
|
||||||
const nodes: TreeNode[] = data;
|
const nodes: TreeNode[] = data;
|
||||||
|
let nodeIndex: number = 0;
|
||||||
|
|
||||||
const f_a: boolean = flagInfo.has('a') || flagInfo.has('all');
|
const f_a: boolean = flagInfo.has('a') || flagInfo.has('all');
|
||||||
const f_A: boolean = flagInfo.has('A') || flagInfo.has('almost-all');
|
const f_A: boolean = flagInfo.has('A') || flagInfo.has('almost-all');
|
||||||
const f_G: boolean = flagInfo.has('G') || flagInfo.has('no-group');
|
const f_G: boolean = flagInfo.has('G') || flagInfo.has('no-group');
|
||||||
const f_h: boolean = flagInfo.has('h') || flagInfo.has('human-readable');
|
const f_h: boolean = flagInfo.has('h') || flagInfo.has('human-readable');
|
||||||
const f_r: boolean = flagInfo.has('r') || flagInfo.has('reverse');
|
const f_r: boolean = flagInfo.has('r') || flagInfo.has('reverse');
|
||||||
|
const f_R: boolean = flagInfo.has('R') || flagInfo.has('recursive');
|
||||||
const f_Q: boolean = flagInfo.has('Q') || flagInfo.has('quote-name');
|
const f_Q: boolean = flagInfo.has('Q') || flagInfo.has('quote-name');
|
||||||
const f_n: boolean = flagInfo.has('n') || flagInfo.has('numeric-uid-gid');
|
const f_n: boolean = flagInfo.has('n') || flagInfo.has('numeric-uid-gid');
|
||||||
const f_N: boolean = flagInfo.has('N') || flagInfo.has('literal');
|
const f_N: boolean = flagInfo.has('N') || flagInfo.has('literal');
|
||||||
@@ -102,14 +106,40 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
|||||||
|
|
||||||
const w: HTMLElement = document.createElement('div');
|
const w: HTMLElement = document.createElement('div');
|
||||||
|
|
||||||
|
if(f_R) {
|
||||||
|
const treeWalkResult: TreeNode[] = [];
|
||||||
|
const treeWalkCallback = (node: TreeNode) => { treeWalkResult.push(node); }
|
||||||
|
|
||||||
|
for(const node of nodes) {
|
||||||
|
treeWalkResult.push(node);
|
||||||
|
Fs.recursiveTraversalPre(node, treeWalkCallback);
|
||||||
|
}
|
||||||
|
nodes.length = 0;
|
||||||
|
nodes.push(...treeWalkResult.filter((node) => node.type != Type.File));
|
||||||
|
}
|
||||||
|
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
const elem: HTMLElement = document.createElement('div');
|
const elem: HTMLElement = document.createElement('div');
|
||||||
const children: TreeNode[] = node.children.map((child) => this.getFs().getNodeByINode(child));
|
const childrenMap: TreeNode[] = node.children.map((child) => Fs.getNodeByINode(child));
|
||||||
const rows: string[] = [];
|
|
||||||
|
const children: TreeNode[] = (f_a || f_A)
|
||||||
|
? childrenMap
|
||||||
|
: childrenMap.filter((child) => !child.name.startsWith('.'));
|
||||||
|
|
||||||
const timeArg = valuedArgs.find((flag) => flag.startsWith('time'));
|
const timeArg = valuedArgs.find((flag) => flag.startsWith('time'));
|
||||||
const shouldNamesShift: boolean = children.some((child) => child.name.match(/\s/) !== null);
|
const shouldNamesShift: boolean = children.some((child) => child.name.match(/\s/) !== null);
|
||||||
let timestamp: SortNodeBy.ATIME | SortNodeBy.CTIME | SortNodeBy.MTIME = SortNodeBy.MTIME;
|
let timestamp: SortNodeBy.ATIME | SortNodeBy.CTIME | SortNodeBy.MTIME = SortNodeBy.MTIME;
|
||||||
|
|
||||||
|
if(f_a && !f_A) {
|
||||||
|
const current: TreeNode = node;
|
||||||
|
current.name = '.';
|
||||||
|
|
||||||
|
const parent: TreeNode = Fs.getNodeByINode(node.parent);
|
||||||
|
parent.name = '..';
|
||||||
|
|
||||||
|
children.unshift(current, parent);
|
||||||
|
}
|
||||||
|
|
||||||
if(timeArg) {
|
if(timeArg) {
|
||||||
let value: string = timeArg.split('=')[1];
|
let value: string = timeArg.split('=')[1];
|
||||||
if (value && isValidNodeTimestamp(value)) timestamp = value;
|
if (value && isValidNodeTimestamp(value)) timestamp = value;
|
||||||
@@ -132,14 +162,11 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (f_l || f_g || f_o) {
|
if (f_l || f_g || f_o) {
|
||||||
|
const rows: string[] = [];
|
||||||
for (const node of nodes) {
|
|
||||||
const maxSizeWidth = Math.max(
|
const maxSizeWidth = Math.max(
|
||||||
...children.map((child) => child.size.toString().length));
|
...children.map((child) => child.size.toString().length));
|
||||||
|
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
if (child.name.startsWith('.') && !(f_a || f_A)) continue;
|
|
||||||
|
|
||||||
const entry: LsEntry = {
|
const entry: LsEntry = {
|
||||||
inode: null,
|
inode: null,
|
||||||
perms: formatPermission(child),
|
perms: formatPermission(child),
|
||||||
@@ -155,115 +182,91 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
|||||||
rows.push(LsEntryUtils.toString(entry));
|
rows.push(LsEntryUtils.toString(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f_a && !f_A) {
|
|
||||||
const current: LsEntry = {
|
|
||||||
inode: null,
|
|
||||||
perms: formatPermission(node),
|
|
||||||
children: formatChildren(node),
|
|
||||||
owners: formatOwners.call(this, node, flagInfo),
|
|
||||||
size: formatSize.call(this, f_h, node, maxSizeWidth, f_si),
|
|
||||||
modt: formatModtime(node, timestamp),
|
|
||||||
name: shouldNamesShift ? ' .' : '.'
|
|
||||||
};
|
|
||||||
let parent: LsEntry = {
|
|
||||||
...current,
|
|
||||||
name: shouldNamesShift ? ' ..' : '..'
|
|
||||||
};
|
|
||||||
if (node.parent) {
|
|
||||||
const parentNode: TreeNode = this.getFs().getNodeByINode(node.parent);
|
|
||||||
parent = {
|
|
||||||
inode: null,
|
|
||||||
perms: formatPermission(parentNode),
|
|
||||||
children: formatChildren(parentNode),
|
|
||||||
owners: formatOwners.call(this, parentNode, flagInfo),
|
|
||||||
size: formatSize.call(this, f_h, parentNode, maxSizeWidth, f_si),
|
|
||||||
modt: formatModtime(parentNode, timestamp),
|
|
||||||
name: shouldNamesShift ? ' ..' : '..'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f_i) {
|
|
||||||
current.inode = node.inode;
|
|
||||||
parent.inode = node.parent ? node.parent : node.inode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f_r) {
|
|
||||||
rows.push(LsEntryUtils.toString(parent), LsEntryUtils.toString(current));
|
|
||||||
} else {
|
|
||||||
rows.unshift(LsEntryUtils.toString(current), LsEntryUtils.toString(parent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Calculate the total size of contents in the node
|
//TODO: Calculate the total size of contents in the node
|
||||||
rows.unshift('total ' + node.children.length.toString());
|
rows.unshift('total ' + node.children.length.toString());
|
||||||
|
|
||||||
if (nodes.length > 1) {
|
if (nodes.length > 1) {
|
||||||
const nodePath: string =
|
const nodePath: HTMLElement = document.createElement('p');
|
||||||
node.name === '/' ? '/:' : `${this.getFs().getPathByInode(node.inode).slice(1)}:`;
|
nodePath.innerText = `${Fs.getPathByInode(node.inode)}:`;
|
||||||
rows.unshift(nodePath);
|
w.appendChild(nodePath);
|
||||||
rows.push('\n');
|
if(nodeIndex +1 < nodes.length) elem.style.marginBottom = `${this.getTerminalFontSize() * 2}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (let i = 0; i < rows.length; i++) {
|
for (let i = 0; i < rows.length; i++) {
|
||||||
const p: HTMLElement = document.createElement('p');
|
const p: HTMLElement = document.createElement('p');
|
||||||
|
|
||||||
|
|
||||||
p.innerText = rows[i];
|
p.innerText = rows[i];
|
||||||
|
|
||||||
elem.appendChild(p);
|
elem.appendChild(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
w.appendChild(elem);
|
w.appendChild(elem);
|
||||||
}
|
}
|
||||||
return w;
|
else {
|
||||||
}
|
const maxWidth: number = Math.ceil((this.getTerminalWidth() / this.getTerminalFontSize()) * 0.8);
|
||||||
const maxWidth: number = (this.getTerminalWidth() / this.getTerminalFontSize()) * 0.8;
|
|
||||||
const nameLengths: number[] = nodes.map(node => node.name.length);
|
|
||||||
|
|
||||||
let columns: string[][] = [];
|
let columns: string[][] = [];
|
||||||
|
let colWidths: number[];
|
||||||
let lowBound: number = 1;
|
let lowBound: number = 1;
|
||||||
let highBound: number = Math.floor(maxWidth / 3);
|
let highBound: number = children.length;
|
||||||
let c: number = (lowBound + highBound) / 2;
|
|
||||||
|
|
||||||
nodeBinarySearch(nodes.length, nameLengths, lowBound, highBound, maxWidth);
|
while(lowBound + 1 < highBound) {
|
||||||
|
const c = lowBound + (highBound - lowBound) / 2;
|
||||||
|
|
||||||
for(let i = 0; i < c -1; i++) {
|
columns = [];
|
||||||
const colSize: number = i < (nodes.length % c) ? nodes.length : nodes.length -1;
|
colWidths = [];
|
||||||
|
let fileIndex = 0;
|
||||||
|
|
||||||
for(let j = 0; j < colSize -1; j++){
|
for(let i = 0; i < c; i++) {
|
||||||
if(j >= nodes.length -1) break;
|
if(fileIndex >= children.length) break;
|
||||||
|
columns[i] = [];
|
||||||
columns[i].push(nodes[j].name);
|
for(let j = 0; j < Math.ceil(children.length / c); j++) {
|
||||||
|
if(fileIndex >= children.length) break;
|
||||||
|
columns[i].push(children[fileIndex].name);
|
||||||
|
fileIndex++;
|
||||||
}
|
}
|
||||||
|
colWidths.push(Math.max(...columns[i].map((name) => name.length)));
|
||||||
}
|
}
|
||||||
//w.appendChild();
|
|
||||||
|
const calcWidth: number = colWidths.reduce((prev, curr) => prev + curr) + ((c-1) * 3);
|
||||||
|
|
||||||
|
if(calcWidth < maxWidth) lowBound = c + 1;
|
||||||
|
else if(calcWidth > maxWidth) highBound = c -1
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper: HTMLElement = document.createElement('div');
|
||||||
|
|
||||||
|
wrapper.style.display = 'flex';
|
||||||
|
wrapper.style.marginBottom = `${this.getTerminalFontSize() * 2}px`;
|
||||||
|
|
||||||
|
let fileIndex = 0;
|
||||||
|
|
||||||
|
for(let i = 0; i < lowBound; i++) {
|
||||||
|
if(fileIndex >= children.length) break;
|
||||||
|
const col: HTMLElement = document.createElement('div');
|
||||||
|
|
||||||
|
for(let j = 0; j < Math.ceil(children.length / lowBound); j++) {
|
||||||
|
if(fileIndex >= children.length) break;
|
||||||
|
|
||||||
|
const entry: HTMLElement = document.createElement('p');
|
||||||
|
|
||||||
|
entry.innerText = formatName(children[fileIndex], flagInfo, shouldNamesShift);
|
||||||
|
col.appendChild(entry);
|
||||||
|
fileIndex++;
|
||||||
|
}
|
||||||
|
wrapper.appendChild(col);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodes.length > 1) {
|
||||||
|
const nodePath: HTMLElement = document.createElement('p');
|
||||||
|
nodePath.innerText = `${Fs.getPathByInode(node.inode)}`;
|
||||||
|
w.appendChild(nodePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
w.appendChild(wrapper);
|
||||||
|
}
|
||||||
|
nodeIndex++;
|
||||||
}
|
}
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeBinarySearch(
|
|
||||||
n: number,
|
|
||||||
nameLengths: number[],
|
|
||||||
low: number,
|
|
||||||
high: number,
|
|
||||||
max: number) {
|
|
||||||
|
|
||||||
let c: number = (low + high) / 2;
|
|
||||||
|
|
||||||
if(low + 1 < high) {
|
|
||||||
const calcWidth: number =
|
|
||||||
nameLengths.reduce((result, value) => result + value) + (c-1) * 2
|
|
||||||
|
|
||||||
if (calcWidth <= max) {
|
|
||||||
low = c;
|
|
||||||
} else high = c;
|
|
||||||
|
|
||||||
nodeBinarySearch(n, nameLengths, low, high, max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isValidNodeSortMethod(value: string): value is SortNodeBy {
|
function isValidNodeSortMethod(value: string): value is SortNodeBy {
|
||||||
return Object.values(SortNodeBy).includes(value as SortNodeBy);
|
return Object.values(SortNodeBy).includes(value as SortNodeBy);
|
||||||
}
|
}
|
||||||
@@ -319,6 +322,7 @@ function formatChildren(node: TreeNode): string {
|
|||||||
if (!node.children) throw new Error('children array is null on this node');
|
if (!node.children) throw new Error('children array is null on this node');
|
||||||
|
|
||||||
const c = node.children.length.toString();
|
const c = node.children.length.toString();
|
||||||
|
console.log(c, "TEST TEST");
|
||||||
return c.length > 1 ? c : ` ${c}`;
|
return c.length > 1 ? c : ` ${c}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,17 +359,29 @@ function formatModtime(node: TreeNode, sortBy: SortNodeBy.ATIME | SortNodeBy.CTI
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatName(node: TreeNode, flag: any, shouldShift: boolean) {
|
function formatName(node: TreeNode, flag: any, shouldShift: boolean) {
|
||||||
let name: string;
|
let name: string = node.name;
|
||||||
const char: string = flag.has('Q') ? '"' : "'";
|
const char: string = flag.has('Q') ? '"' : "'";
|
||||||
|
|
||||||
if (/\s/.test(node.name)) {
|
if (/\s/.test(node.name)) name = `${char}${name}${char}`;
|
||||||
name = `${char}${node.name}${char}`
|
|
||||||
} else {
|
if(flag.has('p') && node.type === Type.Directory) name = `${name}/`
|
||||||
|
|
||||||
|
if((flag.has('l') || flag.has('g') || flag.has('o'))) {
|
||||||
|
// Is the ls in long format
|
||||||
|
if (!(/\s/.test(node.name))) {
|
||||||
//Shift non quoted names 1 char right to align if any names in group have a quote
|
//Shift non quoted names 1 char right to align if any names in group have a quote
|
||||||
name = `${shouldShift ? ' ' : ''}${node.name}`;
|
name = `${shouldShift ? ' ' : ''}${name}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!(/\s/.test(node.name))) {
|
||||||
|
name = ` ${name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flag.has('p') && node.type === Type.Directory ? `${name}/` : name;
|
name = `${name} `;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkFlags = (pFlags: string[]) => {
|
const checkFlags = (pFlags: string[]) => {
|
||||||
@@ -392,6 +408,7 @@ export const ls: ICommand = {
|
|||||||
't',
|
't',
|
||||||
'S',
|
'S',
|
||||||
'r',
|
'r',
|
||||||
|
'R',
|
||||||
'Q',
|
'Q',
|
||||||
'p',
|
'p',
|
||||||
'o',
|
'o',
|
||||||
@@ -408,6 +425,7 @@ export const ls: ICommand = {
|
|||||||
'no-group',
|
'no-group',
|
||||||
'human-readable',
|
'human-readable',
|
||||||
'reverse',
|
'reverse',
|
||||||
|
'recursive',
|
||||||
'quote-name',
|
'quote-name',
|
||||||
'indicator-style',
|
'indicator-style',
|
||||||
'literal',
|
'literal',
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export type FsInitArgs = {
|
|||||||
|
|
||||||
export type TreeNode = {
|
export type TreeNode = {
|
||||||
inode: number;
|
inode: number;
|
||||||
parent?: number;
|
parent: number;
|
||||||
name: string;
|
name: string;
|
||||||
type: Type;
|
type: Type;
|
||||||
size: number; //Size in Bytes
|
size: number; //Size in Bytes
|
||||||
@@ -110,11 +110,11 @@ export class VirtualFS {
|
|||||||
return typeof path === 'string' && path.startsWith('/');
|
return typeof path === 'string' && path.startsWith('/');
|
||||||
};
|
};
|
||||||
|
|
||||||
getPathByInode(inode: number): string {
|
public getPathByInode(inode: number): string {
|
||||||
return this._iNodeToPathString(inode);
|
return this._iNodeToPathString(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
formatPath(path: string): string {
|
public formatPath(path: string): string {
|
||||||
console.log(path, 'formatPath');
|
console.log(path, 'formatPath');
|
||||||
const prefix = this._iNodeToPathString(this.home);
|
const prefix = this._iNodeToPathString(this.home);
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ export class VirtualFS {
|
|||||||
} else return path;
|
} else return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolvePath(path: string): TreeNode {
|
public resolvePath(path: string): TreeNode {
|
||||||
if (path === '/') return this.getNodeByINode(this.rootINode);
|
if (path === '/') return this.getNodeByINode(this.rootINode);
|
||||||
let parsedPath: string = path;
|
let parsedPath: string = path;
|
||||||
|
|
||||||
@@ -144,22 +144,32 @@ export class VirtualFS {
|
|||||||
return Node;
|
return Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
getNodeByINode(inode: number): TreeNode {
|
public getNodeByINode(inode: number): TreeNode {
|
||||||
const node: TreeNode | undefined = this.FsTable.get(inode);
|
const node: TreeNode | undefined = this.FsTable.get(inode);
|
||||||
if (!node) throw new Error('Could not get the node, no such i node exists');
|
if (!node) throw new Error(`Could not get the node, no such inode exists - ${inode}`);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* private _getPathToNode(node: TreeNode): string[] {
|
public recursiveTraversalPre(node: TreeNode, callback: (param: TreeNode) => void, childIndex?: number[], depthIndex?: number): void {
|
||||||
const path: string[] = [];
|
if(!depthIndex) depthIndex = 0;
|
||||||
let current = node;
|
if(!childIndex) childIndex = [0];
|
||||||
path.push(node.name);
|
|
||||||
|
|
||||||
while (current.parent) {
|
if(node.type != Type.File && node.children[childIndex[depthIndex]]) {
|
||||||
current = current.parent;
|
node = this.getNodeByINode(node.children[childIndex[depthIndex]]);
|
||||||
path.unshift(current.name);
|
depthIndex++;
|
||||||
|
if(!childIndex[depthIndex]) childIndex[depthIndex] = 0;
|
||||||
|
|
||||||
|
callback(node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node = this.getNodeByINode(node.parent);
|
||||||
|
childIndex[depthIndex] = 0;
|
||||||
|
depthIndex--;
|
||||||
|
childIndex[depthIndex]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
if(depthIndex < 0) return;
|
||||||
} */
|
|
||||||
|
this.recursiveTraversalPre(node, callback, childIndex, depthIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class Sort {
|
|||||||
reverse: boolean = false,
|
reverse: boolean = false,
|
||||||
sortBy: SortNodeBy = SortNodeBy.NAME
|
sortBy: SortNodeBy = SortNodeBy.NAME
|
||||||
): TreeNode[] {
|
): TreeNode[] {
|
||||||
if (nodes.length === 0) throw new Error('Tried to sort an empty node array!');
|
if (nodes.length === 0) {console.warn('Tried to sort an empty node array!'); return [];}
|
||||||
const parsedNodes: TreeNode[] = [];
|
const parsedNodes: TreeNode[] = [];
|
||||||
|
|
||||||
if (typeof nodes[0] === 'number') {
|
if (typeof nodes[0] === 'number') {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Bash, ExitCode, type Group, type User } from './bash';
|
import { Bash, ExitCode, type Group, type User } from './bash';
|
||||||
import { ls } from './commands/ls';
|
import { ls } from './commands/ls';
|
||||||
import { cd } from './commands/cd';
|
import { cd } from './commands/cd';
|
||||||
|
import { clear } from './commands/clear';
|
||||||
|
|
||||||
export type ICommand = {
|
export type ICommand = {
|
||||||
method: (this: Bash, args: CommandArgs) => Result;
|
method: (this: Bash, args: CommandArgs) => Result;
|
||||||
@@ -76,7 +77,8 @@ export const PASSWD: User[] = [
|
|||||||
|
|
||||||
export const COMMANDS = {
|
export const COMMANDS = {
|
||||||
cd,
|
cd,
|
||||||
ls
|
ls,
|
||||||
|
clear
|
||||||
} as const satisfies Record<string, ICommand>;
|
} as const satisfies Record<string, ICommand>;
|
||||||
|
|
||||||
/* //export const commands {
|
/* //export const commands {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function isInitializing(): boolean {
|
|||||||
return initializing;
|
return initializing;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsonToNodeTable(data: any, parent?: number): Map<number, TreeNode> {
|
function jsonToNodeTable(data: any): 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);
|
const entryList = Object.entries(data);
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ export function print(e: HTMLElement, data: PrintData): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function clear(): void {
|
export function clear(): void {
|
||||||
for (const n of outputInstances) {
|
console.log("outInstances", outputInstances);
|
||||||
unmount(n);
|
unmount(outputInstances);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export type PrintData = {
|
|||||||
|
|
||||||
export type PageCallbacks = {
|
export type PageCallbacks = {
|
||||||
print: (data: PrintData) => void;
|
print: (data: PrintData) => void;
|
||||||
|
clear: () => void;
|
||||||
getWidth: () => number;
|
getWidth: () => number;
|
||||||
getFontSize: () => number;
|
getFontSize: () => number;
|
||||||
};
|
};
|
||||||
@@ -107,7 +108,6 @@ export class Terminal {
|
|||||||
const width = this.callbacks.getWidth?.();
|
const width = this.callbacks.getWidth?.();
|
||||||
if(!width) { throw new Error('somehow width is undefined still after all the checks'); }
|
if(!width) { throw new Error('somehow width is undefined still after all the checks'); }
|
||||||
|
|
||||||
console.log(width);
|
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +115,6 @@ export class Terminal {
|
|||||||
const size = this.callbacks.getFontSize?.();
|
const size = this.callbacks.getFontSize?.();
|
||||||
if(!size) { throw new Error('somehow font size is undefined still after all the checks'); }
|
if(!size) { throw new Error('somehow font size is undefined still after all the checks'); }
|
||||||
|
|
||||||
console.log(size);
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,21 +22,24 @@
|
|||||||
}
|
}
|
||||||
//gets an int from padding property value (which is a string) by cutting last 2 letters "px" and parsing to int
|
//gets an int from padding property value (which is a string) by cutting last 2 letters "px" and parsing to int
|
||||||
const padding: number = parseInt(window.getComputedStyle(e, null).getPropertyValue('padding').slice(0, -2));
|
const padding: number = parseInt(window.getComputedStyle(e, null).getPropertyValue('padding').slice(0, -2));
|
||||||
console.log(padding);
|
|
||||||
return e.clientWidth - (padding * 2);
|
return e.clientWidth - (padding * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFontSize() {
|
function getFontSize() {
|
||||||
const e = document.getElementById('cout');
|
return 10;
|
||||||
|
/* const e = document.getElementById('cout');
|
||||||
if(!e) {
|
if(!e) {
|
||||||
throw new Error('cant get font size of the terminal element. its null');
|
throw new Error('cant get font size of the terminal element. its null');
|
||||||
}
|
}
|
||||||
const size: number = parseInt(window.getComputedStyle(e, null).getPropertyValue('font-size').slice(0, -2));
|
|
||||||
return size;
|
const canvas = document.createElement('canvas');
|
||||||
|
const ctx = canvas.getContext('2d')!;
|
||||||
|
ctx.font = `${window.getComputedStyle(e, null).getPropertyValue('font-size')} 'JetBrains Mono', monospace;`;
|
||||||
|
return ctx.measureText(' ').width; */
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleInput(e: KeyboardEvent) {
|
function handleInput(event: KeyboardEvent) {
|
||||||
switch (e.key) {
|
switch (event.key) {
|
||||||
case 'Enter': {
|
case 'Enter': {
|
||||||
terminal.executeCommand(inputValue);
|
terminal.executeCommand(inputValue);
|
||||||
updateTerminal();
|
updateTerminal();
|
||||||
@@ -55,6 +58,13 @@
|
|||||||
//TODO: Make a traverse history function with up/down args
|
//TODO: Make a traverse history function with up/down args
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const elem = document.getElementById('cout');
|
||||||
|
if(!elem){
|
||||||
|
throw new Error('cant scroll to bottom, element is null');
|
||||||
|
}
|
||||||
|
|
||||||
|
elem.scrollTop = elem.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Callback initializer
|
//Callback initializer
|
||||||
@@ -64,6 +74,7 @@
|
|||||||
if (!e) return;
|
if (!e) return;
|
||||||
printOutput(e, data);
|
printOutput(e, data);
|
||||||
},
|
},
|
||||||
|
clear: clear,
|
||||||
getWidth: getWidth,
|
getWidth: getWidth,
|
||||||
getFontSize: getFontSize
|
getFontSize: getFontSize
|
||||||
};
|
};
|
||||||
@@ -95,8 +106,8 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label for="input" onkeydowncapture={(e) => handleInput(e)}>
|
<label for="input" onkeydowncapture={(e) => handleInput(e)} class="w-11/12">
|
||||||
<div id="terminal" class="terminal-window shadow-() size-full rounded-md shadow-bg">
|
<div id="terminal" class="terminal-window shadow-() h-full w-full rounded-md shadow-bg">
|
||||||
<div
|
<div
|
||||||
class="terminal-bar flex h-9 w-full flex-row items-center rounded-t-md bg-bg-dark text-center font-terminal text-sm font-bold text-primary-dark light:bg-bg-dark-light light:text-primary-light"
|
class="terminal-bar flex h-9 w-full flex-row items-center rounded-t-md bg-bg-dark text-center font-terminal text-sm font-bold text-primary-dark light:bg-bg-dark-light light:text-primary-light"
|
||||||
>
|
>
|
||||||
@@ -105,7 +116,7 @@
|
|||||||
<button class="size-2.5 cursor-pointer rounded-full p-0" title=""></button>
|
<button class="size-2.5 cursor-pointer rounded-full p-0" title=""></button>
|
||||||
<button class="size-2.5 cursor-pointer rounded-full p-0" title=""></button>
|
<button class="size-2.5 cursor-pointer rounded-full p-0" title=""></button>
|
||||||
</div>
|
</div>
|
||||||
<div class=" flex">
|
<div class=" flex mr-2 grow">
|
||||||
<h5>{username}</h5>
|
<h5>{username}</h5>
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<h5 class=" mr-2">@terminal: </h5>
|
<h5 class=" mr-2">@terminal: </h5>
|
||||||
@@ -113,7 +124,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="inner-content scroll-hidden h-[860px] origin-top overflow-y-auto rounded-b-md bg-bg-light-dark p-4 text-text-dark shadow-subtle light:bg-bg-lighter-light light:text-text-light"
|
class="inner-content scroll-hidden h-7/8 origin-top overflow-y-auto rounded-b-md bg-bg-light-dark p-4 text-text-dark shadow-subtle light:bg-bg-lighter-light light:text-text-light"
|
||||||
id="cout"
|
id="cout"
|
||||||
>
|
>
|
||||||
<div id="outputWrapper"></div>
|
<div id="outputWrapper"></div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Settings></Settings>
|
<Settings></Settings>
|
||||||
<div class="h-dvh w-full p-24">
|
<div class="h-dvh w-full p-24 flex justify-center">
|
||||||
<TerminalModule />
|
<TerminalModule />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user