Curses中的颜色

4

我正在尝试为我的 curses 输出添加颜色。然而,挑战在于文本是通过单个长字符串 self.all_results 打印的。有没有办法给字符串的某个部分添加颜色。

def main(self,stdscr):
    x,y = 0,0 # size of the window
    xx,yy = 50,200  # where to place window - up,across
    pad = curses.newpad(150,150) # nlines, ncols
    pad_pos = 0
    exit = False

    pad.addstr(4,0,str(self.all_results))

    while not exit:
        sleep(0.2)
        if self.timer != None:
            if time() - start > self.timer:
                self.stop = True
                break

        pad.addstr(0,0,str(self.format_results()))
        pad.refresh(pad_pos,0, x,y, xx,yy)

        cmd = stdscr.getch()
        stdscr.nodelay(1)

        if cmd != -1:
            pad.refresh(pad_pos,0, x,y, xx,yy)
            if len(self.format_results().split('\n')) > 100:
                if  cmd == curses.KEY_DOWN:
                    if pad_pos < len(self.format_results())+1:
                        pad_pos += 1
                    try:
                        pad.refresh(pad_pos,0, x,y, xx,yy)
                    except curses.error:
                        pass
                elif cmd == curses.KEY_UP:
                    if pad_pos != 0:
                        pad_pos -= 1
                    try:
                        pad.refresh(pad_pos,0, x,y, xx,yy)
                    except curses.error:
                        pass

2
如何给字符串的一部分添加颜色取决于如何选择要着色的字符串部分。是通过字符串偏移量?通过字符串内容?还是通过屏幕上的位置? - Robᵩ
1
字符串类似于...'probe1 | NY | ERROR\nprobe1 | NY | OK',我想让ERROR显示为红色,OK显示为绿色。 - felix001
1
当然。将字符串分成您想要着色和不想要着色的部分。对于您想要着色的部分,在调用pad.addstr之前调用pad.attronpad.attroff - Ross Ridge
我编写了一个简单的curses包装器,名为cusser,它完全按照@RossRidge上面的策略执行,并且可以理解嵌入式ANSI转义代码。API与标准curses基本相同,因此您无需更改任何内容。 - schneiderfelipe
2个回答

2
我会使用re将字符串分割,然后使用非x,y形式的addstr,为每个部分指定颜色。
#!/usr/bin/env python
import curses
from curses.wrapper import wrapper
import re


def addstr_colorized(win, y, x, s):
    colors = {'OK': curses.COLOR_GREEN, 'ERROR': curses.COLOR_RED}
    win.move(y, x)
    pattern = r'({0:s})'.format(
        '|'.join(r'\b{0:s}\b'.format(word) for word in colors.keys()))
    s = re.split(pattern, s)
    for s in s:
        win.addstr(s, curses.color_pair(colors.get(s, 0)))


def main(stdscr):
    curses.init_pair(curses.COLOR_RED,
                     curses.COLOR_RED,
                     curses.COLOR_BLACK)
    curses.init_pair(curses.COLOR_GREEN,
                     curses.COLOR_GREEN,
                     curses.COLOR_BLACK)

    addstr_colorized(stdscr,
                     4,
                     0,
                     "This line is OK.\nBut there is an ERROR in this line\n")
    stdscr.refresh()
    stdscr.getch()


wrapper(main)

enter image description here


1
这是我用来完成它的代码(不太漂亮,但对于我的需求来说还可以)。
你只需要在某个地方定义你的颜色对,例如:
curses.init_pair(1, curses.COLOR_BLUE, curses.COLOR_GREEN);

接着,只需要使用包含colourN[str]的消息调用该函数,其中N是颜色对编号,而str是要着色的字符串部分。

例如:

addStrColour(stdscr, 0, "This is an example message, colour1[This is coloured using colour pair 1!!!] and now we have normal text again");

这是函数:

def addstrColour(stdscr, pos, message):
  #Split messages based on colour components
  newMes = re.split("(colour\d\[.*?\])", message);

  totalOut = 0;

  for line in newMes:
    m = re.match("colour(\d{1})\[(.*)\]", line);
    if m:
      colourPairNum = int((m.groups()[0]));

      stdscr.addstr(pos, totalOut, m.groups()[1], curses.color_pair(colourPairNum));
      totalOut += len(m.groups()[1]);
    else:
      stdscr.addstr(pos, totalOut, line);
      totalOut += len(line);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接