是否可以使用question
将命令提示符(只有Node.js提示符或类似内容)固定到终端的底部,并在其上方记录输出。
一个非常糟糕的例子:
Your favourite food is sushi.
Your favourite food is chicken.
Your favourite food is okra.
--> What is your favourite food?
基本上,我希望用户始终能够输入,并在输入上方回显输入。
interface.question("What is your favourite food?", function(answer) {
// output the answer above where this prompt was
// and somehow keep this same prompt where is is
});
我希望使用它的特定应用程序是一个简单的IRC客户端,我有一个供用户输入的位置,并具有所有输出(用户键入的内容,以及其他人也输入的内容)输出在用户输入的上方。下图中的线条是虚构的。
----------------------------------------------------------------------
| |
| |
| |
| |
| |
| |
| |
| Stuff |
| Stuff |
| Stuff |
----------------------------------------------------------------------
| --> The user can type here |
----------------------------------------------------------------------
答案 0 :(得分:9)
兼容:Linux / Windows;)
功能:
请参阅https://asciinema.org/a/10583,是控制台记录。
myReadline.js:const readline = require('readline'),
util = require('util'),
EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
var rl,
stdoutMuted = false,
myPrompt = "> ",
completions = [];
module.exports = (function() {
return {
start: start,
getPrompt: function() {
return myPrompt;
},
isMuted: function() {
return stdoutMuted;
},
setCompletion: function(obj) {
completions = (typeof obj == "object") ? obj : completions;
},
setMuted: function(bool, msg) {
stdoutMuted = !!bool;
msg = (msg && typeof msg == "string") ? msg : "> [hidden]";
rl.setPrompt((!stdoutMuted) ? myPrompt : msg);
return stdoutMuted;
},
setPrompt: function(str) {
myPrompt = str;
rl.setPrompt(myPrompt);
},
on: function(line) {
myEmitter.on.apply(myEmitter, arguments);
}
};
})();
function start(strPrompt, callback) {
myPrompt = strPrompt || "> ";
rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
completer: completer
});
rl.setPrompt(myPrompt);
rl.on("line", function(line) {
if (!stdoutMuted)
rl.history.push(line);
myEmitter.emit("line", line);
rl.prompt();
});
rl.on("close", function() {
myEmitter.emit("close");
return process.exit(1);
});
rl.on("SIGINT", function() {
rl.clearLine();
if (!myEmitter.emit("SIGINT", rl))
process.exit(1);
});
rl.prompt();
hiddenOverwrite();
consoleOverwrite();
console.log(">> Readline : Ok.");
}
function hiddenOverwrite() {
rl._refreshLine = (function(refresh) {
//https://github.com/nodejs/node/blob/v9.5.0/lib/readline.js#L335
return function _refreshLine() {
if (stdoutMuted) {
var abc = rl.line;
rl.line = "";
}
refresh.apply(rl);
if (stdoutMuted) {
rl.line = abc;
}
}
})(rl._refreshLine);
//https://github.com/nodejs/node/blob/v9.5.0/lib/readline.js#L442
function _insertString(c) {
if (this.cursor < this.line.length) {
var beg = this.line.slice(0, this.cursor);
var end = this.line.slice(this.cursor, this.line.length);
this.line = beg + c + end;
this.cursor += c.length;
this._refreshLine();
} else {
this.line += c;
this.cursor += c.length;
if (this._getCursorPos().cols === 0) {
this._refreshLine();
} else {
if (!stdoutMuted) {
this._writeToOutput(c);
}
}
// a hack to get the line refreshed if it's needed
this._moveCursor(0);
}
};
rl._insertString = _insertString;
}
function consoleOverwrite() {
var myWrite = function(stream, string, errorhandler) {
process.stdout.write(rl.columns);
var nbline = Math.ceil((rl.line.length + 3) / rl.columns);
var text = "";
text += "\n\r\x1B[" + nbline + "A\x1B[0J";
text += string + "\r";
text += Array(nbline).join("\r\x1B[1E");
stream.write(text, errorhandler);
rl._refreshLine();
};
const kGroupIndent = Symbol('groupIndent');
console[kGroupIndent] = '';
let MAX_STACK_MESSAGE;
function noop() {}
//Internal function console.js : https://github.com/nodejs/node/blob/v9.5.0/lib/console.js#L96
function write(ignoreErrors, stream, string, errorhandler, groupIndent) {
if (groupIndent.length !== 0) {
if (string.indexOf('\n') !== -1) {
string = string.replace(/\n/g, `\n${groupIndent}`);
}
string = groupIndent + string;
}
string += "\n";
if (ignoreErrors === false) return myWrite(stream, string, errorhandler);
try {
stream.once('error', noop);
myWrite(stream, string, errorhandler);
} catch (e) {
if (MAX_STACK_MESSAGE === undefined) {
try {
function a() {
a();
}
} catch (err) {
MAX_STACK_MESSAGE = err.message;
}
}
if (e.message === MAX_STACK_MESSAGE && e.name === 'RangeError')
throw e;
} finally {
stream.removeListener('error', noop);
}
}
console.log = function log(...args) {
write(console._ignoreErrors,
console._stdout,
util.format.apply(null, args),
console._stdoutErrorHandler,
console[kGroupIndent]);
};
console.debug = console.log;
console.info = console.log;
console.dirxml = console.log;
console.warn = function warn(...args) {
write(console._ignoreErrors,
console._stderr,
util.format.apply(null, args),
console._stderrErrorHandler,
console[kGroupIndent]);
};
console.error = console.warn;
console.dir = function dir(object, options) {
options = Object.assign({
customInspect: false
}, options);
write(console._ignoreErrors,
console._stdout,
util.inspect(object, options),
console._stdoutErrorHandler,
console[kGroupIndent]);
};
}
function completer(line) {
var hits = completions.filter(function(c) {
return c.indexOf(line) == 0;
});
if (hits.length == 1) {
return [hits, line];
} else {
console.log("Suggest :");
var list = "",
l = 0,
c = "",
t = hits.length ? hits : completions;
for (var i = 0; i < t.length; i++) {
c = t[i].replace(/(\s*)$/g, "")
if (list != "") {
list += ", ";
}
if (((list + c).length + 4 - l) > process.stdout.columns) {
list += "\n";
l = list.length;
}
list += c;
}
console.log(list + "\n");
return [hits, line];
}
}
main.js:
process.stdout.write("\x1Bc");
const promptFixed = require("./myReadline.js");
// in same file: const promptFixed = module.exports;
promptFixed.start();
promptFixed.setCompletion(["help", "command1", "command2", "login", "check", "ping"]);
promptFixed.on("line", function(line) {
console.log("cmd:", line);
if (line == "help") {
console.log("help: To get this message.");
} else if (line == "pwd") {
console.log("toggle muted", !promptFixed.isMuted());
promptFixed.setMuted(!promptFixed.isMuted(), "> [hidden]");
return true;
}
if (promptFixed.isMuted())
promptFixed.setMuted(false);
});
promptFixed.on("SIGINT", function(rl) {
rl.question("Confirm exit : ", function(answer) {
console.log(arguments);
return (answer.match(/^o(ui)?$/i) || answer.match(/^y(es)?$/i)) ? process.exit(1) : rl.output.write("> ");
});
});
function main() {
var ___i = 0;
setInterval(function() {
var num = function() {
return Math.floor(Math.random() * 255) + 1;
};
console.log(num() + "." + num() + "." + num() + " user connected.");
}, 1700);
}
setTimeout(function() {
main();
}, 10);
promptFixed.on("line", function(line) {
try {
console.log(eval(line));
} catch (e) {
console.error(e);
}
});
答案 1 :(得分:3)
我正在使用inquirer来解决这类问题..已经解决了所有这些问题..它很容易使用,并且你有不同类型的propmt类型。
这里有一个文字的例子:
var inquirer = require('inquirer');
inquirer.prompt([/* Pass your questions in here */]).then(function (answers) {
// Use user feedback for... whatever!!
});
答案 2 :(得分:2)
这是一个简单的解决方案(在macos上使用node v6.4.0进行测试):
const readline = require('readline');
const rl = readline.createInterface(process.stdin, process.stdout);
// Logs a message keeping prompt on last line
function log(message) {
readline.cursorTo(process.stdout, 0);
console.log(message);
rl.prompt(true);
}
// Testing the solution
rl.question('Enter something...:', userInput => {
log('You typed ' + userInput);
rl.close();
});
log('this should appear above the prompt');
setTimeout(
() => log('this should appear above the prompt'),
1000
);
答案 3 :(得分:0)
只需使用readline核心模块:
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question("What do you think of node.js? ", function(answer) {
console.log("Thank you for your valuable feedback:", answer);
rl.close();
});
这将解决您的问题:
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var fav_foods = [];
var ask_question = function() {
rl.question("What is your favourite food? ", function(answer) {
fav_foods.push(answer)
fav_foods.forEach(function (element) {
console.log("Your favourite food is " + element)
})
ask_question()
});
}
ask_question()