shell-dsl 0.0.8 → 0.0.10

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.
Files changed (89) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/commands/awk/awk.cjs +79 -32
  3. package/dist/cjs/src/commands/awk/awk.cjs.map +3 -3
  4. package/dist/cjs/src/commands/cat/cat.cjs +16 -3
  5. package/dist/cjs/src/commands/cat/cat.cjs.map +3 -3
  6. package/dist/cjs/src/commands/cp/cp.cjs +26 -20
  7. package/dist/cjs/src/commands/cp/cp.cjs.map +3 -3
  8. package/dist/cjs/src/commands/echo/echo.cjs +22 -7
  9. package/dist/cjs/src/commands/echo/echo.cjs.map +3 -3
  10. package/dist/cjs/src/commands/grep/grep.cjs +126 -140
  11. package/dist/cjs/src/commands/grep/grep.cjs.map +3 -3
  12. package/dist/cjs/src/commands/head/head.cjs +29 -14
  13. package/dist/cjs/src/commands/head/head.cjs.map +3 -3
  14. package/dist/cjs/src/commands/ls/ls.cjs +27 -27
  15. package/dist/cjs/src/commands/ls/ls.cjs.map +3 -3
  16. package/dist/cjs/src/commands/mkdir/mkdir.cjs +21 -10
  17. package/dist/cjs/src/commands/mkdir/mkdir.cjs.map +3 -3
  18. package/dist/cjs/src/commands/mv/mv.cjs +22 -15
  19. package/dist/cjs/src/commands/mv/mv.cjs.map +3 -3
  20. package/dist/cjs/src/commands/pwd/pwd.cjs +13 -1
  21. package/dist/cjs/src/commands/pwd/pwd.cjs.map +3 -3
  22. package/dist/cjs/src/commands/rm/rm.cjs +25 -22
  23. package/dist/cjs/src/commands/rm/rm.cjs.map +3 -3
  24. package/dist/cjs/src/commands/sed/sed.cjs +157 -18
  25. package/dist/cjs/src/commands/sed/sed.cjs.map +3 -3
  26. package/dist/cjs/src/commands/sort/sort.cjs +27 -24
  27. package/dist/cjs/src/commands/sort/sort.cjs.map +3 -3
  28. package/dist/cjs/src/commands/tail/tail.cjs +29 -14
  29. package/dist/cjs/src/commands/tail/tail.cjs.map +3 -3
  30. package/dist/cjs/src/commands/tee/tee.cjs +21 -10
  31. package/dist/cjs/src/commands/tee/tee.cjs.map +3 -3
  32. package/dist/cjs/src/commands/touch/touch.cjs +21 -10
  33. package/dist/cjs/src/commands/touch/touch.cjs.map +3 -3
  34. package/dist/cjs/src/commands/tree/tree.cjs +45 -48
  35. package/dist/cjs/src/commands/tree/tree.cjs.map +3 -3
  36. package/dist/cjs/src/commands/uniq/uniq.cjs +27 -24
  37. package/dist/cjs/src/commands/uniq/uniq.cjs.map +3 -3
  38. package/dist/cjs/src/commands/wc/wc.cjs +28 -24
  39. package/dist/cjs/src/commands/wc/wc.cjs.map +3 -3
  40. package/dist/cjs/src/utils/flag-parser.cjs +162 -0
  41. package/dist/cjs/src/utils/flag-parser.cjs.map +10 -0
  42. package/dist/cjs/src/utils/index.cjs +4 -2
  43. package/dist/cjs/src/utils/index.cjs.map +3 -3
  44. package/dist/mjs/package.json +1 -1
  45. package/dist/mjs/src/commands/awk/awk.mjs +79 -32
  46. package/dist/mjs/src/commands/awk/awk.mjs.map +3 -3
  47. package/dist/mjs/src/commands/cat/cat.mjs +16 -3
  48. package/dist/mjs/src/commands/cat/cat.mjs.map +3 -3
  49. package/dist/mjs/src/commands/cp/cp.mjs +26 -20
  50. package/dist/mjs/src/commands/cp/cp.mjs.map +3 -3
  51. package/dist/mjs/src/commands/echo/echo.mjs +22 -7
  52. package/dist/mjs/src/commands/echo/echo.mjs.map +3 -3
  53. package/dist/mjs/src/commands/grep/grep.mjs +126 -140
  54. package/dist/mjs/src/commands/grep/grep.mjs.map +3 -3
  55. package/dist/mjs/src/commands/head/head.mjs +29 -14
  56. package/dist/mjs/src/commands/head/head.mjs.map +3 -3
  57. package/dist/mjs/src/commands/ls/ls.mjs +27 -27
  58. package/dist/mjs/src/commands/ls/ls.mjs.map +3 -3
  59. package/dist/mjs/src/commands/mkdir/mkdir.mjs +21 -10
  60. package/dist/mjs/src/commands/mkdir/mkdir.mjs.map +3 -3
  61. package/dist/mjs/src/commands/mv/mv.mjs +22 -15
  62. package/dist/mjs/src/commands/mv/mv.mjs.map +3 -3
  63. package/dist/mjs/src/commands/pwd/pwd.mjs +13 -1
  64. package/dist/mjs/src/commands/pwd/pwd.mjs.map +3 -3
  65. package/dist/mjs/src/commands/rm/rm.mjs +25 -22
  66. package/dist/mjs/src/commands/rm/rm.mjs.map +3 -3
  67. package/dist/mjs/src/commands/sed/sed.mjs +157 -18
  68. package/dist/mjs/src/commands/sed/sed.mjs.map +3 -3
  69. package/dist/mjs/src/commands/sort/sort.mjs +27 -24
  70. package/dist/mjs/src/commands/sort/sort.mjs.map +3 -3
  71. package/dist/mjs/src/commands/tail/tail.mjs +29 -14
  72. package/dist/mjs/src/commands/tail/tail.mjs.map +3 -3
  73. package/dist/mjs/src/commands/tee/tee.mjs +21 -10
  74. package/dist/mjs/src/commands/tee/tee.mjs.map +3 -3
  75. package/dist/mjs/src/commands/touch/touch.mjs +21 -10
  76. package/dist/mjs/src/commands/touch/touch.mjs.map +3 -3
  77. package/dist/mjs/src/commands/tree/tree.mjs +45 -48
  78. package/dist/mjs/src/commands/tree/tree.mjs.map +3 -3
  79. package/dist/mjs/src/commands/uniq/uniq.mjs +27 -24
  80. package/dist/mjs/src/commands/uniq/uniq.mjs.map +3 -3
  81. package/dist/mjs/src/commands/wc/wc.mjs +28 -24
  82. package/dist/mjs/src/commands/wc/wc.mjs.map +3 -3
  83. package/dist/mjs/src/utils/flag-parser.mjs +132 -0
  84. package/dist/mjs/src/utils/flag-parser.mjs.map +10 -0
  85. package/dist/mjs/src/utils/index.mjs +6 -2
  86. package/dist/mjs/src/utils/index.mjs.map +3 -3
  87. package/dist/types/src/utils/flag-parser.d.ts +36 -0
  88. package/dist/types/src/utils/index.d.ts +1 -0
  89. package/package.json +1 -1
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/commands/awk/awk.ts"],
4
4
  "sourcesContent": [
5
- "import type { Command } from \"../../types.mjs\";\n\ninterface AwkRule {\n pattern?: RegExp;\n action: string;\n}\n\ninterface AwkOptions {\n fieldSeparator: RegExp;\n program: AwkRule[];\n}\n\nfunction parseProgram(programStr: string): AwkRule[] {\n const rules: AwkRule[] = [];\n const trimmed = programStr.trim();\n\n // Simple parser for patterns like: /regex/ {action} or {action}\n // Handle multiple rules separated by whitespace/newlines\n\n let remaining = trimmed;\n\n while (remaining.length > 0) {\n remaining = remaining.trim();\n if (remaining.length === 0) break;\n\n let pattern: RegExp | undefined;\n let action = \"\";\n\n // Check for /pattern/ prefix\n if (remaining.startsWith(\"/\")) {\n const endSlash = remaining.indexOf(\"/\", 1);\n if (endSlash > 1) {\n const patternStr = remaining.slice(1, endSlash);\n try {\n pattern = new RegExp(patternStr);\n } catch {\n // Invalid regex, skip\n }\n remaining = remaining.slice(endSlash + 1).trim();\n }\n }\n\n // Check for {action} block\n if (remaining.startsWith(\"{\")) {\n let braceCount = 1;\n let i = 1;\n while (i < remaining.length && braceCount > 0) {\n if (remaining[i] === \"{\") braceCount++;\n else if (remaining[i] === \"}\") braceCount--;\n i++;\n }\n action = remaining.slice(1, i - 1).trim();\n remaining = remaining.slice(i).trim();\n } else if (pattern) {\n // Pattern without action - default action is print\n action = \"print\";\n } else {\n // No pattern and no action block, might be malformed\n break;\n }\n\n if (action || pattern) {\n rules.push({ pattern, action: action || \"print\" });\n }\n }\n\n return rules;\n}\n\nfunction parseArgs(args: string[]): { options: AwkOptions; files: string[] } {\n const options: AwkOptions = {\n fieldSeparator: /[ \\t]+/,\n program: [],\n };\n const files: string[] = [];\n\n let i = 0;\n let programFound = false;\n\n while (i < args.length) {\n const arg = args[i]!;\n\n if (arg === \"-F\" && args[i + 1] !== undefined) {\n const fs = args[i + 1]!;\n // For single character separators, match exactly\n // For patterns, use as regex\n if (fs.length === 1) {\n options.fieldSeparator = new RegExp(escapeRegex(fs));\n } else {\n try {\n options.fieldSeparator = new RegExp(fs);\n } catch {\n options.fieldSeparator = new RegExp(escapeRegex(fs));\n }\n }\n i += 2;\n continue;\n }\n\n // -Ffs format (no space)\n if (arg.startsWith(\"-F\") && arg.length > 2) {\n const fs = arg.slice(2);\n if (fs.length === 1) {\n options.fieldSeparator = new RegExp(escapeRegex(fs));\n } else {\n try {\n options.fieldSeparator = new RegExp(fs);\n } catch {\n options.fieldSeparator = new RegExp(escapeRegex(fs));\n }\n }\n i++;\n continue;\n }\n\n // Non-flag argument\n if (!arg.startsWith(\"-\")) {\n if (!programFound) {\n options.program = parseProgram(arg);\n programFound = true;\n } else {\n files.push(arg);\n }\n }\n i++;\n }\n\n return { options, files };\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction splitFields(line: string, separator: RegExp): string[] {\n // Split and filter empty strings for whitespace separation\n const parts = line.split(separator);\n // For whitespace separator, filter leading empty string\n if (separator.source === \"[ \\\\t]+\" && parts[0] === \"\") {\n parts.shift();\n }\n return parts;\n}\n\nfunction executeAction(\n action: string,\n fields: string[],\n line: string,\n lineNumber: number\n): string | null {\n // Parse and execute the action\n // Supported: print, print $0, print $1, print $1, $2, etc.\n\n const trimmedAction = action.trim();\n\n if (trimmedAction === \"\" || trimmedAction === \"print\" || trimmedAction === \"print $0\") {\n return line;\n }\n\n // Check for print with field references\n if (trimmedAction.startsWith(\"print\")) {\n const printArgs = trimmedAction.slice(5).trim();\n return evaluatePrintArgs(printArgs, fields, line, lineNumber);\n }\n\n // Just field reference without print (implicit print)\n if (trimmedAction.startsWith(\"$\")) {\n return evaluatePrintArgs(trimmedAction, fields, line, lineNumber);\n }\n\n return null;\n}\n\nfunction evaluatePrintArgs(\n argsStr: string,\n fields: string[],\n line: string,\n lineNumber: number\n): string {\n const results: string[] = [];\n\n // Split by comma for multiple arguments\n const args = argsStr.split(\",\").map((a) => a.trim());\n\n for (const arg of args) {\n const value = evaluateExpression(arg, fields, line, lineNumber);\n results.push(value);\n }\n\n return results.join(\" \");\n}\n\nfunction tokenizeExpression(expr: string): string[] {\n const tokens: string[] = [];\n let i = 0;\n const str = expr.trim();\n\n while (i < str.length) {\n // Skip whitespace\n while (i < str.length && /\\s/.test(str[i]!)) {\n i++;\n }\n if (i >= str.length) break;\n\n // String literal\n if (str[i] === '\"' || str[i] === \"'\") {\n const quote = str[i]!;\n let j = i + 1;\n while (j < str.length && str[j] !== quote) {\n j++;\n }\n tokens.push(str.slice(i, j + 1));\n i = j + 1;\n }\n // Field reference or variable\n else if (str[i] === '$' || /[a-zA-Z]/.test(str[i]!)) {\n let j = i;\n while (j < str.length && /[\\w$]/.test(str[j]!)) {\n j++;\n }\n tokens.push(str.slice(i, j));\n i = j;\n }\n // Other characters\n else {\n tokens.push(str[i]!);\n i++;\n }\n }\n\n return tokens;\n}\n\nfunction evaluateExpression(\n expr: string,\n fields: string[],\n line: string,\n lineNumber: number\n): string {\n const tokens = tokenizeExpression(expr);\n\n if (tokens.length === 0) {\n return \"\";\n }\n\n // Evaluate each token and concatenate\n const parts: string[] = [];\n for (const token of tokens) {\n // String literal\n if ((token.startsWith('\"') && token.endsWith('\"')) ||\n (token.startsWith(\"'\") && token.endsWith(\"'\"))) {\n parts.push(token.slice(1, -1));\n }\n // Field reference $0, $1, etc.\n else if (token.match(/^\\$(\\d+)$/)) {\n const fieldNum = parseInt(token.slice(1), 10);\n if (fieldNum === 0) {\n parts.push(line);\n } else {\n parts.push(fields[fieldNum - 1] ?? \"\");\n }\n }\n // Built-in variables\n else if (token === \"NF\") {\n parts.push(String(fields.length));\n }\n else if (token === \"NR\") {\n parts.push(String(lineNumber));\n }\n // Unknown - return as-is\n else {\n parts.push(token);\n }\n }\n\n return parts.join(\"\");\n}\n\nfunction processLine(\n line: string,\n lineNumber: number,\n options: AwkOptions\n): string[] {\n const fields = splitFields(line, options.fieldSeparator);\n const outputs: string[] = [];\n\n for (const rule of options.program) {\n // Check pattern match\n if (rule.pattern && !rule.pattern.test(line)) {\n continue;\n }\n\n const result = executeAction(rule.action, fields, line, lineNumber);\n if (result !== null) {\n outputs.push(result);\n }\n }\n\n return outputs;\n}\n\nexport const awk: Command = async (ctx) => {\n const { options, files } = parseArgs(ctx.args);\n\n if (options.program.length === 0) {\n await ctx.stderr.writeText(\"awk: missing program\\n\");\n return 1;\n }\n\n let lineNumber = 0;\n\n const processContent = async (content: string): Promise<void> => {\n const lines = content.split(\"\\n\");\n // Handle trailing newline\n if (lines.length > 0 && lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n\n for (const line of lines) {\n lineNumber++;\n const outputs = processLine(line, lineNumber, options);\n for (const output of outputs) {\n await ctx.stdout.writeText(output + \"\\n\");\n }\n }\n };\n\n if (files.length === 0) {\n // Read from stdin\n const content = await ctx.stdin.text();\n await processContent(content);\n } else {\n // Read from files\n for (const file of files) {\n try {\n const path = ctx.fs.resolve(ctx.cwd, file);\n const content = await ctx.fs.readFile(path);\n await processContent(content.toString());\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.stderr.writeText(`awk: ${file}: ${message}\\n`);\n return 1;\n }\n }\n }\n\n return 0;\n};\n"
5
+ "import type { Command } from \"../../types.mjs\";\n\ninterface AwkRule {\n pattern?: RegExp;\n action: string;\n}\n\ninterface AwkOptions {\n fieldSeparator: RegExp;\n program: AwkRule[];\n}\n\ninterface ParseArgsResult {\n options: AwkOptions;\n files: string[];\n error?: { type: \"unrecognized_option\" | \"missing_value\"; option: string };\n}\n\nfunction parseProgram(programStr: string): AwkRule[] {\n const rules: AwkRule[] = [];\n const trimmed = programStr.trim();\n\n // Simple parser for patterns like: /regex/ {action} or {action}\n // Handle multiple rules separated by whitespace/newlines\n\n let remaining = trimmed;\n\n while (remaining.length > 0) {\n remaining = remaining.trim();\n if (remaining.length === 0) break;\n\n let pattern: RegExp | undefined;\n let action = \"\";\n\n // Check for /pattern/ prefix\n if (remaining.startsWith(\"/\")) {\n const endSlash = remaining.indexOf(\"/\", 1);\n if (endSlash > 1) {\n const patternStr = remaining.slice(1, endSlash);\n try {\n pattern = new RegExp(patternStr);\n } catch {\n // Invalid regex, skip\n }\n remaining = remaining.slice(endSlash + 1).trim();\n }\n }\n\n // Check for {action} block\n if (remaining.startsWith(\"{\")) {\n let braceCount = 1;\n let i = 1;\n while (i < remaining.length && braceCount > 0) {\n if (remaining[i] === \"{\") braceCount++;\n else if (remaining[i] === \"}\") braceCount--;\n i++;\n }\n action = remaining.slice(1, i - 1).trim();\n remaining = remaining.slice(i).trim();\n } else if (pattern) {\n // Pattern without action - default action is print\n action = \"print\";\n } else {\n // No pattern and no action block, might be malformed\n break;\n }\n\n if (action || pattern) {\n rules.push({ pattern, action: action || \"print\" });\n }\n }\n\n return rules;\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction parseArgs(args: string[]): ParseArgsResult {\n const options: AwkOptions = {\n fieldSeparator: /[ \\t]+/,\n program: [],\n };\n const files: string[] = [];\n\n let i = 0;\n let programFound = false;\n\n while (i < args.length) {\n const arg = args[i]!;\n\n // Handle -- to stop flag parsing\n if (arg === \"--\") {\n i++;\n while (i < args.length) {\n const remaining = args[i]!;\n if (!programFound) {\n options.program = parseProgram(remaining);\n programFound = true;\n } else {\n files.push(remaining);\n }\n i++;\n }\n break;\n }\n\n // Long flag handling\n if (arg.startsWith(\"--\")) {\n return {\n options,\n files,\n error: { type: \"unrecognized_option\", option: arg },\n };\n }\n\n // Short flag handling\n if (arg.startsWith(\"-\") && arg.length > 1) {\n const char = arg[1]!;\n\n if (char === \"F\") {\n // -F takes a field separator argument\n const restOfArg = arg.slice(2);\n let fs: string;\n\n if (restOfArg.length > 0) {\n fs = restOfArg;\n } else if (i + 1 < args.length) {\n fs = args[++i]!;\n } else {\n return {\n options,\n files,\n error: { type: \"missing_value\", option: \"-F\" },\n };\n }\n\n // For single character separators, match exactly\n // For patterns, use as regex\n if (fs.length === 1) {\n options.fieldSeparator = new RegExp(escapeRegex(fs));\n } else {\n try {\n options.fieldSeparator = new RegExp(fs);\n } catch {\n options.fieldSeparator = new RegExp(escapeRegex(fs));\n }\n }\n i++;\n continue;\n } else {\n // Unknown flag\n return {\n options,\n files,\n error: { type: \"unrecognized_option\", option: `-${char}` },\n };\n }\n }\n\n // Non-flag argument\n if (!programFound) {\n options.program = parseProgram(arg);\n programFound = true;\n } else {\n files.push(arg);\n }\n i++;\n }\n\n return { options, files };\n}\n\nfunction formatError(error: NonNullable<ParseArgsResult[\"error\"]>): string {\n let message: string;\n if (error.type === \"unrecognized_option\") {\n if (error.option.startsWith(\"--\")) {\n message = `awk: unrecognized option '${error.option}'\\n`;\n } else {\n message = `awk: invalid option -- '${error.option.slice(1)}'\\n`;\n }\n } else {\n message = `awk: option '${error.option}' requires an argument\\n`;\n }\n return message + `usage: awk [-F fs] 'program' [file ...]\\n`;\n}\n\nfunction splitFields(line: string, separator: RegExp): string[] {\n // Split and filter empty strings for whitespace separation\n const parts = line.split(separator);\n // For whitespace separator, filter leading empty string\n if (separator.source === \"[ \\\\t]+\" && parts[0] === \"\") {\n parts.shift();\n }\n return parts;\n}\n\nfunction executeAction(\n action: string,\n fields: string[],\n line: string,\n lineNumber: number\n): string | null {\n // Parse and execute the action\n // Supported: print, print $0, print $1, print $1, $2, etc.\n\n const trimmedAction = action.trim();\n\n if (trimmedAction === \"\" || trimmedAction === \"print\" || trimmedAction === \"print $0\") {\n return line;\n }\n\n // Check for print with field references\n if (trimmedAction.startsWith(\"print\")) {\n const printArgs = trimmedAction.slice(5).trim();\n return evaluatePrintArgs(printArgs, fields, line, lineNumber);\n }\n\n // Just field reference without print (implicit print)\n if (trimmedAction.startsWith(\"$\")) {\n return evaluatePrintArgs(trimmedAction, fields, line, lineNumber);\n }\n\n return null;\n}\n\nfunction evaluatePrintArgs(\n argsStr: string,\n fields: string[],\n line: string,\n lineNumber: number\n): string {\n const results: string[] = [];\n\n // Split by comma for multiple arguments\n const args = argsStr.split(\",\").map((a) => a.trim());\n\n for (const arg of args) {\n const value = evaluateExpression(arg, fields, line, lineNumber);\n results.push(value);\n }\n\n return results.join(\" \");\n}\n\nfunction tokenizeExpression(expr: string): string[] {\n const tokens: string[] = [];\n let i = 0;\n const str = expr.trim();\n\n while (i < str.length) {\n // Skip whitespace\n while (i < str.length && /\\s/.test(str[i]!)) {\n i++;\n }\n if (i >= str.length) break;\n\n // String literal\n if (str[i] === '\"' || str[i] === \"'\") {\n const quote = str[i]!;\n let j = i + 1;\n while (j < str.length && str[j] !== quote) {\n j++;\n }\n tokens.push(str.slice(i, j + 1));\n i = j + 1;\n }\n // Field reference or variable\n else if (str[i] === '$' || /[a-zA-Z]/.test(str[i]!)) {\n let j = i;\n while (j < str.length && /[\\w$]/.test(str[j]!)) {\n j++;\n }\n tokens.push(str.slice(i, j));\n i = j;\n }\n // Other characters\n else {\n tokens.push(str[i]!);\n i++;\n }\n }\n\n return tokens;\n}\n\nfunction evaluateExpression(\n expr: string,\n fields: string[],\n line: string,\n lineNumber: number\n): string {\n const tokens = tokenizeExpression(expr);\n\n if (tokens.length === 0) {\n return \"\";\n }\n\n // Evaluate each token and concatenate\n const parts: string[] = [];\n for (const token of tokens) {\n // String literal\n if ((token.startsWith('\"') && token.endsWith('\"')) ||\n (token.startsWith(\"'\") && token.endsWith(\"'\"))) {\n parts.push(token.slice(1, -1));\n }\n // Field reference $0, $1, etc.\n else if (token.match(/^\\$(\\d+)$/)) {\n const fieldNum = parseInt(token.slice(1), 10);\n if (fieldNum === 0) {\n parts.push(line);\n } else {\n parts.push(fields[fieldNum - 1] ?? \"\");\n }\n }\n // Built-in variables\n else if (token === \"NF\") {\n parts.push(String(fields.length));\n }\n else if (token === \"NR\") {\n parts.push(String(lineNumber));\n }\n // Unknown - return as-is\n else {\n parts.push(token);\n }\n }\n\n return parts.join(\"\");\n}\n\nfunction processLine(\n line: string,\n lineNumber: number,\n options: AwkOptions\n): string[] {\n const fields = splitFields(line, options.fieldSeparator);\n const outputs: string[] = [];\n\n for (const rule of options.program) {\n // Check pattern match\n if (rule.pattern && !rule.pattern.test(line)) {\n continue;\n }\n\n const result = executeAction(rule.action, fields, line, lineNumber);\n if (result !== null) {\n outputs.push(result);\n }\n }\n\n return outputs;\n}\n\nexport const awk: Command = async (ctx) => {\n const { options, files, error } = parseArgs(ctx.args);\n\n if (error) {\n await ctx.stderr.writeText(formatError(error));\n return 1;\n }\n\n if (options.program.length === 0) {\n await ctx.stderr.writeText(\"awk: missing program\\n\");\n return 1;\n }\n\n let lineNumber = 0;\n\n const processContent = async (content: string): Promise<void> => {\n const lines = content.split(\"\\n\");\n // Handle trailing newline\n if (lines.length > 0 && lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n\n for (const line of lines) {\n lineNumber++;\n const outputs = processLine(line, lineNumber, options);\n for (const output of outputs) {\n await ctx.stdout.writeText(output + \"\\n\");\n }\n }\n };\n\n if (files.length === 0) {\n // Read from stdin\n const content = await ctx.stdin.text();\n await processContent(content);\n } else {\n // Read from files\n for (const file of files) {\n try {\n const path = ctx.fs.resolve(ctx.cwd, file);\n const content = await ctx.fs.readFile(path);\n await processContent(content.toString());\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.stderr.writeText(`awk: ${file}: ${message}\\n`);\n return 1;\n }\n }\n }\n\n return 0;\n};\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "4A06D5FDB8035EFF64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "28D810CAF4D96C7864756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,11 +1,24 @@
1
1
  // src/commands/cat/cat.ts
2
+ import { createFlagParser } from "../../utils/flag-parser.mjs";
3
+ var spec = {
4
+ name: "cat",
5
+ flags: [],
6
+ usage: "cat [file ...]"
7
+ };
8
+ var parser = createFlagParser(spec, {}, () => {});
2
9
  var cat = async (ctx) => {
3
- if (ctx.args.length === 0) {
10
+ const result = parser.parse(ctx.args);
11
+ if (result.error) {
12
+ await parser.writeError(result.error, ctx.stderr);
13
+ return 1;
14
+ }
15
+ const files = result.args;
16
+ if (files.length === 0) {
4
17
  for await (const chunk of ctx.stdin.stream()) {
5
18
  await ctx.stdout.write(chunk);
6
19
  }
7
20
  } else {
8
- for (const file of ctx.args) {
21
+ for (const file of files) {
9
22
  try {
10
23
  const path = ctx.fs.resolve(ctx.cwd, file);
11
24
  const content = await ctx.fs.readFile(path);
@@ -24,4 +37,4 @@ export {
24
37
  cat
25
38
  };
26
39
 
27
- //# debugId=08C64154E1A80D8D64756E2164756E21
40
+ //# debugId=F3F231DCE871E0EC64756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/commands/cat/cat.ts"],
4
4
  "sourcesContent": [
5
- "import type { Command } from \"../../types.mjs\";\n\nexport const cat: Command = async (ctx) => {\n if (ctx.args.length === 0) {\n // Read from stdin\n for await (const chunk of ctx.stdin.stream()) {\n await ctx.stdout.write(chunk);\n }\n } else {\n // Read from files\n for (const file of ctx.args) {\n try {\n const path = ctx.fs.resolve(ctx.cwd, file);\n const content = await ctx.fs.readFile(path);\n await ctx.stdout.write(new Uint8Array(content));\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.stderr.writeText(`cat: ${file}: ${message}\\n`);\n return 1;\n }\n }\n }\n return 0;\n};\n"
5
+ "import type { Command } from \"../../types.mjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.mjs\";\n\nconst spec = {\n name: \"cat\",\n flags: [] as FlagDefinition[],\n usage: \"cat [file ...]\",\n};\n\nconst parser = createFlagParser(spec, {}, () => {});\n\nexport const cat: 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 files = result.args;\n\n if (files.length === 0) {\n // Read from stdin\n for await (const chunk of ctx.stdin.stream()) {\n await ctx.stdout.write(chunk);\n }\n } else {\n // Read from files\n for (const file of files) {\n try {\n const path = ctx.fs.resolve(ctx.cwd, file);\n const content = await ctx.fs.readFile(path);\n await ctx.stdout.write(new Uint8Array(content));\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.stderr.writeText(`cat: ${file}: ${message}\\n`);\n return 1;\n }\n }\n }\n return 0;\n};\n"
6
6
  ],
7
- "mappings": ";AAEO,IAAM,MAAe,OAAO,QAAQ;AAAA,EACzC,IAAI,IAAI,KAAK,WAAW,GAAG;AAAA,IAEzB,iBAAiB,SAAS,IAAI,MAAM,OAAO,GAAG;AAAA,MAC5C,MAAM,IAAI,OAAO,MAAM,KAAK;AAAA,IAC9B;AAAA,EACF,EAAO;AAAA,IAEL,WAAW,QAAQ,IAAI,MAAM;AAAA,MAC3B,IAAI;AAAA,QACF,MAAM,OAAO,IAAI,GAAG,QAAQ,IAAI,KAAK,IAAI;AAAA,QACzC,MAAM,UAAU,MAAM,IAAI,GAAG,SAAS,IAAI;AAAA,QAC1C,MAAM,IAAI,OAAO,MAAM,IAAI,WAAW,OAAO,CAAC;AAAA,QAC9C,OAAO,KAAK;AAAA,QACZ,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QAC/D,MAAM,IAAI,OAAO,UAAU,QAAQ,SAAS;AAAA,CAAW;AAAA,QACvD,OAAO;AAAA;AAAA,IAEX;AAAA;AAAA,EAEF,OAAO;AAAA;",
8
- "debugId": "08C64154E1A80D8D64756E2164756E21",
7
+ "mappings": ";AACA;AAEA,IAAM,OAAO;AAAA,EACX,MAAM;AAAA,EACN,OAAO,CAAC;AAAA,EACR,OAAO;AACT;AAEA,IAAM,SAAS,iBAAiB,MAAM,CAAC,GAAG,MAAM,EAAE;AAE3C,IAAM,MAAe,OAAO,QAAQ;AAAA,EACzC,MAAM,SAAS,OAAO,MAAM,IAAI,IAAI;AAAA,EAEpC,IAAI,OAAO,OAAO;AAAA,IAChB,MAAM,OAAO,WAAW,OAAO,OAAO,IAAI,MAAM;AAAA,IAChD,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,OAAO;AAAA,EAErB,IAAI,MAAM,WAAW,GAAG;AAAA,IAEtB,iBAAiB,SAAS,IAAI,MAAM,OAAO,GAAG;AAAA,MAC5C,MAAM,IAAI,OAAO,MAAM,KAAK;AAAA,IAC9B;AAAA,EACF,EAAO;AAAA,IAEL,WAAW,QAAQ,OAAO;AAAA,MACxB,IAAI;AAAA,QACF,MAAM,OAAO,IAAI,GAAG,QAAQ,IAAI,KAAK,IAAI;AAAA,QACzC,MAAM,UAAU,MAAM,IAAI,GAAG,SAAS,IAAI;AAAA,QAC1C,MAAM,IAAI,OAAO,MAAM,IAAI,WAAW,OAAO,CAAC;AAAA,QAC9C,OAAO,KAAK;AAAA,QACZ,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QAC/D,MAAM,IAAI,OAAO,UAAU,QAAQ,SAAS;AAAA,CAAW;AAAA,QACvD,OAAO;AAAA;AAAA,IAEX;AAAA;AAAA,EAEF,OAAO;AAAA;",
8
+ "debugId": "F3F231DCE871E0EC64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,25 +1,31 @@
1
1
  // src/commands/cp/cp.ts
2
+ import { createFlagParser } from "../../utils/flag-parser.mjs";
3
+ var spec = {
4
+ name: "cp",
5
+ flags: [
6
+ { short: "r", long: "recursive" },
7
+ { short: "R" },
8
+ { short: "n", long: "no-clobber" },
9
+ { short: "f", long: "force" }
10
+ ],
11
+ usage: "cp [-rRnf] source ... dest"
12
+ };
13
+ var defaults = { recursive: false, noClobber: false };
14
+ var handler = (flags, flag) => {
15
+ if (flag.short === "r" || flag.short === "R")
16
+ flags.recursive = true;
17
+ if (flag.short === "n")
18
+ flags.noClobber = true;
19
+ };
20
+ var parser = createFlagParser(spec, defaults, handler);
2
21
  var cp = async (ctx) => {
3
- let recursive = false;
4
- let noClobber = false;
5
- const paths = [];
6
- for (const arg of ctx.args) {
7
- if (arg === "-r" || arg === "-R" || arg === "--recursive") {
8
- recursive = true;
9
- } else if (arg === "-n" || arg === "--no-clobber") {
10
- noClobber = true;
11
- } else if (arg === "-f" || arg === "--force") {} else if (arg.startsWith("-")) {
12
- for (const flag of arg.slice(1)) {
13
- if (flag === "r" || flag === "R")
14
- recursive = true;
15
- else if (flag === "n")
16
- noClobber = true;
17
- else if (flag === "f") {}
18
- }
19
- } else {
20
- paths.push(arg);
21
- }
22
+ const result = parser.parse(ctx.args);
23
+ if (result.error) {
24
+ await parser.writeError(result.error, ctx.stderr);
25
+ return 1;
22
26
  }
27
+ const { recursive, noClobber } = result.flags;
28
+ const paths = result.args;
23
29
  if (paths.length < 2) {
24
30
  await ctx.stderr.writeText(`cp: missing destination file operand
25
31
  `);
@@ -93,4 +99,4 @@ export {
93
99
  cp
94
100
  };
95
101
 
96
- //# debugId=D99DFD6940EFC55C64756E2164756E21
102
+ //# debugId=81F040E34932ED3764756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/commands/cp/cp.ts"],
4
4
  "sourcesContent": [
5
- "import type { Command } from \"../../types.mjs\";\n\nexport const cp: Command = async (ctx) => {\n let recursive = false;\n let noClobber = false;\n const paths: string[] = [];\n\n for (const arg of ctx.args) {\n if (arg === \"-r\" || arg === \"-R\" || arg === \"--recursive\") {\n recursive = true;\n } else if (arg === \"-n\" || arg === \"--no-clobber\") {\n noClobber = true;\n } else if (arg === \"-f\" || arg === \"--force\") {\n // Force is default behavior, just accept the flag\n } else if (arg.startsWith(\"-\")) {\n // Parse combined flags like -rn\n for (const flag of arg.slice(1)) {\n if (flag === \"r\" || flag === \"R\") recursive = true;\n else if (flag === \"n\") noClobber = true;\n else if (flag === \"f\") { /* force is default */ }\n }\n } else {\n paths.push(arg);\n }\n }\n\n if (paths.length < 2) {\n await ctx.stderr.writeText(\"cp: missing destination file operand\\n\");\n return 1;\n }\n\n const sources = paths.slice(0, -1);\n const dest = paths[paths.length - 1]!;\n const destPath = ctx.fs.resolve(ctx.cwd, dest);\n\n // Check if destination is a directory\n let destIsDir = false;\n try {\n const stat = await ctx.fs.stat(destPath);\n destIsDir = stat.isDirectory();\n } catch {\n // Destination doesn't exist\n }\n\n // If multiple sources, dest must be a directory\n if (sources.length > 1 && !destIsDir) {\n await ctx.stderr.writeText(`cp: target '${dest}' is not a directory\\n`);\n return 1;\n }\n\n for (const source of sources) {\n const srcPath = ctx.fs.resolve(ctx.cwd, source);\n\n try {\n const srcStat = await ctx.fs.stat(srcPath);\n\n if (srcStat.isDirectory()) {\n if (!recursive) {\n await ctx.stderr.writeText(`cp: -r not specified; omitting directory '${source}'\\n`);\n return 1;\n }\n // Copy directory recursively\n const finalDest = destIsDir\n ? ctx.fs.resolve(destPath, ctx.fs.basename(srcPath))\n : destPath;\n\n await copyDirectory(ctx, srcPath, finalDest, noClobber);\n } else {\n // Copy file\n const finalDest = destIsDir\n ? ctx.fs.resolve(destPath, ctx.fs.basename(srcPath))\n : destPath;\n\n // Check if dest exists and noClobber\n if (noClobber) {\n const exists = await ctx.fs.exists(finalDest);\n if (exists) continue; // Skip silently\n }\n\n const content = await ctx.fs.readFile(srcPath);\n await ctx.fs.writeFile(finalDest, content);\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.stderr.writeText(`cp: cannot stat '${source}': ${message}\\n`);\n return 1;\n }\n }\n\n return 0;\n};\n\nasync function copyDirectory(\n ctx: Parameters<Command>[0],\n src: string,\n dest: string,\n noClobber: boolean\n): Promise<void> {\n // Create destination directory\n await ctx.fs.mkdir(dest, { recursive: true });\n\n // Read source directory contents\n const entries = await ctx.fs.readdir(src);\n\n for (const entry of entries) {\n const srcPath = ctx.fs.resolve(src, entry);\n const destPath = ctx.fs.resolve(dest, entry);\n\n const stat = await ctx.fs.stat(srcPath);\n\n if (stat.isDirectory()) {\n await copyDirectory(ctx, srcPath, destPath, noClobber);\n } else {\n if (noClobber) {\n const exists = await ctx.fs.exists(destPath);\n if (exists) continue;\n }\n const content = await ctx.fs.readFile(srcPath);\n await ctx.fs.writeFile(destPath, content);\n }\n }\n}\n"
5
+ "import type { Command } from \"../../types.mjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.mjs\";\n\ninterface CpFlags {\n recursive: boolean;\n noClobber: boolean;\n}\n\nconst spec = {\n name: \"cp\",\n flags: [\n { short: \"r\", long: \"recursive\" },\n { short: \"R\" },\n { short: \"n\", long: \"no-clobber\" },\n { short: \"f\", long: \"force\" },\n ] as FlagDefinition[],\n usage: \"cp [-rRnf] source ... dest\",\n};\n\nconst defaults: CpFlags = { recursive: false, noClobber: false };\n\nconst handler = (flags: CpFlags, flag: FlagDefinition) => {\n if (flag.short === \"r\" || flag.short === \"R\") flags.recursive = true;\n if (flag.short === \"n\") flags.noClobber = true;\n // -f is default behavior, so we don't need to do anything\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const cp: 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 { recursive, noClobber } = result.flags;\n const paths = result.args;\n\n if (paths.length < 2) {\n await ctx.stderr.writeText(\"cp: missing destination file operand\\n\");\n return 1;\n }\n\n const sources = paths.slice(0, -1);\n const dest = paths[paths.length - 1]!;\n const destPath = ctx.fs.resolve(ctx.cwd, dest);\n\n // Check if destination is a directory\n let destIsDir = false;\n try {\n const stat = await ctx.fs.stat(destPath);\n destIsDir = stat.isDirectory();\n } catch {\n // Destination doesn't exist\n }\n\n // If multiple sources, dest must be a directory\n if (sources.length > 1 && !destIsDir) {\n await ctx.stderr.writeText(`cp: target '${dest}' is not a directory\\n`);\n return 1;\n }\n\n for (const source of sources) {\n const srcPath = ctx.fs.resolve(ctx.cwd, source);\n\n try {\n const srcStat = await ctx.fs.stat(srcPath);\n\n if (srcStat.isDirectory()) {\n if (!recursive) {\n await ctx.stderr.writeText(`cp: -r not specified; omitting directory '${source}'\\n`);\n return 1;\n }\n // Copy directory recursively\n const finalDest = destIsDir\n ? ctx.fs.resolve(destPath, ctx.fs.basename(srcPath))\n : destPath;\n\n await copyDirectory(ctx, srcPath, finalDest, noClobber);\n } else {\n // Copy file\n const finalDest = destIsDir\n ? ctx.fs.resolve(destPath, ctx.fs.basename(srcPath))\n : destPath;\n\n // Check if dest exists and noClobber\n if (noClobber) {\n const exists = await ctx.fs.exists(finalDest);\n if (exists) continue; // Skip silently\n }\n\n const content = await ctx.fs.readFile(srcPath);\n await ctx.fs.writeFile(finalDest, content);\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.stderr.writeText(`cp: cannot stat '${source}': ${message}\\n`);\n return 1;\n }\n }\n\n return 0;\n};\n\nasync function copyDirectory(\n ctx: Parameters<Command>[0],\n src: string,\n dest: string,\n noClobber: boolean\n): Promise<void> {\n // Create destination directory\n await ctx.fs.mkdir(dest, { recursive: true });\n\n // Read source directory contents\n const entries = await ctx.fs.readdir(src);\n\n for (const entry of entries) {\n const srcPath = ctx.fs.resolve(src, entry);\n const destPath = ctx.fs.resolve(dest, entry);\n\n const stat = await ctx.fs.stat(srcPath);\n\n if (stat.isDirectory()) {\n await copyDirectory(ctx, srcPath, destPath, noClobber);\n } else {\n if (noClobber) {\n const exists = await ctx.fs.exists(destPath);\n if (exists) continue;\n }\n const content = await ctx.fs.readFile(srcPath);\n await ctx.fs.writeFile(destPath, content);\n }\n }\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "D99DFD6940EFC55C64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "81F040E34932ED3764756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,12 +1,27 @@
1
1
  // src/commands/echo/echo.ts
2
+ import { createFlagParser } from "../../utils/flag-parser.mjs";
3
+ var spec = {
4
+ name: "echo",
5
+ flags: [
6
+ { short: "n" }
7
+ ],
8
+ usage: "echo [-n] [string ...]",
9
+ stopAfterFirstPositional: true
10
+ };
11
+ var defaults = { noNewline: false };
12
+ var handler = (flags, flag) => {
13
+ if (flag.short === "n")
14
+ flags.noNewline = true;
15
+ };
16
+ var parser = createFlagParser(spec, defaults, handler);
2
17
  var echo = async (ctx) => {
3
- let output = ctx.args.join(" ");
4
- let newline = true;
5
- if (ctx.args[0] === "-n") {
6
- newline = false;
7
- output = ctx.args.slice(1).join(" ");
18
+ const result = parser.parse(ctx.args);
19
+ if (result.error) {
20
+ await parser.writeError(result.error, ctx.stderr);
21
+ return 1;
8
22
  }
9
- if (newline) {
23
+ let output = result.args.join(" ");
24
+ if (!result.flags.noNewline) {
10
25
  output += `
11
26
  `;
12
27
  }
@@ -17,4 +32,4 @@ export {
17
32
  echo
18
33
  };
19
34
 
20
- //# debugId=7DA64F60F07EE35564756E2164756E21
35
+ //# debugId=0A8B87523F81DD1364756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/commands/echo/echo.ts"],
4
4
  "sourcesContent": [
5
- "import type { Command } from \"../../types.mjs\";\n\nexport const echo: Command = async (ctx) => {\n let output = ctx.args.join(\" \");\n let newline = true;\n\n // Handle -n flag (no newline)\n if (ctx.args[0] === \"-n\") {\n newline = false;\n output = ctx.args.slice(1).join(\" \");\n }\n\n if (newline) {\n output += \"\\n\";\n }\n\n await ctx.stdout.writeText(output);\n return 0;\n};\n"
5
+ "import type { Command } from \"../../types.mjs\";\nimport { createFlagParser, type FlagDefinition } from \"../../utils/flag-parser.mjs\";\n\ninterface EchoFlags {\n noNewline: boolean;\n}\n\nconst spec = {\n name: \"echo\",\n flags: [\n { short: \"n\" },\n ] as FlagDefinition[],\n usage: \"echo [-n] [string ...]\",\n stopAfterFirstPositional: true,\n};\n\nconst defaults: EchoFlags = { noNewline: false };\n\nconst handler = (flags: EchoFlags, flag: FlagDefinition) => {\n if (flag.short === \"n\") flags.noNewline = true;\n};\n\nconst parser = createFlagParser(spec, defaults, handler);\n\nexport const echo: 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 let output = result.args.join(\" \");\n\n if (!result.flags.noNewline) {\n output += \"\\n\";\n }\n\n await ctx.stdout.writeText(output);\n return 0;\n};\n"
6
6
  ],
7
- "mappings": ";AAEO,IAAM,OAAgB,OAAO,QAAQ;AAAA,EAC1C,IAAI,SAAS,IAAI,KAAK,KAAK,GAAG;AAAA,EAC9B,IAAI,UAAU;AAAA,EAGd,IAAI,IAAI,KAAK,OAAO,MAAM;AAAA,IACxB,UAAU;AAAA,IACV,SAAS,IAAI,KAAK,MAAM,CAAC,EAAE,KAAK,GAAG;AAAA,EACrC;AAAA,EAEA,IAAI,SAAS;AAAA,IACX,UAAU;AAAA;AAAA,EACZ;AAAA,EAEA,MAAM,IAAI,OAAO,UAAU,MAAM;AAAA,EACjC,OAAO;AAAA;",
8
- "debugId": "7DA64F60F07EE35564756E2164756E21",
7
+ "mappings": ";AACA;AAMA,IAAM,OAAO;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AAAA,IACL,EAAE,OAAO,IAAI;AAAA,EACf;AAAA,EACA,OAAO;AAAA,EACP,0BAA0B;AAC5B;AAEA,IAAM,WAAsB,EAAE,WAAW,MAAM;AAE/C,IAAM,UAAU,CAAC,OAAkB,SAAyB;AAAA,EAC1D,IAAI,KAAK,UAAU;AAAA,IAAK,MAAM,YAAY;AAAA;AAG5C,IAAM,SAAS,iBAAiB,MAAM,UAAU,OAAO;AAEhD,IAAM,OAAgB,OAAO,QAAQ;AAAA,EAC1C,MAAM,SAAS,OAAO,MAAM,IAAI,IAAI;AAAA,EAEpC,IAAI,OAAO,OAAO;AAAA,IAChB,MAAM,OAAO,WAAW,OAAO,OAAO,IAAI,MAAM;AAAA,IAChD,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,SAAS,OAAO,KAAK,KAAK,GAAG;AAAA,EAEjC,IAAI,CAAC,OAAO,MAAM,WAAW;AAAA,IAC3B,UAAU;AAAA;AAAA,EACZ;AAAA,EAEA,MAAM,IAAI,OAAO,UAAU,MAAM;AAAA,EACjC,OAAO;AAAA;",
8
+ "debugId": "0A8B87523F81DD1364756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,6 +1,34 @@
1
1
  // src/commands/grep/grep.ts
2
- function parseArgs(args) {
3
- const options = {
2
+ import { createFlagParser } from "../../utils/flag-parser.mjs";
3
+ var spec = {
4
+ name: "grep",
5
+ flags: [
6
+ { short: "E", long: "extended-regexp" },
7
+ { short: "F", long: "fixed-strings" },
8
+ { short: "i", long: "ignore-case" },
9
+ { short: "w", long: "word-regexp" },
10
+ { short: "x", long: "line-regexp" },
11
+ { short: "v", long: "invert-match" },
12
+ { short: "c", long: "count" },
13
+ { short: "l", long: "files-with-matches" },
14
+ { short: "L", long: "files-without-match" },
15
+ { short: "n", long: "line-number" },
16
+ { short: "o", long: "only-matching" },
17
+ { short: "q", long: "quiet" },
18
+ { short: "H", long: "with-filename" },
19
+ { short: "h", long: "no-filename" },
20
+ { short: "r", long: "recursive" },
21
+ { short: "R" },
22
+ { short: "e", long: "regexp", takesValue: true },
23
+ { short: "m", long: "max-count", takesValue: true },
24
+ { short: "A", long: "after-context", takesValue: true },
25
+ { short: "B", long: "before-context", takesValue: true },
26
+ { short: "C", long: "context", takesValue: true }
27
+ ],
28
+ usage: "grep [-ivnclLqHhEFwxorR] [-e pattern] [-m num] pattern [file ...]"
29
+ };
30
+ function createDefaults() {
31
+ return {
4
32
  patterns: [],
5
33
  extendedRegex: true,
6
34
  fixedStrings: false,
@@ -20,134 +48,80 @@ function parseArgs(args) {
20
48
  afterContext: 0,
21
49
  recursive: false
22
50
  };
23
- const files = [];
24
- let pattern;
25
- let i = 0;
26
- while (i < args.length) {
27
- const arg = args[i];
28
- if (arg === "--") {
29
- files.push(...args.slice(i + 1));
51
+ }
52
+ var handler = (flags, flag, value) => {
53
+ switch (flag.short) {
54
+ case "E":
55
+ flags.extendedRegex = true;
30
56
  break;
31
- }
32
- if (arg === "-e" && args[i + 1] !== undefined) {
33
- options.patterns.push(args[i + 1]);
34
- i += 2;
35
- continue;
36
- }
37
- if (arg === "-m" && args[i + 1] !== undefined) {
38
- options.maxMatches = parseInt(args[i + 1], 10);
39
- i += 2;
40
- continue;
41
- }
42
- if (arg.startsWith("-m") && arg.length > 2) {
43
- options.maxMatches = parseInt(arg.slice(2), 10);
44
- i++;
45
- continue;
46
- }
47
- if (arg === "-A" && args[i + 1] !== undefined) {
48
- options.afterContext = parseInt(args[i + 1], 10);
49
- i += 2;
50
- continue;
51
- }
52
- if (arg.startsWith("-A") && arg.length > 2) {
53
- options.afterContext = parseInt(arg.slice(2), 10);
54
- i++;
55
- continue;
56
- }
57
- if (arg === "-B" && args[i + 1] !== undefined) {
58
- options.beforeContext = parseInt(args[i + 1], 10);
59
- i += 2;
60
- continue;
61
- }
62
- if (arg.startsWith("-B") && arg.length > 2) {
63
- options.beforeContext = parseInt(arg.slice(2), 10);
64
- i++;
65
- continue;
66
- }
67
- if (arg === "-C" && args[i + 1] !== undefined) {
68
- const num = parseInt(args[i + 1], 10);
69
- options.beforeContext = num;
70
- options.afterContext = num;
71
- i += 2;
72
- continue;
73
- }
74
- if (arg.startsWith("-C") && arg.length > 2) {
75
- const num = parseInt(arg.slice(2), 10);
76
- options.beforeContext = num;
77
- options.afterContext = num;
78
- i++;
79
- continue;
80
- }
81
- if (arg.startsWith("-") && arg.length > 1 && !arg.startsWith("--")) {
82
- for (const flag of arg.slice(1)) {
83
- switch (flag) {
84
- case "v":
85
- options.invert = true;
86
- break;
87
- case "i":
88
- options.ignoreCase = true;
89
- break;
90
- case "n":
91
- options.showLineNumbers = true;
92
- break;
93
- case "c":
94
- options.countOnly = true;
95
- break;
96
- case "l":
97
- options.filesWithMatches = true;
98
- break;
99
- case "L":
100
- options.filesWithoutMatches = true;
101
- break;
102
- case "q":
103
- options.quiet = true;
104
- break;
105
- case "H":
106
- options.showFilename = true;
107
- break;
108
- case "h":
109
- options.showFilename = false;
110
- break;
111
- case "E":
112
- options.extendedRegex = true;
113
- break;
114
- case "F":
115
- options.fixedStrings = true;
116
- break;
117
- case "w":
118
- options.wholeWord = true;
119
- break;
120
- case "x":
121
- options.wholeLine = true;
122
- break;
123
- case "o":
124
- options.onlyMatching = true;
125
- break;
126
- case "r":
127
- case "R":
128
- options.recursive = true;
129
- break;
130
- }
57
+ case "F":
58
+ flags.fixedStrings = true;
59
+ break;
60
+ case "i":
61
+ flags.ignoreCase = true;
62
+ break;
63
+ case "w":
64
+ flags.wholeWord = true;
65
+ break;
66
+ case "x":
67
+ flags.wholeLine = true;
68
+ break;
69
+ case "v":
70
+ flags.invert = true;
71
+ break;
72
+ case "c":
73
+ flags.countOnly = true;
74
+ break;
75
+ case "l":
76
+ flags.filesWithMatches = true;
77
+ break;
78
+ case "L":
79
+ flags.filesWithoutMatches = true;
80
+ break;
81
+ case "n":
82
+ flags.showLineNumbers = true;
83
+ break;
84
+ case "o":
85
+ flags.onlyMatching = true;
86
+ break;
87
+ case "q":
88
+ flags.quiet = true;
89
+ break;
90
+ case "H":
91
+ flags.showFilename = true;
92
+ break;
93
+ case "h":
94
+ flags.showFilename = false;
95
+ break;
96
+ case "r":
97
+ case "R":
98
+ flags.recursive = true;
99
+ break;
100
+ case "e":
101
+ if (value)
102
+ flags.patterns.push(value);
103
+ break;
104
+ case "m":
105
+ if (value)
106
+ flags.maxMatches = parseInt(value, 10);
107
+ break;
108
+ case "A":
109
+ if (value)
110
+ flags.afterContext = parseInt(value, 10);
111
+ break;
112
+ case "B":
113
+ if (value)
114
+ flags.beforeContext = parseInt(value, 10);
115
+ break;
116
+ case "C":
117
+ if (value) {
118
+ const num = parseInt(value, 10);
119
+ flags.beforeContext = num;
120
+ flags.afterContext = num;
131
121
  }
132
- i++;
133
- continue;
134
- }
135
- if (pattern === undefined && options.patterns.length === 0) {
136
- pattern = arg;
137
- } else {
138
- files.push(arg);
139
- }
140
- i++;
141
- }
142
- if (pattern !== undefined) {
143
- if (options.patterns.length === 0) {
144
- options.patterns.push(pattern);
145
- } else {
146
- files.unshift(pattern);
147
- }
122
+ break;
148
123
  }
149
- return { options, files };
150
- }
124
+ };
151
125
  function escapeRegex(str) {
152
126
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
153
127
  }
@@ -167,11 +141,25 @@ function buildMatcher(options) {
167
141
  return new RegExp(combined, flags);
168
142
  }
169
143
  var grep = async (ctx) => {
170
- const { options, files } = parseArgs(ctx.args);
144
+ const parser = createFlagParser(spec, createDefaults(), handler);
145
+ const result = parser.parse(ctx.args);
146
+ if (result.error) {
147
+ await parser.writeError(result.error, ctx.stderr);
148
+ return 1;
149
+ }
150
+ const options = result.flags;
151
+ const args = result.args;
152
+ let files;
171
153
  if (options.patterns.length === 0) {
172
- await ctx.stderr.writeText(`grep: missing pattern
154
+ if (args.length === 0) {
155
+ await ctx.stderr.writeText(`grep: missing pattern
173
156
  `);
174
- return 1;
157
+ return 1;
158
+ }
159
+ options.patterns.push(args[0]);
160
+ files = args.slice(1);
161
+ } else {
162
+ files = args;
175
163
  }
176
164
  let regex;
177
165
  try {
@@ -279,8 +267,6 @@ var grep = async (ctx) => {
279
267
  let fileFound = false;
280
268
  let fileMatchCount = 0;
281
269
  let lastPrintedLine = -1;
282
- let needSeparator = false;
283
- let afterRemaining = 0;
284
270
  const matchingLines = new Set;
285
271
  for (let lineIdx = 0;lineIdx < lines.length; lineIdx++) {
286
272
  const line = lines[lineIdx];
@@ -442,27 +428,27 @@ var grep = async (ctx) => {
442
428
  }
443
429
  let hasFilesWithoutMatches = false;
444
430
  if (options.filesWithMatches) {
445
- for (const [filename, result] of perFileResults) {
446
- if (result.found && !options.quiet) {
431
+ for (const [filename, result2] of perFileResults) {
432
+ if (result2.found && !options.quiet) {
447
433
  await ctx.stdout.writeText(filename + `
448
434
  `);
449
435
  }
450
436
  }
451
437
  } else if (options.filesWithoutMatches) {
452
- for (const [filename, result] of perFileResults) {
453
- if (!result.found) {
438
+ for (const [filename, result2] of perFileResults) {
439
+ if (!result2.found) {
454
440
  hasFilesWithoutMatches = true;
455
441
  await ctx.stdout.writeText(filename + `
456
442
  `);
457
443
  }
458
444
  }
459
445
  } else if (options.countOnly && !options.quiet) {
460
- for (const [filename, result] of perFileResults) {
446
+ for (const [filename, result2] of perFileResults) {
461
447
  if (showFilenames) {
462
- await ctx.stdout.writeText(`${filename}:${result.count}
448
+ await ctx.stdout.writeText(`${filename}:${result2.count}
463
449
  `);
464
450
  } else {
465
- await ctx.stdout.writeText(result.count + `
451
+ await ctx.stdout.writeText(result2.count + `
466
452
  `);
467
453
  }
468
454
  }
@@ -477,4 +463,4 @@ export {
477
463
  grep
478
464
  };
479
465
 
480
- //# debugId=436FB2887B1A147364756E2164756E21
466
+ //# debugId=68721590A11FCEF564756E2164756E21