How to use terminal color palette with curses

与世无争的帅哥 提交于 2019-12-02 15:53:28

The following I figured out by experiment on my own pc (Ubuntu 14.04, python 3).

  • There are 256 colors (defined by the first 8 bits).
  • The other bits are used for additional attributes, such as highlighting.
  • Passing the number -1 as color falls back to the default background and foreground colors.
  • The color pair 0 (mod 256) is fixed on (-1, -1).
  • The colors 0 till 15 are the terminal palette colors.

Consider the following testing code. Add this to your .bashrc:

# Set proper $TERM if we are running gnome-terminal
if [ "$COLORTERM" == "gnome-terminal" ]
then
    TERM=xterm-256color
fi

Put this in a python file and run it.

import curses

def main(stdscr):
    curses.start_color()
    curses.use_default_colors()
    for i in range(0, curses.COLORS):
        curses.init_pair(i + 1, i, -1)
    try:
        for i in range(0, 255):
            stdscr.addstr(str(i), curses.color_pair(i))
    except curses.ERR:
        # End of screen reached
        pass
    stdscr.getch()

curses.wrapper(main)

Running it will yield the following output.

As you see, the colors pairs 1-16 are the terminal color palette for foreground colors.

The terminal 'color palette' is set by the terminal application itself to map default curses colours to application-specific 'interpretations'. If you use red, the terminal can choose to display that as burgundy or cherry red, or if the user so desires, something completely different.

In other words, just use the curses colours (combined with or without the bright or blink modifiers) and things should Just Work.

I believe that the curses.use_default_colors() call merely makes transparency available; it is a direct call to the use_default_colors() ncurses API function. ncurses colors are otherwise palette based; you need to set your own color attributes per pair number with curses.init_pair() calls, then select a color pair with curses.color_pair() from the palette to display text with that specific pair; or build text attributes directly for a given addstr() call.

I currently put these lines in front of my script.

curses.use_default_colors()
for i in range(0, curses.COLORS):
    curses.init_pair(i, i, -1);

I don't know if it is the best solution, but at least it yields some color pairs that are consistent with the terminal color palette.

user1404316

I don't have the rep-points to submit this as a comment to Chiel ten Brinke's excellent answer, so I'll offer here a more useful version of his color script:

import curses
def main(stdscr):
    curses.start_color()
    curses.use_default_colors()
    for i in range(0, curses.COLORS):
        curses.init_pair(i + 1, i, -1)
    stdscr.addstr(0, 0, '{0} colors available'.format(curses.COLORS))
    maxy, maxx = stdscr.getmaxyx()
    maxx = maxx - maxx % 5
    x = 0
    y = 1
    try:
        for i in range(0, curses.COLORS):
            stdscr.addstr(y, x, '{0:5}'.format(i), curses.color_pair(i))
            x = (x + 5) % maxx
            if x == 0:
                y += 1
    except curses.ERR:
        pass
    stdscr.getch()
curses.wrapper(main)

You can use the culour package by installing with:

pip install culour

And then you can use it to print with color to curses:

culour.addstr(window, "colored string")
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!