Using node.js's prompt for user input? [duplicate] - javascript

This question already has answers here:
Get user input through Node.js console
(6 answers)
Closed last month.
I'm working on a JS project running with node.js and I can't figure out how to get the prompt to work correctly for user input. I installed it from npm, followed the steps and I can get the program to prompt for user input but I can't store the result in a variable.
What I want is to prompt the user for his next move (up,down,left or right) every turn and use the result. I tried making a global move variable and affecting it in the prompt section, but it doesn't seem to work.
var Moving = function(maxMoves){
for(var n=maxMoves; n>0;){
var move;
var l;
//This would prompt for a direction (up,down,left,right)
move = prompt();
//And this would prompt for the number of tiles to advance;
l = prompt();
Direction(move,l);
n-=l;
}
};

Using require('prompt') or require('readline') are both good, easy ways to do this, but I wanted to find THE EASIEST WAY, and I didn't care about whether it is synchronous or asynchronous. Finding it took me longer than it should have, so maybe I can save people some time if they read this before digging any further.
Here you go:
# npm install readline-sync
var readline = require('readline-sync');
var name = readline.question("What is your name?");
console.log("Hi " + name + ", nice to meet you.");
Disclaimer: I am just spreading the word, here are my sources:
https://teamtreehouse.com/community/how-to-get-input-in-the-console-in-nodejs
How to take in text input from a keyboard and store it into a variable?

When you say "installed it from npm" I'm assuming you're referring to the prompt module from flatiron.
From their docs, as with most Node things, it looks like it exposes an asynchronous function, so you'll handle input inside the prompt callback:
var prompt = require('prompt');
//
// Start the prompt
//
prompt.start();
//
// Get two properties from the user: username and email
//
prompt.get(['username', 'email'], function (err, result) {
//
// Log the results.
//
console.log('Command-line input received:');
console.log(' username: ' + result.username);
console.log(' email: ' + result.email);
});
Storing it in a variable would be no different than accessing it from the result object above, but realize that since it's async it'll only be reliable available inside that callback.

you can use two packages readline and prompt
Here's a simple example with readline package https://nodejs.org/en/knowledge/command-line/how-to-prompt-for-command-line-input/
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('What is your name ? ', function (name) {
rl.question('Where do you live ? ', function (country) {
console.log(`${name}, is a citizen of ${country}`);
rl.close();
});
});
rl.on('close', function () {
console.log('\nBYE BYE !!!');
process.exit(0);
});
Here is an another example with prompt package. https://www.npmjs.com/package/prompt
const prompt = require('prompt');
prompt.start();
prompt.get(['username','email'], function (err, result) {
console.log('Command-line input received:');
console.log(' username: ' + result.username);
console.log(' email: ' + result.email);
});

inquirer module has a prompt function.
Use
const { prompt } = require('inquirer');
prompt([array] | object | string ')

Related

How can we read random number of lines data from nodejs stdin?

I am trying to run a simple program in Visual studio code terminal using node.js which requires reading inputs from the user and the operating on those inputs and printing the results.
I have tried many approaches but have not got success yet. I am using the following code:
process.stdin.resume();
process.stdin.setEncoding("ascii");
var input = "";
process.stdin.on("data", (c) => (input += c));
process.stdin.on("end", () => {
console.log(input);
});
process.stdin.on("SIGINT", () => {
console.log(input);
const { EOL } = require("os");
const lines = input.split(EOL); /*your input text, split by lines*/
console.log(lines);
});
I run the above code in VSCode using the in-built terminal with the command node filename.js. The program runs and keeps taking inputs but it never ends and never triggers "end" block or "SIGINT" block. Finally to stop the program I have to use ctrl+C.
Can someone please help me how to accomplish this as I want to practise solving www.codeforces.com problems on my local machine using VSCode+terminal?
This way it won't quit until you explicitly end the program. You can use process.exit() function to achieve that.
So your program should look like this :
process.stdin.resume();
process.stdin.setEncoding("ascii");
var input = "";
const inputLength = (Math.random()*10 +1) | 0;
console.log(inputLength);
let current=0;
process.stdin.on("data", (c) => {
input += c;
current++;
if(current>= inputLength){
console.clear();
console.log("reached max number of inputs");
console.log(input);
process.exit(0);
}
});
Here is the glitch link. You can test it opening console below and type node server.js
TBH, I don't understand what do you want to achieve, but you can write something like:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
})
rl.on('line', (input) => {
console.log(`Received: ${input}`);
});
when you hit enter, you will see you line. CTRL+C also works
readline is a part of the standard library

Replace certain character in Discord.JS

Now, before you say that this has been posted before, I have a different situation.
With that out of the way, let's get on with the question.
I am making a Discord bot for a friend that does duties for the group and things like that.
Quick note too, I am using the Sitepoint version of Discord.JS because I'm a beginner.
I want the bot to send a message to a certain channel when the show gets canceled for a reason. For example, they would send something like this:
afv!cancel Roblox went down.
or something similar.
But every time it sends a message, every space turns into a comma like this:
:x: The show has been cancelled because: "Roblox,went,down.". Sorry for that!
Here's the index.js code that handles executing commands:
bot.on('message', msg => {
const args = msg.content.split(/ +/);
const command = args.shift().toLowerCase();
const prefix = command.startsWith("afv!");
if (prefix == true) {
console.info(`Called command: ${command}`);
if (!bot.commands.has(command)) return;
msg.delete(1);
try {
bot.commands.get(command).execute(msg, args, bot);
} catch (error) {
console.error(error);
msg.reply('there was an error trying to execute that command!');
};
And the cancelled.js file:
module.exports = {
name: 'afv!cancel',
description: "in-case the show gets cancelled",
execute(msg, args, bot) {
if (msg.member.roles.find(r => r.name === "Bot Perms")) {
const reason = args.replace(/,/g, " ");
bot.channels.get('696135370987012240').send(':x: **The show has been cancelled** because: "' + args + '". *Sorry for that!*');
bot.user.setActivity("AFV! | afv!help", { type: 'PLAYING' });
} else {
msg.reply('you are missing the role: Bot Perms!');
}
},
};
By the way, upon executing the command, it prints this:
TypeError: args.replace is not a function
Thanks for reading! :)
From what I can see, here
const reason = args.replace(/,/g, " ");
bot.channels.get('696135370987012240').send(':x: **The show has been cancelled** because: "' + args + '". *Sorry for that!*');
you are making a const reason, wherein you try to handle that as a string and replace all commas with spaces. Unfortunately, even though it can be displayed in a string and looks to be one, in reality it is an array, so replace() won't work on it. To be able to use replace() you need to first transform your array to an actual string:
const reason = args.join().replace(/,/g, " ");
With that done you won't be seeing this pesky "not a function" error, and you can easily use reason to display your message:
bot.channels.get('696135370987012240').send(':x: **The show has been cancelled** because: "' + reason + '". *Sorry for that!*');

How to use readlineSync on Nodejs

So I'm trying out readlineSync to get user input (saw it was the best option to get user input). But then it doesn't output to the console. And it breaks out of node as soon as its done running. Help me out.
var readlineSync = require("readline-sync");
var firstName = readlineSync.question("First Name:");
console.log("Hi" + firstName);
"Expected Output: Hi Ifeoluwa"
"Actual result: Undefined and node exits automatically"
Node Console
The library does not work inside the REPL.
There is a line within the source code that reads:
if (process.stdin.isTTY) {
process.stdin.pause();
try {
fdR = fs.openSync('/dev/tty', 'r'); // device file, not process.stdin
ttyR = process.stdin._handle;
} catch (e) { /* ignore */ }
}
The process.stdin.pause will stop your current REPL session. However, when run from a file, the library works well.
i've read the documantion and it's working as expected, try to put the code to this sandbox
const express = require("express");
const app = express();
const readlineSync = require('readline-sync');
// Wait for user's response.
var userName = readlineSync.question('May I have your name? ');
console.log('Hi ' + userName + '!');
server.listen(3000, () => {
console.log(`Server is running`);
});

NodeJs: fs.appendFile function seems to miss last String given

I'm new to nodejs I was trying the append function.
When I run below code that simply takes User input after prompting him, about fav singer and puts in a file with singer name. And appending fav songs, It seems if user entered exit it should be append it to the file but, its not???
Meanwhile if its change to appendFileSync (Synchronous version of the fn) exit is added??
Code:
var readline = require ('readline');
var fs = require('fs');
var rl = readline.createInterface(process.stdin, process.stdout);
var singer = {
name:'',
songs: []
};
rl.question("What is your fav singer? ", function(answer) {
singer.name = answer;
//creating a file for this singer
fs.writeFileSync(singer.name+".md", `${singer.name}\n====================\n\n`);
rl.setPrompt(`What's your fav songs for ${singer.name} ?`);
rl.prompt();
rl.on('line', function(song) {
singer.songs.push(song.trim());
fs.appendFile(singer.name+".md", `* ${song.trim()} \n`);
//***** WHY IF ITS EXIT ITS NEVER APPEND IT TO THE FILE
console.log(`* ${song.trim()} \n`);
if (song.toLowerCase().trim() === 'exit') {
fs.appendFile(singer.name+".md", "Bye");
//***** WHY ITS NEVER APPEND IT TO THE FILE
rl.close();
} else {
rl.setPrompt(`what else would ${singer.name} say? ('exit'to leave)`);
rl.prompt();
}
});
});
rl.on ('close', function() {
console.log ("%s is a real person that says %j", singer.name, singer.songs);
process.exit();
});
Because fs.appendFile is asynchronous. When you call it, io operations are queued only. Unfortunately, your script exits before the real io-operations happen.
So. you have to use either fs.appendFileSync or fs.appendFile with callback (the 3rd argument) and when the callback is called, do all further activities.

How do I implement tab completion in node.js shell?

I was looking for this feature in node.js and I haven't found it.
Can I implement it myself? As far as I know, node.js doesn't load any file at it's startup (like Bash does with .bashrc) and I haven't noticed any way to somehow override shell prompt.
Is there a way to implement it without writing custom shell?
You could monkey-patch the REPL. Note that you must use the callback version of the completer, otherwise it won't work correctly:
var repl = require('repl').start()
var _completer = repl.completer.bind(repl)
repl.completer = function(line, cb) {
// ...
_completer(line, cb)
}
Just as a reference.
readline module has readline.createInterface(options) method that accepts an optional completer function that makes a tab completion.
function completer(line) {
var completions = '.help .error .exit .quit .q'.split(' ')
var hits = completions.filter(function(c) { return c.indexOf(line) == 0 })
// show all completions if none found
return [hits.length ? hits : completions, line]
}
and
function completer(linePartial, callback) {
callback(null, [['123'], linePartial]);
}
link to the api docs: http://nodejs.org/api/readline.html#readline_readline_createinterface_options
You can implement tab functionality using completer function like below.
const readline = require('readline');
/*
* This function returns an array of matched strings that starts with given
* line, if there is not matched string then it return all the options
*/
var autoComplete = function completer(line) {
const completions = 'var const readline console globalObject'.split(' ');
const hits = completions.filter((c) => c.startsWith(line));
// show all completions if none found
return [hits.length ? hits : completions, line];
}
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
completer: autoComplete
});
rl.setPrompt("Type some character and press Tab key for auto completion....\n");
rl.prompt();
rl.on('line', (data) => {
console.log(`Received: ${data}`);
});
Reference :
https://self-learning-java-tutorial.blogspot.com/2018/10/nodejs-readlinecreateinterfaceoptions_2.html

Categories

Resources