@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
72 lines • 2.87 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ghostHintClearSequence = exports.defaultReplHint = void 0;
exports.ghostHintShowSequence = ghostHintShowSequence;
exports.ghostHintEnabled = ghostHintEnabled;
exports.installGhostHint = installGhostHint;
exports.defaultReplHint = ':help · Tab completes · :query @config +repl.hints=false to hide';
/** ANSI that draws the dimmed `hint` and restores the cursor to where it was. */
function ghostHintShowSequence(hint) {
return `\x1b7\x1b[2m${hint}\x1b[0m\x1b8`;
}
exports.ghostHintClearSequence = '\x1b[0K';
const noopController = { show: () => { }, clear: () => { } };
/** Whether hints may be shown: enabled in the config and on an interactive TTY (honoring `NO_COLOR`/`TERM=dumb`). */
function ghostHintEnabled(config, env = process.env, stdout = process.stdout, stdin = process.stdin) {
return Boolean(config.repl.hints && stdout.isTTY && stdin.isTTY && !env.NO_COLOR && env.TERM !== 'dumb');
}
/**
* Installs an opt-out ghost hint on the REPL prompt: a dim placeholder on the empty prompt and, as the user
* types, a dim preview of the best Tab-completion. A no-op on non-interactive terminals (see
* {@link ghostHintEnabled}) and whenever the text would not fit the line, so it can never wrap or corrupt output.
*/
function installGhostHint(rl, config, { hint = exports.defaultReplHint, suggest } = {}, io = { stdin: process.stdin, stdout: process.stdout }) {
if (!ghostHintEnabled(config, process.env, io.stdout, io.stdin)) {
return noopController;
}
const state = rl;
const getLine = () => state.line ?? '';
const cursorAtEnd = () => state.cursor === undefined || state.cursor === getLine().length;
const fits = (text) => getLine().length + text.length + 6 < (io.stdout.columns ?? 80);
let shown = false;
const clear = () => {
if (shown) {
io.stdout.write(exports.ghostHintClearSequence);
shown = false;
}
};
const render = (text) => {
clear();
if (text && fits(text)) {
io.stdout.write(ghostHintShowSequence(text));
shown = true;
}
};
const update = () => {
if (!config.repl.hints) {
clear();
return;
}
const line = getLine();
if (line.length === 0) {
render(hint);
}
else if (cursorAtEnd()) {
render(suggest?.(line) ?? '');
}
else {
clear();
}
};
io.stdin.prependListener('keypress', clear);
io.stdin.on('keypress', (_s, key) => {
if (!isSubmitKey(key)) {
update();
}
});
return { show: update, clear };
}
function isSubmitKey(key) {
return key?.name === 'return' || key?.name === 'enter';
}
//# sourceMappingURL=ghost-hint.js.map