def colors_init():
"""
Initializes all color pairs possible into the dictionary CURSES_COLORPAIRS.
Thus, getting an attribute for a black foreground and a green background
would look like:
>>> curses_color.colors_init()
>>> green_black_attr = curses_color.CURSES_COLORPAIRS['black-green']
>>> stdscr.addstr(0, 0, "test", curses.color_pair(green_black_attr))
"""
if len(CURSES_COLORPAIRS): return
assert curses.has_colors(
), "Curses wasn't configured to support colors. Call curses.start_color()"
start_number = 120
for fg in BASE_CURSES_COLORS.keys():
for bg in BASE_CURSES_COLORS.keys():
pair_num = len(CURSES_COLORPAIRS) + start_number
curses.init_pair(pair_num, BASE_CURSES_COLORS[fg],
BASE_CURSES_COLORS[bg])
pair_name = "{}-{}".format(fg, bg)
CURSES_COLORPAIRS[pair_name] = pair_num
python类color_pair()的实例源码
def _test(stdscr):
import time
colors_init()
label_width = max([len(k) for k in CURSES_COLORPAIRS.keys()])
cols = 4
for idx, k in enumerate(CURSES_COLORPAIRS.keys()):
label = "{{:<{}}}".format(label_width).format(k)
x = (idx % cols) * (label_width + 1)
y = idx // cols
pair = curses.color_pair(CURSES_COLORPAIRS[k])
stdscr.addstr(y, x, label, pair)
time.sleep(0.1)
stdscr.refresh()
stdscr.getch()
def __display_body_line(self, lineNum, station):
col = curses.color_pair(5)
# if the cursor is on the highligted chat/group
is_current = self.selection == self.showing
if lineNum + self.startPos == self.selection and is_current:
col = curses.color_pair(9)
self.body_win.hline(lineNum + 1, 1, ' ', self.bodyMaxX - 2, col)
elif lineNum + self.startPos == self.selection:
col = curses.color_pair(6)
self.body_win.hline(lineNum + 1, 1, ' ', self.bodyMaxX - 2, col)
elif lineNum + self.startPos == self.showing:
col = curses.color_pair(4)
self.body_win.hline(lineNum + 1, 1, ' ', self.bodyMaxX - 2, col)
line = "{0}. {1}".format(lineNum + self.startPos + 1, station)
self.body_win.addstr(lineNum + 1, 1, line, col)
def init_layout(self):
"""Initialize the each windows with their size and shape"""
self.height, self.width = self.window.getmaxyx()
# Title section
self.window.addstr(0, 0, '[awesome-{}] Find awesome things!'.format(self.awesome_title), curses.color_pair(1))
self.window.hline(1, 0, curses.ACS_HLINE, self.width)
# Search result section
self.result_window = curses.newwin(self.height - 4, self.width, 2, 0)
self.result_window.keypad(True)
# Search bar section
self.window.hline(self.height - 2, 0, curses.ACS_HLINE, self.width)
self.window.addch(self.height - 1, 0, '>')
self.search_window = curses.newwin(1, self.width - 1, self.height - 1, 2)
self.search_window.keypad(True)
self.window.refresh()
def display(self):
"""Display the found awesome content on result window"""
self.result_window.erase()
for idx, val in enumerate(self.matched_blocks[self.top:self.top + self.max_lines]):
if val['type'] == 'category':
if idx == self.current:
self.result_window.addstr(idx, 0, shorten(val['line'], self.width, placeholder='...'),
curses.color_pair(2))
else:
self.result_window.addstr(idx, 0, shorten(val['line'], self.width, placeholder='...'),
curses.color_pair(1))
elif val['type'] == 'awesome':
if idx == self.current:
self.result_window.addstr(idx, 2, shorten(val['line'], self.width - 3, placeholder='...'),
curses.color_pair(2))
else:
self.result_window.addstr(idx, 2, shorten(val['line'], self.width - 3, placeholder='...'))
self.result_window.refresh()
def initcolors():
""" initialize color pallet """
curses.start_color()
if not curses.has_colors():
raise RuntimeError("Sorry. Terminal does not support colors")
# setup colors on black background
for i in range(1,9):
curses.init_pair(i,i,BLACK)
CPS[i] = curses.color_pair(i)
# have to individually set up special cases
curses.init_pair(BUTTON,WHITE,GRAY) # white on gray for buttons
CPS[BUTTON] = curses.color_pair(BUTTON)
curses.init_pair(HLITE,BLACK,GREEN) # black on Green for highlight aps,stas
CPS[HLITE] = curses.color_pair(HLITE)
curses.init_pair(ERR,WHITE,RED) # white on red
CPS[ERR] = curses.color_pair(ERR)
curses.init_pair(WARN,BLACK,YELLOW) # white on yellow
CPS[WARN] = curses.color_pair(WARN)
curses.init_pair(NOTE,WHITE,GREEN) # white on red
CPS[NOTE] = curses.color_pair(NOTE)
def get_option_lines(self):
lines = []
for index, option in enumerate (self.options):
if index == self.index:
prefix = self.indicator
else:
prefix = len (self.indicator) * ' '
if self.multi_select and index in self.all_selected:
format = curses.color_pair (1)
line = ('{0} {1}'.format (prefix, option), format)
else:
line = '{0} {1}'.format (prefix, option)
lines.append (line)
return lines
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))
stdscr.addstr(" ")
except curses.ERR:
# End of screen reached
pass
stdscr.getch()
def tick(self, scr, steps):
height, width = scr.getmaxyx()
if self.advances(steps):
# if window was resized and char is out of bounds, reset
self.out_of_bounds_reset(width, height)
# make previous char curses.A_NORMAL
if USE_COLORS:
scr.addstr(self.y, self.x, self.char, curses.color_pair(COLOR_CHAR_NORMAL))
else:
scr.addstr(self.y, self.x, self.char, curses.A_NORMAL)
# choose new char and draw it A_REVERSE if not out of bounds
self.char = random.choice(FallingChar.matrixchr).encode(encoding)
self.y += 1
if not self.out_of_bounds_reset(width, height):
if USE_COLORS:
scr.addstr(self.y, self.x, self.char, curses.color_pair(COLOR_CHAR_HIGHLIGHT))
else:
scr.addstr(self.y, self.x, self.char, curses.A_REVERSE)
def draw_frame(self, scr, x1, y1, x2, y2, attrs, clear_char=None):
if USE_COLORS:
if attrs == curses.A_REVERSE:
attrs = curses.color_pair(COLOR_WINDOW)
h, w = scr.getmaxyx()
for y in (y1, y2):
for x in range(x1, x2+1):
if x < 0 or x > w-1 or y < 0 or y > h-2:
continue
if clear_char is None:
scr.chgat(y, x, 1, attrs)
else:
scr.addstr(y, x, clear_char, attrs)
for x in (x1, x2):
for y in range(y1, y2+1):
if x < 0 or x > w-1 or y < 0 or y > h-2:
continue
if clear_char is None:
scr.chgat(y, x, 1, attrs)
else:
scr.addstr(y, x, clear_char, attrs)
# we don't need a good PRNG, just something that looks a bit random.
def _add_line(y, x, window, line):
# split but \033 which stands for a color change
color_split = line.split('\033')
# Print the first part of the line without color change
default_color_pair = _get_color(curses.COLOR_WHITE, curses.COLOR_BLACK)
window.addstr(y, x, color_split[0], curses.color_pair(default_color_pair))
x += len(color_split[0])
# Iterate over the rest of the line-parts and print them with their colors
for substring in color_split[1:]:
color_str = substring.split('m')[0]
substring = substring[len(color_str)+1:]
color_pair = _color_str_to_color_pair(color_str)
window.addstr(y, x, substring, curses.color_pair(color_pair))
x += len(substring)
def status(self):
"""
Draw `Status` frame and `Hosts File` frame in the TUI window.
"""
screen = self._stdscr.subwin(11, 25, 10, 0)
screen.bkgd(' ', curses.color_pair(4))
# Set local variable
normal = curses.A_NORMAL
green = curses.color_pair(7)
red = curses.color_pair(9)
# Status info
for i, stat in enumerate(self.statusinfo):
screen.addstr(2 + i, 2, stat[0], normal)
stat_str = ''.join(['[', stat[1], ']']).ljust(9)
screen.addstr(2 + i, 15, stat_str,
green if stat[2] == "GREEN" else red)
# Hosts file info
i = 0
for key, info in self.hostsinfo.items():
screen.addstr(7 + i, 2, key, normal)
screen.addstr(7 + i, 15, info, normal)
i += 1
screen.refresh()
def __init__(self):
self._colors = {
'white': curses.color_pair(self.PAIRS['white']),
'black': curses.color_pair(self.PAIRS['white']) | curses.A_REVERSE,
'red': curses.color_pair(self.PAIRS['red']),
'blue': curses.color_pair(self.PAIRS['blue']),
'green': curses.color_pair(self.PAIRS['green']),
'green_reverse': (curses.color_pair(self.PAIRS['green'])
| curses.A_REVERSE),
'cyan': curses.color_pair(self.PAIRS['cyan']),
'cyan_reverse': (curses.color_pair(self.PAIRS['cyan'])
| curses.A_REVERSE),
'yellow': curses.color_pair(self.PAIRS['yellow']),
'yellow_reverse': (curses.color_pair(self.PAIRS['yellow'])
| curses.A_REVERSE),
'magenta': curses.color_pair(self.PAIRS['magenta']),
'magenta_reverse': (curses.color_pair(self.PAIRS['magenta'])
| curses.A_REVERSE),
}
curses.start_color()
curses.use_default_colors()
for definition, (color, background) in self.DEFINITION.items():
curses.init_pair(definition, color, background)
def _draw_footer(self, footer_window):
"""
Given a footer window and a list of items, draw the items in the footer and highlight the selected item.
Parameters:
footer_window (WindowObject): the window the footer will be drawn in
"""
for item in self.footer_items:
if self.footer_items.index(item) == self.current_column:
# Highlight the item that is currently selected
footer_window.addstr(1,
self.footer_items.index(item) * 10 + 1,
item,
curses.color_pair(1) | curses.A_BOLD)
else:
footer_window.addstr(1,
self.footer_items.index(item) * 10 + 1,
item)
def __getitem__(self, pair):
fg, bg = pair
assert isinstance(fg, int) and -1 <= fg < 256
assert isinstance(bg, int) and -1 <= bg < 256
if pair in self.pair_numbers:
# If pair is stored, retrieve it.
return curses.color_pair(self.pair_numbers[pair])
elif self.counter < MAX_PAIRS:
# If we still haven't filled our queue, add the new pair.
curses.init_pair(self.counter, fg, bg)
self.pair_numbers[pair] = self.counter
self.counter += 1
return curses.color_pair(self.counter - 1)
else:
# If the queue is full, pop the oldest one out
# and use its pair number to create the new one.
_, oldest = self.pair_numbers.popitem(last=False)
curses.init_pair(oldest, fg, bg)
self.pair_numbers[pair] = oldest
return curses.color_pair(oldest)
def display(self, title, content):
curses.curs_set(0)
self.infowin.clear()
y, x = self.infowin.getmaxyx()
self.infowin.bkgd(" ", curses.color_pair(6))
self.infowin.box()
self.infowin.addstr(0, 0, title + " - 'q' to close", curses.A_UNDERLINE | curses.A_BOLD)
for count, line in enumerate(content.split('\n'), start=1):
try:
self.infowin.addstr(count, 1, line)
except:
pass
self.infopanel.show()
curses.panel.update_panels()
curses.doupdate()
while self.infowin.getch() != ord('q'):
pass
curses.curs_set(1)
def get_curses_colour_enum_closest_to_cpair(cpair):
if cpair in MAP_CONST_COLOURS_TO_CPAIR:
return curses.color_pair(MAP_CONST_COLOURS_TO_CPAIR[cpair])|curses.A_BOLD
else:
choice_cpair = None
for (avail_cpair, curses_pair_id) in MAP_CONST_COLOURS_TO_CPAIR.items():
if choice_cpair == None:
choice_cpair = avail_cpair
continue
# Locate the closest to the desired cpair that is not larger than
# it
if avail_cpair > cpair:
continue
elif avail_cpair > choice_cpair:
choice_cpair = avail_cpair
return avail_cpair|curses.A_BOLD
def getinstr(self,prompt):
self.scr.nodelay(0)
self.scr.addstr(self.y+2,self.x+1,' '*(self.w-2),curses.color_pair(TOPSTATUS))
self.scr.addstr(self.y+2,self.x+1,prompt,curses.color_pair(TOPSTATUS))
self.scr.refresh()
curses.curs_set(1)
curses.echo()
self.scr.attron(curses.color_pair(TOPSTATUS))
retval = self.scr.getstr(self.y+2,self.x+len(prompt)+1,8)
self.scr.addstr(self.y+2,self.x+len(prompt)+1,str(retval),curses.color_pair(TOPSTATUS))
self.scr.attroff(curses.color_pair(TOPSTATUS))
self.scr.refresh()
curses.noecho()
curses.curs_set(0)
self.scr.nodelay(1)
return retval
def tick(self, scr, steps, padding_rows, padding_cols, output_rows, output_cols):
height, width = scr.getmaxyx()
in_picture_frame = self.y >= padding_rows and self.y <= padding_rows + output_rows and self.x >= padding_cols and self.x <= padding_cols + output_cols
if self.advances(steps):
# if window was resized and char is out of bounds, reset
self.out_of_bounds_reset(width, height)
# make previous char curses.A_NORMAL
if not in_picture_frame:
if USE_COLORS:
scr.addstr(self.y, self.x, self.char, curses.color_pair(COLOR_CHAR_NORMAL))
else:
scr.addstr(self.y, self.x, self.char, curses.A_NORMAL)
# choose new char and draw it A_REVERSE if not out of bounds
self.char = random.choice(FallingChar.matrixchr).encode(encoding)
self.y += 1
in_picture_frame = self.y >= padding_rows and self.y <= padding_rows + output_rows and self.x >= padding_cols and self.x <= padding_cols + output_cols
if not self.out_of_bounds_reset(width, height) and not in_picture_frame:
if USE_COLORS:
scr.addstr(self.y, self.x, self.char, curses.color_pair(COLOR_CHAR_HIGHLIGHT))
else:
scr.addstr(self.y, self.x, self.char, curses.A_REVERSE)
def setup(self):
curses.start_color()
curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
curses.cbreak()
curses.echo()
lines, cols = self.stdscr.getmaxyx()
self.logwin = self.stdscr.subwin(lines - 2, cols, 0, 0)
self.sepwin = self.stdscr.subwin(1, cols, lines - 2, 0)
self.cmdwin = self.stdscr.subwin(1, cols, lines - 1, 0)
self.logwin.scrollok(True)
self.sepwin.bkgd(curses.color_pair(1))
self.sepwin.refresh()
def getUserAgentColor(subver):
'''
userAgent = subver.lower()
if "classic" in userAgent:
color = COLOR_GOLD
elif "unlimited" in userAgent:
color = COLOR_LTBLUE
elif "xt" in userAgent:
color = COLOR_GREEN
elif "satoshi" not in userAgent:
color = COLOR_RED
else:
color = COLOR_WHITE
return color
'''
hash = hashlib.sha256(subver).hexdigest()
return curses.color_pair((int(hash[10:20], 16) % 7) + 1)
# turn any arbitrary string into a (r, g, b) color via hash
def countdown(stdscr, end_time, font, fg_color, bg_color, msg=None):
stdscr.clear()
curses.curs_set(False)
curses.init_pair(1, fg_color, bg_color)
now = datetime.datetime.now()
timefmt = '%I:%M %p' if now.day == end_time.day else '%I:%M %p, %d %b'
stdscr.addstr(0, 0, 'Alarm set for: ' + end_time.strftime(timefmt))
stdscr.refresh()
win = None
while now < end_time:
time_left = str(end_time - now).split('.')[0]
win = center(stdscr, time_left, font, curses.color_pair(1), win)
sleep(1)
now = datetime.datetime.now()
alert(stdscr, args, win)
def start_bottom_window(window, chat_sender):
window.bkgd(curses.A_NORMAL, curses.color_pair(2))
window.clear()
window.box()
window.refresh()
while True:
window.clear()
window.box()
window.refresh()
s = window.getstr(1, 1).decode('utf-8')
if s is not None and s != "":
chat_sender.send_string(s)
# need to do sleep here...
# if bottom window gets down to `window.getstr...` while top window is setting up,
# it registers a bunch of control characters as the user's input
time.sleep(0.005)
def printc(self, c, x, y):
char = c
color = None
if isinstance(c, tuple):
char = c[0]
color = c[1]
elif isinstance(c, dict):
char = c['txt']
color = c['color']
cmap = self.chars[char]
h = len(cmap)
w = len(cmap[0])
for i in range(0, h):
for j in range(0, w):
if color is not None:
self.scr.addstr(y + i, x + j, cmap[i][j], color_pair(color), )
else:
self.scr.addstr(y + i, x + j, cmap[i][j])
return (w, h)
def print_random_chars(scr, lock, n, tx, ty, sx, sy, sw, sh):
lock.acquire()
try:
for i in range(0, n):
x = randint(1, tx-2)
y = randint(1, ty-2)
if (x > sx and x < (sx + sw) )\
and (y > sy and y < (sy + sh)):
continue
color = randint(100, 199)
c = '%x' % randint(0, 15)
if randint(0,100) % 2 == 0:
c = ' '
scr.addstr(y, x, c, color_pair(color))
scr.refresh()
finally:
lock.release()
def addString(y, x, string, string_color=color.BLACK, bold=False):
if x == position.CENTER:
x = width/2 - len(string)/2
options = 0
if curses.can_change_color():
# tokens special cases color
if string == 'X':
options = curses.color_pair(color.RED) if not bold else curses.color_pair(color.RED_H) | curses.A_BOLD
elif string == 'O':
options = curses.color_pair(color.YELLOW) if not bold else curses.color_pair(color.YELLOW_H) | curses.A_BOLD
else:
options = curses.color_pair(string_color)
if bold:
options |= curses.A_BOLD
stdscr.addstr(y, x, string, options)
stdscr.refresh()
# main display
def get(colorType, delta=0):
global cache__
if type(colorType) == type(0):
colorIndex = colorType
else:
colorIndex = app.prefs.color[colorType]
colorIndex = min(colors - 1, colorIndex + delta)
#colorIndex = colorIndex % colors
r = cache__.get(colorIndex)
if r is not None:
return r
color = curses.color_pair(colorIndex)
if colorType in ('error', 'misspelling'):
color |= curses.A_BOLD | curses.A_REVERSE
cache__[colorIndex] = color
return color
def get_option_lines(self):
lines = []
for index, option in enumerate(self.options):
if index == self.index:
prefix = self.indicator
else:
prefix = len(self.indicator) * ' '
if self.multi_select and index in self.all_selected:
format = curses.color_pair(1)
line = ('{0} {1}'.format(prefix, option), format)
else:
line = '{0} {1}'.format(prefix, option)
lines.append(line)
return lines
def print_char(self, char, color_code, row=None, col=None):
"""
Print one char to the screen with coloration.
In compat_debug this will just append the char to stdout. This checks for silent mode
:param char: The character to print
:param color_code: The colorcode 1234 = RGYB
:param row: The y pos used with curses
:param col: The x pos used with curses
"""
if self.silent:
return 42
if self.compat_debug:
if not color_code:
# Zero is the regular print, but the code 33 will draw black over black and we dont want that
print(char, end='')
else:
print('\033[0;3', color_code, 'm', char, '\033[0m', sep='', end='')
else:
self.win_program.addstr(row, col, char, curses.color_pair(color_code))
def color_attr():
idx = [0]
def next_color():
possible = sorted(curses_colors.CURSES_COLORPAIRS.keys())
key = possible[idx[0]]
val = curses_colors.CURSES_COLORPAIRS[key]
cp = curses.color_pair(val)
idx[0] = (idx[0] + 1) % len(possible)
return cp
return next_color