Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nodejs - how to keep an status at top of stdout

Tags:

node.js

I'm trying to output something like these:

counter is: 10            <= fixed line and auto updating
console.logs, etc...      <= other console.logs, errors, defaul outputs
console.logs, etc...
console.logs, etc...
console.logs, etc...

Is this possible?

I have tried with process.stdout.write() but it is not working.

var counter = 0;
setInterval(function(){
    counter++;
    process.stdout.write("counter is " + counter + " \r");
}, 500);

setInterval(function(){
    console.log('some output');
}, 1500);
like image 749
user3175226 Avatar asked May 24 '14 14:05

user3175226


2 Answers

Here's an example using blessed:

var blessed = require('blessed');

var screen = blessed.screen(),
    body = blessed.box({
      top: 1,
      left: 0,
      width: '100%',
      height: '99%'
    }),
    statusbar = blessed.box({
      top: 0,
      left: 0,
      width: '100%',
      height: 1,
      style: {
        fg: 'white',
        bg: 'blue'
      }
    });

screen.append(statusbar);
screen.append(body);

screen.key(['escape', 'q', 'C-c'], function(ch, key) {
  return process.exit(0);
});

function status(text) { statusbar.setContent(text); screen.render(); }
function log(text) { body.insertLine(0, text); screen.render(); }

var c = 1;
setInterval(function() {
  status((new Date()).toISOString());
  log('This is line #' + (c++));
}, 100);

Here's a simpler example that has almost the same effect (the status bar doesn't fill in extra space with background color):

var screen = blessed.screen(),
    body = blessed.box({
      top: 0,
      left: 0,
      width: '100%',
      height: '100%',
      tags: true
    });

screen.append(body);

screen.key(['escape', 'q', 'C-c'], function(ch, key) {
  return process.exit(0);
});

function status(text) {
  body.setLine(0, '{blue-bg}' + text + '{/blue-bg}');
  screen.render();
}
function log(text) {
  body.insertLine(1, text);
  screen.render();
}

var c = 1;
setInterval(function() {
  status((new Date()).toISOString());
  log('This is line #' + (c++));
}, 100);
like image 75
mscdex Avatar answered Oct 01 '22 02:10

mscdex


Aside there are a lot of node modules that can help you do this,(blessed, ncurses, ansi, termhelper), for educational purposes you can also do it with vanilla node easily using process.stdout.moveCursor:

var logs = [];
function log(text) {
  logs.push(text);
  console.log(text);
}
function changeCounter(n) {
  process.stdout.moveCursor(0, -logs.length - 1);
  printCounter(n);
  logs.forEach(function (log) { console.log(log) });
}
function printCounter(n) {
  console.log('Counter is:', n);
}

// Now lets test
printCounter(0);
var i = 1;
setInterval(function () {
  log('meoww');
  changeCounter(i++);
});

Though you have to write to extra code to prevent overflowing terminal.

like image 30
Farid Nouri Neshat Avatar answered Oct 01 '22 02:10

Farid Nouri Neshat