blessed

repository·master·Indexed 11 days ago

https://github.com/chjj/blessed

A high-level, curses-like terminal interface library for Node.js providing a DOM-like API for building complex terminal user interfaces (TUIs) using a widget-based system. Version 0.1.81.

Tokens
17.6K
Snippets
46
Records
77
Agent score
94%

What's inside blessed

  1. Set Element dimensions and positioning

    master

    Elements use a coordinate system relative to their parent. You can specify dimensions and offsets using numbers, percentages (e.g., 50%), or keywords.

    Dimensions:

    • width, height: Can be a number, percentage (0-100%), or keywords like half or shrink.
    • Percentages support offsets: 50%+1 or 50%-1.

    Positioning:

    • left, right, top, bottom: Offsets relative to the parent.
    • left and top accept the keyword center.
    • right and bottom do not accept keywords.
    • Percentages also support offsets (e.g., 50%+1).
    • position: An object containing these properties can be used to group them.
  2. Use Layout for automatic child positioning

    master

    The Layout element (inherited from Element) automatically positions children based on a renderer method. It is currently experimental.

    Important Constraints:

    • You must always provide a width and height to the Layout element. blessed cannot calculate these dynamically before children are positioned.
    • Use el.position (e.g., el.position.left) to set coordinates. Setting el.left directly may interfere with the renderer.

    Layout Modes (layout option):

    • inline (default): Positions children like display: inline-block; in CSS.
    • grid: Creates an automatic grid where cell dimensions are determined by the largest children.

    Custom Renderers: You can provide a custom renderer callback. This callback is called before children are iterated. It must return an iterator(el, i) function that is called for each child.

    Renderer Coordinates (coords / el.lpos): The coords object passed to the renderer has border and padding already subtracted.

    • coords.xi: Absolute X of the left side.
    • coords.xl: Absolute X of the right side.
    • coords.yi: Absolute Y of the top side.
    • coords.yl: Absolute Y of the bottom side.
    var layout = blessed.layout({
      parent: screen,
      top: 'center',
      left: 'center',
      width: '50%',
      height: '50%',
      border: 'line',
      renderer: function(coords) {
        var self = this;
        var width = coords.xl - coords.xi;
        var height = coords.yl - coords.yi;
        var xi = coords.xi;
        var yi = coords.yi;
    
        return function iterator(el, i) {
          // Custom positioning logic here
          var last = self.getLastCoords(i);
          if (!last) {
            el.position.left = 0;
            el.position.top = 0;
          } else {
            el.position.left = last.xl - xi;
          }
        };
      }
    });
  3. Use RadioSet and RadioButton for exclusive selection

    master

    A RadioSet (extending Box) acts as a container for RadioButton elements. When used within a RadioSet, the RadioButton elements become mutually exclusive (selecting one deselects the others).

    RadioButton itself extends Checkbox and inherits its properties and methods.

  4. Configure element styles and attributes

    master

    Blessed supports various terminal attributes via the style object. Attributes like bold, underline, blink, inverse, and invisible are represented as booleans.

    Transparency

    You can set an element's opacity to 50% using style.transparent = true;. This uses a color blending algorithm to blend the element's foreground with the background color (note: characters themselves cannot be blended, only background colors).

    Shadow

    You can enable a translucent shadow by setting shadow: true. This creates a 50% opacity, 2-cell wide, 1-cell high shadow offset to the bottom-right.

    Hover and Focus Effects

    Blessed supports hover and focus styles. Note that hover requires mouse input to be enabled.

    Scrollbar Styling

    For scrollable elements, you can style the scrollbar using style.scrollbar with bg and fg properties. The scrollbar property itself can be a boolean or an object containing character definitions.

    // Example of combined styles
    style: {
      hover: {
        bg: 'red'
      },
      focus: {
        border: {
          fg: 'blue'
        }
      },
      scrollbar: {
        bg: 'red',
        fg: 'blue'
      }
    }
    
    // Enabling shadow
    shadow: true
    
    // Configuring scrollbar character
    scrollbar: {
      ch: ' '
    }
  5. Handle Element mouse and key events

    master

    Elements emit various events that can be listened to using the standard .on() pattern (inherited from Node).

    Mouse Events:

    • mousedown, mouseup: Button press/release.
    • wheeldown, wheelup: Scrolling.
    • mouseover, mouseout: Hovering.
    • mousemove: Movement.
    • click: A smart click event (similar to mouseup).

    Key Events:

    • keypress: General keypress event.
    • key [name]: Keypress event for a specific key name.

    Note: To receive these events, you may need to call .enableMouse(), .enableKeys(), or .enableInput() on the element or screen.

  6. Handle events and event bubbling

    master

    Events in Blessed follow a tree-based model with event bubbling. You can listen for specific events on an element, or use the element prefix to listen for events occurring on that element or any of its children.

    To cancel event propagation (preventing the event from bubbling up to parent elements), return false from the event handler.

    When using the element event pattern, the first argument passed to the callback is el, which refers to the target element where the event actually occurred.

    // Standard event listener (only for 'box')
    box.on('click', function(mouse) {
      box.setContent('You clicked ' + mouse.x + ', ' + mouse.y + '.');
      screen.render();
    });
    
    // Bubbling event listener (for 'box' and all its children)
    box.on('element click', function(el, mouse) {
      box.setContent('You clicked ' + el.type + ' at ' + mouse.x + ', ' + mouse.y + '.');
      screen.render();
      if (el === box) {
        return false; // Cancel propagation up the tree
      }
    });
  7. Understand the Node base class

    master

    In Blessed, every UI element (widget) inherits from the Node class. A Node is an EventEmitter that manages its own position in the UI tree via a parent-child relationship. It serves as the fundamental building block for all widgets.

    Key Properties

    • type: The type of the node (e.g., box).
    • parent: The parent node.
    • screen: The screen associated with this node.
    • children: An array of child nodes.
    • __data, _, $__: Objects for storing miscellaneous user data.
    • __index: The render index (document order index) from the last render call.

    Common Methods

    • append(node) / prepend(node): Add a child node to the end or beginning of the children array.
    • insert(node, i) / insertBefore(node, refNode) / insertAfter(node, refNode): Position a child node at a specific index or relative to another node.
    • remove(node): Remove a specific child node.
    • detach(): Remove the node from its current parent.
    • emitDescendants(type, args..., [iterator]): Emits an event for the node itself and recursively for all its descendants.
    • get(name, [default]) / set(name, value): Access or modify user-defined properties.
  8. How blessed works

    master

    Blessed is a high-level terminal interface API for Node.js that reimplements ncurses. It consists of two main parts:

    1. A Program object: Reimplements ncurses by parsing and compiling terminfo and termcap, allowing output compatible with any terminal.
    2. A Widget API: A DOM-like API optimized for terminals.

    The renderer uses CSR (change-scroll-region) and BCE (back-color-erase) with a painter's algorithm and a screen damage buffer. This ensures efficiency by only drawing changes (damage) to the screen.

  9. Use Prompts (Prompt, Question, Message, Loading)

    master

    Blessed provides several specialized Box subclasses for user interaction and feedback:

    Prompt

    Displays a text input with 'okay' and 'cancel' buttons (buttons are automatically hidden).

    • input(text, value, callback): Shows the prompt, sets the label and initial value, and waits for the textbox result.
    • setInput(text, value): Sets the text and initial value.
    • readInput(text, value, callback): Shows the prompt and waits for the result.

    Question

    A box containing 'okay' and 'cancel' buttons (automatically hidden).

    • ask(question, callback): Asks a question; the callback yields the result.

    Message

    A box for displaying messages (automatically hidden).

    • log(text, [time], callback): Displays a message for a duration (default 3s). Set time to 0 for a perpetual message dismissed on keypress.
    • display(text, [time], callback): Same as log.
    • error(text, [time], callback): Displays an error message using the same logic as log.

    Loading

    A box with a spinning line to indicate background activity (automatically hidden).

    • load(text): Displays the loading box with a message. This locks keys until stop() is called.
    • stop(): Hides the loading box and unlocks keys.
  10. Create a basic blessed application

    master

    To build a blessed application, you typically follow these steps:

    1. Create a screen object using blessed.screen(). It is recommended to use smartCSR: true or fastCSR: true as an option to enable CSR when scrolling or manipulating lines.
    2. Create widgets (like blessed.box()) and configure their properties (position, size, content, style).
    3. Append widgets to the screen using screen.append(widget).
    4. Handle user input using .on('event', callback) or .key('key', callback).
    5. Call screen.render() to draw the changes to the terminal.
    var blessed = require('blessed');
    
    // Create a screen object.
    var screen = blessed.screen({
      smartCSR: true
    });
    
    screen.title = 'my window title';
    
    // Create a box perfectly centered horizontally and vertically.
    var box = blessed.box({
      top: 'center',
      left: 'center',
      width: '50%',
      height: '50%',
      content: 'Hello {bold}world{/bold}!',
      tags: true,
      border: {
        type: 'line'
      },
      style: {
        fg: 'white',
        bg: 'magenta',
        border: {
          fg: '#f0f0f0'
        },
        hover: {
          bg: 'green'
        }
      }
    });
    
    // Append our box to the screen.
    screen.append(box);
    
    // If our box is clicked, change the content.
    box.on('click', function(data) {
      box.setContent('{center}Some different {red-fg}content{/red-fg}.{/center}');
      screen.render();
    });
    
    // Quit on Escape, q, or Control-C.
    screen.key(['escape', 'q', 'C-c'], function(ch, key) {
      return process.exit(0);
    });
    
    // Focus our element.
    box.focus();
    
    // Render the screen.
    screen.render();
  11. Render the screen

    master

    To reflect changes made to elements (like setContent) on the terminal screen, you must explicitly call screen.render() or the element's .render() method.

    box.setContent('Hello {#0fe1ab-fg}world{/}.');
    screen.render();
  12. Format text content with tags and colors

    master

    Every element can display formatted text using setContent. If tags: true is passed to the element constructor, you can use a tag-based syntax.

    Coloring:

    • Use basic 16 colors: {red-fg}, {green-bg}, etc.
    • Use 256-color hex values: {#ff0000-fg} or {#00ff00-bg}.
    • Use {/} to cancel all current character attributes.

    Attributes:

    • Supports bold, underline, blink, inverse, and invisible.

    Alignment:

    • Supports newlines (\n) and alignment tags: {right}text{/right}, {center}text{/center}, and {left}text{/left}.

    Escaping: To display literal tags, use blessed.escape() or the {open} and {close} tags.

    SGR Sequences: Elements can also handle raw SGR escape codes (e.g., from git log) directly in the content.

    // Basic color and attribute
    box.setContent('hello {red-fg}{green-bg}{bold}world{/bold}{/green-bg}{/red-fg}');
    
    // Using hex colors
    box.setContent('hello {#ff0000-fg}world{/}');
    
    // Using alignment
    box.setContent('hello\n' + '{right}world{/right}\n' + '{center}foo{/center}\n' + 'left{|}right');
    
    // Escaping tags
    box.setContent('escaped tag: ' + blessed.escape('{bold}{/bold}'));