UNPKG

promptify

Version:
209 lines (174 loc) 7.67 kB
"use strict"; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var ul = require("ul"), isWin = require("is-win"), fs = require("fs"); var CARRIAGE_RETURN = 13; var Promptify = function () { /** * Promptify * Creates a new `Promptify`. In most of the cases, * there will be one such instance per process. * * @name Promptify * @function * @param {Object} conf The `Promptify` config: * @returns {Promptify} The `Promptify` instance. */ function Promptify(conf) { _classCallCheck(this, Promptify); conf = ul.merge(conf, { sigint: true }); this.conf = conf; } /** * sync * Synchronous version of the prompt. * * @name sync * @function * @param {String} message The message do display. * @param {String} defMsg The default value. * @param {Object} options An object containing the following fields: * * - `char` (String): The character to display when writing something. For * example, if it's `*`, the text characters will be replaced with `*`. * - `delimiter` (String): The delimiter between message and the value (default: `": "`). * * @returns {String} The result. */ _createClass(Promptify, [{ key: "sync", value: function sync(message, defMsg, options) { var insert = 0, savedinsert = 0, res = void 0; if ((typeof defMsg === "undefined" ? "undefined" : _typeof(defMsg)) === "object") { options = defMsg; defMsg = ""; } options = ul.merge(options, { delimiter: ": " }); message = message || ""; message = "" + message + options.delimiter; var char = options.char; var mmessageed = "char" in options; var fd = isWin() ? process.stdin.fd : fs.openSync("/dev/tty", "rs"); var wasRaw = process.stdin.isRaw; if (!wasRaw) { process.stdin.setRawMode(true); } var buf = new Buffer.alloc(3); var str = "", character = void 0, read = void 0; if (message) { process.stdout.write(message); } var cycle = 0; var prevComplete = void 0; while (true) { read = fs.readSync(fd, buf, 0, 3); if (read > 1) { switch (buf.toString()) { // Up/Down arrows case "\x1B[A": case "\x1B[B": process.stdout.write("\x1B[2K\x1B[0G" + message + str); break; // Left arrow case "\x1B[D": if (mmessageed) break; var before = insert; insert = --insert < 0 ? 0 : insert; if (before - insert) process.stdout.write("\x1B[1D"); break; // Right arrow case "\x1B[C": if (mmessageed) break; insert = ++insert > str.length ? str.length : insert; process.stdout.write("\x1B[" + (insert + message.length + 1) + 'G'); break; default: if (buf.toString()) { str = str + buf.toString(); str = str.replace(/\0/g, ''); insert = str.length; process.stdout.write("\x1B[2K\x1B[0G" + message + str); process.stdout.write("\x1B[" + (insert + message.length + 1) + 'G'); buf = new Buffer(3); break; } } continue; } // if it is not a control character seq, assume only one character is read character = buf[read - 1]; // catch a ^C and return null if (character == 3) { process.stdout.write('^C\n'); fs.closeSync(fd); if (this.conf.sigint) process.exit(130); process.stdin.setRawMode(wasRaw); return null; } if (character == CARRIAGE_RETURN) { fs.closeSync(fd); break; } if (character == 127 || process.platform == 'win32' && character == 8) { //backspace if (!insert) continue; str = str.slice(0, insert - 1) + str.slice(insert); insert--; process.stdout.write("\x1B[2D"); } else { if (character < 32 || character > 126) continue; str = str.slice(0, insert) + String.fromCharCode(character) + str.slice(insert); insert++; }; if (mmessageed) { process.stdout.write("\x1B[2K\x1B[0G" + message + Array(str.length + 1).join(char)); } else { process.stdout.write("\x1B[s"); if (insert == str.length) { process.stdout.write("\x1B[2K\x1B[0G" + message + str); } else { if (message) { process.stdout.write("\x1B[2K\x1B[0G" + message + str); } else { process.stdout.write("\x1B[2K\x1B[0G" + str + "\x1B[" + (str.length - insert) + 'D'); } } process.stdout.write("\x1B[u"); process.stdout.write("\x1B[1C"); } } process.stdout.write('\n'); process.stdin.setRawMode(wasRaw); return str || defMsg || ''; } }]); return Promptify; }(); var _ = null; /** * promptify * Prompt a message to the user. The arguments are passed to the `sync` method. * * @name promptify * @function */ module.exports = function () { var _ref; if (!process.stdin.isTTY) { return; } _ = _ || new Promptify(); return (_ref = _).sync.apply(_ref, arguments); }; module.exports.Promptify = Promptify;