Inquirer.js
Inquirer.js copied to clipboard
Edit Default Value on "input" Type
I came across a use-case whereby I wanted people to be able to edit their previously submitted answers. I tried utilizing the filter and transformer attributes to no avail. I think the space-bar could be used for replacing the current answer in-memory with the default value. I can submit a PR if this is desired functionality.
I created a custom prompt that can be used to override the input type and will allow you to edit the default value by pressing the spacebar. The code is the same as the input prompt of inquirer with 5 added lines to onKeypress(). It can be found below:
"use strict";
const chalk = require("chalk");
const { map, takeUntil } = require("rxjs/operators");
const Base = require("inquirer/lib/prompts/base");
const observe = require("inquirer/lib/utils/events");
class InputPrompt extends Base {
/**
* Start the Inquiry session
* @param {Function} cb Callback when prompt is done
* @return {this}
*/
_run(cb) {
this.done = cb;
// Once user confirm (enter key)
const events = observe(this.rl);
const submit = events.line.pipe(map(this.filterInput.bind(this)));
const validation = this.handleSubmitEvents(submit);
validation.success.forEach(this.onEnd.bind(this));
validation.error.forEach(this.onError.bind(this));
events.keypress
.pipe(takeUntil(validation.success))
.forEach(this.onKeypress.bind(this));
// Init
this.render();
return this;
}
/**
* Render the prompt to screen
* @return {InputPrompt} self
*/
render(error) {
let bottomContent = "";
let appendContent = "";
let message = this.getQuestion();
const transformer = this.opt.transformer;
const isFinal = this.status === "answered";
if (isFinal) {
appendContent = this.answer;
} else {
appendContent = this.rl.line;
}
if (transformer) {
message += transformer(appendContent, this.answers, { isFinal });
} else {
message += isFinal ? chalk.cyan(appendContent) : appendContent;
}
if (error) {
bottomContent = chalk.red(">> ") + error;
}
this.screen.render(message, bottomContent);
}
/**
* When user press `enter` key
*/
filterInput(input) {
if (!input) {
return this.opt.default == null ? "" : this.opt.default;
}
return input;
}
onEnd(state) {
this.answer = state.value;
this.status = "answered";
// Re-render prompt
this.render();
this.screen.done();
this.done(state.value);
}
onError({ value = "", isValid }) {
this.rl.line += value;
this.rl.cursor += value.length;
this.render(isValid);
}
/**
* When user press a key
*/
onKeypress() {
// If user presses the space-bar as the first key and default value exists, replace current value with default value
if (this.rl.line === " " && this.opt.default) {
this.rl.line = this.opt.default;
this.rl.cursor = this.opt.default.length;
}
// If user press a key, just clear the default value
if (this.opt.default) {
this.opt.default = undefined;
}
// console.log("Keypress state A: ", this.rl);
// console.log("Keypress state B: ", this);
this.render();
}
}
module.exports = InputPrompt;
looking forward to this feature
I just extended class InputPrompt, really cool solution @alex-ppg
"use strict";
const InputPrompt = require("inquirer/lib/prompts/input");
class InputPromptWithDefaultEdit extends InputPrompt {
/**
* When user press a key
*/
onKeypress() {
// If user presses the space-bar as the first key and default value exists, replace current value with default value
if (this.rl.line === " " && this.opt.default) {
this.rl.line = this.opt.default;
this.rl.cursor = this.opt.default.length;
}
// If user press a key, just clear the default value
if (this.opt.default) {
this.opt.default = undefined;
}
this.render();
}
}
module.exports = InputPromptWithDefaultEdit;
@SBoudrias tagging in case you missed the issue, looks like very useful functionality which can be added with only a few lines.
I'm not against adding this; but I think it needs some refinement on the UX and how it'd be controlled by the user. I'm not too sure about the current hotkeys proposed.
Would it work if we only auto-fill the value, and let the user delete the input with backspace? (or cmd+backspace)
If someone wants to make a PR, I'll review and make a release. I'd ask though to please implement in both the new (@inquirer/input) and old code (inquirer) as to not create more work to be done to eventually release the rewrite.
@SBoudrias Any updates here?
I'll close this one in favour of the more recent #1215 where I think we have an agreement on a suggested UX for this feature.