UNPKG

@ayonli/jsext

Version:

A JavaScript extension package for building strong and modern applications.

148 lines (145 loc) 5.29 kB
import bytes, { equals, concat } from '../../bytes.js'; import { chars } from '../../string.js'; import '../../env.js'; import '../../external/event-target-polyfill/index.js'; import '../../path.js'; import { ControlKeys, NavigationKeys, ControlSequences } from '../../cli/constants.js'; import { writeStdout, readStdin, moveLeftBy, moveRightBy, isTypingInput } from '../../cli/common.js'; const { BS, CTRL_A, CTRL_C, CTRL_E, CR, DEL, ESC, LF } = ControlKeys; const { UP, DOWN, LEFT, RIGHT } = NavigationKeys; const { CLR_RIGHT } = ControlSequences; function getMasks(mask, length) { return new Array(length).fill(mask).join(""); } async function question(message, options = {}) { const { defaultValue = "", mask } = options; const buf = []; let cursor = 0; await writeStdout(bytes(message)); if (defaultValue) { const _chars = chars(defaultValue); buf.push(..._chars); cursor += _chars.length; if (mask === undefined) { await writeStdout(bytes(defaultValue)); } else if (mask) { await writeStdout(bytes(getMasks(mask, _chars.length))); } } while (true) { const input = await readStdin(); if (!input.length || equals(input, UP) || equals(input, DOWN)) { continue; } else if (equals(input, LEFT)) { if (cursor > 0) { const char = buf[--cursor]; if (mask === undefined) { await moveLeftBy(char); } else if (mask) { await moveLeftBy(mask); } } } else if (equals(input, RIGHT)) { if (cursor < buf.length) { const char = buf[cursor++]; if (mask === undefined) { await moveRightBy(char); } else if (mask) { await moveRightBy(mask); } } } else if (equals(input, CTRL_A)) { const left = buf.slice(0, cursor); if (left.length) { cursor = 0; if (mask === undefined) { await moveLeftBy(left.join("")); } else if (mask) { await moveLeftBy(getMasks(mask, left.length)); } } } else if (equals(input, CTRL_E)) { const right = buf.slice(cursor); if (right.length) { cursor = buf.length; if (mask === undefined) { await moveRightBy(right.join("")); } else if (mask) { await moveRightBy(getMasks(mask, right.length)); } } } else if (equals(input, ESC) || equals(input, CTRL_C)) { await writeStdout(LF); return null; } else if (equals(input, CR) || equals(input, LF)) { await writeStdout(LF); return buf.join(""); } else if (equals(input, BS) || equals(input, DEL)) { if (cursor > 0) { cursor--; const [char] = buf.splice(cursor, 1); const rest = buf.slice(cursor); if (mask === undefined) { await moveLeftBy(char); await writeStdout(CLR_RIGHT); if (rest.length) { const output = rest.join(""); await writeStdout(bytes(output)); await moveLeftBy(output); } } else if (mask) { await moveLeftBy(mask); await writeStdout(CLR_RIGHT); if (rest.length) { const output = getMasks(mask, rest.length); await writeStdout(bytes(output)); await moveLeftBy(output); } } } } else if (isTypingInput(input)) { const _chars = chars(String(input)); if (cursor === buf.length) { buf.push(..._chars); cursor += _chars.length; if (mask === undefined) { await writeStdout(input); } else if (mask) { await writeStdout(bytes(getMasks(mask, _chars.length))); } } else { buf.splice(cursor, 0, ..._chars); cursor += _chars.length; if (mask === undefined) { const rest = buf.slice(cursor).join(""); await writeStdout(concat(input, bytes(rest))); await moveLeftBy(rest); } else if (mask) { const output = getMasks(mask, _chars.length); const rest = getMasks(mask, buf.slice(cursor).length); await writeStdout(bytes(output + rest)); await moveLeftBy(rest); } } } } } export { question as default }; //# sourceMappingURL=question.js.map