UNPKG

@eagleoutice/flowr-dev

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

72 lines 2.87 kB
"use strict"; 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