From 7fbf3593fbb1977fb53254d38f9af767f8014184 Mon Sep 17 00:00:00 2001 From: Kamil Olszewski Date: Fri, 13 Feb 2026 07:34:42 +0100 Subject: [PATCH] ls command now prints output in short format aswell (no flags support yet) --- src/lib/stores/bash/commands/ls.ts | 226 +++++++++++++++++----------- src/lib/stores/terminal/terminal.ts | 2 - src/modules/Terminal.svelte | 27 ++-- src/routes/+page.svelte | 2 +- 4 files changed, 154 insertions(+), 103 deletions(-) diff --git a/src/lib/stores/bash/commands/ls.ts b/src/lib/stores/bash/commands/ls.ts index a2e8b7a..723ccca 100755 --- a/src/lib/stores/bash/commands/ls.ts +++ b/src/lib/stores/bash/commands/ls.ts @@ -105,7 +105,6 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement { 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; @@ -131,114 +130,150 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement { Sort.nodeArraySort.call(this, children, f_r, sortBy); } - 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( - ...children.map((child) => child.size.toString().length)); + for (const node of nodes) { + 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; + for (const child of children) { + if (child.name.startsWith('.') && !(f_a || f_A)) continue; - 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, shouldNamesShift) - }; - - if (f_i) entry.inode = child.inode; - - 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 = { + const entry: LsEntry = { 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), + 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, shouldNamesShift) + }; + + if (f_i) entry.inode = child.inode; + + 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)); + } } - if (f_i) { - current.inode = node.inode; - parent.inode = node.parent ? node.parent : node.inode; + //TODO: Calculate the total size of contents in the node + rows.unshift('total ' + node.children.length.toString()); + + if (nodes.length > 1) { + const nodePath: string = + node.name === '/' ? '/:' : `${this.getFs().getPathByInode(node.inode).slice(1)}:`; + rows.unshift(nodePath); + rows.push('\n'); } - if (f_r) { - rows.push(LsEntryUtils.toString(parent), LsEntryUtils.toString(current)); - } else { - rows.unshift(LsEntryUtils.toString(current), LsEntryUtils.toString(parent)); + + + for (let i = 0; i < rows.length; i++) { + const p: HTMLElement = document.createElement('p'); + + + p.innerText = rows[i]; + + elem.appendChild(p); } + + w.appendChild(elem); } - //TODO: Calculate the total size of contents in the node - rows.unshift('total ' + node.children.length.toString()); - - if (nodes.length > 1) { - const nodePath: string = - node.name === '/' ? '/:' : `${this.getFs().getPathByInode(node.inode).slice(1)}:`; - rows.unshift(nodePath); - rows.push('\n'); - } - - - - for (let i = 0; i < rows.length; i++) { - const p: HTMLElement = document.createElement('p'); - - - p.innerText = rows[i]; - - elem.appendChild(p); - } - - w.appendChild(elem); - } return w; - } - const maxWidth: number = (this.getTerminalWidth() / this.getTerminalFontSize()) * 0.8; - const nameLengths: number[] = nodes.map(node => node.name.length); + } + const maxWidth: number = Math.ceil((this.getTerminalWidth() / this.getTerminalFontSize()) * 0.8); + const nameLengths: number[] = children.map(node => node.name.length); let columns: string[][] = []; + let colWidths: number[]; 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; + while(lowBound + 1 < highBound) { + let c: number = Math.ceil((lowBound + highBound) / 2); - for(let j = 0; j < colSize -1; j++){ - if(j >= nodes.length -1) break; + columns = []; + colWidths = []; - columns[i].push(nodes[j].name); - } + for(let i = 0; i < c; i++) { + columns[i] = []; + for(let j = 0; j < Math.ceil((children.length / c)); j++){ + const fileIndex: number = i * Math.floor((children.length / c)) + j; + columns[i].push(children[fileIndex].name); + } + colWidths.push(Math.max(...columns[i].map((string) => string.length))); + } + + let calcWidth: number = + Math.ceil(colWidths.reduce((result, value) => result + value) + ((c-1) * 2)); + + if(calcWidth <= maxWidth) { + lowBound = c; + } + else highBound = c; } - //w.appendChild(); + + const wrapper: HTMLElement = document.createElement('div'); + wrapper.style.display = 'flex'; + wrapper.style.columnGap = `${this.getTerminalFontSize() * 2}px`; + + for(let i = 0; i < columns.length -1; i++) { + const col: HTMLElement = document.createElement('div'); + for(let j = 0; j < columns[i].length -1; j++) { + const name: HTMLElement = document.createElement('p'); + name.innerText = columns[i][j]; + col.appendChild(name); + } + wrapper.appendChild(col); + } + + if (nodes.length > 1) { + const nodePath: HTMLElement = document.createElement('p'); + nodePath.innerText = node.name === '/' ? '/:' : `${this.getFs().getPathByInode(node.inode).slice(1)}:`; + w.appendChild(nodePath); + } + + w.appendChild(wrapper); } return w; } @@ -248,20 +283,29 @@ function nodeBinarySearch( nameLengths: number[], low: number, high: number, - max: number) { + max: number): number { - let c: number = (low + high) / 2; + let cols: number = Math.floor((low + high) / 2); + + console.log("new bounds", low, high); if(low + 1 < high) { + + const calcWidth: number = - nameLengths.reduce((result, value) => result + value) + (c-1) * 2 + Math.ceil(nameLengths.reduce((result, value) => result + value) + ((cols-1) * 2)); + + console.log(calcWidth, "calcWidth"); + console.log(cols); if (calcWidth <= max) { - low = c; - } else high = c; + low = cols; + } else high = cols; nodeBinarySearch(n, nameLengths, low, high, max); } + console.log("out values", low, cols); + return low } function isValidNodeSortMethod(value: string): value is SortNodeBy { diff --git a/src/lib/stores/terminal/terminal.ts b/src/lib/stores/terminal/terminal.ts index 744c316..25f456c 100755 --- a/src/lib/stores/terminal/terminal.ts +++ b/src/lib/stores/terminal/terminal.ts @@ -107,7 +107,6 @@ export class Terminal { const width = this.callbacks.getWidth?.(); if(!width) { throw new Error('somehow width is undefined still after all the checks'); } - console.log(width); return width; } @@ -115,7 +114,6 @@ export class Terminal { const size = this.callbacks.getFontSize?.(); if(!size) { throw new Error('somehow font size is undefined still after all the checks'); } - console.log(size); return size; } diff --git a/src/modules/Terminal.svelte b/src/modules/Terminal.svelte index 98ab43a..2c4772e 100755 --- a/src/modules/Terminal.svelte +++ b/src/modules/Terminal.svelte @@ -22,7 +22,6 @@ } //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)); - console.log(padding); return e.clientWidth - (padding * 2); } @@ -31,12 +30,15 @@ if(!e) { 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('M').width; } - function handleInput(e: KeyboardEvent) { - switch (e.key) { + function handleInput(event: KeyboardEvent) { + switch (event.key) { case 'Enter': { terminal.executeCommand(inputValue); updateTerminal(); @@ -55,6 +57,13 @@ //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 @@ -95,8 +104,8 @@ }); -