( options: InstallPromptOptions, )
| 121 | } |
| 122 | |
| 123 | export async function promptForInstallChoice( |
| 124 | options: InstallPromptOptions, |
| 125 | ): Promise<InstallPromptChoiceValue> { |
| 126 | const input = options.input ?? process.stdin; |
| 127 | const output = options.output ?? process.stdout; |
| 128 | const choices = createInstallPromptChoices(options.target); |
| 129 | let selectedIndex = getDefaultInstallPromptSelection(choices); |
| 130 | |
| 131 | return new Promise<InstallPromptChoiceValue>((resolve) => { |
| 132 | let lineCount = 0; |
| 133 | const hadRawMode = 'isRaw' in input ? input.isRaw : false; |
| 134 | const canSetRawMode = typeof input.setRawMode === 'function'; |
| 135 | |
| 136 | const cleanup = (): void => { |
| 137 | input.off('keypress', onKeypress); |
| 138 | if (canSetRawMode) { |
| 139 | input.setRawMode(hadRawMode); |
| 140 | } |
| 141 | output.write(SHOW_CURSOR); |
| 142 | output.write('\n'); |
| 143 | }; |
| 144 | |
| 145 | const finish = (choice: InstallPromptChoiceValue): void => { |
| 146 | cleanup(); |
| 147 | resolve(choice); |
| 148 | }; |
| 149 | |
| 150 | const render = (): void => { |
| 151 | lineCount = writePromptFrame( |
| 152 | output, |
| 153 | renderInstallPrompt(options, choices, selectedIndex), |
| 154 | lineCount, |
| 155 | ); |
| 156 | }; |
| 157 | |
| 158 | const onKeypress = (_input: string, key: { name?: string; ctrl?: boolean }): void => { |
| 159 | if (key.name === 'up') { |
| 160 | selectedIndex = moveInstallPromptSelection(selectedIndex, 'up', choices.length); |
| 161 | render(); |
| 162 | return; |
| 163 | } |
| 164 | if (key.name === 'down') { |
| 165 | selectedIndex = moveInstallPromptSelection(selectedIndex, 'down', choices.length); |
| 166 | render(); |
| 167 | return; |
| 168 | } |
| 169 | if (key.name === 'return' || key.name === 'enter') { |
| 170 | const chosen = choices[selectedIndex]?.value ?? 'skip'; |
| 171 | finish(chosen); |
| 172 | return; |
| 173 | } |
| 174 | if (key.name === 'escape' || (key.ctrl === true && key.name === 'c')) { |
| 175 | finish('skip'); |
| 176 | } |
| 177 | }; |
| 178 | |
| 179 | emitKeypressEvents(input); |
| 180 | if (canSetRawMode) { |
no test coverage detected