( command: string, args: string[], spec: CommandSpec | null, )
| 86 | } |
| 87 | |
| 88 | export async function buildPrefix( |
| 89 | command: string, |
| 90 | args: string[], |
| 91 | spec: CommandSpec | null, |
| 92 | ): Promise<string> { |
| 93 | const maxDepth = await calculateDepth(command, args, spec) |
| 94 | const parts = [command] |
| 95 | const hasSubcommands = !!spec?.subcommands?.length |
| 96 | let foundSubcommand = false |
| 97 | |
| 98 | for (let i = 0; i < args.length; i++) { |
| 99 | const arg = args[i] |
| 100 | if (!arg || parts.length >= maxDepth) break |
| 101 | |
| 102 | if (arg.startsWith('-')) { |
| 103 | // Special case: python -c should stop after -c |
| 104 | if (arg === '-c' && ['python', 'python3'].includes(command.toLowerCase())) |
| 105 | break |
| 106 | |
| 107 | // Check for isCommand/isModule flags that should be included in prefix |
| 108 | if (spec?.options) { |
| 109 | const option = spec.options.find(opt => |
| 110 | Array.isArray(opt.name) ? opt.name.includes(arg) : opt.name === arg, |
| 111 | ) |
| 112 | if ( |
| 113 | option?.args && |
| 114 | toArray(option.args).some(a => a?.isCommand || a?.isModule) |
| 115 | ) { |
| 116 | parts.push(arg) |
| 117 | continue |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | // For commands with subcommands, skip global flags to find the subcommand |
| 122 | if (hasSubcommands && !foundSubcommand) { |
| 123 | if (flagTakesArg(arg, args[i + 1], spec)) i++ |
| 124 | continue |
| 125 | } |
| 126 | break // Stop at flags (original behavior) |
| 127 | } |
| 128 | |
| 129 | if (await shouldStopAtArg(arg, args.slice(0, i), spec)) break |
| 130 | if (hasSubcommands && !foundSubcommand) { |
| 131 | foundSubcommand = isKnownSubcommand(arg, spec) |
| 132 | } |
| 133 | parts.push(arg) |
| 134 | } |
| 135 | |
| 136 | return parts.join(' ') |
| 137 | } |
| 138 | |
| 139 | async function calculateDepth( |
| 140 | command: string, |
no test coverage detected