UNPKG

cli-kit

Version:

Everything you need to create awesome command line interfaces

172 lines (145 loc) 4.13 kB
import { encode } from './util.js'; export const bel = '\x07'; export const clear = '\x1bc'; export const cursor = { show: '\x1b[?25h', hide: '\x1b[?25l', save: '\x1b7', restore: '\x1b8', get: '\x1b[6n', home: '\x1b[H', left: '\x1b[G', down(n = 1) { return n ? `\x1b[${n}B` : ''; }, up(n = 1) { return n ? `\x1b[${n}A` : ''; }, backward(n = 1) { return n ? `\x1b[${n}D` : ''; }, forward(n = 1) { return n ? `\x1b[${n}C` : ''; }, move(dx, dy) { let s = dx ? `\x1b[${dx > 0 ? `${dx}C` : `${-dx}D`}` : ''; if (dy) { s += `\x1b[${dy > 0 ? `${dy}B` : `${-dy}A`}`; } return s; }, to(x, y) { return y ? `\x1b[${y + 1};${x + 1}H` : `\x1b[${x + 1}G`; }, position: /^\x1b\[(\d+);(\d+)R$/, next(n = 1) { return !n ? '' : (n < 0 ? '\x1b[F' : '\x1b[E').repeat(Math.abs(n)); }, prev(n = 1) { return !n ? '' : (n > 0 ? '\x1b[F' : '\x1b[E').repeat(Math.abs(n)); } }; export const custom = { echo(enabled) { return `\x1b]666;Echo=${enabled ? 'on' : 'off'}\x07`; }, exec(command) { return `\x1b]666;Exec=${encode(command)}\x07`; }, exit(code) { return `\x1b]666;Exit=${code}\x07`; }, keypress(key) { return `\x1b]666;Keypress=${encode(key)}\x07`; } }; custom.echo.re = /^\x1b\]666;Echo=(\w+)\x07$/; custom.exec.re = /^\x1b\]666;Exec=(.+)\x07$/; custom.exit.re = /^\x1b\]666;Exit=(\d+)\x07$/; custom.keypress.re = /^\x1b\]666;Keypress=(.+)\x07$/; export const erase = { down: '\x1b[J', line: '\x1b[2K', lines(count = 0) { let s = ''; while (count > 0) { s += this.line + (--count ? cursor.up() : ''); } return s ? `${s}${cursor.left}` : ''; }, screen: '\x1b[2J', toEnd: '\x1b[K', toStart: '\x1b[1K', up: '\x1b[1J' }; export const esc = '\x1b['; export const scroll = { down: '\x1b[T', up: '\x1b[S' }; /** * Creates a hyperlink for rendering in a terminal. * * @param {String} [text] - The clickable text to display. * @param {String} url - The link URL. * @returns {String} */ export function link(text, url) { return `\x1b]8;;${url || text}\x07${text}\x1b]8;;\x07`; } /** * Splits a string into an array where even number indices are plain strings and odd number * indices are ANSI escape sequences. * * @param {String} str - The string to split. * @returns {Array.<String>} */ export function split(str) { if (typeof str !== 'string') { return str; } const results = []; const re = /\x07|\x1b(?:[a-z\d]|\[\?25[hl]|\[[A-Za-z]|\[\d+[A-Za-z]|\[\d+;\d+H|\]\d+[^\x07]+\x07)/; let m; while (m = re.exec(str)) { results.push(m.index ? str.substring(0, m.index) : ''); results.push(str.substr(m.index, m[0].length)); str = str.substring(m.index + m[0].length); } if (str) { results.push(str); } return results; } const stripRegExp = /\x1b\[(;?\d+)+m/g; /** * Removes all ansi control sequences from the specified string. * * @param {String} str - The string to strip. * @returns {String} */ export function strip(str = '') { return String(str).replace(stripRegExp, ''); } /** * Converts a string to lower case without tampering with any ANSI escape sequences. * * @param {String} str - The string to lower case. * @returns {String} */ export function toLowerCase(str) { return split(str).map((s, i) => i % 2 === 0 ? s.toLowerCase() : s).join(''); } /** * Converts a string to upper case without tampering with any ANSI escape sequences. * * @param {String} str - The string to upper case. * @returns {String} */ export function toUpperCase(str) { return split(str).map((s, i) => i % 2 === 0 ? s.toUpperCase() : s).join(''); } export function trim(str) { return trimStart(trimEnd(str)); } export function trimStart(str) { if (str !== undefined && str !== null) { str = String(str).replace(/^\s*(\x07|\x1b(?:[a-z\d]|\[\?25[hl]|\[[A-Za-z]|\[\d+[A-Za-z]|\[\d+;\d+H|\]\d+[^\x07]+\x07))?\s*/, '$1'); } return str; } export function trimEnd(str) { if (str !== undefined && str !== null) { // '\u001b[' + b + 'm' str = String(str).replace(/\s*(\x07|\x1b(?:[a-z\d]|\[\?25[hl]|\[[A-Za-z]|\[\d+[A-Za-z]|\[\d+;\d+H|\]\d+[^\x07]+\x07))?\s*$/, '$1'); } return str; }