Added test to ensure that release notes are parsed properly Updated to latest dependencies to fix security vulnerability Updated GH Actions Workflow to run test before updating tag Updated README.md to reflect proper whatsnew documentation.
166 lines
4.6 KiB
JavaScript
166 lines
4.6 KiB
JavaScript
'use strict';
|
|
|
|
const color = require('kleur');
|
|
const Prompt = require('./prompt');
|
|
const { style, clear, figures, wrap, entriesToDisplay } = require('../util');
|
|
const { cursor } = require('sisteransi');
|
|
|
|
/**
|
|
* SelectPrompt Base Element
|
|
* @param {Object} opts Options
|
|
* @param {String} opts.message Message
|
|
* @param {Array} opts.choices Array of choice objects
|
|
* @param {String} [opts.hint] Hint to display
|
|
* @param {Number} [opts.initial] Index of default value
|
|
* @param {Stream} [opts.stdin] The Readable stream to listen to
|
|
* @param {Stream} [opts.stdout] The Writable stream to write readline data to
|
|
* @param {Number} [opts.optionsPerPage=10] Max options to display at once
|
|
*/
|
|
class SelectPrompt extends Prompt {
|
|
constructor(opts={}) {
|
|
super(opts);
|
|
this.msg = opts.message;
|
|
this.hint = opts.hint || '- Use arrow-keys. Return to submit.';
|
|
this.warn = opts.warn || '- This option is disabled';
|
|
this.cursor = opts.initial || 0;
|
|
this.choices = opts.choices.map((ch, idx) => {
|
|
if (typeof ch === 'string')
|
|
ch = {title: ch, value: idx};
|
|
return {
|
|
title: ch && (ch.title || ch.value || ch),
|
|
value: ch && (ch.value === undefined ? idx : ch.value),
|
|
description: ch && ch.description,
|
|
selected: ch && ch.selected,
|
|
disabled: ch && ch.disabled
|
|
};
|
|
});
|
|
this.optionsPerPage = opts.optionsPerPage || 10;
|
|
this.value = (this.choices[this.cursor] || {}).value;
|
|
this.clear = clear('');
|
|
this.render();
|
|
}
|
|
|
|
moveCursor(n) {
|
|
this.cursor = n;
|
|
this.value = this.choices[n].value;
|
|
this.fire();
|
|
}
|
|
|
|
reset() {
|
|
this.moveCursor(0);
|
|
this.fire();
|
|
this.render();
|
|
}
|
|
|
|
abort() {
|
|
this.done = this.aborted = true;
|
|
this.fire();
|
|
this.render();
|
|
this.out.write('\n');
|
|
this.close();
|
|
}
|
|
|
|
submit() {
|
|
if (!this.selection.disabled) {
|
|
this.done = true;
|
|
this.aborted = false;
|
|
this.fire();
|
|
this.render();
|
|
this.out.write('\n');
|
|
this.close();
|
|
} else
|
|
this.bell();
|
|
}
|
|
|
|
first() {
|
|
this.moveCursor(0);
|
|
this.render();
|
|
}
|
|
|
|
last() {
|
|
this.moveCursor(this.choices.length - 1);
|
|
this.render();
|
|
}
|
|
|
|
up() {
|
|
if (this.cursor === 0) return this.bell();
|
|
this.moveCursor(this.cursor - 1);
|
|
this.render();
|
|
}
|
|
|
|
down() {
|
|
if (this.cursor === this.choices.length - 1) return this.bell();
|
|
this.moveCursor(this.cursor + 1);
|
|
this.render();
|
|
}
|
|
|
|
next() {
|
|
this.moveCursor((this.cursor + 1) % this.choices.length);
|
|
this.render();
|
|
}
|
|
|
|
_(c, key) {
|
|
if (c === ' ') return this.submit();
|
|
}
|
|
|
|
get selection() {
|
|
return this.choices[this.cursor];
|
|
}
|
|
|
|
render() {
|
|
if (this.closed) return;
|
|
if (this.firstRender) this.out.write(cursor.hide);
|
|
else this.out.write(clear(this.outputText));
|
|
super.render();
|
|
|
|
let { startIndex, endIndex } = entriesToDisplay(this.cursor, this.choices.length, this.optionsPerPage);
|
|
|
|
// Print prompt
|
|
this.outputText = [
|
|
style.symbol(this.done, this.aborted),
|
|
color.bold(this.msg),
|
|
style.delimiter(false),
|
|
this.done ? this.selection.title : this.selection.disabled
|
|
? color.yellow(this.warn) : color.gray(this.hint)
|
|
].join(' ');
|
|
|
|
// Print choices
|
|
if (!this.done) {
|
|
this.outputText += '\n';
|
|
for (let i = startIndex; i < endIndex; i++) {
|
|
let title, prefix, desc = '', v = this.choices[i];
|
|
|
|
// Determine whether to display "more choices" indicators
|
|
if (i === startIndex && startIndex > 0) {
|
|
prefix = figures.arrowUp;
|
|
} else if (i === endIndex - 1 && endIndex < this.choices.length) {
|
|
prefix = figures.arrowDown;
|
|
} else {
|
|
prefix = ' ';
|
|
}
|
|
|
|
if (v.disabled) {
|
|
title = this.cursor === i ? color.gray().underline(v.title) : color.strikethrough().gray(v.title);
|
|
prefix = (this.cursor === i ? color.bold().gray(figures.pointer) + ' ' : ' ') + prefix;
|
|
} else {
|
|
title = this.cursor === i ? color.cyan().underline(v.title) : v.title;
|
|
prefix = (this.cursor === i ? color.cyan(figures.pointer) + ' ' : ' ') + prefix;
|
|
if (v.description && this.cursor === i) {
|
|
desc = ` - ${v.description}`;
|
|
if (prefix.length + title.length + desc.length >= this.out.columns
|
|
|| v.description.split(/\r?\n/).length > 1) {
|
|
desc = '\n' + wrap(v.description, { margin: 3, width: this.out.columns });
|
|
}
|
|
}
|
|
}
|
|
|
|
this.outputText += `${prefix} ${title}${color.gray(desc)}\n`;
|
|
}
|
|
}
|
|
|
|
this.out.write(this.outputText);
|
|
}
|
|
}
|
|
|
|
module.exports = SelectPrompt;
|