How is autocomplete shadow in nodejs implemented as a console application?
By "autocomplete shadow" I mean ... as I type in the node REPL 'func' without hitting tab I get a shadow of the keyword 'function':
How can I do this in my own console app:
// Simple REPL with tab completion ... how to make it into a REPL with shadow completion?
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
completer: (line) => { // This will only give me tab completion
const completions = ['function', 'let', 'const']
const hits = completions.filter(completion => completion.startsWith(line))
return [hits.length ? hits : completions, line]
}
})
rl.prompt()
rl.on('line', input => {
console.log(input)
rl.prompt()
})
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'm trying to query for sixel support in Node.js using the Primary Device Attributes ANSI escape code but I can't find a way to catch the terminal response.
In a Linux environment, it's as simple as
echo -e '\e[0c'
However, in Node.js executing a command and capturing its stdin reply appears harder than it sounds.
Since not all OSes and environments support the -e option, I need to create a Node.js implementation that does that in a different way.
I started by trying to use readline:
const readline = require("readline")
const ESC = '\u001B[';
const askText = prompt => new Promise((resolve) => {
const rl = readline.createInterface(process.stdin, process.stdout)
rl.question(prompt, (answer) => {
resolve(answer)
rl.close()
})
})
askText(ESC + "0c").then(console.log)
but this just showed a prompt and waited for the user to press enter.
I also tried streaming it and logging it to no avail
const readline = require("readline")
const toReadableStream = require("to-readable-stream")
const wstream = require("fs").createWriteStream("a.txt")
const rl = readline.createInterface({
input: toReadableStream(code), output: wstream
})
rl.on("line", (line) => {
console.log(`Received: ${JSON.stringify(line)}`);
})
I also investigated using child_process.exec but it doesn't support a stdin output as far as I can tell.
How should I actually do this?
Here's a simple solution (suggested by #jerch):
const ESC = "\u001B["
stdin.setEncoding("utf8")
stdin.setRawMode(true)
stdin.once("data", data => {
// Handle resulting data...
stdin.setRawMode(false)
stdin.destroy()
})
stdout.write(ESC + '0c')
I was running code from here:
https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_example_read_file_stream_line_by_line
const fs = require('fs');
const readline = require('readline');
async function processLineByLine() {
const fileStream = fs.createReadStream('input.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
}
}
processLineByLine();
and got this warning:
(node:13735) ExperimentalWarning: readline Interface [Symbol.asyncIterator] is an experimental feature. This feature could change at any time
(node:13735) ExperimentalWarning: Readable[Symbol.asyncIterator] is an experimental feature. This feature could change at any time
What is experimental exactly? There is no line number.
It says:
readline Interface [Symbol.asyncIterator]
So look for an interface:
const rl = readline.createInterface
that you are iterating over:
const line of rl
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' ]
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();