cli-select
Version:
Simple and interactive solution to provide a list of selectable items on the command line
159 lines (124 loc) • 3.35 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _readline = _interopRequireDefault(require("readline"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Handle cli input
*/
class Input {
/**
* Input constructor
*
* @param {any} stream - stream to catch (optional)
*/
constructor(stream = process.stdin) {
// set default values
this.stream = stream;
this.values = [];
this.selectedValue = 0;
this.onSelectListener = () => {};
this.onKeyPress = this.onKeyPress.bind(this);
}
/**
* Set the available values
*
* @param {array} values - all available values
*/
setValues(values) {
this.values = values;
if (this.renderer) {
this.renderer.setValues(values);
}
}
/**
* Set the default value
*
* @param {number} defaultValue - default value id
*/
setDefaultValue(defaultValue) {
this.selectedValue = defaultValue;
}
/**
* Attach a renderer to the input catcher
*
* @param {Renderer} renderer - renderer to use for rendering responses
*/
attachRenderer(renderer) {
this.renderer = renderer;
this.renderer.setValues(this.values);
}
/**
* Register an on select listener
*
* @param {function} listener - listener function which receives two parameters: valueId and value
*/
onSelect(listener) {
this.onSelectListener = listener;
}
/**
* Open the stream and listen for input
*/
open() {
// register keypress event
_readline.default.emitKeypressEvents(this.stream); // handle keypress
this.stream.on('keypress', this.onKeyPress); // initially render the response
if (this.renderer) {
this.renderer.render(this.selectedValue);
} // hide pressed keys and start listening on input
this.stream.setRawMode(true);
this.stream.resume();
}
/**
* Close the stream
*
* @param {boolean} cancelled - true if no value was selected (optional)
*/
close(cancelled = false) {
// reset stream properties
this.stream.setRawMode(false);
this.stream.pause(); // cleanup the output
if (this.renderer) {
this.renderer.cleanup();
} // call the on select listener
if (cancelled) {
this.onSelectListener(null);
} else {
this.onSelectListener(this.selectedValue, this.values[this.selectedValue]);
}
this.stream.removeListener('keypress', this.onKeyPress);
}
/**
* Render the response
*/
render() {
if (!this.renderer) {
return;
}
this.renderer.render(this.selectedValue);
}
/**
* Handle key press event
*
* @param {string} string - input string
* @param {object} key - object containing information about the pressed key
*/
onKeyPress(string, key) {
if (key) {
if (key.name === 'up' && this.selectedValue > 0) {
this.selectedValue--;
this.render();
} else if (key.name === 'down' && this.selectedValue + 1 < this.values.length) {
this.selectedValue++;
this.render();
} else if (key.name === 'return') {
this.close();
} else if (key.name === 'escape' || key.name === 'c' && key.ctrl) {
this.close(true);
}
}
}
}
exports.default = Input;