diff --git a/src/lib/stores/bash/commands/ls.ts b/src/lib/stores/bash/commands/ls.ts index b386972..a2e8b7a 100755 --- a/src/lib/stores/bash/commands/ls.ts +++ b/src/lib/stores/bash/commands/ls.ts @@ -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; diff --git a/src/lib/stores/bash/posix.ts b/src/lib/stores/bash/posix.ts new file mode 100644 index 0000000..88d09de --- /dev/null +++ b/src/lib/stores/bash/posix.ts @@ -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]; + + + } +} \ No newline at end of file diff --git a/src/lib/stores/bash/search.ts b/src/lib/stores/bash/search.ts index 22d3289..1d04b8c 100644 --- a/src/lib/stores/bash/search.ts +++ b/src/lib/stores/bash/search.ts @@ -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); - } - } } diff --git a/src/lib/stores/bash/sort.ts b/src/lib/stores/bash/sort.ts index eac3d0a..2b8d7b2 100755 --- a/src/lib/stores/bash/sort.ts +++ b/src/lib/stores/bash/sort.ts @@ -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: diff --git a/src/modules/terminal/Output.svelte b/src/modules/terminal/Output.svelte index 6b9f0dd..948cc84 100755 --- a/src/modules/terminal/Output.svelte +++ b/src/modules/terminal/Output.svelte @@ -8,7 +8,7 @@ $
{cmd}
-