This is possible in Linux terminal because there is shell like fish that use different highlighting for input text. Is it possible to have something like this in Node.js. Or do I need to reimplement readLine library with this feature.
Does anyone know how to do this in Node.js? I was checking the code for fish on GitHub and it seems that the project use NCurses. Can I do the same in Node.js to have REPL where input text is in color?
EDIT:
I've tested this code from #MehdiBelbal solution:
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question("lips> ", function(code) {
console.log('\ncode is ' + code);
rl.close();
});
rl._writeToOutput = function _writeToOutput(stringToWrite) {
rl.output.write(stringToWrite.replace(/define/g, '\u001b[1;34mdefine\x1b[0m'));
};
but it don't highlight the word define after you type it, you need to type space (or any character) and delete it with backspace.
You can acheive this by overriding _writeToOutput method
The '\x1b[31m' is the console red color unicode
you need to add '\x1b[0m' is the reset,
it is necessary for the colors to stop at this position:
rl._writeToOutput = function _writeToOutput(stringToWrite) {
rl.output.write('\x1b[31m'+stringToWrite+'\x1b[0m');
};
colors unicodes:
Black: \u001b[30m.
Red: \u001b[31m.
Green: \u001b[32m.
Yellow: \u001b[33m.
Blue: \u001b[34m.
Magenta: \u001b[35m.
Cyan: \u001b[36m.
White: \u001b[37m.
code example:
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question("code: ", function(code) {
console.log('\ncode is ' + code);
rl.close();
});
// force trigger of _writeToOutput on each keystroke
process.stdin.on('keypress', (c, k) => {
// setTimeout is needed otherwise if you call console.log
// it will include the prompt in the output
setTimeout(() => {
rl._refreshLine();
}, 0);
});
rl._writeToOutput = function _writeToOutput(stringToWrite) {
rl.output.write(stringToWrite.replace(/define/g, '\u001b[1;34mdefine\x1b[0m'));
};
type "define" to have it in blue.
If you mean the console, i can suggest the extension Chalk.
Example using chalk:
const chalk = require("chalk");
//...
console.log(chalk.red("Red text, ") + "normal text");
This will log "Red text, " in red.
Related
In Python I used input function to get user input but in javascript I am trying to use prompt()
which I seen in goolgle search but it is not working. I am using visual studio code editor.
the code is something like that,
let name = prompt('what is your name')
console.log(name + 'is your name')
If you are using NodeJS, to prompt for user input, you can use the readline module.
Here is an example of how you can prompt the user for their name and then greet them:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('What is your name? ', (name) => {
console.log(`Hello, ${name}!`);
rl.close();
});
More info: https://nodejs.org/api/readline.html.
I'd like to create a convenience function that does something like this for the purposes of CodeAbbey:
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var lines = [];
rl.on('line', (line) => {
lines.push(line);
});
return lines;
However, because of how readline functions as an event handler of course all I get back is an empty array.
How do I get readline to carry out the desired behavior here? Or do I use some other library? I'd rather just use "default" components but if I have to use something else I will.
var lines = [];
rl.on('line', (line) => {
lines.push(line);
}).on('close', () => {
// Do what you need to do with lines here
process.exit(0);
});
As Node.js runs on an event-loop, a lot of the functionality available in many packages, including Readline, are asynchronous. In general you will need to process lines when the close event is emitted.
You may find this very similar resolved question helpful:
node.js: read a text file into an array. (Each line an item in the array.)
Hope this helps!
You'll want to access the lines array on close event:
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var lines = [];
rl.on('line', (line) => {
lines.push(line);
});
rl.on('close', () => {
console.log(lines);
});
This code will establish the createInterface, and initialize an empty of array lines. At the prompt, when the user hits the enter key it fires the "line" event and adds the previous written line to the lines array. When you close the interface (by killing the process or manually closing in code) it will log out the array.
$ node readlines.js
this is
the second line
third
[ 'this is', 'the second line', 'third' ]
So I'm using this example code from the NodeJS docs:
const readline = require('readline');
const rl = readline.createInterface(process.stdin, process.stdout);
console.log("Hello!");
rl.setPrompt('OHAI> ');
rl.prompt();
rl.on('line', (line) => {
switch(line.trim()) {
case 'hello':
console.log('world!');
break;
default:
console.log('Say what? I might have heard `' + line.trim() + '`');
break;
}
rl.prompt();
}).on('close', () => {
console.log('Have a great day!');
process.exit(0);
});
I'm on Windows, running NodeJS 6.0.0. When I run the file, it writes "Hello!", followed by the first "OHAI> ". So far so good. Now I try writing an arbitrary "asd". When I press enter, one of two things happens:
It prints:
asd
Say what? I might have heard 'asd'
OHAI>
It prints
Say what? I might have heard 'asd'
OHAI>
This only happens on the first input line. It seems to be completely random, however if, after I type node test.js, I press enter fast enough, sometimes I get a newline before the first "OHAI> " and it doesn't print my arbitrary input.
Is there something wrong with the example? Is it a bug in NodeJS? Even if it can't be fixed, I'd be relieved to know what causes it, since I've been pulling my hairs out for hours now.
This should solve the issue.
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
I'm still not sure why this happens, but I've found a way around it. It's a bit ugly, but it does the job.
var rl;
function cli() {
const readline = require('readline');
rl = readline.createInterface(process.stdin, process.stdout);
rl.prompt();
rl.on('line', exec_cmd);
rl.on('close', () => {
console.log('And now we part company.');
process.exit(0);
});
}
function fixfunc() {
//get first input
var input = process.stdin.read();
if (input == null)
return;
input = input.toString("utf-8");
//No longer needed, so remove the listener
process.stdin.removeListener('readable', fixfunc);
process.stdin.resume();
//do whatever you want with the input
exec_cmd(input);
//Initialize readline and let it do its job
cli();
}
process.stdin.pause();
process.stdin.on('readable', fixfunc);
process.stdout.write("> Welcome, Commander!\n> ");
What this basically does, is pause stdin, get the first input, manually call the parsing function and then initalize readline and let it do its job.
I am using the readline module to create a command line interface (CLI) for an application in Node.js.
The problem is that I can not scroll up to view the past commands as I usually can in Terminal. My CLI is just a fixed window and if I print too much out to the screen, I lose information at the top and there is no way to scroll up to see it.
(I am running my program on Mac OSX Mavericks)
Thanks in advance.
Code Snippet:
var readline = require('readline');
var Cli = function () {
this.txtI = process.stdin;
this.txtO = process.stdout;
process.stdout.write('CLI initialized.');
this.rl = readline.createInterface({input: this.txtI, output: this.txtO });
this.rl.setPrompt('>>>');
this.rl.prompt();
this.rl.on('line', function(line) {
var input = line.toString().trim();
if (input) {
this.txtO.write('cmd: ' + input);
}
this.rl.prompt();
}.bind(this)).on('close', function() {
this.txtO.write('Have a great day!');
process.exit(0);
}.bind(this));
};
new Cli();
Save this file as snippet.js and run
node snippet.js
in terminal.
It probably is working, just readline is overwriting your line. Try outputting multiple lines:
process.stdout.write("1\n2\n3\n4\n5");
Readline is quite an awesome module. History is already there. As is the possibility to add completion. Try the snippet below.
var readline = require('readline');
function createCLI(opt) {
var rl = readline.createInterface({
input : opt.input,
output : opt.output,
terminal : opt.terminal || true,
completer : opt.completer ||
function asyncCompleter(linePartial, callback){
var completion = linePartial.split(/[ ]+/);
callback(null, [completion, linePartial]);
}
});
rl.on('line', function(line) {
if( !line.trim() ){ this.prompt(); }
else { this.write(line); }
}).on('close', function() {
this.output.write('\n Have a great day!');
process.exit(0);
}).setPrompt(' > ');
rl.output.write(' CLI initialized\n');
return rl;
}
var cli = createCLI({
input : process.stdin,
output : process.stdout
});
cli.prompt();
I'm trying to read user input with this coffee code:
_readEmail = (program, opts, c, u, cb) ->
program.prompt 'email: ', /^.+#.+\..+$/, (email) =>
u.email = email
cb()
However, backspace is not handled correctly. Its just read as another character, and not deleting the characters.
Is there a simple way to handle this?
You should use the readline module:
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) {
// TODO: Log the answer in a database
console.log("Thank you for your valuable feedback:", answer);
rl.close();
});
See http://nodejs.org/api/readline.html or https://sourcegraph.com/github.com/joyent/node/symbols/javascript/lib/readline.js for docs and examples.