Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to get the default background color using curses in python?

Using curses in python you can easily use the default color scheme for the terminal using:

curses.use_default_colors()

However once you try to recolor any character, using a color pair you have to declare a background color:

curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)

I really don't want to change the background from the default but I would like to change the foreground.

Is there any way to either get the default background color? or to change just the foreground color?

I am aware that I could use ANSI escape codes to adjust just the foreground color, however ANSI codes are not compatible with curses and I would rather work with curses than rewrite everything in ANSI codes.

like image 413
Wheat Wizard Avatar asked May 17 '17 02:05

Wheat Wizard


2 Answers

Ok, I figured it out,

If you call init_pair with -1 as a value it will fill in the terminal default. For example to make red text with the default background:

curses.init_pair(1, curses.COLOR_RED, -1)

Now curses.color_pair(1) will be set to the background. This will even work if you change the terminal's default while the program is running.

You do have to call curses.use_default_colors() first to use this.

like image 114
Wheat Wizard Avatar answered Oct 29 '22 23:10

Wheat Wizard


window.inch(0,0) will return a value from reading the character at position (0,0) of the window that includes the attributes at that location. If you use stdscr as the window you should get the current colors for the whole screen. Quoting the official documentation:

"Return the character at the given position in the window. The bottom 8 bits are the character proper, and upper bits are the attributes."

colors = stdscr.inch(0,0) & curses.A_COLOR

should extract the current colors for both foreground and background. Separating the foreground and background colors is something I am currently trying to figure out myself but haven't had much luck yet. On a Windows machine the curses implementation is PDCurses, and the source code for PDCurses seems to say that the two colors are combined in the leftmost byte of a 4-byte integer field, but I haven't confirmed that yet.

There is also window.getbkgd() which the documentation says will:

"Return the given window’s current background character/attribute pair."

which is more than a little vague. I am working on nailing down exactly what that function actually returns, though it sounds a lot like the value returned from the inch function.

HTH

Peter

[Edit] This sequence of curses calls reliably gives you the foreground and background color numbers. On *ix systems the defaults are fg=-1 and bg=-1 (-1 means "default" to the init_color() function) but on windows (python 3.8+, windows-curses 2.2.0) the default values are fg=7 (COLOR_WHITE) and bg=0 (COLOR_BLACK).

    attr = stdscr.getbkgd()
    stdscr.addstr("scrbkgd={:08X}={}\n".format(attr, attr))
    pair = curses.pair_number(attr)
    if platform.system() == "Windows":
        pair = pair >> 16
    fg, bg = curses.pair_content (pair)
    stdscr.addstr("color(scrbkgd) fg={:08X}={},bg={:08X}={}\n".format(fg, fg, bg, bg))
    stdscr.getch()
like image 1
pjfarley3 Avatar answered Oct 29 '22 21:10

pjfarley3