45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { createInterface } from 'node:readline';
|
|
import { Cancelled, type Io } from '../src/cli/userWizard';
|
|
|
|
export function makeIo(): { io: Io; close: () => void } {
|
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
const queue: string[] = [];
|
|
let waiting: ((line: string | null) => void) | null = null;
|
|
let ended = false;
|
|
|
|
rl.on('line', (line) => {
|
|
if (waiting) {
|
|
const w = waiting;
|
|
waiting = null;
|
|
w(line);
|
|
} else {
|
|
queue.push(line);
|
|
}
|
|
});
|
|
rl.on('close', () => {
|
|
ended = true;
|
|
if (waiting) {
|
|
const w = waiting;
|
|
waiting = null;
|
|
w(null);
|
|
}
|
|
});
|
|
|
|
async function read(question: string): Promise<string> {
|
|
rl.setPrompt(question);
|
|
rl.prompt();
|
|
const line = queue.length > 0 ? queue.shift()! : ended ? null : await new Promise<string | null>((r) => (waiting = r));
|
|
if (line === null) throw new Cancelled();
|
|
return line;
|
|
}
|
|
|
|
const io: Io = {
|
|
ask: async (question) => (await read(question)).trim(),
|
|
askExact: read,
|
|
say(line = '') {
|
|
console.log(line);
|
|
},
|
|
};
|
|
return { io, close: () => rl.close() };
|
|
}
|