Search code examples
javascriptnode.jssyntax-highlightingread-eval-print-loopansi-escape

How to have syntax highlighting of input text in Node.js REPL?


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.


Solution

  • 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.