Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom RGB colors with Python curses

I'm writing a program in Python using the curses module in the standard library.

I want my program to just exit if it can't use custom colors I specify with RGB triples.

So I have some starter code that looks like:

import curses

def main(stdscr):
  if not curses.can_change_color():
    raise Exception('Cannot change color')

  curses.init_color(curses.COLOR_BLACK, 999,   0,   0)
  curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
  curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLACK)
  stdscr.addstr('hello', curses.color_pair(1))
  stdscr.addstr(' world', curses.color_pair(2))
  stdscr.getch()

curses.wrapper(main)

And the result I get is:

enter image description here

I expected the black to be replaced by red.

Am I misunderstanding the docs? How can I get curses to respect custom RGB colors I want to use? Or at least fail and tell me that the terminal doesn't support it?

The docs for curses here seem to suggest that on failure it will return an error, and the CPython source seems to propagate curses errors pretty faithfully.

In case it is relevant, I'm on OS X 10.11, and I'm testing on Python3 I installed with Homebrew. But I get the same effect with OS X's builtin Python interpreter as well.

EDIT:

Slightly modified sample code to display color content:

import curses

def main(stdscr):
  if not curses.can_change_color():
    raise Exception('Cannot change color')

  stdscr.addstr(1, 0, repr(curses.color_content(curses.COLOR_BLACK)))
  curses.init_color(curses.COLOR_BLACK, 999,   0,   0)
  curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
  curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLACK)
  stdscr.addstr(0, 0, 'hello', curses.color_pair(1))
  stdscr.addstr(' world', curses.color_pair(2))
  stdscr.addstr(2, 0, repr(curses.color_content(curses.COLOR_BLACK)))
  stdscr.getch()

curses.wrapper(main)

The result this time is: enter image description here

like image 339
math4tots Avatar asked Nov 09 '22 16:11

math4tots


1 Answers

The screenshot may be of Terminal.app; in a quick check it does not honor the escape sequences used for changing color. On the other hand, iTerm2 does use those escape sequences.

If you're using Terminal.app, setting TERM to xterm-256color is pointless, due to the large number of differences versus xterm. There's discussion in the terminal database as commentary that you may find interesting.

The relevant features which curses uses to decide if the terminal can change color are ccc and initc. Those capabilities are not defined in the nsterm terminal descriptions. The terminal descriptions use the xterm+256setaf building block rather than xterm+256color, which infocmp shows are different:

    comparing xterm+256setaf to xterm+256color.
        comparing booleans.
            ccc: F:T.
        comparing numbers.
        comparing strings.
            initc: NULL, '\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\'.
            oc: NULL, '\E]104\007'.
            op: '\E[39;49m', NULL.
like image 182
Thomas Dickey Avatar answered Nov 14 '22 22:11

Thomas Dickey