Adding color to repl prompt (node) - node.js

I find that adding color to the prompt in repl really helps to separate the outputs. I achieved this by using NPM's chalk, but this adds a bunch of space between the prompt and the cursor.
var term = repl.start({
prompt: chalk.blue('goose> '),
eval: function(cmd, context, filename, cb){
...
}
});
The prompt comes out like this ('|' is the cursor):
goose> |
Any ideas on how to fix?

It turns out to be very simple:
var prompt = 'My fancy prompt >>> ';
rl.setPrompt(chalk.blue(prompt), prompt.length);
You need to specify the count of characters because readline doesn't understand that escape sequences are really displayed as zero width.
(This is based on Felix's answer.)

Run this before repl.start():
var readline = require('readline');
var hasAnsi = require('has-ansi');
var stripAnsi = require('strip-ansi');
var _setPrompt = readline.Interface.prototype.setPrompt;
readline.Interface.prototype.setPrompt = function() {
if (arguments.length === 1 && hasAnsi(arguments[0])) {
return _setPrompt.call(this, arguments[0], stripAnsi(arguments[0]).length);
} else {
return _setPrompt.apply(this, arguments);
}
};
Dependencies: npm install has-ansi strip-ansi

Related

nodejs get file character encoding

How can I find out what character encoding a given text file has?
var inputFile = "filename.txt";
var file = fs.readFileSync(inputFile);
var data = new Buffer(file, "ascii");
var fileEncoding = some_clever_function(file);
if (fileEncoding !== "utf8") {
// do something
}
Thanks
You can try to use external module, such as https://www.npmjs.com/package/detect-character-encoding
The previously mentioned module works for me too. Alternatively you could have a look at detect-file-encoding-and-language which I'm using at the moment.
Installation:
$ npm install detect-file-encoding-and-language
Usage:
// index.js
const languageEncoding = require("detect-file-encoding-and-language");
const pathToFile = "/home/username/documents/my-text-file.txt"
languageEncoding(pathToFile).then(fileInfo => console.log(fileInfo));
// Possible result: { language: japanese, encoding: Shift-JIS, confidence: { language: 0.97, encoding: 1 } }

Is there a way to enable paging in node js REPL

I would like to see paging when I have long outputs in node js REPL.
Is that possible, how?
Vorpal.js is a Node module that looks like it would do the trick. Vorpal turns your Node app into an interactive CLI, and supports extensions including an implementation of the less command in Node.
Something like this would work:
var vorpal = require('vorpal')();
var less = require('vorpal-less');
vorpal
.catch('[commands...]')
.action(function (args, cb) {
args.commands = args.commands || [];
var cmd = args.commands.join(' ');
var res;
try {
res = eval(cmd);
} catch(e) {
res = e;
}
this.log(res);
cb();
});
vorpal
.delimiter('myrepl>')
.show();
This will turn your application into a REPL within the context of your app, which can also accept the less command:
$ node myrepl.js
myrepl> 6 * 6 | less
36
: (less prompt)
Disclaimer: I wrote Vorpal

nodejs child_process.spawn msdeploy.exe with space in dest site

I am trying to use child_process.spawn with msdeploy.exe to automate deployement of some applications in IIS.
Whenever i have a space in my dest site name this makes msdeploy crash.
var command = 'C:/Program Files/IIS/Microsoft Web Deploy V3/msdeploy.exe';
var args = [];
args.push('-verb=sync');
args.push('-source:iisApp=C:/Users/PATH_TO_DEPLOY/dist');
args.push('-dest:iisApp=Default Web Site/test');
var process = spawn(command,args);
process.stdout.on('data', function(data) { grunt.log.write(data) });
process.stderr.on('data', function(data) { grunt.log.error(data); });
process.on('exit', function(code) {
if (code !== 0) {
grunt.fail.warn('Something went wrong');
}
done();
});
I've tried some others alternative like put " '-dest:iisApp="Default Web Site/test"' but msdeploy give me an error too.
This error is like : Argument '"-dest:iisApp=Default Web Site/haha"' not recognized. All arguments must begin with "-" char.
When i try to escape the space char or put " like describe above this gave me a similar error.
Is this is a bug in nodejs ? Maybe i've made something wrong ?
Thank.
How to accomplish this:
var path = require('path');
var platform = require('platform');
var cp = require('child_process');
var full_cmd = '/path/to/dir with space/program.exe';
var cmd = '.' + path.sep + path.basename(full_cmd); // cannot include double quotes -- the work-around is to use the 'cmd_opts.cwd'
var cmd_args = ['"--import-path=/path/to/dir with space/import_file"']; // can wrap each with double-quotes (Windows only -- fails on Unix)
var cmd_opts = {
cwd: path.dirname(full_cmd),
encoding: 'utf8'
};
if (platform.os() === 'win32') {
cmd_opts.windowsVerbatimArguments = true;
}
var proc = cp.spawn(
cmd,
cmd_args,
cmd_opts
);
The only way this doesn't work is if 'program.exe' is named something like 'program name with space.exe'

Is there a module equivalent of Python's argparse for node.js?

argparse for python makes it quick and easy to handle command-line input, handling positional arguments, optional arguments, flags, input validation and much more. I've started writing applications in node.js and I'm finding it tedious and time consuming to write all that stuff manually.
Is there a node.js module for handling this?
There is one direct port, conveniently also called argparse.
There are a slew of various command line argument handlers at https://github.com/joyent/node/wiki/modules#wiki-parsers-commandline
The one I use in most projects is https://github.com/visionmedia/commander.js though I would take a look at all of them to see which one suits your specific needs.
In 18.3.0 nodejs has landed a core addition util.parseArgs([config])
Detailed documentation is available here: https://github.com/pkgjs/parseargs#faqs
There's yargs, which seems to be pretty complete and well documented.
Here is some simple boilerplate code which allows you to provide named args:
const parse_args = () => {
const argv = process.argv.slice(2);
let args = {};
for (const arg of argv){
const [key,value] = arg.split("=");
args[key] = value;
}
return args;
}
const main = () => {
const args = parse_args()
console.log(args.name);
}
Example usage:
# pass arg name equal to monkey
node arg_test.js name=monkey
# Output
>> monkey
You can also add a Set of accepted names and throw exception if an invalid name is provided:
const parse_args = (valid_args) => {
const argv = process.argv.slice(2);
let args = {};
let invalid_args = [];
for (const arg of argv){
const [key,value] = arg.split("=");
if(valid_args.has(key)){
args[key] = value;
} else {
invalid_args.push(key);
}
}
if(invalid_args.length > 0){
throw new Exception(`Invalid args ${invalid_args} provided`);
}
return args;
}
const main = () => {
const valid_args = new Set(["name"])
const args = parse_args(valid_args)
console.log(args.name);
}

Clear terminal window in Node.js readline shell

I have a simple readline shell written in Coffeescript:
rl = require 'readline'
cli = rl.createInterface process.stdin, process.stdout, null
cli.setPrompt "hello> "
cli.on 'line', (line) ->
console.log line
cli.prompt()
cli.prompt()
Running this displays a prompt:
$ coffee cli.coffee
hello>
I would like to be able to hit Ctrl-L to clear the screen. Is this possible?
I have also noticed that I cannot hit Ctrl-L in either the node or coffee REPLs either.
I am running on Ubuntu 11.04.
You can watch for the keypress yourself and clear the screen.
process.stdin.on 'keypress', (s, key) ->
if key.ctrl && key.name == 'l'
process.stdout.write '\u001B[2J\u001B[0;0f'
Clearing is done with ASCII control sequences like those written here:
http://ascii-table.com/ansi-escape-sequences-vt-100.php
The first code \u001B[2J instructs the terminal to clear itself, and the second one \u001B[0;0f forces the cursor back to position 0,0.
Note
The keypress event is no longer part of the standard Node API in Node >= 0.10.x but you can use the keypress module instead.
In the MAC terminal, to clear the console in NodeJS, you just hit COMMAND+K just like in Google Developer Tools Console so I'm guessing that on Windows it would be CTRL+K.
This is the only answer that will clear the screen AND scroll history.
function clear() {
// 1. Print empty lines until the screen is blank.
process.stdout.write('\033[2J');
// 2. Clear the scrollback.
process.stdout.write('\u001b[H\u001b[2J\u001b[3J');
}
// Try this example to see it in action!
(function loop() {
let i = -40; // Print 40 lines extra.
(function printLine() {
console.log('line ' + (i + 41));
if (++i < process.stdout.columns) {
setTimeout(printLine, 40);
}
else {
clear();
setTimeout(loop, 3000);
}
})()
})()
The first line ensures the visible lines are always cleared.
The second line ensures the scroll history is cleared.
Try also:
var rl = require('readline');
rl.cursorTo(process.stdout, 0, 0);
rl.clearScreenDown(process.stdout);
On response to #loganfsmyth comment on his answer (thanks for the edit!).
I have been looking here and there and, besides of the wonderfull keypress module, there is a core module that makes possible to create a cli with all standard terminal behavior (all things we give for granted today such as history, options to provide an auto-complete function and input events such as keypress are there).
The module is readline (documentation). The good news is that all the standar behaviour is already done for us so there is no need to attach event handlers (i.e. history, clearing the screen on Ctrl+L, man if you provided the auto complete function it'll be on Tabpress).
Just as an example
var readline = require('readline')
, cli = readline.createInterface({
input : process.stdin,
output : process.stdout
});
var myPrompt = ' > myPropmt '
cli.setPrompt(myPrompt, myPrompt.length);
// prompt length so you can use "color" in your prompt
cli.prompt();
// Display ' > myPrompt ' with all standard features (history also!)
cli.on('line', function(cmd){ // fired each time the input has a new line
cli.prompt();
})
cli.input.on('keypress', function(key){ // self explanatory
// arguments is a "key" object
// with really nice properties such as ctrl : false
process.stdout.write(JSON.stringify(arguments))
});
Really good discovery.
The node version I'm using is v0.10.29. I have been looking at the changelog and it was there since 2010 (commit 10d8ad).
You can clear screen using console.log() and escape sequences.
cli.on 'line', (line) ->
if line == 'cls'
console.log("\033[2J\033[0f")
else
console.log line
cli.prompt()
Vorpal.js makes things like this really easy.
For an interactive CLI with a clear command as well as a REPL within the context of your application, do this:
var vorpal = require('vorpal')();
var repl = require('vorpal-repl');
vorpal
.delimiter('hello>')
.use(repl)
.show();
vorpal
.command('clear', 'Clears the screen.')
.action(function (args, cb) {
var blank = '';
for (var i = 0; i < process.stdout.rows; ++i) {
blank += '\n';
}
vorpal.ui.rewrite(blank);
vorpal.ui.rewrite('');
cb();
});
If you are using readline.createInterface you could do something like:
function clearPrompt() {
rl.setPrompt("");
rl.prompt();
}
Note this won't clear the entire terminal, just the readline prompt. Still useful if you want the user to keep their place in the terminal

Resources