Prevent empty lines from output in node readline - node.js

When I press and hold ENTER on my keyboard, the readline module will then output empty lines to my writeable stream(in this case it is process.stdout).
But since I don't want empty lines to clutter my console I want to prevent it somehow from being outputted.
Can I use something to filter out empty lines in my stream? Maybe using a transform stream of some sorts?
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
removeHistoryDuplicates: true
});
rl.on("line", (line) => {
if(line.trim().length === 0) {
// don't output anything, but it is already too late because it is already written to stream :'-(
}
rl.prompt();
})

use this
readline.cursorTo(process.stdout, 0,0);
enter will automatically be ignored and return to the begining
https://nodejs.org/api/readline.html#readline_readline_clearline_stream_dir
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
removeHistoryDuplicates: true
});
const enterPressed=(line)=>{
return line.replace(/[^a-zA-Z]/g, "").trim().length === 0
}
rl.on("line", (line) => {
if(enterPressed(line)) {
readline.cursorTo(process.stdout, 0,0);
}
rl.prompt();
})

Related

How to read variable number of lines from the terminal?

I need to ask how many inputs the user want to give (one input per line) and read them.
I am trying to keep it as simple as possible without using any libraries or even async. Why? Because I am doing a course on Coursera and I have to upload a JavaScript/Node file as assignment. The one I wrote with async and promise got rejected (for that version look at the end of this post). Somehow input and output is not working with the "Coursera system".
So I am trying to do it without any bells and whistles:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
terminal: false
});
const r2 = readline.createInterface({
input: process.stdin,
terminal: false
});
let x = null;
let y = [];
rl.on('line', line1 => {
if (line1 !== "\n") {
x = parseInt(line1);
while(x > 0){
r2.on('line', line2 => {
y.push(line2);
});
x -= 1;
}
console.log('You entered these colors:', y);
process.exit();
}
});
Output:
3
You entered these colors: []
Expected output:
[input]3
[input]green
[input]blue
[input]red
[output]You entered these colors: ["green", "blue", "red"]
One that worked but rejected buy Coursera "assignment system":
const readline = require('readline');
const readLineAsync = () => {
const rl = readline.createInterface({
input: process.stdin,
terminal: false
});
return new Promise((resolve) => {
rl.prompt();
rl.on('line', (line) => {
rl.close();
resolve(line);
});
});
};
async function start() {
let line = null;
let colors = [];
line = await readLineAsync();
const numColors = parseInt(line);
for(let count = numColors; count > 0; count--) {
line = await readLineAsync();
colors.push(line);
}
console.log('You entered these colors:', colors);
}
start();
Initially, we want to ask how many colors the user intends to enter. We are sure the input is expected only once so r1.once() is used.
But, the number of times we ask the user for input varies according to the previous input. So we use r1.on() which will not close until terminated. We will use a variable, counter, to ensure the input is asked of the user the required number of times.
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
terminal: false
});
process.stdin.setEncoding('utf8');
rl.once('line', line => {
const count = parseInt(line.toString());
const colors = [];
let counter = 0;
rl.on('line', line => {
const color = readLine(line);
colors.push(color);
if(++counter >= count) {
console.log('You have entered these colros:', colors);
process.exit();
}
});
});
function readLine(line) {
return line.toString();
}
output
3
red
green
blue
You have entered these colros: [ 'red', 'green', 'blue' ]

Node.js readline property doesn't ask for input

Node.js readline property doesn't stop for input, instead continues program, causing app to crash. While trying to solve this I found out that apparently node does the whole code simultaneously and doesn't because of that stop for input. I found out ways to run this code but they didn't work for me.
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var token;
var pass;
rl.question('token: ', (tok) => {
token = tok;
rl.close();
});
rl.question('pass: ', (pas) => {
pass = pas;
rl.close();
});
What can I do to solve this?
I hope you are looking something like below:
const readLine = require('readline');
const util = require('util')
const { promisify } = util;
const readline = readLine.createInterface({
input: process.stdin,
output: process.stdout,
});
// Prepare readline.question for promisification
readline.question[util.promisify.custom] = (question) => {
return new Promise((resolve) => {
readline.question(question, resolve);
});
};
let questionPs = promisify(readline.question);
async function askQuestions (questions,readline) {
let answers= [];
for(let i=0;i<2;i++){
let tmp = await questionPs(q[i]);
answers.push(tmp)
}
console.log(answers);
readline.close();
}
// Usage example:
let q = ['token:','pass:']
askQuestions(q,readline)

nodejs - readline interface prompt value modification

In nodejs, I am creating a CLI using readline module. initially I using the following code to start the prompt
let _interface = require('readline').createInterface{
input: process.stdin,
output: process.stdout,
prompt: '>'};
_interface.prompt();
/*some operation*/
_interface.prompt();
But I am trying to change the prompt icon from > to $ as the user try's to change it. How can this be done, without restarting the prompt.
You can achieve this by using rl.setPrompt() method.
Consider this example
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: '> '
});
rl.prompt();
rl.on('line', (line) => {
if(line.trim()=='change --$'){
rl.setPrompt('$');
}
rl.prompt();
}).on('close', () => {
console.log('Have a great day!');
process.exit(0);
});
I hope it will work for you.

How do I use readline's rl.on('line') multiple times in Node.js?

I need to take input from the user such as the listening and connecting port, I've tried seperating the rl.on('line')'s and I've tried using them inside one another. If the is some way to save the data from the line to a global variabel that would work too, but I don't know how.
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
rl.on('line', (line) => {
const listenPort = line
rl.on('line', (line) => {
const connectPort = line
})
})

How to read line by line and detect eof (end of file)?

Followup to a solution to reading a file line by line, as described here: https://stackoverflow.com/a/16013228/570796
var fs = require('fs'),
readline = require('readline'),
instream = fs.createReadStream('/path/to/file');
var rl = readline.createInterface(
{
input: instream,
terminal: false
});
rl.on('line', function(line)
{
console.log(line);
// if(instream.isEnd()) ...
});
How do I detect if I reached the end of the file?
I understand that there is an event on the ReadStream on('end', () => {/*...*/}) But I need a solution where I can check it through an if statement.
Here's a solution:
let ended = false;
instream.on('end', () => { ended = true });
rl.on('line', function(line) {
if (ended) {
//...
However, there's a reasonable chance you don't actually need this, and your application could be structured differently.
I'm not sure whether the line event can even happen after the end event.
Turns out my suspicions were true, so you need to do it this way around.
let lastLine;
rl.on('line', line => { lastLine = line })
instream.on('end', () => {
assert.notStrictEqual(lastLine, undefined, 'There were no lines!');
// ...
});
You can also use the close event.
const fs = require("fs");
const readline = require('readline');
const readInterface = readline.createInterface({
input: fs.createReadStream("path/to/file.txt"),
output: process.stdout,
terminal: false,
})
rl.on("line", function(line){
console.log(line);
}).on("close", function() {
console.log("EOF");
})
The close event will run when the file has no more data left to be read from.
Another (elegant), approach could be implementing a Promise.
You could furthermore add a reject("Error while reading File"), linked to input.on('error') while reading. But it's not 100% required for your problem.
var fs = require('fs');
var input = require('fs').createReadStream('./inputFile.txt')
var promise = new Promise(function(resolve, reject) {
var lineReader = require('readline').createInterface({
input: input
});
input.on('end', () => {
resolve("I reached the end!");
});
lineReader.on('line', (line) => {
// DO STH. WITH EACH LINE (IF DESIRED)
});
});
promise.then((resolveResult) => {
// DO WHATEVER YOU WANT TO DO AFTER
}
For more information about promises, I'd check the following introduction:
https://developers.google.com/web/fundamentals/primers/promises

Resources