StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
4.8 KiB
208 lines
4.8 KiB
4 years ago
|
'use strict';
|
||
|
|
||
|
/**
|
||
|
* `list` type prompt
|
||
|
*/
|
||
|
|
||
|
var util = require('util');
|
||
|
var Paginator = require('../utils/paginator');
|
||
|
var observe = require('../utils/events');
|
||
|
var utils = require('../utils/');
|
||
|
var Base = require('./base');
|
||
|
|
||
|
/**
|
||
|
* Module exports
|
||
|
*/
|
||
|
|
||
|
module.exports = Prompt;
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*/
|
||
|
|
||
|
function Prompt() {
|
||
|
Base.apply(this, arguments);
|
||
|
|
||
|
if (!this.opt.choices) {
|
||
|
this.throwParamError('choices');
|
||
|
}
|
||
|
|
||
|
if (Array.isArray(this.opt.default)) {
|
||
|
this.opt.choices.forEach(function(choice) {
|
||
|
if (this.opt.default.indexOf(choice.value) >= 0) {
|
||
|
choice.checked = true;
|
||
|
}
|
||
|
}, this);
|
||
|
}
|
||
|
|
||
|
this.firstRender = true;
|
||
|
this.pointer = 0;
|
||
|
|
||
|
// Make sure no default is set (so it won't be printed)
|
||
|
this.opt.default = null;
|
||
|
this.paginator = new Paginator();
|
||
|
}
|
||
|
util.inherits(Prompt, Base);
|
||
|
|
||
|
/**
|
||
|
* Start the Inquiry session
|
||
|
* @param {Function} cb Callback when prompt is done
|
||
|
* @return {this}
|
||
|
*/
|
||
|
|
||
|
Prompt.prototype._run = function(cb) {
|
||
|
this.done = cb;
|
||
|
|
||
|
var events = observe(this.rl);
|
||
|
|
||
|
var validation = this.handleSubmitEvents(events.line);
|
||
|
validation.success.forEach(this.onEnd.bind(this));
|
||
|
validation.error.forEach(this.onError.bind(this));
|
||
|
|
||
|
events.normalizedUpKey.takeUntil(validation.success).forEach(this.onUpKey.bind(this));
|
||
|
events.normalizedDownKey.takeUntil(validation.success).forEach(this.onDownKey.bind(this));
|
||
|
events.numberKey.takeUntil(validation.success).forEach(this.onNumberKey.bind(this));
|
||
|
events.spaceKey.takeUntil(validation.success).forEach(this.onSpaceKey.bind(this));
|
||
|
|
||
|
// Init the prompt
|
||
|
utils.cliCursor.hide();
|
||
|
this.render();
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Render the prompt to screen
|
||
|
* @return {Prompt} self
|
||
|
*/
|
||
|
|
||
|
Prompt.prototype.render = function(error) {
|
||
|
// Render question
|
||
|
var cursor = 0;
|
||
|
var message = this.getQuestion();
|
||
|
|
||
|
if (this.firstRender) {
|
||
|
message += '(Press <space> to select)';
|
||
|
}
|
||
|
|
||
|
// Render choices or answer depending on the state
|
||
|
if (this.status === 'answered') {
|
||
|
message += utils.chalk.cyan(this.selection.join(', '));
|
||
|
} else {
|
||
|
var choicesStr = renderChoices(this.opt.choices, this.pointer);
|
||
|
message += '\n' + this.paginator.paginate(choicesStr, this.pointer, this.opt.pageSize);
|
||
|
}
|
||
|
|
||
|
if (error) {
|
||
|
message += '\n' + utils.chalk.red('>> ') + error;
|
||
|
cursor++;
|
||
|
}
|
||
|
|
||
|
this.firstRender = false;
|
||
|
|
||
|
this.screen.render(message, {
|
||
|
cursor: cursor
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* When user press `enter` key
|
||
|
*/
|
||
|
|
||
|
Prompt.prototype.onEnd = function(state) {
|
||
|
|
||
|
this.status = 'answered';
|
||
|
|
||
|
// Rerender prompt (and clean subline error)
|
||
|
this.render();
|
||
|
|
||
|
this.screen.done();
|
||
|
utils.cliCursor.show();
|
||
|
this.done(state.value);
|
||
|
};
|
||
|
|
||
|
Prompt.prototype.onError = function(state) {
|
||
|
this.render(state.isValid);
|
||
|
};
|
||
|
|
||
|
Prompt.prototype.getCurrentValue = function() {
|
||
|
var choices = this.opt.choices.filter(function(choice) {
|
||
|
return !!choice.checked && !choice.disabled;
|
||
|
});
|
||
|
|
||
|
this.selection = utils.pluck(choices, 'short');
|
||
|
return utils.pluck(choices, 'value');
|
||
|
};
|
||
|
|
||
|
Prompt.prototype.onUpKey = function() {
|
||
|
var len = this.opt.choices.realLength;
|
||
|
this.pointer = (this.pointer > 0) ? this.pointer - 1 : len - 1;
|
||
|
this.render();
|
||
|
};
|
||
|
|
||
|
Prompt.prototype.onDownKey = function() {
|
||
|
var len = this.opt.choices.realLength;
|
||
|
this.pointer = (this.pointer < len - 1) ? this.pointer + 1 : 0;
|
||
|
this.render();
|
||
|
};
|
||
|
|
||
|
Prompt.prototype.onNumberKey = function(input) {
|
||
|
if (input <= this.opt.choices.realLength) {
|
||
|
this.pointer = input - 1;
|
||
|
this.toggleChoice(this.pointer);
|
||
|
}
|
||
|
this.render();
|
||
|
};
|
||
|
|
||
|
Prompt.prototype.onSpaceKey = function(input) {
|
||
|
this.toggleChoice(this.pointer);
|
||
|
this.render();
|
||
|
};
|
||
|
|
||
|
Prompt.prototype.toggleChoice = function(index) {
|
||
|
var checked = this.opt.choices.getChoice(index).checked;
|
||
|
this.opt.choices.getChoice(index).checked = !checked;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Function for rendering checkbox choices
|
||
|
* @param {Number} pointer Position of the pointer
|
||
|
* @return {String} Rendered content
|
||
|
*/
|
||
|
|
||
|
function renderChoices(choices, pointer) {
|
||
|
var output = '';
|
||
|
var separatorOffset = 0;
|
||
|
|
||
|
choices.forEach(function(choice, i) {
|
||
|
if (choice.type === 'separator') {
|
||
|
separatorOffset++;
|
||
|
output += ' ' + choice + '\n';
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (choice.disabled) {
|
||
|
separatorOffset++;
|
||
|
output += ' - ' + choice.name;
|
||
|
output += ' (' + (typeof choice.disabled === 'string' ? choice.disabled : 'Disabled') + ')';
|
||
|
} else {
|
||
|
var isSelected = (i - separatorOffset === pointer);
|
||
|
output += isSelected ? utils.chalk.cyan(utils.figures.pointer) : ' ';
|
||
|
output += getCheckbox(choice.checked) + ' ' + choice.name;
|
||
|
}
|
||
|
|
||
|
output += '\n';
|
||
|
});
|
||
|
|
||
|
return output.replace(/\n$/, '');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the checkbox
|
||
|
* @param {Boolean} checked - add a X or not to the checkbox
|
||
|
* @return {String} Composited checkbox string
|
||
|
*/
|
||
|
|
||
|
function getCheckbox(checked) {
|
||
|
return checked ? utils.chalk.green(utils.figures.radioOn) : utils.figures.radioOff;
|
||
|
}
|