Added custom Posix class that holds the custom character weight table with a public GetCharWeight method to retrieve the weight from the table. Fixed spacing of the ls -l output and slowly working with the binary search in the ls.ts file
This commit is contained in:
@@ -18,7 +18,7 @@ const LsEntryUtils = {
|
||||
return Object.entries(entry)
|
||||
.filter(([_, value]) => value !== '')
|
||||
.map(([_, value]) => value)
|
||||
.join(' ');
|
||||
.join(' ').trimStart();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -71,6 +71,7 @@ export const cmd_ls = function (this: Bash, args: CommandArgs): Result {
|
||||
|
||||
function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
||||
const dummysonoerror: HTMLElement = document.createElement('div');
|
||||
|
||||
|
||||
const flagInfo = checkFlags(args.flags);
|
||||
const nodes: TreeNode[] = data;
|
||||
@@ -96,65 +97,62 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
||||
const f_g: boolean = flagInfo.has('g');
|
||||
const f_o: boolean = flagInfo.has('o');
|
||||
|
||||
let shouldShift: boolean = false
|
||||
|
||||
const valuedArgs = args.flags.filter((flag: string) =>
|
||||
flag.includes('=') && ls.flags.includes(flag.split('=')[0]));
|
||||
|
||||
const w: HTMLElement = document.createElement('div');
|
||||
|
||||
for (const node of nodes) {
|
||||
const elem: HTMLElement = document.createElement('div');
|
||||
const children: TreeNode[] = node.children.map((child) => this.getFs().getNodeByINode(child));
|
||||
const rows: string[] = [];
|
||||
const timeArg = valuedArgs.find((flag) => flag.startsWith('time'));
|
||||
const shouldNamesShift: boolean = children.some((child) => child.name.match(/\s/) !== null);
|
||||
let timestamp: SortNodeBy.ATIME | SortNodeBy.CTIME | SortNodeBy.MTIME = SortNodeBy.MTIME;
|
||||
|
||||
if(timeArg) {
|
||||
let value: string = timeArg.split('=')[1];
|
||||
if (value && isValidNodeTimestamp(value)) timestamp = value;
|
||||
}
|
||||
|
||||
if (!f_U && !f_f) {
|
||||
const sortArg = valuedArgs.find((flag) => flag.startsWith('sort'));
|
||||
let sortBy: SortNodeBy = SortNodeBy.NAME;
|
||||
|
||||
if(f_t) sortBy = timestamp;
|
||||
if(f_S) sortBy = SortNodeBy.SIZE;
|
||||
if(f_X) sortBy = SortNodeBy.EXTENSION;
|
||||
|
||||
if(sortArg) {
|
||||
let value = sortArg.split('=')[1];
|
||||
if(value && isValidNodeSortMethod(value)) sortBy = value;
|
||||
}
|
||||
|
||||
Sort.nodeArraySort.call(this, children, f_r, sortBy);
|
||||
}
|
||||
|
||||
if (f_l || f_g || f_o) {
|
||||
const w: HTMLElement = document.createElement('div');
|
||||
|
||||
for (const node of nodes) {
|
||||
const elem: HTMLElement = document.createElement('div');
|
||||
const children: TreeNode[] = node.children.map((child) => this.getFs().getNodeByINode(child));
|
||||
const rows: string[] = [];
|
||||
|
||||
const timeArg = valuedArgs.find((flag) => flag.startsWith('time'));
|
||||
let timestamp: SortNodeBy.ATIME | SortNodeBy.CTIME | SortNodeBy.MTIME = SortNodeBy.MTIME;
|
||||
if(timeArg) {
|
||||
let value: string = timeArg.split('=')[1];
|
||||
if (value && isValidNodeTimestamp(value)) {
|
||||
timestamp = value;
|
||||
console.log(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
if (!f_U && !f_f) {
|
||||
const sortArg = valuedArgs.find((flag) => flag.startsWith('sort'));
|
||||
let sortBy: SortNodeBy = SortNodeBy.NAME;
|
||||
if(f_t) sortBy = timestamp;
|
||||
if(f_S) sortBy = SortNodeBy.SIZE;
|
||||
if(f_X) sortBy = SortNodeBy.EXTENSION;
|
||||
if(sortArg) {
|
||||
let value = sortArg.split('=')[1];
|
||||
if(value && isValidNodeSortMethod(value)) {
|
||||
sortBy = value;
|
||||
console.log(sortBy, 'sortBy');
|
||||
}
|
||||
}
|
||||
|
||||
Sort.nodeArraySort.call(this, children, f_r, sortBy);
|
||||
}
|
||||
|
||||
const sizes = children.map((child) => child.size);
|
||||
const maxSizeWidth = Math.max(...sizes.map((size) => size));
|
||||
const maxSizeWidth = Math.max(
|
||||
...children.map((child) => child.size.toString().length));
|
||||
|
||||
for (const child of children) {
|
||||
if (child.name.startsWith('.') && !(f_a || f_A)) continue;
|
||||
|
||||
const cols: LsEntry = {
|
||||
const entry: LsEntry = {
|
||||
inode: null,
|
||||
perms: formatPermission(child),
|
||||
children: formatChildren(child),
|
||||
owners: formatOwners.call(this, child, flagInfo),
|
||||
size: formatSize.call(this, f_h, child, maxSizeWidth, f_si),
|
||||
modt: formatModtime(child, timestamp),
|
||||
name: formatName(child, flagInfo, shouldShift)
|
||||
name: formatName(child, flagInfo, shouldNamesShift)
|
||||
};
|
||||
|
||||
if (f_i) cols.inode = child.inode;
|
||||
if (f_i) entry.inode = child.inode;
|
||||
|
||||
rows.push(LsEntryUtils.toString(cols));
|
||||
rows.push(LsEntryUtils.toString(entry));
|
||||
}
|
||||
|
||||
if (f_a && !f_A) {
|
||||
@@ -165,11 +163,11 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
||||
owners: formatOwners.call(this, node, flagInfo),
|
||||
size: formatSize.call(this, f_h, node, maxSizeWidth, f_si),
|
||||
modt: formatModtime(node, timestamp),
|
||||
name: '.'
|
||||
name: shouldNamesShift ? ' .' : '.'
|
||||
};
|
||||
let parent: LsEntry = {
|
||||
...current,
|
||||
name: '..'
|
||||
name: shouldNamesShift ? ' ..' : '..'
|
||||
};
|
||||
if (node.parent) {
|
||||
const parentNode: TreeNode = this.getFs().getNodeByINode(node.parent);
|
||||
@@ -180,7 +178,7 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
||||
owners: formatOwners.call(this, parentNode, flagInfo),
|
||||
size: formatSize.call(this, f_h, parentNode, maxSizeWidth, f_si),
|
||||
modt: formatModtime(parentNode, timestamp),
|
||||
name: '..'
|
||||
name: shouldNamesShift ? ' ..' : '..'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -206,12 +204,7 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
||||
rows.push('\n');
|
||||
}
|
||||
|
||||
for(const row of rows) {
|
||||
const name: string = row[row.length - 1];
|
||||
if(!name.startsWith('"') || !name.startsWith("'"))
|
||||
name.padStart(1, ' ');
|
||||
else continue;
|
||||
}
|
||||
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
const p: HTMLElement = document.createElement('p');
|
||||
@@ -226,23 +219,49 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
||||
}
|
||||
return w;
|
||||
}
|
||||
const maxWidth: number = (this.getTerminalWidth() / this.getTerminalFontSize()) * 0.8;
|
||||
const nameLengths: number[] = nodes.map(node => node.name.length);
|
||||
|
||||
let columns: string[][] = [];
|
||||
let lowBound: number = 1;
|
||||
let highBound: number = Math.floor(maxWidth / 3);
|
||||
let c: number = (lowBound + highBound) / 2;
|
||||
|
||||
nodeBinarySearch(nodes.length, nameLengths, lowBound, highBound, maxWidth);
|
||||
|
||||
for(let i = 0; i < c -1; i++) {
|
||||
const colSize: number = i < (nodes.length % c) ? nodes.length : nodes.length -1;
|
||||
|
||||
for(let j = 0; j < colSize -1; j++){
|
||||
if(j >= nodes.length -1) break;
|
||||
|
||||
|
||||
return dummysonoerror; //TEMP SO NO ERROR CUZ RETURNS HTMLElement EVERY TIME, DELETE LATER
|
||||
columns[i].push(nodes[j].name);
|
||||
}
|
||||
}
|
||||
//w.appendChild();
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
function checkMaxColumns(this: Bash, files: TreeNode[]) {
|
||||
const paddingWidth: number = 2;
|
||||
const maxWidth: number = (this.getTerminalWidth() / this.getTerminalFontSize()) * 0.8;
|
||||
function nodeBinarySearch(
|
||||
n: number,
|
||||
nameLengths: number[],
|
||||
low: number,
|
||||
high: number,
|
||||
max: number) {
|
||||
|
||||
let c: number = (low + high) / 2;
|
||||
|
||||
//Upper bound set to max width / min column width - 1 character + padding
|
||||
let lowBound: number = 1;
|
||||
let highBound: number = Math.floor(maxWidth / (1 + paddingWidth));
|
||||
|
||||
|
||||
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 {
|
||||
@@ -341,9 +360,9 @@ function formatName(node: TreeNode, flag: any, shouldShift: boolean) {
|
||||
|
||||
if (/\s/.test(node.name)) {
|
||||
name = `${char}${node.name}${char}`
|
||||
shouldShift = true;
|
||||
} else {
|
||||
name = `${node.name}`;
|
||||
//Shift non quoted names 1 char right to align if any names in group have a quote
|
||||
name = `${shouldShift ? ' ' : ''}${node.name}`;
|
||||
}
|
||||
|
||||
return flag.has('p') && node.type === Type.Directory ? `${name}/` : name;
|
||||
|
||||
80
src/lib/stores/bash/posix.ts
Normal file
80
src/lib/stores/bash/posix.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
export class Posix {
|
||||
private static readonly CharTable = {
|
||||
// Space and punctuation (32-47)
|
||||
' ': 32,
|
||||
'!': 33,
|
||||
'"': 34,
|
||||
'#': 35,
|
||||
'$': 36,
|
||||
'%': 37,
|
||||
'&': 38,
|
||||
"'": 39,
|
||||
'(': 40,
|
||||
')': 41,
|
||||
'*': 42,
|
||||
'+': 43,
|
||||
',': 44,
|
||||
'-': 45,
|
||||
'.': 46,
|
||||
'/': 47,
|
||||
|
||||
// Numbers 0-9 (48-57)
|
||||
'0': 48, '1': 49, '2': 50, '3': 51, '4': 52,
|
||||
'5': 53, '6': 54, '7': 55, '8': 56, '9': 57,
|
||||
|
||||
// More punctuation (58-64)
|
||||
':': 58,
|
||||
';': 59,
|
||||
'<': 60,
|
||||
'=': 61,
|
||||
'>': 62,
|
||||
'?': 63,
|
||||
'@': 64,
|
||||
|
||||
// LETTERS - INTERLEAVED AaBbCc... (65-116)
|
||||
'A': 65, 'a': 66,
|
||||
'B': 67, 'b': 68,
|
||||
'C': 69, 'c': 70,
|
||||
'D': 71, 'd': 72,
|
||||
'E': 73, 'e': 74,
|
||||
'F': 75, 'f': 76,
|
||||
'G': 77, 'g': 78,
|
||||
'H': 79, 'h': 80,
|
||||
'I': 81, 'i': 82,
|
||||
'J': 83, 'j': 84,
|
||||
'K': 85, 'k': 86,
|
||||
'L': 87, 'l': 88,
|
||||
'M': 89, 'm': 90,
|
||||
'N': 91, 'n': 92,
|
||||
'O': 93, 'o': 94,
|
||||
'P': 95, 'p': 96,
|
||||
'Q': 97, 'q': 98,
|
||||
'R': 99, 'r': 100,
|
||||
'S': 101, 's': 102,
|
||||
'T': 103, 't': 104,
|
||||
'U': 105, 'u': 106,
|
||||
'V': 107, 'v': 108,
|
||||
'W': 109, 'w': 110,
|
||||
'X': 111, 'x': 112,
|
||||
'Y': 113, 'y': 114,
|
||||
'Z': 115, 'z': 116,
|
||||
|
||||
// Specials after letters (now 117-126)
|
||||
'[': 117,
|
||||
'\\': 118,
|
||||
']': 119,
|
||||
'^': 120,
|
||||
'_': 121,
|
||||
'`': 122,
|
||||
'{': 123,
|
||||
'|': 124,
|
||||
'}': 125,
|
||||
'~': 126
|
||||
} as const;
|
||||
|
||||
public static GetCharWeight(char: string): number {
|
||||
return this.CharTable[char as keyof typeof this.CharTable];
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,46 +3,5 @@ import type { TreeNode } from "./fs";
|
||||
|
||||
export class Search {
|
||||
|
||||
public static nodeBinarySearch(
|
||||
this: Bash,
|
||||
nodes: TreeNode[],
|
||||
max: number
|
||||
): number {
|
||||
let low: number = 1;
|
||||
let high: number = nodes.length;
|
||||
let c: number = (low + high) / 2;
|
||||
const nameLengths: number[] = nodes.map(node => node.name.length);
|
||||
|
||||
}
|
||||
|
||||
private static binarySearchDNC(
|
||||
n: number,
|
||||
nameLengths: number[],
|
||||
low: number,
|
||||
high: number,
|
||||
max: number): number {
|
||||
|
||||
let c: number = (low + high) / 2;
|
||||
|
||||
if(low + 1 < high) {
|
||||
for(let i = 0; i < c; i++) {
|
||||
const colSize: number =
|
||||
i < (n % c) ? n : n -1;
|
||||
}
|
||||
|
||||
const calculatedWidth: number =
|
||||
nameLengths.reduce((result, value) => result + value) + (c-1) * 2
|
||||
|
||||
if (calculatedWidth <= max) {
|
||||
low = c;
|
||||
return c;
|
||||
}
|
||||
else {
|
||||
high = c;
|
||||
}
|
||||
|
||||
this.binarySearchDNC(n, nameLengths, low, high, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { TreeNode } from './fs';
|
||||
import type { Bash } from './bash';
|
||||
import { Posix } from './posix';
|
||||
|
||||
export enum SortNodeBy {
|
||||
NAME = 'name',
|
||||
@@ -85,17 +86,19 @@ export class Sort {
|
||||
): number {
|
||||
switch (sortBy) {
|
||||
case SortNodeBy.NAME: {
|
||||
const minLength = Math.min(a.name.length, b.name.length);
|
||||
const nameA: string = a.name.startsWith('.') ? a.name.slice(1) : a.name;
|
||||
const nameB: string = b.name.startsWith('.') ? b.name.slice(1) : b.name;
|
||||
const minLength = Math.min(nameA.length, nameB.length);
|
||||
|
||||
for (let i = 0; i < minLength; i++) {
|
||||
const charCodeA = a.name.charCodeAt(i);
|
||||
const charCodeB = b.name.charCodeAt(i);
|
||||
const charCodeA = Posix.GetCharWeight(nameA[i]);
|
||||
const charCodeB = Posix.GetCharWeight(nameB[i]);
|
||||
|
||||
if (charCodeA !== charCodeB) {
|
||||
return reverse ? charCodeB - charCodeA : charCodeA - charCodeB;
|
||||
}
|
||||
}
|
||||
return reverse ? b.name.length - a.name.length : a.name.length - b.name.length;
|
||||
return reverse ? nameB.length - nameA.length : nameA.length - nameB.length;
|
||||
}
|
||||
case SortNodeBy.MTIME:
|
||||
case SortNodeBy.ATIME:
|
||||
|
||||
Reference in New Issue
Block a user