( prompter: Prompter, deps: Pick<WizardDeps, 'listRepos'>, )
| 137 | // ── Step 2: pick repos ───────────────────────────────────────────────────── |
| 138 | |
| 139 | export async function stepPickRepos( |
| 140 | prompter: Prompter, |
| 141 | deps: Pick<WizardDeps, 'listRepos'>, |
| 142 | ): Promise< |
| 143 | | { kind: 'picked'; repos: string[] } |
| 144 | | { kind: 'cancelled'; reason: string } |
| 145 | > { |
| 146 | const saved = deps.listRepos(); |
| 147 | |
| 148 | prompter.write(''); |
| 149 | if (saved.length > 0) { |
| 150 | prompter.write(`Saved repo set (${saved.length}):`); |
| 151 | for (const r of saved) prompter.write(` - ${r}`); |
| 152 | prompter.write(''); |
| 153 | const answer = await prompter.ask( |
| 154 | `Use all saved repos? [Y/n] (or enter space-separated paths): `, |
| 155 | ); |
| 156 | if (answer === '' || answer.toLowerCase() === 'y') { |
| 157 | return { kind: 'picked', repos: saved }; |
| 158 | } |
| 159 | if (answer.toLowerCase() === 'n') { |
| 160 | const override = await prompter.ask('Enter space-separated repo paths: '); |
| 161 | const repos = parseRepoList(override); |
| 162 | if (repos.length === 0) { |
| 163 | return { kind: 'cancelled', reason: 'empty-repo-override' }; |
| 164 | } |
| 165 | return { kind: 'picked', repos }; |
| 166 | } |
| 167 | if (answer.toLowerCase() === 'q') { |
| 168 | return { kind: 'cancelled', reason: 'quit-at-repos' }; |
| 169 | } |
| 170 | // Any other non-empty answer is treated as a direct space-separated path |
| 171 | // list. Lets users skip the "n, then type" two-step. |
| 172 | const repos = parseRepoList(answer); |
| 173 | if (repos.length === 0) { |
| 174 | return { kind: 'cancelled', reason: 'invalid-repo-answer' }; |
| 175 | } |
| 176 | return { kind: 'picked', repos }; |
| 177 | } |
| 178 | |
| 179 | prompter.write('No saved repos. Save some with `ft repos add <path>`, or enter them now.'); |
| 180 | const answer = await prompter.ask('Space-separated repo paths (or `q` to quit): '); |
| 181 | if (answer === 'q' || answer === 'Q') { |
| 182 | return { kind: 'cancelled', reason: 'quit-at-repos-empty' }; |
| 183 | } |
| 184 | const repos = parseRepoList(answer); |
| 185 | if (repos.length === 0) { |
| 186 | return { kind: 'cancelled', reason: 'empty-repo-answer' }; |
| 187 | } |
| 188 | return { kind: 'picked', repos }; |
| 189 | } |
| 190 | |
| 191 | // ── Step 3: pick a frame ─────────────────────────────────────────────────── |
| 192 |
no test coverage detected