shell-dsl 0.0.13 → 0.0.15
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/dist/cjs/package.json +1 -1
- package/dist/cjs/src/commands/find/find.cjs +144 -80
- package/dist/cjs/src/commands/find/find.cjs.map +3 -3
- package/dist/cjs/src/commands/ls/ls.cjs +65 -42
- package/dist/cjs/src/commands/ls/ls.cjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/src/commands/find/find.mjs +144 -80
- package/dist/mjs/src/commands/find/find.mjs.map +3 -3
- package/dist/mjs/src/commands/ls/ls.mjs +65 -42
- package/dist/mjs/src/commands/ls/ls.mjs.map +3 -3
- package/package.json +1 -1
package/dist/cjs/package.json
CHANGED
|
@@ -88,88 +88,173 @@ function matchGlob(pattern, str, caseInsensitive = false) {
|
|
|
88
88
|
return false;
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
+
function evalExpr(expr, basename, isFile, isDir) {
|
|
92
|
+
switch (expr.type) {
|
|
93
|
+
case "true":
|
|
94
|
+
return true;
|
|
95
|
+
case "name":
|
|
96
|
+
return matchGlob(expr.pattern, basename, expr.ignoreCase);
|
|
97
|
+
case "ftype":
|
|
98
|
+
return expr.value === "f" ? isFile : isDir;
|
|
99
|
+
case "and":
|
|
100
|
+
return evalExpr(expr.left, basename, isFile, isDir) && evalExpr(expr.right, basename, isFile, isDir);
|
|
101
|
+
case "or":
|
|
102
|
+
return evalExpr(expr.left, basename, isFile, isDir) || evalExpr(expr.right, basename, isFile, isDir);
|
|
103
|
+
case "not":
|
|
104
|
+
return !evalExpr(expr.expr, basename, isFile, isDir);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
class ParseError extends Error {
|
|
109
|
+
constructor(msg) {
|
|
110
|
+
super(msg);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function parseExprArgs(args) {
|
|
114
|
+
if (args.length === 0)
|
|
115
|
+
return { type: "true" };
|
|
116
|
+
let pos = 0;
|
|
117
|
+
function peek() {
|
|
118
|
+
return args[pos];
|
|
119
|
+
}
|
|
120
|
+
function advance() {
|
|
121
|
+
return args[pos++];
|
|
122
|
+
}
|
|
123
|
+
function parseOr() {
|
|
124
|
+
let left = parseAnd();
|
|
125
|
+
while (peek() === "-o") {
|
|
126
|
+
advance();
|
|
127
|
+
const right = parseAnd();
|
|
128
|
+
left = { type: "or", left, right };
|
|
129
|
+
}
|
|
130
|
+
return left;
|
|
131
|
+
}
|
|
132
|
+
function parseAnd() {
|
|
133
|
+
let left = parseUnary();
|
|
134
|
+
while (pos < args.length) {
|
|
135
|
+
const next = peek();
|
|
136
|
+
if (next === "-o" || next === ")" || next === undefined)
|
|
137
|
+
break;
|
|
138
|
+
if (next === "-a") {
|
|
139
|
+
advance();
|
|
140
|
+
}
|
|
141
|
+
const right = parseUnary();
|
|
142
|
+
left = { type: "and", left, right };
|
|
143
|
+
}
|
|
144
|
+
return left;
|
|
145
|
+
}
|
|
146
|
+
function parseUnary() {
|
|
147
|
+
const next = peek();
|
|
148
|
+
if (next === "!" || next === "-not") {
|
|
149
|
+
advance();
|
|
150
|
+
const expr2 = parseUnary();
|
|
151
|
+
return { type: "not", expr: expr2 };
|
|
152
|
+
}
|
|
153
|
+
return parsePrimary();
|
|
154
|
+
}
|
|
155
|
+
function parsePrimary() {
|
|
156
|
+
const tok = peek();
|
|
157
|
+
if (tok === undefined) {
|
|
158
|
+
throw new ParseError("find: expected expression");
|
|
159
|
+
}
|
|
160
|
+
if (tok === "(") {
|
|
161
|
+
advance();
|
|
162
|
+
const expr2 = parseOr();
|
|
163
|
+
if (peek() !== ")") {
|
|
164
|
+
throw new ParseError("find: missing closing ')'");
|
|
165
|
+
}
|
|
166
|
+
advance();
|
|
167
|
+
return expr2;
|
|
168
|
+
}
|
|
169
|
+
if (tok === "-name" || tok === "-iname") {
|
|
170
|
+
advance();
|
|
171
|
+
const pattern = peek();
|
|
172
|
+
if (pattern === undefined) {
|
|
173
|
+
throw new ParseError(`find: missing argument to '${tok}'`);
|
|
174
|
+
}
|
|
175
|
+
advance();
|
|
176
|
+
return { type: "name", pattern, ignoreCase: tok === "-iname" };
|
|
177
|
+
}
|
|
178
|
+
if (tok === "-type") {
|
|
179
|
+
advance();
|
|
180
|
+
const val = peek();
|
|
181
|
+
if (val === undefined) {
|
|
182
|
+
throw new ParseError("find: missing argument to '-type'");
|
|
183
|
+
}
|
|
184
|
+
if (val !== "f" && val !== "d") {
|
|
185
|
+
throw new ParseError(`find: Unknown argument to -type: ${val}`);
|
|
186
|
+
}
|
|
187
|
+
advance();
|
|
188
|
+
return { type: "ftype", value: val };
|
|
189
|
+
}
|
|
190
|
+
throw new ParseError(`find: unknown predicate '${tok}'`);
|
|
191
|
+
}
|
|
192
|
+
const expr = parseOr();
|
|
193
|
+
if (pos < args.length) {
|
|
194
|
+
throw new ParseError(`find: unexpected '${args[pos]}'`);
|
|
195
|
+
}
|
|
196
|
+
return expr;
|
|
197
|
+
}
|
|
91
198
|
var find = async (ctx) => {
|
|
92
199
|
const args = [...ctx.args];
|
|
93
200
|
const paths = [];
|
|
94
|
-
const options = {};
|
|
95
201
|
let i = 0;
|
|
96
|
-
while (i < args.length && !args[i].startsWith("-")) {
|
|
202
|
+
while (i < args.length && !args[i].startsWith("-") && args[i] !== "!" && args[i] !== "(" && args[i] !== ")") {
|
|
97
203
|
paths.push(args[i]);
|
|
98
204
|
i++;
|
|
99
205
|
}
|
|
100
206
|
if (paths.length === 0) {
|
|
101
207
|
paths.push(".");
|
|
102
208
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
options.namePattern = args[i];
|
|
113
|
-
options.nameIgnoreCase = false;
|
|
114
|
-
} else if (arg === "-iname") {
|
|
115
|
-
i++;
|
|
116
|
-
if (i >= args.length) {
|
|
117
|
-
await ctx.stderr.writeText(`find: missing argument to '-iname'
|
|
118
|
-
`);
|
|
119
|
-
return 1;
|
|
120
|
-
}
|
|
121
|
-
options.namePattern = args[i];
|
|
122
|
-
options.nameIgnoreCase = true;
|
|
123
|
-
} else if (arg === "-type") {
|
|
124
|
-
i++;
|
|
125
|
-
if (i >= args.length) {
|
|
126
|
-
await ctx.stderr.writeText(`find: missing argument to '-type'
|
|
127
|
-
`);
|
|
128
|
-
return 1;
|
|
129
|
-
}
|
|
130
|
-
const typeArg = args[i];
|
|
131
|
-
if (typeArg !== "f" && typeArg !== "d") {
|
|
132
|
-
await ctx.stderr.writeText(`find: Unknown argument to -type: ${typeArg}
|
|
133
|
-
`);
|
|
134
|
-
return 1;
|
|
135
|
-
}
|
|
136
|
-
options.type = typeArg;
|
|
137
|
-
} else if (arg === "-maxdepth") {
|
|
138
|
-
i++;
|
|
139
|
-
if (i >= args.length) {
|
|
209
|
+
let maxDepth;
|
|
210
|
+
let minDepth;
|
|
211
|
+
const exprArgs = [];
|
|
212
|
+
let j = i;
|
|
213
|
+
while (j < args.length) {
|
|
214
|
+
const arg = args[j];
|
|
215
|
+
if (arg === "-maxdepth") {
|
|
216
|
+
j++;
|
|
217
|
+
if (j >= args.length) {
|
|
140
218
|
await ctx.stderr.writeText(`find: missing argument to '-maxdepth'
|
|
141
219
|
`);
|
|
142
220
|
return 1;
|
|
143
221
|
}
|
|
144
|
-
const depth = parseInt(args[
|
|
222
|
+
const depth = parseInt(args[j], 10);
|
|
145
223
|
if (isNaN(depth) || depth < 0) {
|
|
146
|
-
await ctx.stderr.writeText(`find: Invalid argument '${args[
|
|
224
|
+
await ctx.stderr.writeText(`find: Invalid argument '${args[j]}' to -maxdepth
|
|
147
225
|
`);
|
|
148
226
|
return 1;
|
|
149
227
|
}
|
|
150
|
-
|
|
228
|
+
maxDepth = depth;
|
|
151
229
|
} else if (arg === "-mindepth") {
|
|
152
|
-
|
|
153
|
-
if (
|
|
230
|
+
j++;
|
|
231
|
+
if (j >= args.length) {
|
|
154
232
|
await ctx.stderr.writeText(`find: missing argument to '-mindepth'
|
|
155
233
|
`);
|
|
156
234
|
return 1;
|
|
157
235
|
}
|
|
158
|
-
const depth = parseInt(args[
|
|
236
|
+
const depth = parseInt(args[j], 10);
|
|
159
237
|
if (isNaN(depth) || depth < 0) {
|
|
160
|
-
await ctx.stderr.writeText(`find: Invalid argument '${args[
|
|
238
|
+
await ctx.stderr.writeText(`find: Invalid argument '${args[j]}' to -mindepth
|
|
161
239
|
`);
|
|
162
240
|
return 1;
|
|
163
241
|
}
|
|
164
|
-
|
|
165
|
-
} else
|
|
166
|
-
|
|
242
|
+
minDepth = depth;
|
|
243
|
+
} else {
|
|
244
|
+
exprArgs.push(arg);
|
|
245
|
+
}
|
|
246
|
+
j++;
|
|
247
|
+
}
|
|
248
|
+
let expr;
|
|
249
|
+
try {
|
|
250
|
+
expr = parseExprArgs(exprArgs);
|
|
251
|
+
} catch (e) {
|
|
252
|
+
if (e instanceof ParseError) {
|
|
253
|
+
await ctx.stderr.writeText(e.message + `
|
|
167
254
|
`);
|
|
168
255
|
return 1;
|
|
169
|
-
} else {
|
|
170
|
-
paths.push(arg);
|
|
171
256
|
}
|
|
172
|
-
|
|
257
|
+
throw e;
|
|
173
258
|
}
|
|
174
259
|
let hasError = false;
|
|
175
260
|
for (const startPath of paths) {
|
|
@@ -185,7 +270,7 @@ var find = async (ctx) => {
|
|
|
185
270
|
continue;
|
|
186
271
|
}
|
|
187
272
|
async function traverse(path, displayPath, depth) {
|
|
188
|
-
if (
|
|
273
|
+
if (maxDepth !== undefined && depth > maxDepth) {
|
|
189
274
|
return;
|
|
190
275
|
}
|
|
191
276
|
let entryStat;
|
|
@@ -197,18 +282,8 @@ var find = async (ctx) => {
|
|
|
197
282
|
const isDir = entryStat.isDirectory();
|
|
198
283
|
const isFile = entryStat.isFile();
|
|
199
284
|
const basename = ctx.fs.basename(path);
|
|
200
|
-
|
|
201
|
-
if (
|
|
202
|
-
matches = false;
|
|
203
|
-
} else if (options.type === "d" && !isDir) {
|
|
204
|
-
matches = false;
|
|
205
|
-
}
|
|
206
|
-
if (matches && options.namePattern !== undefined) {
|
|
207
|
-
if (!matchGlob(options.namePattern, basename, options.nameIgnoreCase)) {
|
|
208
|
-
matches = false;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
if (matches && (options.minDepth === undefined || depth >= options.minDepth)) {
|
|
285
|
+
const matches = evalExpr(expr, basename, isFile, isDir);
|
|
286
|
+
if (matches && (minDepth === undefined || depth >= minDepth)) {
|
|
212
287
|
await ctx.stdout.writeText(displayPath + `
|
|
213
288
|
`);
|
|
214
289
|
}
|
|
@@ -225,20 +300,9 @@ var find = async (ctx) => {
|
|
|
225
300
|
}
|
|
226
301
|
}
|
|
227
302
|
if (stat.isFile()) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
if (matches && options.namePattern !== undefined) {
|
|
233
|
-
const basename = ctx.fs.basename(resolvedStart);
|
|
234
|
-
if (!matchGlob(options.namePattern, basename, options.nameIgnoreCase)) {
|
|
235
|
-
matches = false;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
if (options.maxDepth !== undefined && options.maxDepth < 0) {
|
|
239
|
-
matches = false;
|
|
240
|
-
}
|
|
241
|
-
if (matches && (options.minDepth === undefined || options.minDepth <= 0)) {
|
|
303
|
+
const basename = ctx.fs.basename(resolvedStart);
|
|
304
|
+
const matches = evalExpr(expr, basename, true, false);
|
|
305
|
+
if (maxDepth !== undefined && maxDepth < 0) {} else if (matches && (minDepth === undefined || minDepth <= 0)) {
|
|
242
306
|
await ctx.stdout.writeText(normalizedPath + `
|
|
243
307
|
`);
|
|
244
308
|
}
|
|
@@ -249,4 +313,4 @@ var find = async (ctx) => {
|
|
|
249
313
|
return hasError ? 1 : 0;
|
|
250
314
|
};
|
|
251
315
|
|
|
252
|
-
//# debugId=
|
|
316
|
+
//# debugId=80CE5607A2F2B89F64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/commands/find/find.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { Command } from \"../../types.cjs\";\n\n/**\n * Simple glob pattern matching (fnmatch-style)\n * Supports: * (any chars), ? (single char), [...] (character class)\n */\nfunction matchGlob(pattern: string, str: string, caseInsensitive = false): boolean {\n if (caseInsensitive) {\n pattern = pattern.toLowerCase();\n str = str.toLowerCase();\n }\n\n // Convert glob to regex\n let regex = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i]!;\n switch (c) {\n case \"*\":\n regex += \".*\";\n break;\n case \"?\":\n regex += \".\";\n break;\n case \"[\": {\n // Find closing bracket\n let j = i + 1;\n // Handle negation\n if (pattern[j] === \"!\" || pattern[j] === \"^\") j++;\n // Handle ] as first char in class\n if (pattern[j] === \"]\") j++;\n while (j < pattern.length && pattern[j] !== \"]\") j++;\n if (j >= pattern.length) {\n // No closing bracket, treat [ as literal\n regex += \"\\\\[\";\n } else {\n let charClass = pattern.slice(i, j + 1);\n // Convert ! to ^ for negation in regex\n charClass = charClass.replace(/^\\[!/, \"[^\");\n regex += charClass;\n i = j;\n }\n break;\n }\n case \".\":\n case \"^\":\n case \"$\":\n case \"+\":\n case \"{\":\n case \"}\":\n case \"(\":\n case \")\":\n case \"|\":\n case \"\\\\\":\n regex += \"\\\\\" + c;\n break;\n default:\n regex += c;\n }\n }\n regex += \"$\";\n\n try {\n return new RegExp(regex).test(str);\n } catch {\n return false;\n }\n}\n\
|
|
5
|
+
"import type { Command } from \"../../types.cjs\";\n\n/**\n * Simple glob pattern matching (fnmatch-style)\n * Supports: * (any chars), ? (single char), [...] (character class)\n */\nfunction matchGlob(pattern: string, str: string, caseInsensitive = false): boolean {\n if (caseInsensitive) {\n pattern = pattern.toLowerCase();\n str = str.toLowerCase();\n }\n\n // Convert glob to regex\n let regex = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i]!;\n switch (c) {\n case \"*\":\n regex += \".*\";\n break;\n case \"?\":\n regex += \".\";\n break;\n case \"[\": {\n // Find closing bracket\n let j = i + 1;\n // Handle negation\n if (pattern[j] === \"!\" || pattern[j] === \"^\") j++;\n // Handle ] as first char in class\n if (pattern[j] === \"]\") j++;\n while (j < pattern.length && pattern[j] !== \"]\") j++;\n if (j >= pattern.length) {\n // No closing bracket, treat [ as literal\n regex += \"\\\\[\";\n } else {\n let charClass = pattern.slice(i, j + 1);\n // Convert ! to ^ for negation in regex\n charClass = charClass.replace(/^\\[!/, \"[^\");\n regex += charClass;\n i = j;\n }\n break;\n }\n case \".\":\n case \"^\":\n case \"$\":\n case \"+\":\n case \"{\":\n case \"}\":\n case \"(\":\n case \")\":\n case \"|\":\n case \"\\\\\":\n regex += \"\\\\\" + c;\n break;\n default:\n regex += c;\n }\n }\n regex += \"$\";\n\n try {\n return new RegExp(regex).test(str);\n } catch {\n return false;\n }\n}\n\n// Expression tree types\ntype FindExpr =\n | { type: \"name\"; pattern: string; ignoreCase: boolean }\n | { type: \"ftype\"; value: \"f\" | \"d\" }\n | { type: \"and\"; left: FindExpr; right: FindExpr }\n | { type: \"or\"; left: FindExpr; right: FindExpr }\n | { type: \"not\"; expr: FindExpr }\n | { type: \"true\" };\n\nfunction evalExpr(expr: FindExpr, basename: string, isFile: boolean, isDir: boolean): boolean {\n switch (expr.type) {\n case \"true\":\n return true;\n case \"name\":\n return matchGlob(expr.pattern, basename, expr.ignoreCase);\n case \"ftype\":\n return expr.value === \"f\" ? isFile : isDir;\n case \"and\":\n return evalExpr(expr.left, basename, isFile, isDir) && evalExpr(expr.right, basename, isFile, isDir);\n case \"or\":\n return evalExpr(expr.left, basename, isFile, isDir) || evalExpr(expr.right, basename, isFile, isDir);\n case \"not\":\n return !evalExpr(expr.expr, basename, isFile, isDir);\n }\n}\n\nclass ParseError extends Error {\n constructor(msg: string) {\n super(msg);\n }\n}\n\nfunction parseExprArgs(args: string[]): FindExpr {\n if (args.length === 0) return { type: \"true\" };\n\n let pos = 0;\n\n function peek(): string | undefined {\n return args[pos];\n }\n\n function advance(): string {\n return args[pos++]!;\n }\n\n function parseOr(): FindExpr {\n let left = parseAnd();\n while (peek() === \"-o\") {\n advance();\n const right = parseAnd();\n left = { type: \"or\", left, right };\n }\n return left;\n }\n\n function parseAnd(): FindExpr {\n let left = parseUnary();\n while (pos < args.length) {\n const next = peek();\n if (next === \"-o\" || next === \")\" || next === undefined) break;\n if (next === \"-a\") {\n advance();\n }\n const right = parseUnary();\n left = { type: \"and\", left, right };\n }\n return left;\n }\n\n function parseUnary(): FindExpr {\n const next = peek();\n if (next === \"!\" || next === \"-not\") {\n advance();\n const expr = parseUnary();\n return { type: \"not\", expr };\n }\n return parsePrimary();\n }\n\n function parsePrimary(): FindExpr {\n const tok = peek();\n if (tok === undefined) {\n throw new ParseError(\"find: expected expression\");\n }\n\n if (tok === \"(\") {\n advance();\n const expr = parseOr();\n if (peek() !== \")\") {\n throw new ParseError(\"find: missing closing ')'\");\n }\n advance();\n return expr;\n }\n\n if (tok === \"-name\" || tok === \"-iname\") {\n advance();\n const pattern = peek();\n if (pattern === undefined) {\n throw new ParseError(`find: missing argument to '${tok}'`);\n }\n advance();\n return { type: \"name\", pattern, ignoreCase: tok === \"-iname\" };\n }\n\n if (tok === \"-type\") {\n advance();\n const val = peek();\n if (val === undefined) {\n throw new ParseError(\"find: missing argument to '-type'\");\n }\n if (val !== \"f\" && val !== \"d\") {\n throw new ParseError(`find: Unknown argument to -type: ${val}`);\n }\n advance();\n return { type: \"ftype\", value: val };\n }\n\n throw new ParseError(`find: unknown predicate '${tok}'`);\n }\n\n const expr = parseOr();\n if (pos < args.length) {\n throw new ParseError(`find: unexpected '${args[pos]}'`);\n }\n return expr;\n}\n\nexport const find: Command = async (ctx) => {\n const args = [...ctx.args];\n const paths: string[] = [];\n\n // Parse arguments: paths come before first flag/operator\n let i = 0;\n\n // Collect paths (args before first -, !, or ()\n while (i < args.length && !args[i]!.startsWith(\"-\") && args[i] !== \"!\" && args[i] !== \"(\" && args[i] !== \")\") {\n paths.push(args[i]!);\n i++;\n }\n\n // Default to current directory if no paths\n if (paths.length === 0) {\n paths.push(\".\");\n }\n\n // Extract global options (-maxdepth, -mindepth) from remaining args\n let maxDepth: number | undefined;\n let minDepth: number | undefined;\n const exprArgs: string[] = [];\n\n let j = i;\n while (j < args.length) {\n const arg = args[j]!;\n if (arg === \"-maxdepth\") {\n j++;\n if (j >= args.length) {\n await ctx.stderr.writeText(\"find: missing argument to '-maxdepth'\\n\");\n return 1;\n }\n const depth = parseInt(args[j]!, 10);\n if (isNaN(depth) || depth < 0) {\n await ctx.stderr.writeText(`find: Invalid argument '${args[j]}' to -maxdepth\\n`);\n return 1;\n }\n maxDepth = depth;\n } else if (arg === \"-mindepth\") {\n j++;\n if (j >= args.length) {\n await ctx.stderr.writeText(\"find: missing argument to '-mindepth'\\n\");\n return 1;\n }\n const depth = parseInt(args[j]!, 10);\n if (isNaN(depth) || depth < 0) {\n await ctx.stderr.writeText(`find: Invalid argument '${args[j]}' to -mindepth\\n`);\n return 1;\n }\n minDepth = depth;\n } else {\n exprArgs.push(arg);\n }\n j++;\n }\n\n // Parse expression tree\n let expr: FindExpr;\n try {\n expr = parseExprArgs(exprArgs);\n } catch (e) {\n if (e instanceof ParseError) {\n await ctx.stderr.writeText(e.message + \"\\n\");\n return 1;\n }\n throw e;\n }\n\n let hasError = false;\n\n // Process each starting path\n for (const startPath of paths) {\n const normalizedPath = startPath === \"/\" ? \"/\" : startPath.replace(/\\/+$/, '');\n const resolvedStart = ctx.fs.resolve(ctx.cwd, startPath);\n\n // Check if path exists\n let stat;\n try {\n stat = await ctx.fs.stat(resolvedStart);\n } catch {\n await ctx.stderr.writeText(`find: '${startPath}': No such file or directory\\n`);\n hasError = true;\n continue;\n }\n\n // Recursive traversal function\n async function traverse(path: string, displayPath: string, depth: number): Promise<void> {\n // Check maxdepth\n if (maxDepth !== undefined && depth > maxDepth) {\n return;\n }\n\n let entryStat;\n try {\n entryStat = await ctx.fs.stat(path);\n } catch {\n return;\n }\n\n const isDir = entryStat.isDirectory();\n const isFile = entryStat.isFile();\n const basename = ctx.fs.basename(path);\n\n // Check if this entry matches the expression\n const matches = evalExpr(expr, basename, isFile, isDir);\n\n // Output if matches and above mindepth\n if (matches && (minDepth === undefined || depth >= minDepth)) {\n await ctx.stdout.writeText(displayPath + \"\\n\");\n }\n\n // Recurse into directories\n if (isDir) {\n try {\n const entries = await ctx.fs.readdir(path);\n entries.sort();\n for (const entry of entries) {\n const childPath = ctx.fs.resolve(path, entry);\n const childDisplayPath = displayPath === \".\" ? entry : `${displayPath}/${entry}`;\n await traverse(childPath, childDisplayPath, depth + 1);\n }\n } catch {\n // Ignore errors reading directory contents\n }\n }\n }\n\n // Start traversal\n if (stat.isFile()) {\n const basename = ctx.fs.basename(resolvedStart);\n const matches = evalExpr(expr, basename, true, false);\n\n if (maxDepth !== undefined && maxDepth < 0) {\n // skip\n } else if (matches && (minDepth === undefined || minDepth <= 0)) {\n await ctx.stdout.writeText(normalizedPath + \"\\n\");\n }\n } else {\n await traverse(resolvedStart, normalizedPath, 0);\n }\n }\n\n return hasError ? 1 : 0;\n};\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,SAAS,SAAS,CAAC,SAAiB,KAAa,kBAAkB,OAAgB;AAAA,EACjF,IAAI,iBAAiB;AAAA,IACnB,UAAU,QAAQ,YAAY;AAAA,IAC9B,MAAM,IAAI,YAAY;AAAA,EACxB;AAAA,EAGA,IAAI,QAAQ;AAAA,EACZ,SAAS,IAAI,EAAG,IAAI,QAAQ,QAAQ,KAAK;AAAA,IACvC,MAAM,IAAI,QAAQ;AAAA,IAClB,QAAQ;AAAA,WACD;AAAA,QACH,SAAS;AAAA,QACT;AAAA,WACG;AAAA,QACH,SAAS;AAAA,QACT;AAAA,WACG,KAAK;AAAA,QAER,IAAI,IAAI,IAAI;AAAA,QAEZ,IAAI,QAAQ,OAAO,OAAO,QAAQ,OAAO;AAAA,UAAK;AAAA,QAE9C,IAAI,QAAQ,OAAO;AAAA,UAAK;AAAA,QACxB,OAAO,IAAI,QAAQ,UAAU,QAAQ,OAAO;AAAA,UAAK;AAAA,QACjD,IAAI,KAAK,QAAQ,QAAQ;AAAA,UAEvB,SAAS;AAAA,QACX,EAAO;AAAA,UACL,IAAI,YAAY,QAAQ,MAAM,GAAG,IAAI,CAAC;AAAA,UAEtC,YAAY,UAAU,QAAQ,QAAQ,IAAI;AAAA,UAC1C,SAAS;AAAA,UACT,IAAI;AAAA;AAAA,QAEN;AAAA,MACF;AAAA,WACK;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,QACH,SAAS,OAAO;AAAA,QAChB;AAAA;AAAA,QAEA,SAAS;AAAA;AAAA,EAEf;AAAA,EACA,SAAS;AAAA,EAET,IAAI;AAAA,IACF,OAAO,IAAI,OAAO,KAAK,EAAE,KAAK,GAAG;AAAA,IACjC,MAAM;AAAA,IACN,OAAO;AAAA;AAAA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "80CE5607A2F2B89F64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -38,11 +38,12 @@ var spec = {
|
|
|
38
38
|
flags: [
|
|
39
39
|
{ short: "a", long: "all" },
|
|
40
40
|
{ short: "l" },
|
|
41
|
-
{ short: "1" }
|
|
41
|
+
{ short: "1" },
|
|
42
|
+
{ short: "R" }
|
|
42
43
|
],
|
|
43
|
-
usage: "ls [-
|
|
44
|
+
usage: "ls [-alR1] [file ...]"
|
|
44
45
|
};
|
|
45
|
-
var defaults = { all: false, long: false, onePerLine: false };
|
|
46
|
+
var defaults = { all: false, long: false, onePerLine: false, recursive: false };
|
|
46
47
|
var handler = (flags, flag) => {
|
|
47
48
|
if (flag.short === "a")
|
|
48
49
|
flags.all = true;
|
|
@@ -50,6 +51,8 @@ var handler = (flags, flag) => {
|
|
|
50
51
|
flags.long = true;
|
|
51
52
|
if (flag.short === "1")
|
|
52
53
|
flags.onePerLine = true;
|
|
54
|
+
if (flag.short === "R")
|
|
55
|
+
flags.recursive = true;
|
|
53
56
|
};
|
|
54
57
|
var parser = import_flag_parser.createFlagParser(spec, defaults, handler);
|
|
55
58
|
var ls = async (ctx) => {
|
|
@@ -58,8 +61,63 @@ var ls = async (ctx) => {
|
|
|
58
61
|
await parser.writeError(result.error, ctx.stderr);
|
|
59
62
|
return 1;
|
|
60
63
|
}
|
|
61
|
-
const { all: showAll, long: longFormat, onePerLine } = result.flags;
|
|
64
|
+
const { all: showAll, long: longFormat, onePerLine, recursive } = result.flags;
|
|
62
65
|
const paths = result.args.length === 0 ? ["."] : result.args;
|
|
66
|
+
let needsBlankLine = false;
|
|
67
|
+
const listDir = async (dirPath, displayPath, showHeader) => {
|
|
68
|
+
if (needsBlankLine)
|
|
69
|
+
await ctx.stdout.writeText(`
|
|
70
|
+
`);
|
|
71
|
+
needsBlankLine = true;
|
|
72
|
+
if (showHeader) {
|
|
73
|
+
await ctx.stdout.writeText(`${displayPath}:
|
|
74
|
+
`);
|
|
75
|
+
}
|
|
76
|
+
let entries = await ctx.fs.readdir(dirPath);
|
|
77
|
+
if (!showAll) {
|
|
78
|
+
entries = entries.filter((e) => !e.startsWith("."));
|
|
79
|
+
}
|
|
80
|
+
entries.sort();
|
|
81
|
+
if (longFormat) {
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
const entryPath = ctx.fs.resolve(dirPath, entry);
|
|
84
|
+
try {
|
|
85
|
+
const entryStat = await ctx.fs.stat(entryPath);
|
|
86
|
+
const type = entryStat.isDirectory() ? "d" : "-";
|
|
87
|
+
const perms = "rwxr-xr-x";
|
|
88
|
+
const size = String(entryStat.size).padStart(8);
|
|
89
|
+
const date = entryStat.mtime.toISOString().slice(0, 10);
|
|
90
|
+
await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}
|
|
91
|
+
`);
|
|
92
|
+
} catch {
|
|
93
|
+
await ctx.stdout.writeText(`?????????? ${entry}
|
|
94
|
+
`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} else if (onePerLine) {
|
|
98
|
+
for (const entry of entries) {
|
|
99
|
+
await ctx.stdout.writeText(entry + `
|
|
100
|
+
`);
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
if (entries.length > 0) {
|
|
104
|
+
await ctx.stdout.writeText(entries.join(" ") + `
|
|
105
|
+
`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (recursive) {
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
const entryPath = ctx.fs.resolve(dirPath, entry);
|
|
111
|
+
try {
|
|
112
|
+
const entryStat = await ctx.fs.stat(entryPath);
|
|
113
|
+
if (entryStat.isDirectory()) {
|
|
114
|
+
const subDisplay = displayPath === "." ? entry : `${displayPath}/${entry}`;
|
|
115
|
+
await listDir(entryPath, subDisplay, true);
|
|
116
|
+
}
|
|
117
|
+
} catch {}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
63
121
|
for (let i = 0;i < paths.length; i++) {
|
|
64
122
|
const pathArg = paths[i];
|
|
65
123
|
const path = ctx.fs.resolve(ctx.cwd, pathArg);
|
|
@@ -70,43 +128,8 @@ var ls = async (ctx) => {
|
|
|
70
128
|
`);
|
|
71
129
|
continue;
|
|
72
130
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
await ctx.stdout.writeText(`
|
|
76
|
-
`);
|
|
77
|
-
await ctx.stdout.writeText(`${pathArg}:
|
|
78
|
-
`);
|
|
79
|
-
}
|
|
80
|
-
let entries = await ctx.fs.readdir(path);
|
|
81
|
-
if (!showAll) {
|
|
82
|
-
entries = entries.filter((e) => !e.startsWith("."));
|
|
83
|
-
}
|
|
84
|
-
entries.sort();
|
|
85
|
-
if (longFormat) {
|
|
86
|
-
for (const entry of entries) {
|
|
87
|
-
const entryPath = ctx.fs.resolve(path, entry);
|
|
88
|
-
try {
|
|
89
|
-
const entryStat = await ctx.fs.stat(entryPath);
|
|
90
|
-
const type = entryStat.isDirectory() ? "d" : "-";
|
|
91
|
-
const perms = "rwxr-xr-x";
|
|
92
|
-
const size = String(entryStat.size).padStart(8);
|
|
93
|
-
const date = entryStat.mtime.toISOString().slice(0, 10);
|
|
94
|
-
await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}
|
|
95
|
-
`);
|
|
96
|
-
} catch {
|
|
97
|
-
await ctx.stdout.writeText(`?????????? ${entry}
|
|
98
|
-
`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
} else if (onePerLine) {
|
|
102
|
-
for (const entry of entries) {
|
|
103
|
-
await ctx.stdout.writeText(entry + `
|
|
104
|
-
`);
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
await ctx.stdout.writeText(entries.join(" ") + `
|
|
108
|
-
`);
|
|
109
|
-
}
|
|
131
|
+
const showHeader = recursive || paths.length > 1;
|
|
132
|
+
await listDir(path, pathArg, showHeader);
|
|
110
133
|
} catch (err) {
|
|
111
134
|
await ctx.stderr.writeText(`ls: cannot access '${pathArg}': No such file or directory
|
|
112
135
|
`);
|
|
@@ -116,4 +139,4 @@ var ls = async (ctx) => {
|
|
|
116
139
|
return 0;
|
|
117
140
|
};
|
|
118
141
|
|
|
119
|
-
//# debugId=
|
|
142
|
+
//# debugId=5A080C64ADFFC97C64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/commands/ls/ls.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { Command } from \"../../types.cjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.cjs\";\n\ninterface LsFlags {\n all: boolean;\n long: boolean;\n onePerLine: boolean;\n}\n\nconst spec = {\n name: \"ls\",\n flags: [\n { short: \"a\", long: \"all\" },\n { short: \"l\" },\n { short: \"1\" },\n ] as FlagDefinition[],\n usage: \"ls [-
|
|
5
|
+
"import type { Command } from \"../../types.cjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.cjs\";\n\ninterface LsFlags {\n all: boolean;\n long: boolean;\n onePerLine: boolean;\n recursive: boolean;\n}\n\nconst spec = {\n name: \"ls\",\n flags: [\n { short: \"a\", long: \"all\" },\n { short: \"l\" },\n { short: \"1\" },\n { short: \"R\" },\n ] as FlagDefinition[],\n usage: \"ls [-alR1] [file ...]\",\n};\n\nconst defaults: LsFlags = { all: false, long: false, onePerLine: false, recursive: false };\n\nconst handler = (flags: LsFlags, flag: FlagDefinition) => {\n if (flag.short === \"a\") flags.all = true;\n if (flag.short === \"l\") flags.long = true;\n if (flag.short === \"1\") flags.onePerLine = true;\n if (flag.short === \"R\") flags.recursive = true;\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const ls: Command = async (ctx) => {\n const result = parser.parse(ctx.args);\n\n if (result.error) {\n await parser.writeError(result.error, ctx.stderr);\n return 1;\n }\n\n const { all: showAll, long: longFormat, onePerLine, recursive } = result.flags;\n const paths = result.args.length === 0 ? [\".\"] : result.args;\n let needsBlankLine = false;\n\n const listDir = async (dirPath: string, displayPath: string, showHeader: boolean) => {\n if (needsBlankLine) await ctx.stdout.writeText(\"\\n\");\n needsBlankLine = true;\n\n if (showHeader) {\n await ctx.stdout.writeText(`${displayPath}:\\n`);\n }\n\n let entries = await ctx.fs.readdir(dirPath);\n\n if (!showAll) {\n entries = entries.filter((e) => !e.startsWith(\".\"));\n }\n\n entries.sort();\n\n if (longFormat) {\n for (const entry of entries) {\n const entryPath = ctx.fs.resolve(dirPath, entry);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n const type = entryStat.isDirectory() ? \"d\" : \"-\";\n const perms = \"rwxr-xr-x\";\n const size = String(entryStat.size).padStart(8);\n const date = entryStat.mtime.toISOString().slice(0, 10);\n await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}\\n`);\n } catch {\n await ctx.stdout.writeText(`?????????? ${entry}\\n`);\n }\n }\n } else if (onePerLine) {\n for (const entry of entries) {\n await ctx.stdout.writeText(entry + \"\\n\");\n }\n } else {\n if (entries.length > 0) {\n await ctx.stdout.writeText(entries.join(\" \") + \"\\n\");\n }\n }\n\n if (recursive) {\n for (const entry of entries) {\n const entryPath = ctx.fs.resolve(dirPath, entry);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n if (entryStat.isDirectory()) {\n const subDisplay = displayPath === \".\" ? entry : `${displayPath}/${entry}`;\n await listDir(entryPath, subDisplay, true);\n }\n } catch {\n // skip entries we can't stat\n }\n }\n }\n };\n\n for (let i = 0; i < paths.length; i++) {\n const pathArg = paths[i]!;\n const path = ctx.fs.resolve(ctx.cwd, pathArg);\n\n try {\n const stat = await ctx.fs.stat(path);\n\n if (stat.isFile()) {\n await ctx.stdout.writeText(ctx.fs.basename(path) + \"\\n\");\n continue;\n }\n\n const showHeader = recursive || paths.length > 1;\n await listDir(path, pathArg, showHeader);\n } catch (err) {\n await ctx.stderr.writeText(`ls: cannot access '${pathArg}': No such file or directory\\n`);\n return 1;\n }\n }\n\n return 0;\n};\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACsD,IAAtD;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "5A080C64ADFFC97C64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/mjs/package.json
CHANGED
|
@@ -55,88 +55,173 @@ function matchGlob(pattern, str, caseInsensitive = false) {
|
|
|
55
55
|
return false;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
function evalExpr(expr, basename, isFile, isDir) {
|
|
59
|
+
switch (expr.type) {
|
|
60
|
+
case "true":
|
|
61
|
+
return true;
|
|
62
|
+
case "name":
|
|
63
|
+
return matchGlob(expr.pattern, basename, expr.ignoreCase);
|
|
64
|
+
case "ftype":
|
|
65
|
+
return expr.value === "f" ? isFile : isDir;
|
|
66
|
+
case "and":
|
|
67
|
+
return evalExpr(expr.left, basename, isFile, isDir) && evalExpr(expr.right, basename, isFile, isDir);
|
|
68
|
+
case "or":
|
|
69
|
+
return evalExpr(expr.left, basename, isFile, isDir) || evalExpr(expr.right, basename, isFile, isDir);
|
|
70
|
+
case "not":
|
|
71
|
+
return !evalExpr(expr.expr, basename, isFile, isDir);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
class ParseError extends Error {
|
|
76
|
+
constructor(msg) {
|
|
77
|
+
super(msg);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function parseExprArgs(args) {
|
|
81
|
+
if (args.length === 0)
|
|
82
|
+
return { type: "true" };
|
|
83
|
+
let pos = 0;
|
|
84
|
+
function peek() {
|
|
85
|
+
return args[pos];
|
|
86
|
+
}
|
|
87
|
+
function advance() {
|
|
88
|
+
return args[pos++];
|
|
89
|
+
}
|
|
90
|
+
function parseOr() {
|
|
91
|
+
let left = parseAnd();
|
|
92
|
+
while (peek() === "-o") {
|
|
93
|
+
advance();
|
|
94
|
+
const right = parseAnd();
|
|
95
|
+
left = { type: "or", left, right };
|
|
96
|
+
}
|
|
97
|
+
return left;
|
|
98
|
+
}
|
|
99
|
+
function parseAnd() {
|
|
100
|
+
let left = parseUnary();
|
|
101
|
+
while (pos < args.length) {
|
|
102
|
+
const next = peek();
|
|
103
|
+
if (next === "-o" || next === ")" || next === undefined)
|
|
104
|
+
break;
|
|
105
|
+
if (next === "-a") {
|
|
106
|
+
advance();
|
|
107
|
+
}
|
|
108
|
+
const right = parseUnary();
|
|
109
|
+
left = { type: "and", left, right };
|
|
110
|
+
}
|
|
111
|
+
return left;
|
|
112
|
+
}
|
|
113
|
+
function parseUnary() {
|
|
114
|
+
const next = peek();
|
|
115
|
+
if (next === "!" || next === "-not") {
|
|
116
|
+
advance();
|
|
117
|
+
const expr2 = parseUnary();
|
|
118
|
+
return { type: "not", expr: expr2 };
|
|
119
|
+
}
|
|
120
|
+
return parsePrimary();
|
|
121
|
+
}
|
|
122
|
+
function parsePrimary() {
|
|
123
|
+
const tok = peek();
|
|
124
|
+
if (tok === undefined) {
|
|
125
|
+
throw new ParseError("find: expected expression");
|
|
126
|
+
}
|
|
127
|
+
if (tok === "(") {
|
|
128
|
+
advance();
|
|
129
|
+
const expr2 = parseOr();
|
|
130
|
+
if (peek() !== ")") {
|
|
131
|
+
throw new ParseError("find: missing closing ')'");
|
|
132
|
+
}
|
|
133
|
+
advance();
|
|
134
|
+
return expr2;
|
|
135
|
+
}
|
|
136
|
+
if (tok === "-name" || tok === "-iname") {
|
|
137
|
+
advance();
|
|
138
|
+
const pattern = peek();
|
|
139
|
+
if (pattern === undefined) {
|
|
140
|
+
throw new ParseError(`find: missing argument to '${tok}'`);
|
|
141
|
+
}
|
|
142
|
+
advance();
|
|
143
|
+
return { type: "name", pattern, ignoreCase: tok === "-iname" };
|
|
144
|
+
}
|
|
145
|
+
if (tok === "-type") {
|
|
146
|
+
advance();
|
|
147
|
+
const val = peek();
|
|
148
|
+
if (val === undefined) {
|
|
149
|
+
throw new ParseError("find: missing argument to '-type'");
|
|
150
|
+
}
|
|
151
|
+
if (val !== "f" && val !== "d") {
|
|
152
|
+
throw new ParseError(`find: Unknown argument to -type: ${val}`);
|
|
153
|
+
}
|
|
154
|
+
advance();
|
|
155
|
+
return { type: "ftype", value: val };
|
|
156
|
+
}
|
|
157
|
+
throw new ParseError(`find: unknown predicate '${tok}'`);
|
|
158
|
+
}
|
|
159
|
+
const expr = parseOr();
|
|
160
|
+
if (pos < args.length) {
|
|
161
|
+
throw new ParseError(`find: unexpected '${args[pos]}'`);
|
|
162
|
+
}
|
|
163
|
+
return expr;
|
|
164
|
+
}
|
|
58
165
|
var find = async (ctx) => {
|
|
59
166
|
const args = [...ctx.args];
|
|
60
167
|
const paths = [];
|
|
61
|
-
const options = {};
|
|
62
168
|
let i = 0;
|
|
63
|
-
while (i < args.length && !args[i].startsWith("-")) {
|
|
169
|
+
while (i < args.length && !args[i].startsWith("-") && args[i] !== "!" && args[i] !== "(" && args[i] !== ")") {
|
|
64
170
|
paths.push(args[i]);
|
|
65
171
|
i++;
|
|
66
172
|
}
|
|
67
173
|
if (paths.length === 0) {
|
|
68
174
|
paths.push(".");
|
|
69
175
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
options.namePattern = args[i];
|
|
80
|
-
options.nameIgnoreCase = false;
|
|
81
|
-
} else if (arg === "-iname") {
|
|
82
|
-
i++;
|
|
83
|
-
if (i >= args.length) {
|
|
84
|
-
await ctx.stderr.writeText(`find: missing argument to '-iname'
|
|
85
|
-
`);
|
|
86
|
-
return 1;
|
|
87
|
-
}
|
|
88
|
-
options.namePattern = args[i];
|
|
89
|
-
options.nameIgnoreCase = true;
|
|
90
|
-
} else if (arg === "-type") {
|
|
91
|
-
i++;
|
|
92
|
-
if (i >= args.length) {
|
|
93
|
-
await ctx.stderr.writeText(`find: missing argument to '-type'
|
|
94
|
-
`);
|
|
95
|
-
return 1;
|
|
96
|
-
}
|
|
97
|
-
const typeArg = args[i];
|
|
98
|
-
if (typeArg !== "f" && typeArg !== "d") {
|
|
99
|
-
await ctx.stderr.writeText(`find: Unknown argument to -type: ${typeArg}
|
|
100
|
-
`);
|
|
101
|
-
return 1;
|
|
102
|
-
}
|
|
103
|
-
options.type = typeArg;
|
|
104
|
-
} else if (arg === "-maxdepth") {
|
|
105
|
-
i++;
|
|
106
|
-
if (i >= args.length) {
|
|
176
|
+
let maxDepth;
|
|
177
|
+
let minDepth;
|
|
178
|
+
const exprArgs = [];
|
|
179
|
+
let j = i;
|
|
180
|
+
while (j < args.length) {
|
|
181
|
+
const arg = args[j];
|
|
182
|
+
if (arg === "-maxdepth") {
|
|
183
|
+
j++;
|
|
184
|
+
if (j >= args.length) {
|
|
107
185
|
await ctx.stderr.writeText(`find: missing argument to '-maxdepth'
|
|
108
186
|
`);
|
|
109
187
|
return 1;
|
|
110
188
|
}
|
|
111
|
-
const depth = parseInt(args[
|
|
189
|
+
const depth = parseInt(args[j], 10);
|
|
112
190
|
if (isNaN(depth) || depth < 0) {
|
|
113
|
-
await ctx.stderr.writeText(`find: Invalid argument '${args[
|
|
191
|
+
await ctx.stderr.writeText(`find: Invalid argument '${args[j]}' to -maxdepth
|
|
114
192
|
`);
|
|
115
193
|
return 1;
|
|
116
194
|
}
|
|
117
|
-
|
|
195
|
+
maxDepth = depth;
|
|
118
196
|
} else if (arg === "-mindepth") {
|
|
119
|
-
|
|
120
|
-
if (
|
|
197
|
+
j++;
|
|
198
|
+
if (j >= args.length) {
|
|
121
199
|
await ctx.stderr.writeText(`find: missing argument to '-mindepth'
|
|
122
200
|
`);
|
|
123
201
|
return 1;
|
|
124
202
|
}
|
|
125
|
-
const depth = parseInt(args[
|
|
203
|
+
const depth = parseInt(args[j], 10);
|
|
126
204
|
if (isNaN(depth) || depth < 0) {
|
|
127
|
-
await ctx.stderr.writeText(`find: Invalid argument '${args[
|
|
205
|
+
await ctx.stderr.writeText(`find: Invalid argument '${args[j]}' to -mindepth
|
|
128
206
|
`);
|
|
129
207
|
return 1;
|
|
130
208
|
}
|
|
131
|
-
|
|
132
|
-
} else
|
|
133
|
-
|
|
209
|
+
minDepth = depth;
|
|
210
|
+
} else {
|
|
211
|
+
exprArgs.push(arg);
|
|
212
|
+
}
|
|
213
|
+
j++;
|
|
214
|
+
}
|
|
215
|
+
let expr;
|
|
216
|
+
try {
|
|
217
|
+
expr = parseExprArgs(exprArgs);
|
|
218
|
+
} catch (e) {
|
|
219
|
+
if (e instanceof ParseError) {
|
|
220
|
+
await ctx.stderr.writeText(e.message + `
|
|
134
221
|
`);
|
|
135
222
|
return 1;
|
|
136
|
-
} else {
|
|
137
|
-
paths.push(arg);
|
|
138
223
|
}
|
|
139
|
-
|
|
224
|
+
throw e;
|
|
140
225
|
}
|
|
141
226
|
let hasError = false;
|
|
142
227
|
for (const startPath of paths) {
|
|
@@ -152,7 +237,7 @@ var find = async (ctx) => {
|
|
|
152
237
|
continue;
|
|
153
238
|
}
|
|
154
239
|
async function traverse(path, displayPath, depth) {
|
|
155
|
-
if (
|
|
240
|
+
if (maxDepth !== undefined && depth > maxDepth) {
|
|
156
241
|
return;
|
|
157
242
|
}
|
|
158
243
|
let entryStat;
|
|
@@ -164,18 +249,8 @@ var find = async (ctx) => {
|
|
|
164
249
|
const isDir = entryStat.isDirectory();
|
|
165
250
|
const isFile = entryStat.isFile();
|
|
166
251
|
const basename = ctx.fs.basename(path);
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
matches = false;
|
|
170
|
-
} else if (options.type === "d" && !isDir) {
|
|
171
|
-
matches = false;
|
|
172
|
-
}
|
|
173
|
-
if (matches && options.namePattern !== undefined) {
|
|
174
|
-
if (!matchGlob(options.namePattern, basename, options.nameIgnoreCase)) {
|
|
175
|
-
matches = false;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (matches && (options.minDepth === undefined || depth >= options.minDepth)) {
|
|
252
|
+
const matches = evalExpr(expr, basename, isFile, isDir);
|
|
253
|
+
if (matches && (minDepth === undefined || depth >= minDepth)) {
|
|
179
254
|
await ctx.stdout.writeText(displayPath + `
|
|
180
255
|
`);
|
|
181
256
|
}
|
|
@@ -192,20 +267,9 @@ var find = async (ctx) => {
|
|
|
192
267
|
}
|
|
193
268
|
}
|
|
194
269
|
if (stat.isFile()) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
if (matches && options.namePattern !== undefined) {
|
|
200
|
-
const basename = ctx.fs.basename(resolvedStart);
|
|
201
|
-
if (!matchGlob(options.namePattern, basename, options.nameIgnoreCase)) {
|
|
202
|
-
matches = false;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (options.maxDepth !== undefined && options.maxDepth < 0) {
|
|
206
|
-
matches = false;
|
|
207
|
-
}
|
|
208
|
-
if (matches && (options.minDepth === undefined || options.minDepth <= 0)) {
|
|
270
|
+
const basename = ctx.fs.basename(resolvedStart);
|
|
271
|
+
const matches = evalExpr(expr, basename, true, false);
|
|
272
|
+
if (maxDepth !== undefined && maxDepth < 0) {} else if (matches && (minDepth === undefined || minDepth <= 0)) {
|
|
209
273
|
await ctx.stdout.writeText(normalizedPath + `
|
|
210
274
|
`);
|
|
211
275
|
}
|
|
@@ -219,4 +283,4 @@ export {
|
|
|
219
283
|
find
|
|
220
284
|
};
|
|
221
285
|
|
|
222
|
-
//# debugId=
|
|
286
|
+
//# debugId=5D73614E490180B964756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/commands/find/find.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { Command } from \"../../types.mjs\";\n\n/**\n * Simple glob pattern matching (fnmatch-style)\n * Supports: * (any chars), ? (single char), [...] (character class)\n */\nfunction matchGlob(pattern: string, str: string, caseInsensitive = false): boolean {\n if (caseInsensitive) {\n pattern = pattern.toLowerCase();\n str = str.toLowerCase();\n }\n\n // Convert glob to regex\n let regex = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i]!;\n switch (c) {\n case \"*\":\n regex += \".*\";\n break;\n case \"?\":\n regex += \".\";\n break;\n case \"[\": {\n // Find closing bracket\n let j = i + 1;\n // Handle negation\n if (pattern[j] === \"!\" || pattern[j] === \"^\") j++;\n // Handle ] as first char in class\n if (pattern[j] === \"]\") j++;\n while (j < pattern.length && pattern[j] !== \"]\") j++;\n if (j >= pattern.length) {\n // No closing bracket, treat [ as literal\n regex += \"\\\\[\";\n } else {\n let charClass = pattern.slice(i, j + 1);\n // Convert ! to ^ for negation in regex\n charClass = charClass.replace(/^\\[!/, \"[^\");\n regex += charClass;\n i = j;\n }\n break;\n }\n case \".\":\n case \"^\":\n case \"$\":\n case \"+\":\n case \"{\":\n case \"}\":\n case \"(\":\n case \")\":\n case \"|\":\n case \"\\\\\":\n regex += \"\\\\\" + c;\n break;\n default:\n regex += c;\n }\n }\n regex += \"$\";\n\n try {\n return new RegExp(regex).test(str);\n } catch {\n return false;\n }\n}\n\
|
|
5
|
+
"import type { Command } from \"../../types.mjs\";\n\n/**\n * Simple glob pattern matching (fnmatch-style)\n * Supports: * (any chars), ? (single char), [...] (character class)\n */\nfunction matchGlob(pattern: string, str: string, caseInsensitive = false): boolean {\n if (caseInsensitive) {\n pattern = pattern.toLowerCase();\n str = str.toLowerCase();\n }\n\n // Convert glob to regex\n let regex = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i]!;\n switch (c) {\n case \"*\":\n regex += \".*\";\n break;\n case \"?\":\n regex += \".\";\n break;\n case \"[\": {\n // Find closing bracket\n let j = i + 1;\n // Handle negation\n if (pattern[j] === \"!\" || pattern[j] === \"^\") j++;\n // Handle ] as first char in class\n if (pattern[j] === \"]\") j++;\n while (j < pattern.length && pattern[j] !== \"]\") j++;\n if (j >= pattern.length) {\n // No closing bracket, treat [ as literal\n regex += \"\\\\[\";\n } else {\n let charClass = pattern.slice(i, j + 1);\n // Convert ! to ^ for negation in regex\n charClass = charClass.replace(/^\\[!/, \"[^\");\n regex += charClass;\n i = j;\n }\n break;\n }\n case \".\":\n case \"^\":\n case \"$\":\n case \"+\":\n case \"{\":\n case \"}\":\n case \"(\":\n case \")\":\n case \"|\":\n case \"\\\\\":\n regex += \"\\\\\" + c;\n break;\n default:\n regex += c;\n }\n }\n regex += \"$\";\n\n try {\n return new RegExp(regex).test(str);\n } catch {\n return false;\n }\n}\n\n// Expression tree types\ntype FindExpr =\n | { type: \"name\"; pattern: string; ignoreCase: boolean }\n | { type: \"ftype\"; value: \"f\" | \"d\" }\n | { type: \"and\"; left: FindExpr; right: FindExpr }\n | { type: \"or\"; left: FindExpr; right: FindExpr }\n | { type: \"not\"; expr: FindExpr }\n | { type: \"true\" };\n\nfunction evalExpr(expr: FindExpr, basename: string, isFile: boolean, isDir: boolean): boolean {\n switch (expr.type) {\n case \"true\":\n return true;\n case \"name\":\n return matchGlob(expr.pattern, basename, expr.ignoreCase);\n case \"ftype\":\n return expr.value === \"f\" ? isFile : isDir;\n case \"and\":\n return evalExpr(expr.left, basename, isFile, isDir) && evalExpr(expr.right, basename, isFile, isDir);\n case \"or\":\n return evalExpr(expr.left, basename, isFile, isDir) || evalExpr(expr.right, basename, isFile, isDir);\n case \"not\":\n return !evalExpr(expr.expr, basename, isFile, isDir);\n }\n}\n\nclass ParseError extends Error {\n constructor(msg: string) {\n super(msg);\n }\n}\n\nfunction parseExprArgs(args: string[]): FindExpr {\n if (args.length === 0) return { type: \"true\" };\n\n let pos = 0;\n\n function peek(): string | undefined {\n return args[pos];\n }\n\n function advance(): string {\n return args[pos++]!;\n }\n\n function parseOr(): FindExpr {\n let left = parseAnd();\n while (peek() === \"-o\") {\n advance();\n const right = parseAnd();\n left = { type: \"or\", left, right };\n }\n return left;\n }\n\n function parseAnd(): FindExpr {\n let left = parseUnary();\n while (pos < args.length) {\n const next = peek();\n if (next === \"-o\" || next === \")\" || next === undefined) break;\n if (next === \"-a\") {\n advance();\n }\n const right = parseUnary();\n left = { type: \"and\", left, right };\n }\n return left;\n }\n\n function parseUnary(): FindExpr {\n const next = peek();\n if (next === \"!\" || next === \"-not\") {\n advance();\n const expr = parseUnary();\n return { type: \"not\", expr };\n }\n return parsePrimary();\n }\n\n function parsePrimary(): FindExpr {\n const tok = peek();\n if (tok === undefined) {\n throw new ParseError(\"find: expected expression\");\n }\n\n if (tok === \"(\") {\n advance();\n const expr = parseOr();\n if (peek() !== \")\") {\n throw new ParseError(\"find: missing closing ')'\");\n }\n advance();\n return expr;\n }\n\n if (tok === \"-name\" || tok === \"-iname\") {\n advance();\n const pattern = peek();\n if (pattern === undefined) {\n throw new ParseError(`find: missing argument to '${tok}'`);\n }\n advance();\n return { type: \"name\", pattern, ignoreCase: tok === \"-iname\" };\n }\n\n if (tok === \"-type\") {\n advance();\n const val = peek();\n if (val === undefined) {\n throw new ParseError(\"find: missing argument to '-type'\");\n }\n if (val !== \"f\" && val !== \"d\") {\n throw new ParseError(`find: Unknown argument to -type: ${val}`);\n }\n advance();\n return { type: \"ftype\", value: val };\n }\n\n throw new ParseError(`find: unknown predicate '${tok}'`);\n }\n\n const expr = parseOr();\n if (pos < args.length) {\n throw new ParseError(`find: unexpected '${args[pos]}'`);\n }\n return expr;\n}\n\nexport const find: Command = async (ctx) => {\n const args = [...ctx.args];\n const paths: string[] = [];\n\n // Parse arguments: paths come before first flag/operator\n let i = 0;\n\n // Collect paths (args before first -, !, or ()\n while (i < args.length && !args[i]!.startsWith(\"-\") && args[i] !== \"!\" && args[i] !== \"(\" && args[i] !== \")\") {\n paths.push(args[i]!);\n i++;\n }\n\n // Default to current directory if no paths\n if (paths.length === 0) {\n paths.push(\".\");\n }\n\n // Extract global options (-maxdepth, -mindepth) from remaining args\n let maxDepth: number | undefined;\n let minDepth: number | undefined;\n const exprArgs: string[] = [];\n\n let j = i;\n while (j < args.length) {\n const arg = args[j]!;\n if (arg === \"-maxdepth\") {\n j++;\n if (j >= args.length) {\n await ctx.stderr.writeText(\"find: missing argument to '-maxdepth'\\n\");\n return 1;\n }\n const depth = parseInt(args[j]!, 10);\n if (isNaN(depth) || depth < 0) {\n await ctx.stderr.writeText(`find: Invalid argument '${args[j]}' to -maxdepth\\n`);\n return 1;\n }\n maxDepth = depth;\n } else if (arg === \"-mindepth\") {\n j++;\n if (j >= args.length) {\n await ctx.stderr.writeText(\"find: missing argument to '-mindepth'\\n\");\n return 1;\n }\n const depth = parseInt(args[j]!, 10);\n if (isNaN(depth) || depth < 0) {\n await ctx.stderr.writeText(`find: Invalid argument '${args[j]}' to -mindepth\\n`);\n return 1;\n }\n minDepth = depth;\n } else {\n exprArgs.push(arg);\n }\n j++;\n }\n\n // Parse expression tree\n let expr: FindExpr;\n try {\n expr = parseExprArgs(exprArgs);\n } catch (e) {\n if (e instanceof ParseError) {\n await ctx.stderr.writeText(e.message + \"\\n\");\n return 1;\n }\n throw e;\n }\n\n let hasError = false;\n\n // Process each starting path\n for (const startPath of paths) {\n const normalizedPath = startPath === \"/\" ? \"/\" : startPath.replace(/\\/+$/, '');\n const resolvedStart = ctx.fs.resolve(ctx.cwd, startPath);\n\n // Check if path exists\n let stat;\n try {\n stat = await ctx.fs.stat(resolvedStart);\n } catch {\n await ctx.stderr.writeText(`find: '${startPath}': No such file or directory\\n`);\n hasError = true;\n continue;\n }\n\n // Recursive traversal function\n async function traverse(path: string, displayPath: string, depth: number): Promise<void> {\n // Check maxdepth\n if (maxDepth !== undefined && depth > maxDepth) {\n return;\n }\n\n let entryStat;\n try {\n entryStat = await ctx.fs.stat(path);\n } catch {\n return;\n }\n\n const isDir = entryStat.isDirectory();\n const isFile = entryStat.isFile();\n const basename = ctx.fs.basename(path);\n\n // Check if this entry matches the expression\n const matches = evalExpr(expr, basename, isFile, isDir);\n\n // Output if matches and above mindepth\n if (matches && (minDepth === undefined || depth >= minDepth)) {\n await ctx.stdout.writeText(displayPath + \"\\n\");\n }\n\n // Recurse into directories\n if (isDir) {\n try {\n const entries = await ctx.fs.readdir(path);\n entries.sort();\n for (const entry of entries) {\n const childPath = ctx.fs.resolve(path, entry);\n const childDisplayPath = displayPath === \".\" ? entry : `${displayPath}/${entry}`;\n await traverse(childPath, childDisplayPath, depth + 1);\n }\n } catch {\n // Ignore errors reading directory contents\n }\n }\n }\n\n // Start traversal\n if (stat.isFile()) {\n const basename = ctx.fs.basename(resolvedStart);\n const matches = evalExpr(expr, basename, true, false);\n\n if (maxDepth !== undefined && maxDepth < 0) {\n // skip\n } else if (matches && (minDepth === undefined || minDepth <= 0)) {\n await ctx.stdout.writeText(normalizedPath + \"\\n\");\n }\n } else {\n await traverse(resolvedStart, normalizedPath, 0);\n }\n }\n\n return hasError ? 1 : 0;\n};\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AAMA,SAAS,SAAS,CAAC,SAAiB,KAAa,kBAAkB,OAAgB;AAAA,EACjF,IAAI,iBAAiB;AAAA,IACnB,UAAU,QAAQ,YAAY;AAAA,IAC9B,MAAM,IAAI,YAAY;AAAA,EACxB;AAAA,EAGA,IAAI,QAAQ;AAAA,EACZ,SAAS,IAAI,EAAG,IAAI,QAAQ,QAAQ,KAAK;AAAA,IACvC,MAAM,IAAI,QAAQ;AAAA,IAClB,QAAQ;AAAA,WACD;AAAA,QACH,SAAS;AAAA,QACT;AAAA,WACG;AAAA,QACH,SAAS;AAAA,QACT;AAAA,WACG,KAAK;AAAA,QAER,IAAI,IAAI,IAAI;AAAA,QAEZ,IAAI,QAAQ,OAAO,OAAO,QAAQ,OAAO;AAAA,UAAK;AAAA,QAE9C,IAAI,QAAQ,OAAO;AAAA,UAAK;AAAA,QACxB,OAAO,IAAI,QAAQ,UAAU,QAAQ,OAAO;AAAA,UAAK;AAAA,QACjD,IAAI,KAAK,QAAQ,QAAQ;AAAA,UAEvB,SAAS;AAAA,QACX,EAAO;AAAA,UACL,IAAI,YAAY,QAAQ,MAAM,GAAG,IAAI,CAAC;AAAA,UAEtC,YAAY,UAAU,QAAQ,QAAQ,IAAI;AAAA,UAC1C,SAAS;AAAA,UACT,IAAI;AAAA;AAAA,QAEN;AAAA,MACF;AAAA,WACK;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,QACH,SAAS,OAAO;AAAA,QAChB;AAAA;AAAA,QAEA,SAAS;AAAA;AAAA,EAEf;AAAA,EACA,SAAS;AAAA,EAET,IAAI;AAAA,IACF,OAAO,IAAI,OAAO,KAAK,EAAE,KAAK,GAAG;AAAA,IACjC,MAAM;AAAA,IACN,OAAO;AAAA;AAAA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "5D73614E490180B964756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -5,11 +5,12 @@ var spec = {
|
|
|
5
5
|
flags: [
|
|
6
6
|
{ short: "a", long: "all" },
|
|
7
7
|
{ short: "l" },
|
|
8
|
-
{ short: "1" }
|
|
8
|
+
{ short: "1" },
|
|
9
|
+
{ short: "R" }
|
|
9
10
|
],
|
|
10
|
-
usage: "ls [-
|
|
11
|
+
usage: "ls [-alR1] [file ...]"
|
|
11
12
|
};
|
|
12
|
-
var defaults = { all: false, long: false, onePerLine: false };
|
|
13
|
+
var defaults = { all: false, long: false, onePerLine: false, recursive: false };
|
|
13
14
|
var handler = (flags, flag) => {
|
|
14
15
|
if (flag.short === "a")
|
|
15
16
|
flags.all = true;
|
|
@@ -17,6 +18,8 @@ var handler = (flags, flag) => {
|
|
|
17
18
|
flags.long = true;
|
|
18
19
|
if (flag.short === "1")
|
|
19
20
|
flags.onePerLine = true;
|
|
21
|
+
if (flag.short === "R")
|
|
22
|
+
flags.recursive = true;
|
|
20
23
|
};
|
|
21
24
|
var parser = createFlagParser(spec, defaults, handler);
|
|
22
25
|
var ls = async (ctx) => {
|
|
@@ -25,8 +28,63 @@ var ls = async (ctx) => {
|
|
|
25
28
|
await parser.writeError(result.error, ctx.stderr);
|
|
26
29
|
return 1;
|
|
27
30
|
}
|
|
28
|
-
const { all: showAll, long: longFormat, onePerLine } = result.flags;
|
|
31
|
+
const { all: showAll, long: longFormat, onePerLine, recursive } = result.flags;
|
|
29
32
|
const paths = result.args.length === 0 ? ["."] : result.args;
|
|
33
|
+
let needsBlankLine = false;
|
|
34
|
+
const listDir = async (dirPath, displayPath, showHeader) => {
|
|
35
|
+
if (needsBlankLine)
|
|
36
|
+
await ctx.stdout.writeText(`
|
|
37
|
+
`);
|
|
38
|
+
needsBlankLine = true;
|
|
39
|
+
if (showHeader) {
|
|
40
|
+
await ctx.stdout.writeText(`${displayPath}:
|
|
41
|
+
`);
|
|
42
|
+
}
|
|
43
|
+
let entries = await ctx.fs.readdir(dirPath);
|
|
44
|
+
if (!showAll) {
|
|
45
|
+
entries = entries.filter((e) => !e.startsWith("."));
|
|
46
|
+
}
|
|
47
|
+
entries.sort();
|
|
48
|
+
if (longFormat) {
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
const entryPath = ctx.fs.resolve(dirPath, entry);
|
|
51
|
+
try {
|
|
52
|
+
const entryStat = await ctx.fs.stat(entryPath);
|
|
53
|
+
const type = entryStat.isDirectory() ? "d" : "-";
|
|
54
|
+
const perms = "rwxr-xr-x";
|
|
55
|
+
const size = String(entryStat.size).padStart(8);
|
|
56
|
+
const date = entryStat.mtime.toISOString().slice(0, 10);
|
|
57
|
+
await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}
|
|
58
|
+
`);
|
|
59
|
+
} catch {
|
|
60
|
+
await ctx.stdout.writeText(`?????????? ${entry}
|
|
61
|
+
`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} else if (onePerLine) {
|
|
65
|
+
for (const entry of entries) {
|
|
66
|
+
await ctx.stdout.writeText(entry + `
|
|
67
|
+
`);
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
if (entries.length > 0) {
|
|
71
|
+
await ctx.stdout.writeText(entries.join(" ") + `
|
|
72
|
+
`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (recursive) {
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
const entryPath = ctx.fs.resolve(dirPath, entry);
|
|
78
|
+
try {
|
|
79
|
+
const entryStat = await ctx.fs.stat(entryPath);
|
|
80
|
+
if (entryStat.isDirectory()) {
|
|
81
|
+
const subDisplay = displayPath === "." ? entry : `${displayPath}/${entry}`;
|
|
82
|
+
await listDir(entryPath, subDisplay, true);
|
|
83
|
+
}
|
|
84
|
+
} catch {}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
30
88
|
for (let i = 0;i < paths.length; i++) {
|
|
31
89
|
const pathArg = paths[i];
|
|
32
90
|
const path = ctx.fs.resolve(ctx.cwd, pathArg);
|
|
@@ -37,43 +95,8 @@ var ls = async (ctx) => {
|
|
|
37
95
|
`);
|
|
38
96
|
continue;
|
|
39
97
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
await ctx.stdout.writeText(`
|
|
43
|
-
`);
|
|
44
|
-
await ctx.stdout.writeText(`${pathArg}:
|
|
45
|
-
`);
|
|
46
|
-
}
|
|
47
|
-
let entries = await ctx.fs.readdir(path);
|
|
48
|
-
if (!showAll) {
|
|
49
|
-
entries = entries.filter((e) => !e.startsWith("."));
|
|
50
|
-
}
|
|
51
|
-
entries.sort();
|
|
52
|
-
if (longFormat) {
|
|
53
|
-
for (const entry of entries) {
|
|
54
|
-
const entryPath = ctx.fs.resolve(path, entry);
|
|
55
|
-
try {
|
|
56
|
-
const entryStat = await ctx.fs.stat(entryPath);
|
|
57
|
-
const type = entryStat.isDirectory() ? "d" : "-";
|
|
58
|
-
const perms = "rwxr-xr-x";
|
|
59
|
-
const size = String(entryStat.size).padStart(8);
|
|
60
|
-
const date = entryStat.mtime.toISOString().slice(0, 10);
|
|
61
|
-
await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}
|
|
62
|
-
`);
|
|
63
|
-
} catch {
|
|
64
|
-
await ctx.stdout.writeText(`?????????? ${entry}
|
|
65
|
-
`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
} else if (onePerLine) {
|
|
69
|
-
for (const entry of entries) {
|
|
70
|
-
await ctx.stdout.writeText(entry + `
|
|
71
|
-
`);
|
|
72
|
-
}
|
|
73
|
-
} else {
|
|
74
|
-
await ctx.stdout.writeText(entries.join(" ") + `
|
|
75
|
-
`);
|
|
76
|
-
}
|
|
98
|
+
const showHeader = recursive || paths.length > 1;
|
|
99
|
+
await listDir(path, pathArg, showHeader);
|
|
77
100
|
} catch (err) {
|
|
78
101
|
await ctx.stderr.writeText(`ls: cannot access '${pathArg}': No such file or directory
|
|
79
102
|
`);
|
|
@@ -86,4 +109,4 @@ export {
|
|
|
86
109
|
ls
|
|
87
110
|
};
|
|
88
111
|
|
|
89
|
-
//# debugId=
|
|
112
|
+
//# debugId=C0BF60626A0B8D0564756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/commands/ls/ls.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { Command } from \"../../types.mjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.mjs\";\n\ninterface LsFlags {\n all: boolean;\n long: boolean;\n onePerLine: boolean;\n}\n\nconst spec = {\n name: \"ls\",\n flags: [\n { short: \"a\", long: \"all\" },\n { short: \"l\" },\n { short: \"1\" },\n ] as FlagDefinition[],\n usage: \"ls [-
|
|
5
|
+
"import type { Command } from \"../../types.mjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.mjs\";\n\ninterface LsFlags {\n all: boolean;\n long: boolean;\n onePerLine: boolean;\n recursive: boolean;\n}\n\nconst spec = {\n name: \"ls\",\n flags: [\n { short: \"a\", long: \"all\" },\n { short: \"l\" },\n { short: \"1\" },\n { short: \"R\" },\n ] as FlagDefinition[],\n usage: \"ls [-alR1] [file ...]\",\n};\n\nconst defaults: LsFlags = { all: false, long: false, onePerLine: false, recursive: false };\n\nconst handler = (flags: LsFlags, flag: FlagDefinition) => {\n if (flag.short === \"a\") flags.all = true;\n if (flag.short === \"l\") flags.long = true;\n if (flag.short === \"1\") flags.onePerLine = true;\n if (flag.short === \"R\") flags.recursive = true;\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const ls: Command = async (ctx) => {\n const result = parser.parse(ctx.args);\n\n if (result.error) {\n await parser.writeError(result.error, ctx.stderr);\n return 1;\n }\n\n const { all: showAll, long: longFormat, onePerLine, recursive } = result.flags;\n const paths = result.args.length === 0 ? [\".\"] : result.args;\n let needsBlankLine = false;\n\n const listDir = async (dirPath: string, displayPath: string, showHeader: boolean) => {\n if (needsBlankLine) await ctx.stdout.writeText(\"\\n\");\n needsBlankLine = true;\n\n if (showHeader) {\n await ctx.stdout.writeText(`${displayPath}:\\n`);\n }\n\n let entries = await ctx.fs.readdir(dirPath);\n\n if (!showAll) {\n entries = entries.filter((e) => !e.startsWith(\".\"));\n }\n\n entries.sort();\n\n if (longFormat) {\n for (const entry of entries) {\n const entryPath = ctx.fs.resolve(dirPath, entry);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n const type = entryStat.isDirectory() ? \"d\" : \"-\";\n const perms = \"rwxr-xr-x\";\n const size = String(entryStat.size).padStart(8);\n const date = entryStat.mtime.toISOString().slice(0, 10);\n await ctx.stdout.writeText(`${type}${perms} ${size} ${date} ${entry}\\n`);\n } catch {\n await ctx.stdout.writeText(`?????????? ${entry}\\n`);\n }\n }\n } else if (onePerLine) {\n for (const entry of entries) {\n await ctx.stdout.writeText(entry + \"\\n\");\n }\n } else {\n if (entries.length > 0) {\n await ctx.stdout.writeText(entries.join(\" \") + \"\\n\");\n }\n }\n\n if (recursive) {\n for (const entry of entries) {\n const entryPath = ctx.fs.resolve(dirPath, entry);\n try {\n const entryStat = await ctx.fs.stat(entryPath);\n if (entryStat.isDirectory()) {\n const subDisplay = displayPath === \".\" ? entry : `${displayPath}/${entry}`;\n await listDir(entryPath, subDisplay, true);\n }\n } catch {\n // skip entries we can't stat\n }\n }\n }\n };\n\n for (let i = 0; i < paths.length; i++) {\n const pathArg = paths[i]!;\n const path = ctx.fs.resolve(ctx.cwd, pathArg);\n\n try {\n const stat = await ctx.fs.stat(path);\n\n if (stat.isFile()) {\n await ctx.stdout.writeText(ctx.fs.basename(path) + \"\\n\");\n continue;\n }\n\n const showHeader = recursive || paths.length > 1;\n await listDir(path, pathArg, showHeader);\n } catch (err) {\n await ctx.stderr.writeText(`ls: cannot access '${pathArg}': No such file or directory\\n`);\n return 1;\n }\n }\n\n return 0;\n};\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AACA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "C0BF60626A0B8D0564756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/package.json
CHANGED