dop-stick
Version:
Source control tooling for versionable-upgradeable smart contracts
152 lines • 6.28 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Prompt = void 0;
const terminal_1 = require("./terminal");
const events_1 = require("events");
class Prompt extends events_1.EventEmitter {
constructor() {
super();
this.isReading = false;
process.stdin.setEncoding('utf8');
}
static getInstance() {
if (!Prompt.instance) {
Prompt.instance = new Prompt();
}
return Prompt.instance;
}
async ask(question, options = {}) {
var _a, _b;
if (this.isReading) {
throw new Error('Another prompt is already active');
}
this.isReading = true;
let input = '';
let cursorPos = 0;
// Setup raw mode
const wasRaw = process.stdin.isRaw;
(_b = (_a = process.stdin).setRawMode) === null || _b === void 0 ? void 0 : _b.call(_a, true);
return new Promise((resolve) => {
const cleanup = () => {
var _a, _b;
(_b = (_a = process.stdin).setRawMode) === null || _b === void 0 ? void 0 : _b.call(_a, wasRaw);
process.stdin.removeListener('data', onData);
this.isReading = false;
terminal_1.Terminal.write('\n');
};
const render = () => {
terminal_1.Terminal.eraseLine();
terminal_1.Terminal.cursorTo(0);
const displayText = options.mask ? '•'.repeat(input.length) : input;
terminal_1.Terminal.write(`${question} ${displayText}`);
};
const onData = (data) => {
const key = data.toString();
// Handle special keys
switch (key) {
case '\u0003': // Ctrl+C
cleanup();
process.exit();
break;
case '\r': // Enter
case '\n':
const value = input || options.default || '';
if (options.validate) {
const result = options.validate(value);
if (result !== true) {
terminal_1.Terminal.write('\n');
terminal_1.Terminal.write(terminal_1.Terminal.style(result.toString(), terminal_1.Terminal.colors.red));
terminal_1.Terminal.write('\n');
render();
return;
}
}
cleanup();
resolve(options.transformer ? options.transformer(value) : value);
break;
case '\u007f': // Backspace
if (cursorPos > 0) {
input = input.slice(0, -1);
cursorPos--;
render();
}
break;
default:
if (key.charCodeAt(0) < 32)
return; // Ignore control characters
input += key;
cursorPos++;
render();
}
};
process.stdin.on('data', onData);
render();
});
}
async confirm(message, defaultValue = true) {
const response = await this.ask(`${message} ${defaultValue ? '(Y/n)' : '(y/N)'}: `, {
default: defaultValue ? 'y' : 'n',
validate: (input) => {
const normalized = input.toLowerCase();
return ['y', 'n', 'yes', 'no', ''].includes(normalized) ||
'Please answer with y/n';
},
});
return !!response;
}
async select(message, choices, defaultChoice) {
if (choices.length === 0) {
throw new Error('No choices provided');
}
terminal_1.Terminal.write(`${message}\n`);
let selectedIndex = defaultChoice ?
choices.indexOf(defaultChoice) : 0;
const render = () => {
choices.forEach((choice, index) => {
terminal_1.Terminal.eraseLine();
terminal_1.Terminal.cursorTo(0);
const prefix = index === selectedIndex ? '❯' : ' ';
terminal_1.Terminal.write(`${prefix} ${index === selectedIndex ?
terminal_1.Terminal.style(choice, terminal_1.Terminal.colors.cyan) :
choice}\n`);
});
terminal_1.Terminal.cursorTo(0);
terminal_1.Terminal.cursorUp(choices.length - selectedIndex);
};
return new Promise((resolve) => {
var _a, _b;
const onData = (data) => {
const key = data.toString();
switch (key) {
case '\u001b[A': // Up arrow
selectedIndex = (selectedIndex - 1 + choices.length) % choices.length;
render();
break;
case '\u001b[B': // Down arrow
selectedIndex = (selectedIndex + 1) % choices.length;
render();
break;
case '\r': // Enter
cleanup();
resolve(choices[selectedIndex]);
break;
case '\u0003': // Ctrl+C
cleanup();
process.exit();
break;
}
};
const cleanup = () => {
var _a, _b;
(_b = (_a = process.stdin).setRawMode) === null || _b === void 0 ? void 0 : _b.call(_a, false);
process.stdin.removeListener('data', onData);
terminal_1.Terminal.write('\n');
};
(_b = (_a = process.stdin).setRawMode) === null || _b === void 0 ? void 0 : _b.call(_a, true);
process.stdin.on('data', onData);
render();
});
}
}
exports.Prompt = Prompt;
//# sourceMappingURL=prompt.js.map