--- /dev/null
+'use strict';
+
+const isTerm = process.env.TERM_PROGRAM === 'Apple_Terminal';
+const colors = require('ansi-colors');
+const utils = require('./utils');
+const ansi = module.exports = exports;
+const ESC = '\u001b[';
+const BEL = '\u0007';
+let hidden = false;
+
+const code = ansi.code = {
+ bell: BEL,
+ beep: BEL,
+ beginning: `${ESC}G`,
+ down: `${ESC}J`,
+ esc: ESC,
+ getPosition: `${ESC}6n`,
+ hide: `${ESC}?25l`,
+ line: `${ESC}2K`,
+ lineEnd: `${ESC}K`,
+ lineStart: `${ESC}1K`,
+ restorePosition: ESC + (isTerm ? '8' : 'u'),
+ savePosition: ESC + (isTerm ? '7' : 's'),
+ screen: `${ESC}2J`,
+ show: `${ESC}?25h`,
+ up: `${ESC}1J`
+};
+
+const cursor = ansi.cursor = {
+ get hidden() {
+ return hidden;
+ },
+
+ hide() {
+ hidden = true;
+ return code.hide;
+ },
+ show() {
+ hidden = false;
+ return code.show;
+ },
+
+ forward: (count = 1) => `${ESC}${count}C`,
+ backward: (count = 1) => `${ESC}${count}D`,
+ nextLine: (count = 1) => `${ESC}E`.repeat(count),
+ prevLine: (count = 1) => `${ESC}F`.repeat(count),
+
+ up: (count = 1) => count ? `${ESC}${count}A` : '',
+ down: (count = 1) => count ? `${ESC}${count}B` : '',
+ right: (count = 1) => count ? `${ESC}${count}C` : '',
+ left: (count = 1) => count ? `${ESC}${count}D` : '',
+
+ to(x, y) {
+ return y ? `${ESC}${y + 1};${x + 1}H` : `${ESC}${x + 1}G`;
+ },
+
+ move(x = 0, y = 0) {
+ let res = '';
+ res += (x < 0) ? cursor.left(-x) : (x > 0) ? cursor.right(x) : '';
+ res += (y < 0) ? cursor.up(-y) : (y > 0) ? cursor.down(y) : '';
+ return res;
+ },
+
+ restore(state = {}) {
+ let { after, cursor, initial, input, prompt, size, value } = state;
+ initial = utils.isPrimitive(initial) ? String(initial) : '';
+ input = utils.isPrimitive(input) ? String(input) : '';
+ value = utils.isPrimitive(value) ? String(value) : '';
+
+ if (size) {
+ let codes = ansi.cursor.up(size) + ansi.cursor.to(prompt.length);
+ let diff = input.length - cursor;
+ if (diff > 0) {
+ codes += ansi.cursor.left(diff);
+ }
+ return codes;
+ }
+
+ if (value || after) {
+ let pos = (!input && !!initial) ? -initial.length : -input.length + cursor;
+ if (after) pos -= after.length;
+ if (input === '' && initial && !prompt.includes(initial)) {
+ pos += initial.length;
+ }
+ return ansi.cursor.move(pos);
+ }
+ }
+};
+
+const erase = ansi.erase = {
+ screen: code.screen,
+ up: code.up,
+ down: code.down,
+ line: code.line,
+ lineEnd: code.lineEnd,
+ lineStart: code.lineStart,
+ lines(n) {
+ let str = '';
+ for (let i = 0; i < n; i++) {
+ str += ansi.erase.line + (i < n - 1 ? ansi.cursor.up(1) : '');
+ }
+ if (n) str += ansi.code.beginning;
+ return str;
+ }
+};
+
+ansi.clear = (input = '', columns = process.stdout.columns) => {
+ if (!columns) return erase.line + cursor.to(0);
+ let width = str => [...colors.unstyle(str)].length;
+ let lines = input.split(/\r?\n/);
+ let rows = 0;
+ for (let line of lines) {
+ rows += 1 + Math.floor(Math.max(width(line) - 1, 0) / columns);
+ }
+ return (erase.line + cursor.prevLine()).repeat(rows - 1) + erase.line + cursor.to(0);
+};