Skip to content

Instantly share code, notes, and snippets.

@hawkins
Created January 16, 2017 06:22
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hawkins/5c05d077a5d15d95404c3bb56b2a81d7 to your computer and use it in GitHub Desktop.
Save hawkins/5c05d077a5d15d95404c3bb56b2a81d7 to your computer and use it in GitHub Desktop.
Node.js blessed screen - keep your output separate from your input!
/*
* I've used blessed to create a textbox at the bottom line in the screen.
* The rest of the screen is the 'body' where your code output will be added.
* This way, when you type input, your program won't muddle it with output.
*
* To try this code:
* - $ npm install blessed --save
* - $ node screen.js
*
* Key points here are:
* - Your code should show output using the log function.
* Think of this as a console.log drop-in-replacement.
* Don't use console.* functions anymore, they'll mess up blessed's screen.
* - You have to 'focus' the inputBar element for it to receive input.
* You can have it always focused, however, but my demonstration shows listening for an enter key press or click on the blue bar to focus it.
* - If you write code that manipulates the screen, remember to run screen.render() to render your changes.
*/
const blessed = require('blessed');
var screen = blessed.screen();
var body = blessed.box({
top: 0,
left: 0,
height: '100%-1',
width: '100%',
keys: true,
mouse: true,
alwaysScroll: true,
scrollable: true,
scrollbar: {
ch: ' ',
bg: 'red'
}
});
var inputBar = blessed.textbox({
bottom: 0,
left: 0,
height: 1,
width: '100%',
keys: true,
mouse: true,
inputOnFocus: true,
style: {
fg: 'white',
bg: 'blue' // Blue background so you see this is different from body
}
});
// Add body to blessed screen
screen.append(body);
screen.append(inputBar);
// Close the example on Escape, Q, or Ctrl+C
screen.key(['escape', 'q', 'C-c'], (ch, key) => (process.exit(0)));
// Handle submitting data
inputBar.on('submit', (text) => {
log(text);
inputBar.clearValue();
});
// Add text to body (replacement for console.log)
const log = (text) => {
body.pushLine(text);
screen.render();
}
/*
* Demonstration purposes
*/
// Listen for enter key and focus input then
screen.key('enter', (ch, key) => {
inputBar.focus();
});
// Log example output
setInterval(() => {
log("Just log some example output");
}, 1000);
@neauoire
Copy link

I'd add this, so it renders properly on launch:

inputBar.focus();
screen.render();

@pabrams
Copy link

pabrams commented Dec 26, 2021

I don't get why you're focusing on input when user presses enter. And how does the submit event get triggered?

@hawkins
Copy link
Author

hawkins commented Dec 26, 2021

Check out the comments, they explain everything already. Input bar has to be focused to receive input. I chose to set that on enter for demonstration purposes. As for inputBar submit event, I suggest you check out blessed’s documentation. That should just be an enter key press while focused.

@jhyland87
Copy link

This works great, but I had an issue with the auto-scrolling. It just wasn't doing it. I was able to update it by adding some basic logic to the log function.

const log = (text) => {
  body.pushLine(text);

  // Was using the below for debugging:  
  // body.pushLine(`childOffset:${body.childOffset};\tchildBase:${body.childBase};\tbaseLimit:${body.baseLimit};\theight:${body.height}\tgetScrollHeight:${body.getScrollHeight()};\tgetScroll:${body.getScroll()}`)
  screen.render();
  // The scroll seems to be broken, but this helps. It will only auto-scroll if
  // the scrollbar is at or near the very bottom (thus maintaining the position).
  // If the box is scrolled to anywhere else, it will not auto scroll
  if ( body.getScrollHeight() <= body.getScroll()+3)
    body.scrollTo(body.getScrollHeight())
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment