@ecmaos/coreutils 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +37 -0
- package/LICENSE +1 -1
- package/dist/commands/cal.js +2 -2
- package/dist/commands/cal.js.map +1 -1
- package/dist/commands/cat.js +2 -2
- package/dist/commands/cd.js +2 -2
- package/dist/commands/chmod.d.ts.map +1 -1
- package/dist/commands/chmod.js +16 -11
- package/dist/commands/chmod.js.map +1 -1
- package/dist/commands/cp.js +2 -2
- package/dist/commands/cp.js.map +1 -1
- package/dist/commands/cron.d.ts +4 -0
- package/dist/commands/cron.d.ts.map +1 -0
- package/dist/commands/cron.js +439 -0
- package/dist/commands/cron.js.map +1 -0
- package/dist/commands/date.js +2 -2
- package/dist/commands/date.js.map +1 -1
- package/dist/commands/echo.js +2 -2
- package/dist/commands/echo.js.map +1 -1
- package/dist/commands/false.js +2 -2
- package/dist/commands/fetch.d.ts +4 -0
- package/dist/commands/fetch.d.ts.map +1 -0
- package/dist/commands/fetch.js +210 -0
- package/dist/commands/fetch.js.map +1 -0
- package/dist/commands/format.d.ts +4 -0
- package/dist/commands/format.d.ts.map +1 -0
- package/dist/commands/format.js +178 -0
- package/dist/commands/format.js.map +1 -0
- package/dist/commands/hash.d.ts +4 -0
- package/dist/commands/hash.d.ts.map +1 -0
- package/dist/commands/hash.js +200 -0
- package/dist/commands/hash.js.map +1 -0
- package/dist/commands/head.js +2 -2
- package/dist/commands/id.js +2 -2
- package/dist/commands/id.js.map +1 -1
- package/dist/commands/less.d.ts.map +1 -1
- package/dist/commands/less.js +53 -2
- package/dist/commands/less.js.map +1 -1
- package/dist/commands/ls.d.ts.map +1 -1
- package/dist/commands/ls.js +41 -15
- package/dist/commands/ls.js.map +1 -1
- package/dist/commands/man.d.ts +4 -0
- package/dist/commands/man.d.ts.map +1 -0
- package/dist/commands/man.js +564 -0
- package/dist/commands/man.js.map +1 -0
- package/dist/commands/mkdir.js +2 -2
- package/dist/commands/mkdir.js.map +1 -1
- package/dist/commands/mktemp.d.ts +4 -0
- package/dist/commands/mktemp.d.ts.map +1 -0
- package/dist/commands/mktemp.js +229 -0
- package/dist/commands/mktemp.js.map +1 -0
- package/dist/commands/nc.js +2 -2
- package/dist/commands/nc.js.map +1 -1
- package/dist/commands/open.d.ts +4 -0
- package/dist/commands/open.d.ts.map +1 -0
- package/dist/commands/open.js +74 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/passkey.js +3 -3
- package/dist/commands/play.d.ts +4 -0
- package/dist/commands/play.d.ts.map +1 -0
- package/dist/commands/play.js +231 -0
- package/dist/commands/play.js.map +1 -0
- package/dist/commands/pwd.js +2 -2
- package/dist/commands/pwd.js.map +1 -1
- package/dist/commands/rm.d.ts.map +1 -1
- package/dist/commands/rm.js +57 -12
- package/dist/commands/rm.js.map +1 -1
- package/dist/commands/rmdir.js +2 -2
- package/dist/commands/rmdir.js.map +1 -1
- package/dist/commands/sockets.js +1 -1
- package/dist/commands/stat.d.ts.map +1 -1
- package/dist/commands/stat.js +37 -15
- package/dist/commands/stat.js.map +1 -1
- package/dist/commands/tail.js +2 -2
- package/dist/commands/tar.d.ts +4 -0
- package/dist/commands/tar.d.ts.map +1 -0
- package/dist/commands/tar.js +743 -0
- package/dist/commands/tar.js.map +1 -0
- package/dist/commands/touch.js +2 -2
- package/dist/commands/touch.js.map +1 -1
- package/dist/commands/true.js +2 -2
- package/dist/commands/unzip.d.ts +4 -0
- package/dist/commands/unzip.d.ts.map +1 -0
- package/dist/commands/unzip.js +443 -0
- package/dist/commands/unzip.js.map +1 -0
- package/dist/commands/user.js +1 -1
- package/dist/commands/video.d.ts +4 -0
- package/dist/commands/video.d.ts.map +1 -0
- package/dist/commands/video.js +250 -0
- package/dist/commands/video.js.map +1 -0
- package/dist/commands/view.d.ts +4 -0
- package/dist/commands/view.d.ts.map +1 -0
- package/dist/commands/view.js +488 -0
- package/dist/commands/view.js.map +1 -0
- package/dist/commands/web.d.ts +4 -0
- package/dist/commands/web.d.ts.map +1 -0
- package/dist/commands/web.js +348 -0
- package/dist/commands/web.js.map +1 -0
- package/dist/commands/whoami.js +2 -2
- package/dist/commands/whoami.js.map +1 -1
- package/dist/commands/zip.d.ts +4 -0
- package/dist/commands/zip.d.ts.map +1 -0
- package/dist/commands/zip.js +264 -0
- package/dist/commands/zip.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -2
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
- package/src/commands/cal.ts +2 -2
- package/src/commands/cat.ts +2 -2
- package/src/commands/cd.ts +2 -2
- package/src/commands/chmod.ts +19 -11
- package/src/commands/cp.ts +2 -2
- package/src/commands/cron.ts +499 -0
- package/src/commands/date.ts +2 -2
- package/src/commands/echo.ts +2 -2
- package/src/commands/false.ts +2 -2
- package/src/commands/fetch.ts +205 -0
- package/src/commands/format.ts +204 -0
- package/src/commands/hash.ts +215 -0
- package/src/commands/head.ts +2 -2
- package/src/commands/id.ts +2 -2
- package/src/commands/less.ts +50 -2
- package/src/commands/ls.ts +40 -14
- package/src/commands/man.ts +651 -0
- package/src/commands/mkdir.ts +2 -2
- package/src/commands/mktemp.ts +235 -0
- package/src/commands/nc.ts +2 -2
- package/src/commands/open.ts +84 -0
- package/src/commands/passkey.ts +3 -3
- package/src/commands/play.ts +249 -0
- package/src/commands/pwd.ts +2 -2
- package/src/commands/rm.ts +54 -12
- package/src/commands/rmdir.ts +2 -2
- package/src/commands/sockets.ts +1 -1
- package/src/commands/stat.ts +44 -16
- package/src/commands/tail.ts +2 -2
- package/src/commands/tar.ts +780 -0
- package/src/commands/touch.ts +2 -2
- package/src/commands/true.ts +2 -2
- package/src/commands/unzip.ts +517 -0
- package/src/commands/user.ts +1 -1
- package/src/commands/video.ts +267 -0
- package/src/commands/view.ts +526 -0
- package/src/commands/web.ts +377 -0
- package/src/commands/whoami.ts +2 -2
- package/src/commands/zip.ts +319 -0
- package/src/index.ts +44 -2
package/src/commands/less.ts
CHANGED
|
@@ -33,6 +33,7 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
33
33
|
|
|
34
34
|
let lines: string[] = []
|
|
35
35
|
let currentLine = 0
|
|
36
|
+
let horizontalOffset = 0
|
|
36
37
|
let keyListener: IDisposable | null = null
|
|
37
38
|
let linesRendered = 0
|
|
38
39
|
|
|
@@ -94,6 +95,40 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
94
95
|
const displayRows = rows - 1
|
|
95
96
|
|
|
96
97
|
const render = () => {
|
|
98
|
+
const cols = terminal.cols
|
|
99
|
+
const stripAnsi = (s: string) => s.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '')
|
|
100
|
+
|
|
101
|
+
const getVisibleSlice = (line: string, offset: number): string => {
|
|
102
|
+
const visibleLen = stripAnsi(line).length
|
|
103
|
+
|
|
104
|
+
if (offset < 0) offset = 0
|
|
105
|
+
if (offset > visibleLen) offset = visibleLen
|
|
106
|
+
|
|
107
|
+
let visible = 0
|
|
108
|
+
let result = ''
|
|
109
|
+
let inEscape = false
|
|
110
|
+
let charsSkipped = 0
|
|
111
|
+
|
|
112
|
+
for (const char of line) {
|
|
113
|
+
if (char === '\x1b') inEscape = true
|
|
114
|
+
if (inEscape) {
|
|
115
|
+
if (charsSkipped >= offset) {
|
|
116
|
+
result += char
|
|
117
|
+
}
|
|
118
|
+
if (/[a-zA-Z]/.test(char)) inEscape = false
|
|
119
|
+
} else {
|
|
120
|
+
if (charsSkipped < offset) {
|
|
121
|
+
charsSkipped++
|
|
122
|
+
} else {
|
|
123
|
+
if (visible >= cols) break
|
|
124
|
+
result += char
|
|
125
|
+
visible++
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return result
|
|
130
|
+
}
|
|
131
|
+
|
|
97
132
|
const maxLine = Math.max(0, lines.length - displayRows)
|
|
98
133
|
if (currentLine > maxLine) {
|
|
99
134
|
currentLine = maxLine
|
|
@@ -102,6 +137,11 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
102
137
|
currentLine = 0
|
|
103
138
|
}
|
|
104
139
|
|
|
140
|
+
const maxLineLength = Math.max(...lines.map(l => stripAnsi(l).length), 0)
|
|
141
|
+
const maxHorizontalOffset = Math.max(0, maxLineLength - cols)
|
|
142
|
+
if (horizontalOffset > maxHorizontalOffset) horizontalOffset = maxHorizontalOffset
|
|
143
|
+
if (horizontalOffset < 0) horizontalOffset = 0
|
|
144
|
+
|
|
105
145
|
if (linesRendered > 0) {
|
|
106
146
|
terminal.write(ansi.cursor.up(linesRendered))
|
|
107
147
|
}
|
|
@@ -111,7 +151,7 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
111
151
|
|
|
112
152
|
for (let i = currentLine; i < endLine; i++) {
|
|
113
153
|
terminal.write(ansi.erase.inLine(2))
|
|
114
|
-
const line = lines[i] || ''
|
|
154
|
+
const line = getVisibleSlice(lines[i] || '', horizontalOffset)
|
|
115
155
|
terminal.write(line)
|
|
116
156
|
linesRendered++
|
|
117
157
|
if (i < endLine - 1) {
|
|
@@ -129,7 +169,7 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
129
169
|
const statusLine = `-- ${currentLine + 1}-${endLine} / ${lines.length} (${percentage}%)`
|
|
130
170
|
terminal.write('\n')
|
|
131
171
|
terminal.write(ansi.erase.inLine(2))
|
|
132
|
-
terminal.write(statusLine)
|
|
172
|
+
terminal.write(getVisibleSlice(statusLine, 0))
|
|
133
173
|
linesRendered++
|
|
134
174
|
}
|
|
135
175
|
|
|
@@ -163,6 +203,14 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
163
203
|
currentLine++
|
|
164
204
|
render()
|
|
165
205
|
break
|
|
206
|
+
case 'ArrowLeft':
|
|
207
|
+
horizontalOffset = Math.max(0, horizontalOffset - Math.floor(terminal.cols / 2))
|
|
208
|
+
render()
|
|
209
|
+
break
|
|
210
|
+
case 'ArrowRight':
|
|
211
|
+
horizontalOffset += Math.floor(terminal.cols / 2)
|
|
212
|
+
render()
|
|
213
|
+
break
|
|
166
214
|
case 'PageDown':
|
|
167
215
|
case ' ':
|
|
168
216
|
currentLine = Math.min(currentLine + displayRows, Math.max(0, lines.length - displayRows))
|
package/src/commands/ls.ts
CHANGED
|
@@ -4,14 +4,14 @@ import columnify from 'columnify'
|
|
|
4
4
|
import humanFormat from 'human-format'
|
|
5
5
|
import type { Kernel, Process, Shell, Terminal } from '@ecmaos/types'
|
|
6
6
|
import { TerminalCommand } from '../shared/terminal-command.js'
|
|
7
|
-
import { writelnStdout } from '../shared/helpers.js'
|
|
7
|
+
import { writelnStdout, writelnStderr } from '../shared/helpers.js'
|
|
8
8
|
|
|
9
9
|
function printUsage(process: Process | undefined, terminal: Terminal): void {
|
|
10
10
|
const usage = `Usage: ls [OPTION]... [FILE]...
|
|
11
11
|
List information about the FILEs (the current directory by default).
|
|
12
12
|
|
|
13
13
|
--help display this help and exit`
|
|
14
|
-
|
|
14
|
+
writelnStderr(process, terminal, usage)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal): TerminalCommand {
|
|
@@ -29,12 +29,37 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
29
29
|
return 0
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
// Filter out options/flags and get target paths
|
|
33
|
+
const targets = argv.length > 0
|
|
34
|
+
? argv.filter(arg => !arg.startsWith('-'))
|
|
35
|
+
: [shell.cwd]
|
|
36
|
+
|
|
37
|
+
if (targets.length === 0) targets.push(shell.cwd)
|
|
38
|
+
|
|
36
39
|
const descriptions = kernel.filesystem.descriptions(kernel.i18n.t)
|
|
37
40
|
|
|
41
|
+
// Process each target and collect all entries
|
|
42
|
+
// We'll determine if each entry is a directory when we stat it later
|
|
43
|
+
const allEntries: Array<{ fullPath: string, entry: string }> = []
|
|
44
|
+
|
|
45
|
+
for (const target of targets) {
|
|
46
|
+
const fullPath = path.resolve(shell.cwd, target === '' ? '.' : target)
|
|
47
|
+
try {
|
|
48
|
+
const stats = await shell.context.fs.promises.stat(fullPath)
|
|
49
|
+
if (stats.isDirectory()) {
|
|
50
|
+
// For directories, list all contents
|
|
51
|
+
const dirEntries = await shell.context.fs.promises.readdir(fullPath)
|
|
52
|
+
for (const entry of dirEntries) allEntries.push({ fullPath, entry })
|
|
53
|
+
} else {
|
|
54
|
+
// For files, add the file itself
|
|
55
|
+
allEntries.push({ fullPath: path.dirname(fullPath), entry: path.basename(fullPath) })
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
// If target doesn't exist, skip it (standard ls behavior)
|
|
59
|
+
continue
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
38
63
|
const getModeType = (stats: Awaited<ReturnType<typeof shell.context.fs.promises.stat>>) => {
|
|
39
64
|
let type = '-'
|
|
40
65
|
if (stats.isDirectory()) type = 'd'
|
|
@@ -85,9 +110,9 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
85
110
|
return ''
|
|
86
111
|
}
|
|
87
112
|
|
|
88
|
-
const filesMap = await Promise.all(
|
|
89
|
-
.map(async entry => {
|
|
90
|
-
const target = path.resolve(
|
|
113
|
+
const filesMap = await Promise.all(allEntries
|
|
114
|
+
.map(async ({ fullPath: entryFullPath, entry }) => {
|
|
115
|
+
const target = path.resolve(entryFullPath, entry)
|
|
91
116
|
try {
|
|
92
117
|
let linkTarget: string | null = null
|
|
93
118
|
let linkStats = null
|
|
@@ -119,9 +144,9 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
119
144
|
.filter(entry => entry && entry.stats && !entry.stats.isDirectory())
|
|
120
145
|
.filter((entry): entry is NonNullable<typeof entry> => entry !== null && entry !== undefined)
|
|
121
146
|
|
|
122
|
-
const directoryMap = await Promise.all(
|
|
123
|
-
.map(async entry => {
|
|
124
|
-
const target = path.resolve(
|
|
147
|
+
const directoryMap = await Promise.all(allEntries
|
|
148
|
+
.map(async ({ fullPath: entryFullPath, entry }) => {
|
|
149
|
+
const target = path.resolve(entryFullPath, entry)
|
|
125
150
|
try {
|
|
126
151
|
let linkTarget: string | null = null
|
|
127
152
|
let linkStats = null
|
|
@@ -154,7 +179,8 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
154
179
|
.filter((entry, index, self) => self.findIndex(e => e?.name === entry?.name) === index)
|
|
155
180
|
.filter((entry): entry is NonNullable<typeof entry> => entry !== null && entry !== undefined)
|
|
156
181
|
|
|
157
|
-
|
|
182
|
+
// Check if any entry is in /dev directory
|
|
183
|
+
const isDevDirectory = allEntries.some(e => e.fullPath.startsWith('/dev'))
|
|
158
184
|
const columns = isDevDirectory ? ['Name', 'Mode', 'Owner', 'Info'] : ['Name', 'Size', 'Modified', 'Mode', 'Owner', 'Info']
|
|
159
185
|
|
|
160
186
|
const directoryRows = directories.sort((a, b) => a.name.localeCompare(b.name)).map(directory => {
|
|
@@ -209,7 +235,7 @@ export function createCommand(kernel: Kernel, shell: Shell, terminal: Terminal):
|
|
|
209
235
|
const linkInfo = getLinkInfo(file.linkTarget, file.linkStats, file.stats)
|
|
210
236
|
if (linkInfo) return linkInfo
|
|
211
237
|
|
|
212
|
-
if (descriptions.has(
|
|
238
|
+
if (descriptions.has(file.target)) return descriptions.get(file.target) || ''
|
|
213
239
|
if (file.name.includes('.')) {
|
|
214
240
|
const ext = file.name.split('.').pop()
|
|
215
241
|
if (ext && descriptions.has('.' + ext)) return descriptions.get('.' + ext) || ''
|