Gimme! Gimme! Gimme! (A Man After Midnight)

Additional Topics

How do the styles work?

Behind the scenes in console.core you’ve been working with the two main parent classes of those in console.style:

Palette Collection:

A collection object holding a large number of Palettes and their associated Entries, e.g.:

  • fg, bg, fx
  • defx (for deactivating styles)

While the simplest palettes (original and effects) are created up front, the rest are built up as needed, on demand. Like a traffic cop, builders direct attribute access to the appropriate code to initialize them.

Once created, attributes are cached and available for future use. This namespace cache may also be cleared in uncommon scenarios using huge palettes, with the clear() method.

Palette Entries:

Entrie objects are what actually produce the escape sequences—they are accessed as attributes of a palette collection, e.g.:

  • .red
  • .i22
  • .cornflowerblue

The Entries provide much of the functionality from console.style:

  • Keep track of their ANSI codes and those they’ve been added to.
  • Can be called and “mixed in” with other attributes to render themselves, then end the style when finished.
  • Can be used as a context-manager.
  • Last but not least, can be rendered as an escape sequence string on any form of output.

Similar functionality is available from console.screen’s screen object.

Automatic Detection

When automatic detection is used and palettes are found not to be supported, palette entries are replaced instead with “dummy” blank objects that render to nothing. Well, more specifically empty strings.

╭────────────────────────╮  
·····•·····   │  
…waka waka waka…  

Custom Initialization

Can You Dig It?

Environment Variables

To disable automatic detection of terminal capabilities at import time the environment variable PY_CONSOLE_AUTODETECT may be set to 0.

Forcing the support of all palettes ON can also be done externally with an environment variable, such as CLICOLOR_FORCE, if desired.

Initializing Your Own

To configure auto-detection, palette support, or detect other output streams besides stdout, one may create palette builder objects yourself:

from console.constants import ALL_PALETTES
from console.style import BackgroundPalette

# e.g. force all palettes on:
fullbg = BackgroundPalette(palettes=ALL_PALETTES)

Palette Downgrade

When using true or extended colors on a terminal that is not configured to support it, console with “downgrade” the colors to their nearest neighbors in the available palette.

Neat, huh? It does this using a Euclidian 3D distance method which is quite fast but only somewhat accurate, due to the fact that the RGB color space is not uniform.

That lead to some experimentation with CIEDE2000 libraries like colormath and colorzero. Unfortunately they were both slow as molasses, even with numpy loaded, which is also slow to import.

Fast and inaccurate it is! Unless someone would like to write a very optimized C implementation for kicks, it doesn’t seem worth the trouble for this application.

¸¸,ø¤º°`°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸¸

Context Managers

“I hope you know this violates my warranty!” — Twiki

Configuring Output

Console’s Entry objects can be used as context managers as well. We saw this in the readme previously. An output file can be set if it needs to be changed from stdout and not able to be redirected outside the process:

dodgers = bg.w_dodgerblue
dodgers.set_output(sys.stderr)

with dodgers:
    print('Infield: Garvey, Lopes, Russel, Cey, Yeager')
    print('Outfield: Baker, Monday, Smith')

(There may be a way to streamline this in the future. So, don’t get too dependent on the set_output function. ;-)

Fullscreen Apps, a la Blessings

Here’s a short script to show off console’s full-screen abilities:

from console import fg, fx, defx  # shortcut: sc
from console.screen import screen
from console.utils import wait_key, set_title
from console.constants import ESC

exit_keys = (ESC, 'q', 'Q')

with screen:  # or screen.fullscreen():

    set_title(' 🤓 Hi, from console!')
    with screen.location(5, 4):
        print(
            fg.lightgreen('** Hi from a '
                          f'{fx.i}fullscreen{defx.i} app! **'),
            screen.mv_x(5),  # back up, then down
            screen.down(5),
            fg.yellow(f'(Hit the {fx.reverse}ESC{defx.reverse}'
                       ' key to exit): '),
            end='', flush=True,
        )

    with screen.hidden_cursor():
        wait_key(exit_keys)

The text below should appear. After hitting the ESC restore your terminal shall be restored:


* Hi, from a fullscreen app! **
(Hit the ESC key to exit):

TermStack

TermStack is a content-manager for making temporary modifications to the terminal via termios, that copies the original settings and restores them when finished.

It’s in the detection module because that’s where it’s used, but also aliased to the package namespace. For example:

from console import TermStack

with TermStack() as fd:
    # shut off echo
    tty.setcbreak(fd, termios.TCSANOW)
    sys.stdout.write(f'{CSI}6n')  # fire!
    sys.stdout.flush()

And off you go.

Screen Stuff

What’s Happening, “Raj” !?!

The console.screen module is the one you’re looking for, although there is a preconfigured convenience instance in the root of the package as well:

>>> from console import sc

>>> sc.eraseline(1)  # mode 1, clear to left
'\x1b[1K'

>>> print('already deleted!', sc.eraseline(1))

>>>  # this space intentionally left blank ;-)

Progress Bars

A progress bar implementation is located in console.progress and may be demoed thusly:

⏵ python3 -m console.progress -l

There are multiple themes, but typical use of the module is achieved like so:

import time

from console.screen import sc
from console.utils import clear_line
from console.progress import ProgressBar

with sc.hidden_cursor():
    bar = ProgressBar()

    for i in range(0, 101):
        print(bar(i), flush=True, end='')
        time.sleep(.2)
        print(clear_line(1), sc.mv_x, end='')

Not all of this code is required, of course. For example, you may not want to hide the cursor or clear the line each time, but often will.

Tips

Don’t have many to list yet, but here’s a couple.

  • The styles bold, italic, underline, and strike have one-letter shortcuts as they do in HTML, if you’re into that sort of thing:

    # COWABUNGA !
    XTREME_STYLING = fx.b + fx.i + fx.u + fx.s
    
  • When using the extended or truecolor palettes, keep in mind that some folks will have dark backgrounds and some light—which could make your fancy colors unreadable.

    Checking the background with the detection module is one strategy, though not available on every terminal. An argument to change the theme may also be in order. (Console does acknowledge several environment variables as well.)

  • ANSI support can be enabled on Windows 10 with the following incantation:

    >>> import console.windows as cw
    
    >>> cw.enable_vt_processing()
    (0, 0)  # status for (stdout, stderr)
    

Deeper Dive

Get down, boogie oogie oogie…—A Taste of Honey

Still interested? More than you wanted to know on the subject of terminals and escape codes can be found below:

Aside - Warm Colors

Did you know that thirty years before f.lux and redshift debuted that Amber Monochrome monitors where known as the “ergonomic” choice? Easier on the eyes for extended periods (i.e. late nights) they said. Interesting knowledge rediscovered, perhaps.

“Believe it…

or not!”

—Jack Palance

10-7, Signing Off…

   ♫♪ .ılılıll|̲̅̅●̲̅̅|̲̅̅=̲̅̅|̲̅̅●̲̅̅|llılılı. ♫♪     
_images/bjandbear.jpg

“I’m B. J. McKay and this is my best friend Bear.”🖺🖹


  • Keep On Truckin’
  • Catch you on the flip-side
  • Good night, John-boy

and…

  • Goodbye Seventies