Overview — Blessed 1.17.0 documentation

# Overview

Blessed provides just one top-level object: `Terminal`. Instantiating a `Terminal` figures out whether you’re on a terminal at all and, if so, does any necessary setup:

    >>> term = Terminal()

After that, you can proceed to ask it all sorts of things about the terminal, such as its size:

    >>> term.height, term.width
    (34, 102)

Its color support:

    >>> term.number_of_colors
    256

And use construct strings containing color and styling:

    >>> term.green_reverse('ALL SYSTEMS GO')
    '\x1b[32m\x1b[7mALL SYSTEMS GO\x1b[m'

Furthermore, the special sequences inserted with application keys (arrow and function keys) are understood and decoded, as well as your locale-specific encoded multibyte input, such as utf-8 characters.

## Styling and Formatting

Lots of handy formatting codes are available as attributes on a `Terminal` class instance. For example:

    from blessed import Terminal

    term = Terminal()

    print('I am ' + term.bold + 'bold' + term.normal + '!')

These capabilities (bold, normal) are translated to their sequences, which when displayed simply change the video attributes. And, when used as a callable, automatically wraps the given string with this sequence, and terminates it with normal.

The same can be written as:

    print('I am' + term.bold('bold') + '!')

You may also use the `Terminal` instance as an argument for the `str.format`()` method, so that capabilities can be displayed in-line for more complex strings:

    print('{t.red_on_yellow}Candy corn{t.normal} for everyone!'.format(t=term))

### Capabilities

Capabilities supported by most terminals are:

`bold`

  Turn on ‘extra bright’ mode.

`reverse`

  Switch fore and background attributes.

`blink`

  Turn on blinking.

`normal`

  Reset attributes to default.

`underline`

  Enable underline mode.

Note that, while the inverse of underline is no_underline, the only way to turn off bold or reverse is normal, which also cancels any custom colors.

Many of these are aliases, their true capability names (such as ‘smul’ for ‘begin underline mode’) may still be used. Any capability in the terminfo(5) manual, under column Cap-name, may be used as an attribute of a `Terminal` instance. If it is not a supported capability for the current terminal, or a non-tty is used as output stream, an empty string is always returned.

### Colors

XXX TODO XXX

all X11 colors are available, rgb(int, int, int), truecolor is automatically detected, or, downsampled to 256 or 16, 8, etc colorspace.

Color terminals are capable of at least 8 basic colors.

- `black`

- `red`

- `green`

- `yellow`

- `blue`

- `magenta`

- `cyan`

- `white`

The same colors, prefixed with bright_ (synonymous with bold_), such as bright_blue, provides 16 colors in total.

Prefixed with on_, the given color is used as the background color. Some terminals also provide an additional 8 high-intensity versions using on_bright, some example compound formats:

    from blessed import Terminal

    term = Terminal()

    print(term.on_bright_blue('Blue skies!'))

    print(term.bright_red_on_bright_yellow('Pepperoni Pizza!'))

You may also specify the `color()` index by number, which should be within the bounds of value returned by `number_of_colors`:

    from blessed import Terminal

    term = Terminal()

    for idx in range(term.number_of_colors):
        print(term.color(idx)('Color {0}'.format(idx)))

You can check whether the terminal definition used supports colors, and how many, using the `number_of_colors` property, which returns any of 0, 8 or 256 for terminal types such as vt220, ansi, and xterm-256color, respectively.

### Colorless Terminals

If the terminal defined by the Environment variable TERM does not support colors, these simply return empty strings. When used as a callable, the string passed as an argument is returned as-is. Most sequences emitted to a terminal that does not support them are usually harmless and have no effect.

Colorless terminals (such as the amber or green monochrome vt220) do not support colors but do support reverse video. For this reason, it may be desirable in some applications to simply select a foreground color, followed by reverse video to achieve the desired background color effect:

    from blessed import Terminal

    term = Terminal()

    print(term.green_reverse('some terminals standout more than others'))

Which appears as black on green on color terminals, but black text on amber or green on monochrome terminals. Whereas the more declarative formatter black_on_green would remain colorless.

Note

On most color terminals, bright_black is not invisible – it is actually a very dark shade of grey!

### Compound Formatting

If you want to do lots of crazy formatting all at once, you can just mash it all together:

    from blessed import Terminal

    term = Terminal()

    print(term.bold_underline_green_on_yellow('Woo'))

I’d be remiss if I didn’t credit couleur, where I probably got the idea for all this mashing.

This compound notation comes in handy if you want to allow users to customize formatting, just allow compound formatters, like bold_green, as a command line argument or configuration item such as in the tprint.py demonstration script.

## Moving The Cursor

If you just want to move and aren’t worried about returning, do something like this:

    from blessed import Terminal

    term = Terminal()
    print(term.move_xy(10, 1) + 'Hi, mom!')

There are three basic direct movement capabilities:

`move_xy(x, y)`

  Position cursor at given x, y.

`move_x(x)`

  Position cursor at column x.

`move_y(y)`

  Position cursor at row y.

`home`

  Position cursor at (0, 0).

And your basic set of relative capabilities:

`move_up` or `move_up(y)`

  Position cursor 1 or y cells above the current position.

`move_down` or `move_down(y)`

  Position cursor 1 or y cells below the current position.

`move_left` or `move_left(x)`

  Position cursor 1 or x cells left of the current position.

`move_right` or `move_right(x)`

  Position cursor 1 or x cells right of the current position.

A context manager, `location()` is provided to move the cursor to an (x, y) screen position and restore the previous position on exit:

    from blessed import Terminal

    term = Terminal()

    with term.location(0, term.height - 1):
        print('Here is the bottom.')

    print('This is back where I came from.')

Parameters to `location()` are the optional x and/or y keyword arguments. When only one argument is used, only the row or column is positioned. When both arguments are omitted, it saves the current cursor position, without performing any movement, but restore that position on exit:

    with term.location():
        print(term.move_xy(1, 1) + 'Hi')
        print(term.move_xy(9, 9) + 'Mom')

Note

calls to `location()` may not be nested.

## Finding The Cursor

We can determine the cursor’s current position at anytime using `get_location()`, returning the current (y, x) location. This uses a kind of “answer back” sequence that your terminal emulator responds to. If the terminal may not respond, the `timeout` keyword argument can be specified to return coordinates (-1, -1) after a blocking timeout:

    from blessed import Terminal

    term = Terminal()

    row, col = term.get_location(timeout=5)

    if row < term.height:
        print(term.move_y(term.height) + 'Get down there!')

### One-Notch Movement

Finally, there are some parameterless movement capabilities that move the cursor one character in various directions:

- `move_left`

- `move_right`

- `move_up`

- `move_down`

Note

move_down is often valued as \n, which additionally returns the carriage to column 0, depending on your terminal emulator, and may also destructively destroy any characters at the given position to the end of margin.

## Height And Width

Use the `height` and `width` properties to determine the size of the window:

    from blessed import Terminal

    term = Terminal()
    height, width = term.height, term.width
    with term.location(x=term.width / 3, y=term.height / 3):
        print('1/3 ways in!')

These values are always current. To detect when the size of the window changes, you may author a callback for SIGWINCH signals:

    import signal
    from blessed import Terminal

    term = Terminal()

    def on_resize(sig, action):
        print('height={t.height}, width={t.width}'.format(t=term))

    signal.signal(signal.SIGWINCH, on_resize)

    # wait for keypress
    term.inkey()

Note

This is not compatible with Windows!

## Clearing The Screen

Blessed provides syntactic sugar over some screen-clearing capabilities:

`clear`

  Clear the whole screen.

`clear_eol`

  Clear to the end of the line.

`clear_bol`

  Clear backward to the beginning of the line.

`clear_eos`

  Clear to the end of screen.

## Full-Screen Mode

If you’ve ever noticed a program, such as an editor, restores the previous screen (such as your shell prompt) after exiting, you’re seeing the enter_fullscreen and exit_fullscreen attributes in effect.

`enter_fullscreen`

  Switch to alternate screen, previous screen is stored by terminal driver.

`exit_fullscreen`

  Switch back to standard screen, restoring the same terminal state.

There’s also a context manager you can use as a shortcut:

    from __future__ import division
    from blessed import Terminal

    term = Terminal()
    with term.fullscreen():
        print(term.move_y(term.height // 2) +
              term.center('press any key').rstrip())
        term.inkey()

## Pipe Savvy

If your program isn’t attached to a terminal, such as piped to a program like less(1) or redirected to a file, all the capability attributes on `Terminal` will return empty strings. You’ll get a nice-looking file without any formatting codes gumming up the works.

If you want to override this, such as when piping output to less -r, pass argument value True to the `force_styling` parameter.

In any case, there is a `does_styling` attribute that lets you see whether the terminal attached to the output stream is capable of formatting. If it is False, you may refrain from drawing progress bars and other frippery and just stick to content:

    from blessed import Terminal

    term = Terminal()
    if term.does_styling:
        with term.location(x=0, y=term.height - 1):
            print('Progress: [=======>   ]')
    print(term.bold("60%"))

## Sequence Awareness

Blessed may measure the printable width of strings containing sequences, providing `center()`, `ljust()`, and `rjust()` methods, using the terminal screen’s width as the default width value:

    from __future__ import division
    from blessed import Terminal

    term = Terminal()
    with term.location(y=term.height // 2):
        print(term.center(term.bold('bold and centered')))

Any string containing sequences may have its printable length measured using the `length()` method.

Additionally, a sequence-aware version of `textwrap.wrap()` is supplied as class as method `wrap()` that is also sequence-aware, so now you may word-wrap strings containing sequences. The following example displays a poem word-wrapped to 25 columns:

    from blessed import Terminal

    term = Terminal()

    poem = (term.bold_cyan('Plan difficult tasks'),
            term.cyan('through the simplest tasks'),
            term.bold_cyan('Achieve large tasks'),
            term.cyan('through the smallest tasks'))

    for line in poem:
        print('\n'.join(term.wrap(line, width=25, subsequent_indent=' ' * 4)))

Sometimes it is necessary to make sense of sequences, and to distinguish them from plain text. The `split_seqs()` method can allow us to iterate over a terminal string by its characters or sequences:

    from blessed import Terminal

    term = Terminal()

    phrase = term.bold('bbq')
    print(term.split_seqs(phrase))

Will display something like, `['\x1b[1m', 'b', 'b', 'q', '\x1b(B', '\x1b[m']`

Similarly, the method `strip_seqs()` may be used on a string to remove all occurrences of terminal sequences:

    from blessed import Terminal

    term = Terminal()
    phrase = term.bold_black('coffee')
    print(repr(term.strip_seqs(phrase)))

Will display only `'coffee'`

## Keyboard Input

The built-in python function `raw_input()` does not return a value until the return key is pressed, and is not suitable for detecting each individual keypress, much less arrow or function keys.

Furthermore, when calling `os.read()` on input stream, only bytes are received, which must be decoded to unicode using the locale-preferred encoding. Finally, multiple bytes may be emitted which must be paired with some verb like `KEY_LEFT`: blessed handles all of these special cases for you!

### cbreak

The context manager `cbreak()` can be used to enter key-at-a-time mode: Any keypress by the user is immediately consumed by read calls:

    from blessed import Terminal
    import sys

    term = Terminal()

    with term.cbreak():
        # block until any single key is pressed.
        sys.stdin.read(1)

The mode entered using `cbreak()` is called cbreak(3) in curses:

> The cbreak routine disables line buffering and erase/kill character-processing (interrupt and flow control characters are unaffected), making characters typed by the user immediately available to the program.

### raw

`raw()` is similar to cbreak, except that control-C and other keystrokes are “ignored”, and received as their keystroke value rather than interrupting the program with signals.

Output processing is also disabled, you must print phrases with carriage return after newline. Without raw mode:

    print("hello, world.")

With raw mode:

    print("hello, world.", endl="\r\n")

### inkey

The method `inkey()` combined with cbreak completes the circle of providing key-at-a-time keyboard input with multibyte encoding and awareness of application keys.

`inkey()` resolves many issues with terminal input by returning a unicode-derived `Keystroke` instance. Its return value may be printed, joined with, or compared like any other unicode strings, it also provides the special attributes `is_sequence`, `code`, and `name`:

    from blessed import Terminal

    term = Terminal()

    print("press 'q' to quit.")
    with term.cbreak():
        val = ''
        while val.lower() != 'q':
            val = term.inkey(timeout=5)
            if not val:
               # timeout
               print("It sure is quiet in here ...")
            elif val.is_sequence:
               print("got sequence: {0}.".format((str(val), val.name, val.code)))
            elif val:
               print("got {0}.".format(val))
        print('bye!')

Its output might appear as:

    got sequence: ('\x1b[A', 'KEY_UP', 259).
    got sequence: ('\x1b[1;2A', 'KEY_SUP', 337).
    got sequence: ('\x1b[17~', 'KEY_F6', 270).
    got sequence: ('\x1b', 'KEY_ESCAPE', 361).
    got sequence: ('\n', 'KEY_ENTER', 343).
    got /.
    It sure is quiet in here ...
    got sequence: ('\x1bOP', 'KEY_F1', 265).
    It sure is quiet in here ...
    got q.
    bye!

A `timeout` value of None (default) will block forever until a keypress is received. Any other value specifies the length of time to poll for input: if no input is received after the given time has elapsed, an empty string is returned. A `timeout` value of 0 is non-blocking.

### keyboard codes

When the `is_sequence` property tests True, the value is a special application key of the keyboard. The `code` attribute may then be compared with attributes of `Terminal`, which are duplicated from those found in curs_getch(3), or those constants in `curses` beginning with phrase KEY_.

Some of these mnemonics are shorthand or predate modern PC terms and are difficult to recall. The following helpful aliases are provided instead:

blessed | curses | note
--- | --- | ---
`KEY_DELETE` | `KEY_DC` | chr(127).
`KEY_TAB` |  | chr(9)
`KEY_INSERT` | `KEY_IC` |
`KEY_PGUP` | `KEY_PPAGE` |
`KEY_PGDOWN` | `KEY_NPAGE` |
`KEY_ESCAPE` | `KEY_EXIT` |
`KEY_SUP` | `KEY_SR` | (shift + up)
`KEY_SDOWN` | `KEY_SF` | (shift + down)
`KEY_DOWN_LEFT` | `KEY_C1` | (keypad lower-left)
`KEY_UP_RIGHT` | `KEY_A1` | (keypad upper-left)
`KEY_DOWN_RIGHT` | `KEY_C3` | (keypad lower-left)
`KEY_UP_RIGHT` | `KEY_A3` | (keypad lower-right)
`KEY_CENTER` | `KEY_B2` | (keypad center)
`KEY_BEGIN` | `KEY_BEG` |

The `name` property will prefer these aliases over the built-in `curses` names.

The following are not available in the `curses` module, but are provided for keypad support, especially where the `keypad()` context manager is used with numlock on:

- `KEY_KP_MULTIPLY`

- `KEY_KP_ADD`

- `KEY_KP_SEPARATOR`

- `KEY_KP_SUBTRACT`

- `KEY_KP_DECIMAL`

- `KEY_KP_DIVIDE`

- `KEY_KP_0` through `KEY_KP_9`