initial commit
This commit is contained in:
23
venv/lib/python3.11/site-packages/blessed/__init__.py
Normal file
23
venv/lib/python3.11/site-packages/blessed/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
A thin, practical wrapper around terminal capabilities in Python.
|
||||
|
||||
http://pypi.python.org/pypi/blessed
|
||||
"""
|
||||
# std imports
|
||||
import sys as _sys
|
||||
import platform as _platform
|
||||
|
||||
# isort: off
|
||||
if _platform.system() == 'Windows':
|
||||
from blessed.win_terminal import Terminal
|
||||
else:
|
||||
from blessed.terminal import Terminal # type: ignore
|
||||
|
||||
if (3, 0, 0) <= _sys.version_info[:3] < (3, 2, 3):
|
||||
# Good till 3.2.10
|
||||
# Python 3.x < 3.2.3 has a bug in which tparm() erroneously takes a string.
|
||||
raise ImportError('Blessed needs Python 3.2.3 or greater for Python 3 '
|
||||
'support due to http://bugs.python.org/issue10570.')
|
||||
|
||||
__all__ = ('Terminal',)
|
||||
__version__ = "1.20.0"
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
168
venv/lib/python3.11/site-packages/blessed/_capabilities.py
Normal file
168
venv/lib/python3.11/site-packages/blessed/_capabilities.py
Normal file
@@ -0,0 +1,168 @@
|
||||
"""Terminal capability builder patterns."""
|
||||
# std imports
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
|
||||
__all__ = (
|
||||
'CAPABILITY_DATABASE',
|
||||
'CAPABILITIES_RAW_MIXIN',
|
||||
'CAPABILITIES_ADDITIVES',
|
||||
'CAPABILITIES_CAUSE_MOVEMENT',
|
||||
)
|
||||
|
||||
CAPABILITY_DATABASE = OrderedDict((
|
||||
('bell', ('bel', {})),
|
||||
('carriage_return', ('cr', {})),
|
||||
('change_scroll_region', ('csr', {'nparams': 2})),
|
||||
('clear_all_tabs', ('tbc', {})),
|
||||
('clear_screen', ('clear', {})),
|
||||
('clr_bol', ('el1', {})),
|
||||
('clr_eol', ('el', {})),
|
||||
('clr_eos', ('clear_eos', {})),
|
||||
('column_address', ('hpa', {'nparams': 1})),
|
||||
('cursor_address', ('cup', {'nparams': 2, 'match_grouped': True})),
|
||||
('cursor_down', ('cud1', {})),
|
||||
('cursor_home', ('home', {})),
|
||||
('cursor_invisible', ('civis', {})),
|
||||
('cursor_left', ('cub1', {})),
|
||||
('cursor_normal', ('cnorm', {})),
|
||||
('cursor_report', ('u6', {'nparams': 2, 'match_grouped': True})),
|
||||
('cursor_right', ('cuf1', {})),
|
||||
('cursor_up', ('cuu1', {})),
|
||||
('cursor_visible', ('cvvis', {})),
|
||||
('delete_character', ('dch1', {})),
|
||||
('delete_line', ('dl1', {})),
|
||||
('enter_blink_mode', ('blink', {})),
|
||||
('enter_bold_mode', ('bold', {})),
|
||||
('enter_dim_mode', ('dim', {})),
|
||||
('enter_fullscreen', ('smcup', {})),
|
||||
('enter_standout_mode', ('standout', {})),
|
||||
('enter_superscript_mode', ('superscript', {})),
|
||||
('enter_susimpleript_mode', ('susimpleript', {})),
|
||||
('enter_underline_mode', ('underline', {})),
|
||||
('erase_chars', ('ech', {'nparams': 1})),
|
||||
('exit_alt_charset_mode', ('rmacs', {})),
|
||||
('exit_am_mode', ('rmam', {})),
|
||||
('exit_attribute_mode', ('sgr0', {})),
|
||||
('exit_ca_mode', ('rmcup', {})),
|
||||
('exit_fullscreen', ('rmcup', {})),
|
||||
('exit_insert_mode', ('rmir', {})),
|
||||
('exit_standout_mode', ('rmso', {})),
|
||||
('exit_underline_mode', ('rmul', {})),
|
||||
('flash_hook', ('hook', {})),
|
||||
('flash_screen', ('flash', {})),
|
||||
('insert_line', ('il1', {})),
|
||||
('keypad_local', ('rmkx', {})),
|
||||
('keypad_xmit', ('smkx', {})),
|
||||
('meta_off', ('rmm', {})),
|
||||
('meta_on', ('smm', {})),
|
||||
('orig_pair', ('op', {})),
|
||||
('parm_down_cursor', ('cud', {'nparams': 1})),
|
||||
('parm_left_cursor', ('cub', {'nparams': 1, 'match_grouped': True})),
|
||||
('parm_dch', ('dch', {'nparams': 1})),
|
||||
('parm_delete_line', ('dl', {'nparams': 1})),
|
||||
('parm_ich', ('ich', {'nparams': 1})),
|
||||
('parm_index', ('indn', {'nparams': 1})),
|
||||
('parm_insert_line', ('il', {'nparams': 1})),
|
||||
('parm_right_cursor', ('cuf', {'nparams': 1, 'match_grouped': True})),
|
||||
('parm_rindex', ('rin', {'nparams': 1})),
|
||||
('parm_up_cursor', ('cuu', {'nparams': 1})),
|
||||
('print_screen', ('mc0', {})),
|
||||
('prtr_off', ('mc4', {})),
|
||||
('prtr_on', ('mc5', {})),
|
||||
('reset_1string', ('r1', {})),
|
||||
('reset_2string', ('r2', {})),
|
||||
('reset_3string', ('r3', {})),
|
||||
('restore_cursor', ('rc', {})),
|
||||
('row_address', ('vpa', {'nparams': 1})),
|
||||
('save_cursor', ('sc', {})),
|
||||
('scroll_forward', ('ind', {})),
|
||||
('scroll_reverse', ('rev', {})),
|
||||
('set0_des_seq', ('s0ds', {})),
|
||||
('set1_des_seq', ('s1ds', {})),
|
||||
('set2_des_seq', ('s2ds', {})),
|
||||
('set3_des_seq', ('s3ds', {})),
|
||||
# this 'color' is deceiving, but often matching, and a better match
|
||||
# than set_a_attributes1 or set_a_foreground.
|
||||
('color', ('_foreground_color', {'nparams': 1, 'match_any': True,
|
||||
'numeric': 1})),
|
||||
('set_a_foreground', ('color', {'nparams': 1, 'match_any': True,
|
||||
'numeric': 1})),
|
||||
('set_a_background', ('on_color', {'nparams': 1, 'match_any': True,
|
||||
'numeric': 1})),
|
||||
('set_tab', ('hts', {})),
|
||||
('tab', ('ht', {})),
|
||||
('italic', ('sitm', {})),
|
||||
('no_italic', ('sitm', {})),
|
||||
))
|
||||
|
||||
CAPABILITIES_RAW_MIXIN = {
|
||||
'bell': re.escape('\a'),
|
||||
'carriage_return': re.escape('\r'),
|
||||
'cursor_left': re.escape('\b'),
|
||||
'cursor_report': re.escape('\x1b') + r'\[(\d+)\;(\d+)R',
|
||||
'cursor_right': re.escape('\x1b') + r'\[C',
|
||||
'exit_attribute_mode': re.escape('\x1b') + r'\[m',
|
||||
'parm_left_cursor': re.escape('\x1b') + r'\[(\d+)D',
|
||||
'parm_right_cursor': re.escape('\x1b') + r'\[(\d+)C',
|
||||
'restore_cursor': re.escape(r'\x1b\[u'),
|
||||
'save_cursor': re.escape(r'\x1b\[s'),
|
||||
'scroll_forward': re.escape('\n'),
|
||||
'set0_des_seq': re.escape('\x1b(B'),
|
||||
'tab': re.escape('\t'),
|
||||
}
|
||||
_ANY_NOTESC = '[^' + re.escape('\x1b') + ']*'
|
||||
|
||||
CAPABILITIES_ADDITIVES = {
|
||||
'link': ('link',
|
||||
re.escape('\x1b') + r'\]8;' + _ANY_NOTESC + ';' +
|
||||
_ANY_NOTESC + re.escape('\x1b') + '\\\\'),
|
||||
'color256': ('color', re.escape('\x1b') + r'\[38;5;\d+m'),
|
||||
'on_color256': ('on_color', re.escape('\x1b') + r'\[48;5;\d+m'),
|
||||
'color_rgb': ('color_rgb', re.escape('\x1b') + r'\[38;2;\d+;\d+;\d+m'),
|
||||
'on_color_rgb': ('on_color_rgb', re.escape('\x1b') + r'\[48;2;\d+;\d+;\d+m'),
|
||||
'shift_in': ('', re.escape('\x0f')),
|
||||
'shift_out': ('', re.escape('\x0e')),
|
||||
# sgr(...) outputs strangely, use the basic ANSI/EMCA-48 codes here.
|
||||
'set_a_attributes1': (
|
||||
'sgr', re.escape('\x1b') + r'\[\d+m'),
|
||||
'set_a_attributes2': (
|
||||
'sgr', re.escape('\x1b') + r'\[\d+\;\d+m'),
|
||||
'set_a_attributes3': (
|
||||
'sgr', re.escape('\x1b') + r'\[\d+\;\d+\;\d+m'),
|
||||
'set_a_attributes4': (
|
||||
'sgr', re.escape('\x1b') + r'\[\d+\;\d+\;\d+\;\d+m'),
|
||||
# this helps where xterm's sgr0 includes set0_des_seq, we'd
|
||||
# rather like to also match this immediate substring.
|
||||
'sgr0': ('sgr0', re.escape('\x1b') + r'\[m'),
|
||||
'backspace': ('', re.escape('\b')),
|
||||
'ascii_tab': ('', re.escape('\t')),
|
||||
'clr_eol': ('', re.escape('\x1b[K')),
|
||||
'clr_eol0': ('', re.escape('\x1b[0K')),
|
||||
'clr_bol': ('', re.escape('\x1b[1K')),
|
||||
'clr_eosK': ('', re.escape('\x1b[2K')),
|
||||
}
|
||||
|
||||
CAPABILITIES_CAUSE_MOVEMENT = (
|
||||
'ascii_tab',
|
||||
'backspace',
|
||||
'carriage_return',
|
||||
'clear_screen',
|
||||
'column_address',
|
||||
'cursor_address',
|
||||
'cursor_down',
|
||||
'cursor_home',
|
||||
'cursor_left',
|
||||
'cursor_right',
|
||||
'cursor_up',
|
||||
'enter_fullscreen',
|
||||
'exit_fullscreen',
|
||||
'parm_down_cursor',
|
||||
'parm_left_cursor',
|
||||
'parm_right_cursor',
|
||||
'parm_up_cursor',
|
||||
'restore_cursor',
|
||||
'row_address',
|
||||
'scroll_forward',
|
||||
'tab',
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
# std imports
|
||||
from typing import Any, Dict, Tuple, OrderedDict
|
||||
|
||||
CAPABILITY_DATABASE: OrderedDict[str, Tuple[str, Dict[str, Any]]]
|
||||
CAPABILITIES_RAW_MIXIN: Dict[str, str]
|
||||
CAPABILITIES_ADDITIVES: Dict[str, Tuple[str, str]]
|
||||
CAPABILITIES_CAUSE_MOVEMENT: Tuple[str, ...]
|
||||
258
venv/lib/python3.11/site-packages/blessed/color.py
Normal file
258
venv/lib/python3.11/site-packages/blessed/color.py
Normal file
@@ -0,0 +1,258 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Sub-module providing color functions.
|
||||
|
||||
References,
|
||||
|
||||
- https://en.wikipedia.org/wiki/Color_difference
|
||||
- http://www.easyrgb.com/en/math.php
|
||||
- Measuring Colour by R.W.G. Hunt and M.R. Pointer
|
||||
"""
|
||||
|
||||
# std imports
|
||||
from math import cos, exp, sin, sqrt, atan2
|
||||
|
||||
# isort: off
|
||||
try:
|
||||
from functools import lru_cache
|
||||
except ImportError:
|
||||
# lru_cache was added in Python 3.2
|
||||
from backports.functools_lru_cache import lru_cache
|
||||
|
||||
|
||||
def rgb_to_xyz(red, green, blue):
|
||||
"""
|
||||
Convert standard RGB color to XYZ color.
|
||||
|
||||
:arg int red: RGB value of Red.
|
||||
:arg int green: RGB value of Green.
|
||||
:arg int blue: RGB value of Blue.
|
||||
:returns: Tuple (X, Y, Z) representing XYZ color
|
||||
:rtype: tuple
|
||||
|
||||
D65/2° standard illuminant
|
||||
"""
|
||||
rgb = []
|
||||
for val in red, green, blue:
|
||||
val /= 255.0
|
||||
if val > 0.04045:
|
||||
val = pow((val + 0.055) / 1.055, 2.4)
|
||||
else:
|
||||
val /= 12.92
|
||||
val *= 100
|
||||
rgb.append(val)
|
||||
|
||||
red, green, blue = rgb # pylint: disable=unbalanced-tuple-unpacking
|
||||
x_val = red * 0.4124 + green * 0.3576 + blue * 0.1805
|
||||
y_val = red * 0.2126 + green * 0.7152 + blue * 0.0722
|
||||
z_val = red * 0.0193 + green * 0.1192 + blue * 0.9505
|
||||
|
||||
return x_val, y_val, z_val
|
||||
|
||||
|
||||
def xyz_to_lab(x_val, y_val, z_val):
|
||||
"""
|
||||
Convert XYZ color to CIE-Lab color.
|
||||
|
||||
:arg float x_val: XYZ value of X.
|
||||
:arg float y_val: XYZ value of Y.
|
||||
:arg float z_val: XYZ value of Z.
|
||||
:returns: Tuple (L, a, b) representing CIE-Lab color
|
||||
:rtype: tuple
|
||||
|
||||
D65/2° standard illuminant
|
||||
"""
|
||||
xyz = []
|
||||
for val, ref in (x_val, 95.047), (y_val, 100.0), (z_val, 108.883):
|
||||
val /= ref
|
||||
val = pow(val, 1 / 3.0) if val > 0.008856 else 7.787 * val + 16 / 116.0
|
||||
xyz.append(val)
|
||||
|
||||
x_val, y_val, z_val = xyz # pylint: disable=unbalanced-tuple-unpacking
|
||||
cie_l = 116 * y_val - 16
|
||||
cie_a = 500 * (x_val - y_val)
|
||||
cie_b = 200 * (y_val - z_val)
|
||||
|
||||
return cie_l, cie_a, cie_b
|
||||
|
||||
|
||||
@lru_cache(maxsize=256)
|
||||
def rgb_to_lab(red, green, blue):
|
||||
"""
|
||||
Convert RGB color to CIE-Lab color.
|
||||
|
||||
:arg int red: RGB value of Red.
|
||||
:arg int green: RGB value of Green.
|
||||
:arg int blue: RGB value of Blue.
|
||||
:returns: Tuple (L, a, b) representing CIE-Lab color
|
||||
:rtype: tuple
|
||||
|
||||
D65/2° standard illuminant
|
||||
"""
|
||||
return xyz_to_lab(*rgb_to_xyz(red, green, blue))
|
||||
|
||||
|
||||
def dist_rgb(rgb1, rgb2):
|
||||
"""
|
||||
Determine distance between two rgb colors.
|
||||
|
||||
:arg tuple rgb1: RGB color definition
|
||||
:arg tuple rgb2: RGB color definition
|
||||
:returns: Square of the distance between provided colors
|
||||
:rtype: float
|
||||
|
||||
This works by treating RGB colors as coordinates in three dimensional
|
||||
space and finding the closest point within the configured color range
|
||||
using the formula::
|
||||
|
||||
d^2 = (r2 - r1)^2 + (g2 - g1)^2 + (b2 - b1)^2
|
||||
|
||||
For efficiency, the square of the distance is returned
|
||||
which is sufficient for comparisons
|
||||
"""
|
||||
return sum(pow(rgb1[idx] - rgb2[idx], 2) for idx in (0, 1, 2))
|
||||
|
||||
|
||||
def dist_rgb_weighted(rgb1, rgb2):
|
||||
"""
|
||||
Determine the weighted distance between two rgb colors.
|
||||
|
||||
:arg tuple rgb1: RGB color definition
|
||||
:arg tuple rgb2: RGB color definition
|
||||
:returns: Square of the distance between provided colors
|
||||
:rtype: float
|
||||
|
||||
Similar to a standard distance formula, the values are weighted
|
||||
to approximate human perception of color differences
|
||||
|
||||
For efficiency, the square of the distance is returned
|
||||
which is sufficient for comparisons
|
||||
"""
|
||||
red_mean = (rgb1[0] + rgb2[0]) / 2.0
|
||||
|
||||
return ((2 + red_mean / 256) * pow(rgb1[0] - rgb2[0], 2) +
|
||||
4 * pow(rgb1[1] - rgb2[1], 2) +
|
||||
(2 + (255 - red_mean) / 256) * pow(rgb1[2] - rgb2[2], 2))
|
||||
|
||||
|
||||
def dist_cie76(rgb1, rgb2):
|
||||
"""
|
||||
Determine distance between two rgb colors using the CIE94 algorithm.
|
||||
|
||||
:arg tuple rgb1: RGB color definition
|
||||
:arg tuple rgb2: RGB color definition
|
||||
:returns: Square of the distance between provided colors
|
||||
:rtype: float
|
||||
|
||||
For efficiency, the square of the distance is returned
|
||||
which is sufficient for comparisons
|
||||
"""
|
||||
l_1, a_1, b_1 = rgb_to_lab(*rgb1)
|
||||
l_2, a_2, b_2 = rgb_to_lab(*rgb2)
|
||||
return pow(l_1 - l_2, 2) + pow(a_1 - a_2, 2) + pow(b_1 - b_2, 2)
|
||||
|
||||
|
||||
def dist_cie94(rgb1, rgb2):
|
||||
# pylint: disable=too-many-locals
|
||||
"""
|
||||
Determine distance between two rgb colors using the CIE94 algorithm.
|
||||
|
||||
:arg tuple rgb1: RGB color definition
|
||||
:arg tuple rgb2: RGB color definition
|
||||
:returns: Square of the distance between provided colors
|
||||
:rtype: float
|
||||
|
||||
For efficiency, the square of the distance is returned
|
||||
which is sufficient for comparisons
|
||||
"""
|
||||
l_1, a_1, b_1 = rgb_to_lab(*rgb1)
|
||||
l_2, a_2, b_2 = rgb_to_lab(*rgb2)
|
||||
|
||||
s_l = k_l = k_c = k_h = 1
|
||||
k_1 = 0.045
|
||||
k_2 = 0.015
|
||||
|
||||
delta_l = l_1 - l_2
|
||||
delta_a = a_1 - a_2
|
||||
delta_b = b_1 - b_2
|
||||
c_1 = sqrt(a_1 ** 2 + b_1 ** 2)
|
||||
c_2 = sqrt(a_2 ** 2 + b_2 ** 2)
|
||||
delta_c = c_1 - c_2
|
||||
delta_h = sqrt(delta_a ** 2 + delta_b ** 2 + delta_c ** 2)
|
||||
s_c = 1 + k_1 * c_1
|
||||
s_h = 1 + k_2 * c_1
|
||||
|
||||
return ((delta_l / (k_l * s_l)) ** 2 + # pylint: disable=superfluous-parens
|
||||
(delta_c / (k_c * s_c)) ** 2 +
|
||||
(delta_h / (k_h * s_h)) ** 2)
|
||||
|
||||
|
||||
def dist_cie2000(rgb1, rgb2):
|
||||
# pylint: disable=too-many-locals
|
||||
"""
|
||||
Determine distance between two rgb colors using the CIE2000 algorithm.
|
||||
|
||||
:arg tuple rgb1: RGB color definition
|
||||
:arg tuple rgb2: RGB color definition
|
||||
:returns: Square of the distance between provided colors
|
||||
:rtype: float
|
||||
|
||||
For efficiency, the square of the distance is returned
|
||||
which is sufficient for comparisons
|
||||
"""
|
||||
s_l = k_l = k_c = k_h = 1
|
||||
|
||||
l_1, a_1, b_1 = rgb_to_lab(*rgb1)
|
||||
l_2, a_2, b_2 = rgb_to_lab(*rgb2)
|
||||
|
||||
delta_l = l_2 - l_1
|
||||
l_mean = (l_1 + l_2) / 2
|
||||
|
||||
c_1 = sqrt(a_1 ** 2 + b_1 ** 2)
|
||||
c_2 = sqrt(a_2 ** 2 + b_2 ** 2)
|
||||
c_mean = (c_1 + c_2) / 2
|
||||
delta_c = c_1 - c_2
|
||||
|
||||
g_x = sqrt(c_mean ** 7 / (c_mean ** 7 + 25 ** 7))
|
||||
h_1 = atan2(b_1, a_1 + (a_1 / 2) * (1 - g_x)) % 360
|
||||
h_2 = atan2(b_2, a_2 + (a_2 / 2) * (1 - g_x)) % 360
|
||||
|
||||
if 0 in (c_1, c_2):
|
||||
delta_h_prime = 0
|
||||
h_mean = h_1 + h_2
|
||||
else:
|
||||
delta_h_prime = h_2 - h_1
|
||||
if abs(delta_h_prime) <= 180:
|
||||
h_mean = (h_1 + h_2) / 2
|
||||
else:
|
||||
if h_2 <= h_1:
|
||||
delta_h_prime += 360
|
||||
else:
|
||||
delta_h_prime -= 360
|
||||
h_mean = (h_1 + h_2 + 360) / 2 if h_1 + h_2 < 360 else (h_1 + h_2 - 360) / 2
|
||||
|
||||
delta_h = 2 * sqrt(c_1 * c_2) * sin(delta_h_prime / 2)
|
||||
|
||||
t_x = (1 -
|
||||
0.17 * cos(h_mean - 30) +
|
||||
0.24 * cos(2 * h_mean) +
|
||||
0.32 * cos(3 * h_mean + 6) -
|
||||
0.20 * cos(4 * h_mean - 63))
|
||||
|
||||
s_l = 1 + (0.015 * (l_mean - 50) ** 2) / sqrt(20 + (l_mean - 50) ** 2)
|
||||
s_c = 1 + 0.045 * c_mean
|
||||
s_h = 1 + 0.015 * c_mean * t_x
|
||||
r_t = -2 * g_x * sin(abs(60 * exp(-1 * abs((delta_h - 275) / 25) ** 2)))
|
||||
|
||||
delta_l = delta_l / (k_l * s_l)
|
||||
delta_c = delta_c / (k_c * s_c)
|
||||
delta_h = delta_h / (k_h * s_h)
|
||||
|
||||
return delta_l ** 2 + delta_c ** 2 + delta_h ** 2 + r_t * delta_c * delta_h
|
||||
|
||||
|
||||
COLOR_DISTANCE_ALGORITHMS = {'rgb': dist_rgb,
|
||||
'rgb-weighted': dist_rgb_weighted,
|
||||
'cie76': dist_cie76,
|
||||
'cie94': dist_cie94,
|
||||
'cie2000': dist_cie2000}
|
||||
17
venv/lib/python3.11/site-packages/blessed/color.pyi
Normal file
17
venv/lib/python3.11/site-packages/blessed/color.pyi
Normal file
@@ -0,0 +1,17 @@
|
||||
# std imports
|
||||
from typing import Dict, Tuple, Callable
|
||||
|
||||
_RGB = Tuple[int, int, int]
|
||||
|
||||
def rgb_to_xyz(red: int, green: int, blue: int) -> Tuple[float, float, float]: ...
|
||||
def xyz_to_lab(
|
||||
x_val: float, y_val: float, z_val: float
|
||||
) -> Tuple[float, float, float]: ...
|
||||
def rgb_to_lab(red: int, green: int, blue: int) -> Tuple[float, float, float]: ...
|
||||
def dist_rgb(rgb1: _RGB, rgb2: _RGB) -> float: ...
|
||||
def dist_rgb_weighted(rgb1: _RGB, rgb2: _RGB) -> float: ...
|
||||
def dist_cie76(rgb1: _RGB, rgb2: _RGB) -> float: ...
|
||||
def dist_cie94(rgb1: _RGB, rgb2: _RGB) -> float: ...
|
||||
def dist_cie2000(rgb1: _RGB, rgb2: _RGB) -> float: ...
|
||||
|
||||
COLOR_DISTANCE_ALGORITHMS: Dict[str, Callable[[_RGB, _RGB], float]]
|
||||
973
venv/lib/python3.11/site-packages/blessed/colorspace.py
Normal file
973
venv/lib/python3.11/site-packages/blessed/colorspace.py
Normal file
@@ -0,0 +1,973 @@
|
||||
"""
|
||||
Color reference data.
|
||||
|
||||
References,
|
||||
|
||||
- https://github.com/freedesktop/xorg-rgb/blob/master/rgb.txt
|
||||
- https://github.com/ThomasDickey/xterm-snapshots/blob/master/256colres.h
|
||||
- https://github.com/ThomasDickey/xterm-snapshots/blob/master/XTerm-col.ad
|
||||
- https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
||||
- https://gist.github.com/XVilka/8346728
|
||||
- https://devblogs.microsoft.com/commandline/24-bit-color-in-the-windows-console/
|
||||
- http://jdebp.uk/Softwares/nosh/guide/TerminalCapabilities.html
|
||||
"""
|
||||
|
||||
# std imports
|
||||
import collections
|
||||
|
||||
__all__ = (
|
||||
'CGA_COLORS',
|
||||
'RGBColor',
|
||||
'RGB_256TABLE',
|
||||
'X11_COLORNAMES_TO_RGB',
|
||||
)
|
||||
|
||||
CGA_COLORS = {'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'}
|
||||
|
||||
|
||||
class RGBColor(collections.namedtuple("RGBColor", ["red", "green", "blue"])):
|
||||
"""Named tuple for an RGB color definition."""
|
||||
|
||||
def __str__(self):
|
||||
return '#{0:02x}{1:02x}{2:02x}'.format(*self)
|
||||
|
||||
|
||||
#: X11 Color names to (XTerm-defined) RGB values from xorg-rgb/rgb.txt
|
||||
X11_COLORNAMES_TO_RGB = {
|
||||
'aliceblue': RGBColor(240, 248, 255),
|
||||
'antiquewhite': RGBColor(250, 235, 215),
|
||||
'antiquewhite1': RGBColor(255, 239, 219),
|
||||
'antiquewhite2': RGBColor(238, 223, 204),
|
||||
'antiquewhite3': RGBColor(205, 192, 176),
|
||||
'antiquewhite4': RGBColor(139, 131, 120),
|
||||
'aqua': RGBColor(0, 255, 255),
|
||||
'aquamarine': RGBColor(127, 255, 212),
|
||||
'aquamarine1': RGBColor(127, 255, 212),
|
||||
'aquamarine2': RGBColor(118, 238, 198),
|
||||
'aquamarine3': RGBColor(102, 205, 170),
|
||||
'aquamarine4': RGBColor(69, 139, 116),
|
||||
'azure': RGBColor(240, 255, 255),
|
||||
'azure1': RGBColor(240, 255, 255),
|
||||
'azure2': RGBColor(224, 238, 238),
|
||||
'azure3': RGBColor(193, 205, 205),
|
||||
'azure4': RGBColor(131, 139, 139),
|
||||
'beige': RGBColor(245, 245, 220),
|
||||
'bisque': RGBColor(255, 228, 196),
|
||||
'bisque1': RGBColor(255, 228, 196),
|
||||
'bisque2': RGBColor(238, 213, 183),
|
||||
'bisque3': RGBColor(205, 183, 158),
|
||||
'bisque4': RGBColor(139, 125, 107),
|
||||
'black': RGBColor(0, 0, 0),
|
||||
'blanchedalmond': RGBColor(255, 235, 205),
|
||||
'blue': RGBColor(0, 0, 255),
|
||||
'blue1': RGBColor(0, 0, 255),
|
||||
'blue2': RGBColor(0, 0, 238),
|
||||
'blue3': RGBColor(0, 0, 205),
|
||||
'blue4': RGBColor(0, 0, 139),
|
||||
'blueviolet': RGBColor(138, 43, 226),
|
||||
'brown': RGBColor(165, 42, 42),
|
||||
'brown1': RGBColor(255, 64, 64),
|
||||
'brown2': RGBColor(238, 59, 59),
|
||||
'brown3': RGBColor(205, 51, 51),
|
||||
'brown4': RGBColor(139, 35, 35),
|
||||
'burlywood': RGBColor(222, 184, 135),
|
||||
'burlywood1': RGBColor(255, 211, 155),
|
||||
'burlywood2': RGBColor(238, 197, 145),
|
||||
'burlywood3': RGBColor(205, 170, 125),
|
||||
'burlywood4': RGBColor(139, 115, 85),
|
||||
'cadetblue': RGBColor(95, 158, 160),
|
||||
'cadetblue1': RGBColor(152, 245, 255),
|
||||
'cadetblue2': RGBColor(142, 229, 238),
|
||||
'cadetblue3': RGBColor(122, 197, 205),
|
||||
'cadetblue4': RGBColor(83, 134, 139),
|
||||
'chartreuse': RGBColor(127, 255, 0),
|
||||
'chartreuse1': RGBColor(127, 255, 0),
|
||||
'chartreuse2': RGBColor(118, 238, 0),
|
||||
'chartreuse3': RGBColor(102, 205, 0),
|
||||
'chartreuse4': RGBColor(69, 139, 0),
|
||||
'chocolate': RGBColor(210, 105, 30),
|
||||
'chocolate1': RGBColor(255, 127, 36),
|
||||
'chocolate2': RGBColor(238, 118, 33),
|
||||
'chocolate3': RGBColor(205, 102, 29),
|
||||
'chocolate4': RGBColor(139, 69, 19),
|
||||
'coral': RGBColor(255, 127, 80),
|
||||
'coral1': RGBColor(255, 114, 86),
|
||||
'coral2': RGBColor(238, 106, 80),
|
||||
'coral3': RGBColor(205, 91, 69),
|
||||
'coral4': RGBColor(139, 62, 47),
|
||||
'cornflowerblue': RGBColor(100, 149, 237),
|
||||
'cornsilk': RGBColor(255, 248, 220),
|
||||
'cornsilk1': RGBColor(255, 248, 220),
|
||||
'cornsilk2': RGBColor(238, 232, 205),
|
||||
'cornsilk3': RGBColor(205, 200, 177),
|
||||
'cornsilk4': RGBColor(139, 136, 120),
|
||||
'crimson': RGBColor(220, 20, 60),
|
||||
'cyan': RGBColor(0, 255, 255),
|
||||
'cyan1': RGBColor(0, 255, 255),
|
||||
'cyan2': RGBColor(0, 238, 238),
|
||||
'cyan3': RGBColor(0, 205, 205),
|
||||
'cyan4': RGBColor(0, 139, 139),
|
||||
'darkblue': RGBColor(0, 0, 139),
|
||||
'darkcyan': RGBColor(0, 139, 139),
|
||||
'darkgoldenrod': RGBColor(184, 134, 11),
|
||||
'darkgoldenrod1': RGBColor(255, 185, 15),
|
||||
'darkgoldenrod2': RGBColor(238, 173, 14),
|
||||
'darkgoldenrod3': RGBColor(205, 149, 12),
|
||||
'darkgoldenrod4': RGBColor(139, 101, 8),
|
||||
'darkgray': RGBColor(169, 169, 169),
|
||||
'darkgreen': RGBColor(0, 100, 0),
|
||||
'darkgrey': RGBColor(169, 169, 169),
|
||||
'darkkhaki': RGBColor(189, 183, 107),
|
||||
'darkmagenta': RGBColor(139, 0, 139),
|
||||
'darkolivegreen': RGBColor(85, 107, 47),
|
||||
'darkolivegreen1': RGBColor(202, 255, 112),
|
||||
'darkolivegreen2': RGBColor(188, 238, 104),
|
||||
'darkolivegreen3': RGBColor(162, 205, 90),
|
||||
'darkolivegreen4': RGBColor(110, 139, 61),
|
||||
'darkorange': RGBColor(255, 140, 0),
|
||||
'darkorange1': RGBColor(255, 127, 0),
|
||||
'darkorange2': RGBColor(238, 118, 0),
|
||||
'darkorange3': RGBColor(205, 102, 0),
|
||||
'darkorange4': RGBColor(139, 69, 0),
|
||||
'darkorchid': RGBColor(153, 50, 204),
|
||||
'darkorchid1': RGBColor(191, 62, 255),
|
||||
'darkorchid2': RGBColor(178, 58, 238),
|
||||
'darkorchid3': RGBColor(154, 50, 205),
|
||||
'darkorchid4': RGBColor(104, 34, 139),
|
||||
'darkred': RGBColor(139, 0, 0),
|
||||
'darksalmon': RGBColor(233, 150, 122),
|
||||
'darkseagreen': RGBColor(143, 188, 143),
|
||||
'darkseagreen1': RGBColor(193, 255, 193),
|
||||
'darkseagreen2': RGBColor(180, 238, 180),
|
||||
'darkseagreen3': RGBColor(155, 205, 155),
|
||||
'darkseagreen4': RGBColor(105, 139, 105),
|
||||
'darkslateblue': RGBColor(72, 61, 139),
|
||||
'darkslategray': RGBColor(47, 79, 79),
|
||||
'darkslategray1': RGBColor(151, 255, 255),
|
||||
'darkslategray2': RGBColor(141, 238, 238),
|
||||
'darkslategray3': RGBColor(121, 205, 205),
|
||||
'darkslategray4': RGBColor(82, 139, 139),
|
||||
'darkslategrey': RGBColor(47, 79, 79),
|
||||
'darkturquoise': RGBColor(0, 206, 209),
|
||||
'darkviolet': RGBColor(148, 0, 211),
|
||||
'deeppink': RGBColor(255, 20, 147),
|
||||
'deeppink1': RGBColor(255, 20, 147),
|
||||
'deeppink2': RGBColor(238, 18, 137),
|
||||
'deeppink3': RGBColor(205, 16, 118),
|
||||
'deeppink4': RGBColor(139, 10, 80),
|
||||
'deepskyblue': RGBColor(0, 191, 255),
|
||||
'deepskyblue1': RGBColor(0, 191, 255),
|
||||
'deepskyblue2': RGBColor(0, 178, 238),
|
||||
'deepskyblue3': RGBColor(0, 154, 205),
|
||||
'deepskyblue4': RGBColor(0, 104, 139),
|
||||
'dimgray': RGBColor(105, 105, 105),
|
||||
'dimgrey': RGBColor(105, 105, 105),
|
||||
'dodgerblue': RGBColor(30, 144, 255),
|
||||
'dodgerblue1': RGBColor(30, 144, 255),
|
||||
'dodgerblue2': RGBColor(28, 134, 238),
|
||||
'dodgerblue3': RGBColor(24, 116, 205),
|
||||
'dodgerblue4': RGBColor(16, 78, 139),
|
||||
'firebrick': RGBColor(178, 34, 34),
|
||||
'firebrick1': RGBColor(255, 48, 48),
|
||||
'firebrick2': RGBColor(238, 44, 44),
|
||||
'firebrick3': RGBColor(205, 38, 38),
|
||||
'firebrick4': RGBColor(139, 26, 26),
|
||||
'floralwhite': RGBColor(255, 250, 240),
|
||||
'forestgreen': RGBColor(34, 139, 34),
|
||||
'fuchsia': RGBColor(255, 0, 255),
|
||||
'gainsboro': RGBColor(220, 220, 220),
|
||||
'ghostwhite': RGBColor(248, 248, 255),
|
||||
'gold': RGBColor(255, 215, 0),
|
||||
'gold1': RGBColor(255, 215, 0),
|
||||
'gold2': RGBColor(238, 201, 0),
|
||||
'gold3': RGBColor(205, 173, 0),
|
||||
'gold4': RGBColor(139, 117, 0),
|
||||
'goldenrod': RGBColor(218, 165, 32),
|
||||
'goldenrod1': RGBColor(255, 193, 37),
|
||||
'goldenrod2': RGBColor(238, 180, 34),
|
||||
'goldenrod3': RGBColor(205, 155, 29),
|
||||
'goldenrod4': RGBColor(139, 105, 20),
|
||||
'gray': RGBColor(190, 190, 190),
|
||||
'gray0': RGBColor(0, 0, 0),
|
||||
'gray1': RGBColor(3, 3, 3),
|
||||
'gray10': RGBColor(26, 26, 26),
|
||||
'gray100': RGBColor(255, 255, 255),
|
||||
'gray11': RGBColor(28, 28, 28),
|
||||
'gray12': RGBColor(31, 31, 31),
|
||||
'gray13': RGBColor(33, 33, 33),
|
||||
'gray14': RGBColor(36, 36, 36),
|
||||
'gray15': RGBColor(38, 38, 38),
|
||||
'gray16': RGBColor(41, 41, 41),
|
||||
'gray17': RGBColor(43, 43, 43),
|
||||
'gray18': RGBColor(46, 46, 46),
|
||||
'gray19': RGBColor(48, 48, 48),
|
||||
'gray2': RGBColor(5, 5, 5),
|
||||
'gray20': RGBColor(51, 51, 51),
|
||||
'gray21': RGBColor(54, 54, 54),
|
||||
'gray22': RGBColor(56, 56, 56),
|
||||
'gray23': RGBColor(59, 59, 59),
|
||||
'gray24': RGBColor(61, 61, 61),
|
||||
'gray25': RGBColor(64, 64, 64),
|
||||
'gray26': RGBColor(66, 66, 66),
|
||||
'gray27': RGBColor(69, 69, 69),
|
||||
'gray28': RGBColor(71, 71, 71),
|
||||
'gray29': RGBColor(74, 74, 74),
|
||||
'gray3': RGBColor(8, 8, 8),
|
||||
'gray30': RGBColor(77, 77, 77),
|
||||
'gray31': RGBColor(79, 79, 79),
|
||||
'gray32': RGBColor(82, 82, 82),
|
||||
'gray33': RGBColor(84, 84, 84),
|
||||
'gray34': RGBColor(87, 87, 87),
|
||||
'gray35': RGBColor(89, 89, 89),
|
||||
'gray36': RGBColor(92, 92, 92),
|
||||
'gray37': RGBColor(94, 94, 94),
|
||||
'gray38': RGBColor(97, 97, 97),
|
||||
'gray39': RGBColor(99, 99, 99),
|
||||
'gray4': RGBColor(10, 10, 10),
|
||||
'gray40': RGBColor(102, 102, 102),
|
||||
'gray41': RGBColor(105, 105, 105),
|
||||
'gray42': RGBColor(107, 107, 107),
|
||||
'gray43': RGBColor(110, 110, 110),
|
||||
'gray44': RGBColor(112, 112, 112),
|
||||
'gray45': RGBColor(115, 115, 115),
|
||||
'gray46': RGBColor(117, 117, 117),
|
||||
'gray47': RGBColor(120, 120, 120),
|
||||
'gray48': RGBColor(122, 122, 122),
|
||||
'gray49': RGBColor(125, 125, 125),
|
||||
'gray5': RGBColor(13, 13, 13),
|
||||
'gray50': RGBColor(127, 127, 127),
|
||||
'gray51': RGBColor(130, 130, 130),
|
||||
'gray52': RGBColor(133, 133, 133),
|
||||
'gray53': RGBColor(135, 135, 135),
|
||||
'gray54': RGBColor(138, 138, 138),
|
||||
'gray55': RGBColor(140, 140, 140),
|
||||
'gray56': RGBColor(143, 143, 143),
|
||||
'gray57': RGBColor(145, 145, 145),
|
||||
'gray58': RGBColor(148, 148, 148),
|
||||
'gray59': RGBColor(150, 150, 150),
|
||||
'gray6': RGBColor(15, 15, 15),
|
||||
'gray60': RGBColor(153, 153, 153),
|
||||
'gray61': RGBColor(156, 156, 156),
|
||||
'gray62': RGBColor(158, 158, 158),
|
||||
'gray63': RGBColor(161, 161, 161),
|
||||
'gray64': RGBColor(163, 163, 163),
|
||||
'gray65': RGBColor(166, 166, 166),
|
||||
'gray66': RGBColor(168, 168, 168),
|
||||
'gray67': RGBColor(171, 171, 171),
|
||||
'gray68': RGBColor(173, 173, 173),
|
||||
'gray69': RGBColor(176, 176, 176),
|
||||
'gray7': RGBColor(18, 18, 18),
|
||||
'gray70': RGBColor(179, 179, 179),
|
||||
'gray71': RGBColor(181, 181, 181),
|
||||
'gray72': RGBColor(184, 184, 184),
|
||||
'gray73': RGBColor(186, 186, 186),
|
||||
'gray74': RGBColor(189, 189, 189),
|
||||
'gray75': RGBColor(191, 191, 191),
|
||||
'gray76': RGBColor(194, 194, 194),
|
||||
'gray77': RGBColor(196, 196, 196),
|
||||
'gray78': RGBColor(199, 199, 199),
|
||||
'gray79': RGBColor(201, 201, 201),
|
||||
'gray8': RGBColor(20, 20, 20),
|
||||
'gray80': RGBColor(204, 204, 204),
|
||||
'gray81': RGBColor(207, 207, 207),
|
||||
'gray82': RGBColor(209, 209, 209),
|
||||
'gray83': RGBColor(212, 212, 212),
|
||||
'gray84': RGBColor(214, 214, 214),
|
||||
'gray85': RGBColor(217, 217, 217),
|
||||
'gray86': RGBColor(219, 219, 219),
|
||||
'gray87': RGBColor(222, 222, 222),
|
||||
'gray88': RGBColor(224, 224, 224),
|
||||
'gray89': RGBColor(227, 227, 227),
|
||||
'gray9': RGBColor(23, 23, 23),
|
||||
'gray90': RGBColor(229, 229, 229),
|
||||
'gray91': RGBColor(232, 232, 232),
|
||||
'gray92': RGBColor(235, 235, 235),
|
||||
'gray93': RGBColor(237, 237, 237),
|
||||
'gray94': RGBColor(240, 240, 240),
|
||||
'gray95': RGBColor(242, 242, 242),
|
||||
'gray96': RGBColor(245, 245, 245),
|
||||
'gray97': RGBColor(247, 247, 247),
|
||||
'gray98': RGBColor(250, 250, 250),
|
||||
'gray99': RGBColor(252, 252, 252),
|
||||
'green': RGBColor(0, 255, 0),
|
||||
'green1': RGBColor(0, 255, 0),
|
||||
'green2': RGBColor(0, 238, 0),
|
||||
'green3': RGBColor(0, 205, 0),
|
||||
'green4': RGBColor(0, 139, 0),
|
||||
'greenyellow': RGBColor(173, 255, 47),
|
||||
'grey': RGBColor(190, 190, 190),
|
||||
'grey0': RGBColor(0, 0, 0),
|
||||
'grey1': RGBColor(3, 3, 3),
|
||||
'grey10': RGBColor(26, 26, 26),
|
||||
'grey100': RGBColor(255, 255, 255),
|
||||
'grey11': RGBColor(28, 28, 28),
|
||||
'grey12': RGBColor(31, 31, 31),
|
||||
'grey13': RGBColor(33, 33, 33),
|
||||
'grey14': RGBColor(36, 36, 36),
|
||||
'grey15': RGBColor(38, 38, 38),
|
||||
'grey16': RGBColor(41, 41, 41),
|
||||
'grey17': RGBColor(43, 43, 43),
|
||||
'grey18': RGBColor(46, 46, 46),
|
||||
'grey19': RGBColor(48, 48, 48),
|
||||
'grey2': RGBColor(5, 5, 5),
|
||||
'grey20': RGBColor(51, 51, 51),
|
||||
'grey21': RGBColor(54, 54, 54),
|
||||
'grey22': RGBColor(56, 56, 56),
|
||||
'grey23': RGBColor(59, 59, 59),
|
||||
'grey24': RGBColor(61, 61, 61),
|
||||
'grey25': RGBColor(64, 64, 64),
|
||||
'grey26': RGBColor(66, 66, 66),
|
||||
'grey27': RGBColor(69, 69, 69),
|
||||
'grey28': RGBColor(71, 71, 71),
|
||||
'grey29': RGBColor(74, 74, 74),
|
||||
'grey3': RGBColor(8, 8, 8),
|
||||
'grey30': RGBColor(77, 77, 77),
|
||||
'grey31': RGBColor(79, 79, 79),
|
||||
'grey32': RGBColor(82, 82, 82),
|
||||
'grey33': RGBColor(84, 84, 84),
|
||||
'grey34': RGBColor(87, 87, 87),
|
||||
'grey35': RGBColor(89, 89, 89),
|
||||
'grey36': RGBColor(92, 92, 92),
|
||||
'grey37': RGBColor(94, 94, 94),
|
||||
'grey38': RGBColor(97, 97, 97),
|
||||
'grey39': RGBColor(99, 99, 99),
|
||||
'grey4': RGBColor(10, 10, 10),
|
||||
'grey40': RGBColor(102, 102, 102),
|
||||
'grey41': RGBColor(105, 105, 105),
|
||||
'grey42': RGBColor(107, 107, 107),
|
||||
'grey43': RGBColor(110, 110, 110),
|
||||
'grey44': RGBColor(112, 112, 112),
|
||||
'grey45': RGBColor(115, 115, 115),
|
||||
'grey46': RGBColor(117, 117, 117),
|
||||
'grey47': RGBColor(120, 120, 120),
|
||||
'grey48': RGBColor(122, 122, 122),
|
||||
'grey49': RGBColor(125, 125, 125),
|
||||
'grey5': RGBColor(13, 13, 13),
|
||||
'grey50': RGBColor(127, 127, 127),
|
||||
'grey51': RGBColor(130, 130, 130),
|
||||
'grey52': RGBColor(133, 133, 133),
|
||||
'grey53': RGBColor(135, 135, 135),
|
||||
'grey54': RGBColor(138, 138, 138),
|
||||
'grey55': RGBColor(140, 140, 140),
|
||||
'grey56': RGBColor(143, 143, 143),
|
||||
'grey57': RGBColor(145, 145, 145),
|
||||
'grey58': RGBColor(148, 148, 148),
|
||||
'grey59': RGBColor(150, 150, 150),
|
||||
'grey6': RGBColor(15, 15, 15),
|
||||
'grey60': RGBColor(153, 153, 153),
|
||||
'grey61': RGBColor(156, 156, 156),
|
||||
'grey62': RGBColor(158, 158, 158),
|
||||
'grey63': RGBColor(161, 161, 161),
|
||||
'grey64': RGBColor(163, 163, 163),
|
||||
'grey65': RGBColor(166, 166, 166),
|
||||
'grey66': RGBColor(168, 168, 168),
|
||||
'grey67': RGBColor(171, 171, 171),
|
||||
'grey68': RGBColor(173, 173, 173),
|
||||
'grey69': RGBColor(176, 176, 176),
|
||||
'grey7': RGBColor(18, 18, 18),
|
||||
'grey70': RGBColor(179, 179, 179),
|
||||
'grey71': RGBColor(181, 181, 181),
|
||||
'grey72': RGBColor(184, 184, 184),
|
||||
'grey73': RGBColor(186, 186, 186),
|
||||
'grey74': RGBColor(189, 189, 189),
|
||||
'grey75': RGBColor(191, 191, 191),
|
||||
'grey76': RGBColor(194, 194, 194),
|
||||
'grey77': RGBColor(196, 196, 196),
|
||||
'grey78': RGBColor(199, 199, 199),
|
||||
'grey79': RGBColor(201, 201, 201),
|
||||
'grey8': RGBColor(20, 20, 20),
|
||||
'grey80': RGBColor(204, 204, 204),
|
||||
'grey81': RGBColor(207, 207, 207),
|
||||
'grey82': RGBColor(209, 209, 209),
|
||||
'grey83': RGBColor(212, 212, 212),
|
||||
'grey84': RGBColor(214, 214, 214),
|
||||
'grey85': RGBColor(217, 217, 217),
|
||||
'grey86': RGBColor(219, 219, 219),
|
||||
'grey87': RGBColor(222, 222, 222),
|
||||
'grey88': RGBColor(224, 224, 224),
|
||||
'grey89': RGBColor(227, 227, 227),
|
||||
'grey9': RGBColor(23, 23, 23),
|
||||
'grey90': RGBColor(229, 229, 229),
|
||||
'grey91': RGBColor(232, 232, 232),
|
||||
'grey92': RGBColor(235, 235, 235),
|
||||
'grey93': RGBColor(237, 237, 237),
|
||||
'grey94': RGBColor(240, 240, 240),
|
||||
'grey95': RGBColor(242, 242, 242),
|
||||
'grey96': RGBColor(245, 245, 245),
|
||||
'grey97': RGBColor(247, 247, 247),
|
||||
'grey98': RGBColor(250, 250, 250),
|
||||
'grey99': RGBColor(252, 252, 252),
|
||||
'honeydew': RGBColor(240, 255, 240),
|
||||
'honeydew1': RGBColor(240, 255, 240),
|
||||
'honeydew2': RGBColor(224, 238, 224),
|
||||
'honeydew3': RGBColor(193, 205, 193),
|
||||
'honeydew4': RGBColor(131, 139, 131),
|
||||
'hotpink': RGBColor(255, 105, 180),
|
||||
'hotpink1': RGBColor(255, 110, 180),
|
||||
'hotpink2': RGBColor(238, 106, 167),
|
||||
'hotpink3': RGBColor(205, 96, 144),
|
||||
'hotpink4': RGBColor(139, 58, 98),
|
||||
'indianred': RGBColor(205, 92, 92),
|
||||
'indianred1': RGBColor(255, 106, 106),
|
||||
'indianred2': RGBColor(238, 99, 99),
|
||||
'indianred3': RGBColor(205, 85, 85),
|
||||
'indianred4': RGBColor(139, 58, 58),
|
||||
'indigo': RGBColor(75, 0, 130),
|
||||
'ivory': RGBColor(255, 255, 240),
|
||||
'ivory1': RGBColor(255, 255, 240),
|
||||
'ivory2': RGBColor(238, 238, 224),
|
||||
'ivory3': RGBColor(205, 205, 193),
|
||||
'ivory4': RGBColor(139, 139, 131),
|
||||
'khaki': RGBColor(240, 230, 140),
|
||||
'khaki1': RGBColor(255, 246, 143),
|
||||
'khaki2': RGBColor(238, 230, 133),
|
||||
'khaki3': RGBColor(205, 198, 115),
|
||||
'khaki4': RGBColor(139, 134, 78),
|
||||
'lavender': RGBColor(230, 230, 250),
|
||||
'lavenderblush': RGBColor(255, 240, 245),
|
||||
'lavenderblush1': RGBColor(255, 240, 245),
|
||||
'lavenderblush2': RGBColor(238, 224, 229),
|
||||
'lavenderblush3': RGBColor(205, 193, 197),
|
||||
'lavenderblush4': RGBColor(139, 131, 134),
|
||||
'lawngreen': RGBColor(124, 252, 0),
|
||||
'lemonchiffon': RGBColor(255, 250, 205),
|
||||
'lemonchiffon1': RGBColor(255, 250, 205),
|
||||
'lemonchiffon2': RGBColor(238, 233, 191),
|
||||
'lemonchiffon3': RGBColor(205, 201, 165),
|
||||
'lemonchiffon4': RGBColor(139, 137, 112),
|
||||
'lightblue': RGBColor(173, 216, 230),
|
||||
'lightblue1': RGBColor(191, 239, 255),
|
||||
'lightblue2': RGBColor(178, 223, 238),
|
||||
'lightblue3': RGBColor(154, 192, 205),
|
||||
'lightblue4': RGBColor(104, 131, 139),
|
||||
'lightcoral': RGBColor(240, 128, 128),
|
||||
'lightcyan': RGBColor(224, 255, 255),
|
||||
'lightcyan1': RGBColor(224, 255, 255),
|
||||
'lightcyan2': RGBColor(209, 238, 238),
|
||||
'lightcyan3': RGBColor(180, 205, 205),
|
||||
'lightcyan4': RGBColor(122, 139, 139),
|
||||
'lightgoldenrod': RGBColor(238, 221, 130),
|
||||
'lightgoldenrod1': RGBColor(255, 236, 139),
|
||||
'lightgoldenrod2': RGBColor(238, 220, 130),
|
||||
'lightgoldenrod3': RGBColor(205, 190, 112),
|
||||
'lightgoldenrod4': RGBColor(139, 129, 76),
|
||||
'lightgoldenrodyellow': RGBColor(250, 250, 210),
|
||||
'lightgray': RGBColor(211, 211, 211),
|
||||
'lightgreen': RGBColor(144, 238, 144),
|
||||
'lightgrey': RGBColor(211, 211, 211),
|
||||
'lightpink': RGBColor(255, 182, 193),
|
||||
'lightpink1': RGBColor(255, 174, 185),
|
||||
'lightpink2': RGBColor(238, 162, 173),
|
||||
'lightpink3': RGBColor(205, 140, 149),
|
||||
'lightpink4': RGBColor(139, 95, 101),
|
||||
'lightsalmon': RGBColor(255, 160, 122),
|
||||
'lightsalmon1': RGBColor(255, 160, 122),
|
||||
'lightsalmon2': RGBColor(238, 149, 114),
|
||||
'lightsalmon3': RGBColor(205, 129, 98),
|
||||
'lightsalmon4': RGBColor(139, 87, 66),
|
||||
'lightseagreen': RGBColor(32, 178, 170),
|
||||
'lightskyblue': RGBColor(135, 206, 250),
|
||||
'lightskyblue1': RGBColor(176, 226, 255),
|
||||
'lightskyblue2': RGBColor(164, 211, 238),
|
||||
'lightskyblue3': RGBColor(141, 182, 205),
|
||||
'lightskyblue4': RGBColor(96, 123, 139),
|
||||
'lightslateblue': RGBColor(132, 112, 255),
|
||||
'lightslategray': RGBColor(119, 136, 153),
|
||||
'lightslategrey': RGBColor(119, 136, 153),
|
||||
'lightsteelblue': RGBColor(176, 196, 222),
|
||||
'lightsteelblue1': RGBColor(202, 225, 255),
|
||||
'lightsteelblue2': RGBColor(188, 210, 238),
|
||||
'lightsteelblue3': RGBColor(162, 181, 205),
|
||||
'lightsteelblue4': RGBColor(110, 123, 139),
|
||||
'lightyellow': RGBColor(255, 255, 224),
|
||||
'lightyellow1': RGBColor(255, 255, 224),
|
||||
'lightyellow2': RGBColor(238, 238, 209),
|
||||
'lightyellow3': RGBColor(205, 205, 180),
|
||||
'lightyellow4': RGBColor(139, 139, 122),
|
||||
'lime': RGBColor(0, 255, 0),
|
||||
'limegreen': RGBColor(50, 205, 50),
|
||||
'linen': RGBColor(250, 240, 230),
|
||||
'magenta': RGBColor(255, 0, 255),
|
||||
'magenta1': RGBColor(255, 0, 255),
|
||||
'magenta2': RGBColor(238, 0, 238),
|
||||
'magenta3': RGBColor(205, 0, 205),
|
||||
'magenta4': RGBColor(139, 0, 139),
|
||||
'maroon': RGBColor(176, 48, 96),
|
||||
'maroon1': RGBColor(255, 52, 179),
|
||||
'maroon2': RGBColor(238, 48, 167),
|
||||
'maroon3': RGBColor(205, 41, 144),
|
||||
'maroon4': RGBColor(139, 28, 98),
|
||||
'mediumaquamarine': RGBColor(102, 205, 170),
|
||||
'mediumblue': RGBColor(0, 0, 205),
|
||||
'mediumorchid': RGBColor(186, 85, 211),
|
||||
'mediumorchid1': RGBColor(224, 102, 255),
|
||||
'mediumorchid2': RGBColor(209, 95, 238),
|
||||
'mediumorchid3': RGBColor(180, 82, 205),
|
||||
'mediumorchid4': RGBColor(122, 55, 139),
|
||||
'mediumpurple': RGBColor(147, 112, 219),
|
||||
'mediumpurple1': RGBColor(171, 130, 255),
|
||||
'mediumpurple2': RGBColor(159, 121, 238),
|
||||
'mediumpurple3': RGBColor(137, 104, 205),
|
||||
'mediumpurple4': RGBColor(93, 71, 139),
|
||||
'mediumseagreen': RGBColor(60, 179, 113),
|
||||
'mediumslateblue': RGBColor(123, 104, 238),
|
||||
'mediumspringgreen': RGBColor(0, 250, 154),
|
||||
'mediumturquoise': RGBColor(72, 209, 204),
|
||||
'mediumvioletred': RGBColor(199, 21, 133),
|
||||
'midnightblue': RGBColor(25, 25, 112),
|
||||
'mintcream': RGBColor(245, 255, 250),
|
||||
'mistyrose': RGBColor(255, 228, 225),
|
||||
'mistyrose1': RGBColor(255, 228, 225),
|
||||
'mistyrose2': RGBColor(238, 213, 210),
|
||||
'mistyrose3': RGBColor(205, 183, 181),
|
||||
'mistyrose4': RGBColor(139, 125, 123),
|
||||
'moccasin': RGBColor(255, 228, 181),
|
||||
'navajowhite': RGBColor(255, 222, 173),
|
||||
'navajowhite1': RGBColor(255, 222, 173),
|
||||
'navajowhite2': RGBColor(238, 207, 161),
|
||||
'navajowhite3': RGBColor(205, 179, 139),
|
||||
'navajowhite4': RGBColor(139, 121, 94),
|
||||
'navy': RGBColor(0, 0, 128),
|
||||
'navyblue': RGBColor(0, 0, 128),
|
||||
'oldlace': RGBColor(253, 245, 230),
|
||||
'olive': RGBColor(128, 128, 0),
|
||||
'olivedrab': RGBColor(107, 142, 35),
|
||||
'olivedrab1': RGBColor(192, 255, 62),
|
||||
'olivedrab2': RGBColor(179, 238, 58),
|
||||
'olivedrab3': RGBColor(154, 205, 50),
|
||||
'olivedrab4': RGBColor(105, 139, 34),
|
||||
'orange': RGBColor(255, 165, 0),
|
||||
'orange1': RGBColor(255, 165, 0),
|
||||
'orange2': RGBColor(238, 154, 0),
|
||||
'orange3': RGBColor(205, 133, 0),
|
||||
'orange4': RGBColor(139, 90, 0),
|
||||
'orangered': RGBColor(255, 69, 0),
|
||||
'orangered1': RGBColor(255, 69, 0),
|
||||
'orangered2': RGBColor(238, 64, 0),
|
||||
'orangered3': RGBColor(205, 55, 0),
|
||||
'orangered4': RGBColor(139, 37, 0),
|
||||
'orchid': RGBColor(218, 112, 214),
|
||||
'orchid1': RGBColor(255, 131, 250),
|
||||
'orchid2': RGBColor(238, 122, 233),
|
||||
'orchid3': RGBColor(205, 105, 201),
|
||||
'orchid4': RGBColor(139, 71, 137),
|
||||
'palegoldenrod': RGBColor(238, 232, 170),
|
||||
'palegreen': RGBColor(152, 251, 152),
|
||||
'palegreen1': RGBColor(154, 255, 154),
|
||||
'palegreen2': RGBColor(144, 238, 144),
|
||||
'palegreen3': RGBColor(124, 205, 124),
|
||||
'palegreen4': RGBColor(84, 139, 84),
|
||||
'paleturquoise': RGBColor(175, 238, 238),
|
||||
'paleturquoise1': RGBColor(187, 255, 255),
|
||||
'paleturquoise2': RGBColor(174, 238, 238),
|
||||
'paleturquoise3': RGBColor(150, 205, 205),
|
||||
'paleturquoise4': RGBColor(102, 139, 139),
|
||||
'palevioletred': RGBColor(219, 112, 147),
|
||||
'palevioletred1': RGBColor(255, 130, 171),
|
||||
'palevioletred2': RGBColor(238, 121, 159),
|
||||
'palevioletred3': RGBColor(205, 104, 137),
|
||||
'palevioletred4': RGBColor(139, 71, 93),
|
||||
'papayawhip': RGBColor(255, 239, 213),
|
||||
'peachpuff': RGBColor(255, 218, 185),
|
||||
'peachpuff1': RGBColor(255, 218, 185),
|
||||
'peachpuff2': RGBColor(238, 203, 173),
|
||||
'peachpuff3': RGBColor(205, 175, 149),
|
||||
'peachpuff4': RGBColor(139, 119, 101),
|
||||
'peru': RGBColor(205, 133, 63),
|
||||
'pink': RGBColor(255, 192, 203),
|
||||
'pink1': RGBColor(255, 181, 197),
|
||||
'pink2': RGBColor(238, 169, 184),
|
||||
'pink3': RGBColor(205, 145, 158),
|
||||
'pink4': RGBColor(139, 99, 108),
|
||||
'plum': RGBColor(221, 160, 221),
|
||||
'plum1': RGBColor(255, 187, 255),
|
||||
'plum2': RGBColor(238, 174, 238),
|
||||
'plum3': RGBColor(205, 150, 205),
|
||||
'plum4': RGBColor(139, 102, 139),
|
||||
'powderblue': RGBColor(176, 224, 230),
|
||||
'purple': RGBColor(160, 32, 240),
|
||||
'purple1': RGBColor(155, 48, 255),
|
||||
'purple2': RGBColor(145, 44, 238),
|
||||
'purple3': RGBColor(125, 38, 205),
|
||||
'purple4': RGBColor(85, 26, 139),
|
||||
'rebeccapurple': RGBColor(102, 51, 153),
|
||||
'red': RGBColor(255, 0, 0),
|
||||
'red1': RGBColor(255, 0, 0),
|
||||
'red2': RGBColor(238, 0, 0),
|
||||
'red3': RGBColor(205, 0, 0),
|
||||
'red4': RGBColor(139, 0, 0),
|
||||
'rosybrown': RGBColor(188, 143, 143),
|
||||
'rosybrown1': RGBColor(255, 193, 193),
|
||||
'rosybrown2': RGBColor(238, 180, 180),
|
||||
'rosybrown3': RGBColor(205, 155, 155),
|
||||
'rosybrown4': RGBColor(139, 105, 105),
|
||||
'royalblue': RGBColor(65, 105, 225),
|
||||
'royalblue1': RGBColor(72, 118, 255),
|
||||
'royalblue2': RGBColor(67, 110, 238),
|
||||
'royalblue3': RGBColor(58, 95, 205),
|
||||
'royalblue4': RGBColor(39, 64, 139),
|
||||
'saddlebrown': RGBColor(139, 69, 19),
|
||||
'salmon': RGBColor(250, 128, 114),
|
||||
'salmon1': RGBColor(255, 140, 105),
|
||||
'salmon2': RGBColor(238, 130, 98),
|
||||
'salmon3': RGBColor(205, 112, 84),
|
||||
'salmon4': RGBColor(139, 76, 57),
|
||||
'sandybrown': RGBColor(244, 164, 96),
|
||||
'seagreen': RGBColor(46, 139, 87),
|
||||
'seagreen1': RGBColor(84, 255, 159),
|
||||
'seagreen2': RGBColor(78, 238, 148),
|
||||
'seagreen3': RGBColor(67, 205, 128),
|
||||
'seagreen4': RGBColor(46, 139, 87),
|
||||
'seashell': RGBColor(255, 245, 238),
|
||||
'seashell1': RGBColor(255, 245, 238),
|
||||
'seashell2': RGBColor(238, 229, 222),
|
||||
'seashell3': RGBColor(205, 197, 191),
|
||||
'seashell4': RGBColor(139, 134, 130),
|
||||
'sienna': RGBColor(160, 82, 45),
|
||||
'sienna1': RGBColor(255, 130, 71),
|
||||
'sienna2': RGBColor(238, 121, 66),
|
||||
'sienna3': RGBColor(205, 104, 57),
|
||||
'sienna4': RGBColor(139, 71, 38),
|
||||
'silver': RGBColor(192, 192, 192),
|
||||
'skyblue': RGBColor(135, 206, 235),
|
||||
'skyblue1': RGBColor(135, 206, 255),
|
||||
'skyblue2': RGBColor(126, 192, 238),
|
||||
'skyblue3': RGBColor(108, 166, 205),
|
||||
'skyblue4': RGBColor(74, 112, 139),
|
||||
'slateblue': RGBColor(106, 90, 205),
|
||||
'slateblue1': RGBColor(131, 111, 255),
|
||||
'slateblue2': RGBColor(122, 103, 238),
|
||||
'slateblue3': RGBColor(105, 89, 205),
|
||||
'slateblue4': RGBColor(71, 60, 139),
|
||||
'slategray': RGBColor(112, 128, 144),
|
||||
'slategray1': RGBColor(198, 226, 255),
|
||||
'slategray2': RGBColor(185, 211, 238),
|
||||
'slategray3': RGBColor(159, 182, 205),
|
||||
'slategray4': RGBColor(108, 123, 139),
|
||||
'slategrey': RGBColor(112, 128, 144),
|
||||
'snow': RGBColor(255, 250, 250),
|
||||
'snow1': RGBColor(255, 250, 250),
|
||||
'snow2': RGBColor(238, 233, 233),
|
||||
'snow3': RGBColor(205, 201, 201),
|
||||
'snow4': RGBColor(139, 137, 137),
|
||||
'springgreen': RGBColor(0, 255, 127),
|
||||
'springgreen1': RGBColor(0, 255, 127),
|
||||
'springgreen2': RGBColor(0, 238, 118),
|
||||
'springgreen3': RGBColor(0, 205, 102),
|
||||
'springgreen4': RGBColor(0, 139, 69),
|
||||
'steelblue': RGBColor(70, 130, 180),
|
||||
'steelblue1': RGBColor(99, 184, 255),
|
||||
'steelblue2': RGBColor(92, 172, 238),
|
||||
'steelblue3': RGBColor(79, 148, 205),
|
||||
'steelblue4': RGBColor(54, 100, 139),
|
||||
'tan': RGBColor(210, 180, 140),
|
||||
'tan1': RGBColor(255, 165, 79),
|
||||
'tan2': RGBColor(238, 154, 73),
|
||||
'tan3': RGBColor(205, 133, 63),
|
||||
'tan4': RGBColor(139, 90, 43),
|
||||
'teal': RGBColor(0, 128, 128),
|
||||
'thistle': RGBColor(216, 191, 216),
|
||||
'thistle1': RGBColor(255, 225, 255),
|
||||
'thistle2': RGBColor(238, 210, 238),
|
||||
'thistle3': RGBColor(205, 181, 205),
|
||||
'thistle4': RGBColor(139, 123, 139),
|
||||
'tomato': RGBColor(255, 99, 71),
|
||||
'tomato1': RGBColor(255, 99, 71),
|
||||
'tomato2': RGBColor(238, 92, 66),
|
||||
'tomato3': RGBColor(205, 79, 57),
|
||||
'tomato4': RGBColor(139, 54, 38),
|
||||
'turquoise': RGBColor(64, 224, 208),
|
||||
'turquoise1': RGBColor(0, 245, 255),
|
||||
'turquoise2': RGBColor(0, 229, 238),
|
||||
'turquoise3': RGBColor(0, 197, 205),
|
||||
'turquoise4': RGBColor(0, 134, 139),
|
||||
'violet': RGBColor(238, 130, 238),
|
||||
'violetred': RGBColor(208, 32, 144),
|
||||
'violetred1': RGBColor(255, 62, 150),
|
||||
'violetred2': RGBColor(238, 58, 140),
|
||||
'violetred3': RGBColor(205, 50, 120),
|
||||
'violetred4': RGBColor(139, 34, 82),
|
||||
'webgray': RGBColor(128, 128, 128),
|
||||
'webgreen': RGBColor(0, 128, 0),
|
||||
'webgrey': RGBColor(128, 128, 128),
|
||||
'webmaroon': RGBColor(128, 0, 0),
|
||||
'webpurple': RGBColor(128, 0, 128),
|
||||
'wheat': RGBColor(245, 222, 179),
|
||||
'wheat1': RGBColor(255, 231, 186),
|
||||
'wheat2': RGBColor(238, 216, 174),
|
||||
'wheat3': RGBColor(205, 186, 150),
|
||||
'wheat4': RGBColor(139, 126, 102),
|
||||
'white': RGBColor(255, 255, 255),
|
||||
'whitesmoke': RGBColor(245, 245, 245),
|
||||
'x11gray': RGBColor(190, 190, 190),
|
||||
'x11green': RGBColor(0, 255, 0),
|
||||
'x11grey': RGBColor(190, 190, 190),
|
||||
'x11maroon': RGBColor(176, 48, 96),
|
||||
'x11purple': RGBColor(160, 32, 240),
|
||||
'yellow': RGBColor(255, 255, 0),
|
||||
'yellow1': RGBColor(255, 255, 0),
|
||||
'yellow2': RGBColor(238, 238, 0),
|
||||
'yellow3': RGBColor(205, 205, 0),
|
||||
'yellow4': RGBColor(139, 139, 0),
|
||||
'yellowgreen': RGBColor(154, 205, 50)
|
||||
}
|
||||
|
||||
#: Curses color indices of 8, 16, and 256-color terminals
|
||||
RGB_256TABLE = (
|
||||
RGBColor(0, 0, 0),
|
||||
RGBColor(205, 0, 0),
|
||||
RGBColor(0, 205, 0),
|
||||
RGBColor(205, 205, 0),
|
||||
RGBColor(0, 0, 238),
|
||||
RGBColor(205, 0, 205),
|
||||
RGBColor(0, 205, 205),
|
||||
RGBColor(229, 229, 229),
|
||||
RGBColor(127, 127, 127),
|
||||
RGBColor(255, 0, 0),
|
||||
RGBColor(0, 255, 0),
|
||||
RGBColor(255, 255, 0),
|
||||
RGBColor(92, 92, 255),
|
||||
RGBColor(255, 0, 255),
|
||||
RGBColor(0, 255, 255),
|
||||
RGBColor(255, 255, 255),
|
||||
RGBColor(0, 0, 0),
|
||||
RGBColor(0, 0, 95),
|
||||
RGBColor(0, 0, 135),
|
||||
RGBColor(0, 0, 175),
|
||||
RGBColor(0, 0, 215),
|
||||
RGBColor(0, 0, 255),
|
||||
RGBColor(0, 95, 0),
|
||||
RGBColor(0, 95, 95),
|
||||
RGBColor(0, 95, 135),
|
||||
RGBColor(0, 95, 175),
|
||||
RGBColor(0, 95, 215),
|
||||
RGBColor(0, 95, 255),
|
||||
RGBColor(0, 135, 0),
|
||||
RGBColor(0, 135, 95),
|
||||
RGBColor(0, 135, 135),
|
||||
RGBColor(0, 135, 175),
|
||||
RGBColor(0, 135, 215),
|
||||
RGBColor(0, 135, 255),
|
||||
RGBColor(0, 175, 0),
|
||||
RGBColor(0, 175, 95),
|
||||
RGBColor(0, 175, 135),
|
||||
RGBColor(0, 175, 175),
|
||||
RGBColor(0, 175, 215),
|
||||
RGBColor(0, 175, 255),
|
||||
RGBColor(0, 215, 0),
|
||||
RGBColor(0, 215, 95),
|
||||
RGBColor(0, 215, 135),
|
||||
RGBColor(0, 215, 175),
|
||||
RGBColor(0, 215, 215),
|
||||
RGBColor(0, 215, 255),
|
||||
RGBColor(0, 255, 0),
|
||||
RGBColor(0, 255, 95),
|
||||
RGBColor(0, 255, 135),
|
||||
RGBColor(0, 255, 175),
|
||||
RGBColor(0, 255, 215),
|
||||
RGBColor(0, 255, 255),
|
||||
RGBColor(95, 0, 0),
|
||||
RGBColor(95, 0, 95),
|
||||
RGBColor(95, 0, 135),
|
||||
RGBColor(95, 0, 175),
|
||||
RGBColor(95, 0, 215),
|
||||
RGBColor(95, 0, 255),
|
||||
RGBColor(95, 95, 0),
|
||||
RGBColor(95, 95, 95),
|
||||
RGBColor(95, 95, 135),
|
||||
RGBColor(95, 95, 175),
|
||||
RGBColor(95, 95, 215),
|
||||
RGBColor(95, 95, 255),
|
||||
RGBColor(95, 135, 0),
|
||||
RGBColor(95, 135, 95),
|
||||
RGBColor(95, 135, 135),
|
||||
RGBColor(95, 135, 175),
|
||||
RGBColor(95, 135, 215),
|
||||
RGBColor(95, 135, 255),
|
||||
RGBColor(95, 175, 0),
|
||||
RGBColor(95, 175, 95),
|
||||
RGBColor(95, 175, 135),
|
||||
RGBColor(95, 175, 175),
|
||||
RGBColor(95, 175, 215),
|
||||
RGBColor(95, 175, 255),
|
||||
RGBColor(95, 215, 0),
|
||||
RGBColor(95, 215, 95),
|
||||
RGBColor(95, 215, 135),
|
||||
RGBColor(95, 215, 175),
|
||||
RGBColor(95, 215, 215),
|
||||
RGBColor(95, 215, 255),
|
||||
RGBColor(95, 255, 0),
|
||||
RGBColor(95, 255, 95),
|
||||
RGBColor(95, 255, 135),
|
||||
RGBColor(95, 255, 175),
|
||||
RGBColor(95, 255, 215),
|
||||
RGBColor(95, 255, 255),
|
||||
RGBColor(135, 0, 0),
|
||||
RGBColor(135, 0, 95),
|
||||
RGBColor(135, 0, 135),
|
||||
RGBColor(135, 0, 175),
|
||||
RGBColor(135, 0, 215),
|
||||
RGBColor(135, 0, 255),
|
||||
RGBColor(135, 95, 0),
|
||||
RGBColor(135, 95, 95),
|
||||
RGBColor(135, 95, 135),
|
||||
RGBColor(135, 95, 175),
|
||||
RGBColor(135, 95, 215),
|
||||
RGBColor(135, 95, 255),
|
||||
RGBColor(135, 135, 0),
|
||||
RGBColor(135, 135, 95),
|
||||
RGBColor(135, 135, 135),
|
||||
RGBColor(135, 135, 175),
|
||||
RGBColor(135, 135, 215),
|
||||
RGBColor(135, 135, 255),
|
||||
RGBColor(135, 175, 0),
|
||||
RGBColor(135, 175, 95),
|
||||
RGBColor(135, 175, 135),
|
||||
RGBColor(135, 175, 175),
|
||||
RGBColor(135, 175, 215),
|
||||
RGBColor(135, 175, 255),
|
||||
RGBColor(135, 215, 0),
|
||||
RGBColor(135, 215, 95),
|
||||
RGBColor(135, 215, 135),
|
||||
RGBColor(135, 215, 175),
|
||||
RGBColor(135, 215, 215),
|
||||
RGBColor(135, 215, 255),
|
||||
RGBColor(135, 255, 0),
|
||||
RGBColor(135, 255, 95),
|
||||
RGBColor(135, 255, 135),
|
||||
RGBColor(135, 255, 175),
|
||||
RGBColor(135, 255, 215),
|
||||
RGBColor(135, 255, 255),
|
||||
RGBColor(175, 0, 0),
|
||||
RGBColor(175, 0, 95),
|
||||
RGBColor(175, 0, 135),
|
||||
RGBColor(175, 0, 175),
|
||||
RGBColor(175, 0, 215),
|
||||
RGBColor(175, 0, 255),
|
||||
RGBColor(175, 95, 0),
|
||||
RGBColor(175, 95, 95),
|
||||
RGBColor(175, 95, 135),
|
||||
RGBColor(175, 95, 175),
|
||||
RGBColor(175, 95, 215),
|
||||
RGBColor(175, 95, 255),
|
||||
RGBColor(175, 135, 0),
|
||||
RGBColor(175, 135, 95),
|
||||
RGBColor(175, 135, 135),
|
||||
RGBColor(175, 135, 175),
|
||||
RGBColor(175, 135, 215),
|
||||
RGBColor(175, 135, 255),
|
||||
RGBColor(175, 175, 0),
|
||||
RGBColor(175, 175, 95),
|
||||
RGBColor(175, 175, 135),
|
||||
RGBColor(175, 175, 175),
|
||||
RGBColor(175, 175, 215),
|
||||
RGBColor(175, 175, 255),
|
||||
RGBColor(175, 215, 0),
|
||||
RGBColor(175, 215, 95),
|
||||
RGBColor(175, 215, 135),
|
||||
RGBColor(175, 215, 175),
|
||||
RGBColor(175, 215, 215),
|
||||
RGBColor(175, 215, 255),
|
||||
RGBColor(175, 255, 0),
|
||||
RGBColor(175, 255, 95),
|
||||
RGBColor(175, 255, 135),
|
||||
RGBColor(175, 255, 175),
|
||||
RGBColor(175, 255, 215),
|
||||
RGBColor(175, 255, 255),
|
||||
RGBColor(215, 0, 0),
|
||||
RGBColor(215, 0, 95),
|
||||
RGBColor(215, 0, 135),
|
||||
RGBColor(215, 0, 175),
|
||||
RGBColor(215, 0, 215),
|
||||
RGBColor(215, 0, 255),
|
||||
RGBColor(215, 95, 0),
|
||||
RGBColor(215, 95, 95),
|
||||
RGBColor(215, 95, 135),
|
||||
RGBColor(215, 95, 175),
|
||||
RGBColor(215, 95, 215),
|
||||
RGBColor(215, 95, 255),
|
||||
RGBColor(215, 135, 0),
|
||||
RGBColor(215, 135, 95),
|
||||
RGBColor(215, 135, 135),
|
||||
RGBColor(215, 135, 175),
|
||||
RGBColor(215, 135, 215),
|
||||
RGBColor(215, 135, 255),
|
||||
RGBColor(215, 175, 0),
|
||||
RGBColor(215, 175, 95),
|
||||
RGBColor(215, 175, 135),
|
||||
RGBColor(215, 175, 175),
|
||||
RGBColor(215, 175, 215),
|
||||
RGBColor(215, 175, 255),
|
||||
RGBColor(215, 215, 0),
|
||||
RGBColor(215, 215, 95),
|
||||
RGBColor(215, 215, 135),
|
||||
RGBColor(215, 215, 175),
|
||||
RGBColor(215, 215, 215),
|
||||
RGBColor(215, 215, 255),
|
||||
RGBColor(215, 255, 0),
|
||||
RGBColor(215, 255, 95),
|
||||
RGBColor(215, 255, 135),
|
||||
RGBColor(215, 255, 175),
|
||||
RGBColor(215, 255, 215),
|
||||
RGBColor(215, 255, 255),
|
||||
RGBColor(255, 0, 0),
|
||||
RGBColor(255, 0, 135),
|
||||
RGBColor(255, 0, 95),
|
||||
RGBColor(255, 0, 175),
|
||||
RGBColor(255, 0, 215),
|
||||
RGBColor(255, 0, 255),
|
||||
RGBColor(255, 95, 0),
|
||||
RGBColor(255, 95, 95),
|
||||
RGBColor(255, 95, 135),
|
||||
RGBColor(255, 95, 175),
|
||||
RGBColor(255, 95, 215),
|
||||
RGBColor(255, 95, 255),
|
||||
RGBColor(255, 135, 0),
|
||||
RGBColor(255, 135, 95),
|
||||
RGBColor(255, 135, 135),
|
||||
RGBColor(255, 135, 175),
|
||||
RGBColor(255, 135, 215),
|
||||
RGBColor(255, 135, 255),
|
||||
RGBColor(255, 175, 0),
|
||||
RGBColor(255, 175, 95),
|
||||
RGBColor(255, 175, 135),
|
||||
RGBColor(255, 175, 175),
|
||||
RGBColor(255, 175, 215),
|
||||
RGBColor(255, 175, 255),
|
||||
RGBColor(255, 215, 0),
|
||||
RGBColor(255, 215, 95),
|
||||
RGBColor(255, 215, 135),
|
||||
RGBColor(255, 215, 175),
|
||||
RGBColor(255, 215, 215),
|
||||
RGBColor(255, 215, 255),
|
||||
RGBColor(255, 255, 0),
|
||||
RGBColor(255, 255, 95),
|
||||
RGBColor(255, 255, 135),
|
||||
RGBColor(255, 255, 175),
|
||||
RGBColor(255, 255, 215),
|
||||
RGBColor(255, 255, 255),
|
||||
RGBColor(8, 8, 8),
|
||||
RGBColor(18, 18, 18),
|
||||
RGBColor(28, 28, 28),
|
||||
RGBColor(38, 38, 38),
|
||||
RGBColor(48, 48, 48),
|
||||
RGBColor(58, 58, 58),
|
||||
RGBColor(68, 68, 68),
|
||||
RGBColor(78, 78, 78),
|
||||
RGBColor(88, 88, 88),
|
||||
RGBColor(98, 98, 98),
|
||||
RGBColor(108, 108, 108),
|
||||
RGBColor(118, 118, 118),
|
||||
RGBColor(128, 128, 128),
|
||||
RGBColor(138, 138, 138),
|
||||
RGBColor(148, 148, 148),
|
||||
RGBColor(158, 158, 158),
|
||||
RGBColor(168, 168, 168),
|
||||
RGBColor(178, 178, 178),
|
||||
RGBColor(188, 188, 188),
|
||||
RGBColor(198, 198, 198),
|
||||
RGBColor(208, 208, 208),
|
||||
RGBColor(218, 218, 218),
|
||||
RGBColor(228, 228, 228),
|
||||
RGBColor(238, 238, 238),
|
||||
)
|
||||
12
venv/lib/python3.11/site-packages/blessed/colorspace.pyi
Normal file
12
venv/lib/python3.11/site-packages/blessed/colorspace.pyi
Normal file
@@ -0,0 +1,12 @@
|
||||
# std imports
|
||||
from typing import Set, Dict, Tuple, NamedTuple
|
||||
|
||||
CGA_COLORS: Set[str]
|
||||
|
||||
class RGBColor(NamedTuple):
|
||||
red: int
|
||||
green: int
|
||||
blue: int
|
||||
|
||||
X11_COLORNAMES_TO_RGB: Dict[str, RGBColor]
|
||||
RGB_256TABLE: Tuple[RGBColor, ...]
|
||||
496
venv/lib/python3.11/site-packages/blessed/formatters.py
Normal file
496
venv/lib/python3.11/site-packages/blessed/formatters.py
Normal file
@@ -0,0 +1,496 @@
|
||||
"""Sub-module providing sequence-formatting functions."""
|
||||
# std imports
|
||||
import platform
|
||||
|
||||
# 3rd party
|
||||
import six
|
||||
|
||||
# local
|
||||
from blessed.colorspace import CGA_COLORS, X11_COLORNAMES_TO_RGB
|
||||
|
||||
# isort: off
|
||||
# curses
|
||||
if platform.system() == 'Windows':
|
||||
import jinxed as curses # pylint: disable=import-error
|
||||
else:
|
||||
import curses
|
||||
|
||||
|
||||
def _make_colors():
|
||||
"""
|
||||
Return set of valid colors and their derivatives.
|
||||
|
||||
:rtype: set
|
||||
:returns: Color names with prefixes
|
||||
"""
|
||||
colors = set()
|
||||
# basic CGA foreground color, background, high intensity, and bold
|
||||
# background ('iCE colors' in my day).
|
||||
for cga_color in CGA_COLORS:
|
||||
colors.add(cga_color)
|
||||
colors.add('on_' + cga_color)
|
||||
colors.add('bright_' + cga_color)
|
||||
colors.add('on_bright_' + cga_color)
|
||||
|
||||
# foreground and background VGA color
|
||||
for vga_color in X11_COLORNAMES_TO_RGB:
|
||||
colors.add(vga_color)
|
||||
colors.add('on_' + vga_color)
|
||||
return colors
|
||||
|
||||
|
||||
#: Valid colors and their background (on), bright, and bright-background
|
||||
#: derivatives.
|
||||
COLORS = _make_colors()
|
||||
|
||||
#: Attributes that may be compounded with colors, by underscore, such as
|
||||
#: 'reverse_indigo'.
|
||||
COMPOUNDABLES = set('bold underline reverse blink italic standout'.split())
|
||||
|
||||
|
||||
class ParameterizingString(six.text_type):
|
||||
r"""
|
||||
A Unicode string which can be called as a parameterizing termcap.
|
||||
|
||||
For example::
|
||||
|
||||
>>> from blessed import Terminal
|
||||
>>> term = Terminal()
|
||||
>>> color = ParameterizingString(term.color, term.normal, 'color')
|
||||
>>> color(9)('color #9')
|
||||
u'\x1b[91mcolor #9\x1b(B\x1b[m'
|
||||
"""
|
||||
|
||||
def __new__(cls, cap, normal=u'', name=u'<not specified>'):
|
||||
# pylint: disable = missing-return-doc, missing-return-type-doc
|
||||
"""
|
||||
Class constructor accepting 3 positional arguments.
|
||||
|
||||
:arg str cap: parameterized string suitable for curses.tparm()
|
||||
:arg str normal: terminating sequence for this capability (optional).
|
||||
:arg str name: name of this terminal capability (optional).
|
||||
"""
|
||||
new = six.text_type.__new__(cls, cap)
|
||||
new._normal = normal
|
||||
new._name = name
|
||||
return new
|
||||
|
||||
def __call__(self, *args):
|
||||
"""
|
||||
Returning :class:`FormattingString` instance for given parameters.
|
||||
|
||||
Return evaluated terminal capability (self), receiving arguments
|
||||
``*args``, followed by the terminating sequence (self.normal) into
|
||||
a :class:`FormattingString` capable of being called.
|
||||
|
||||
:raises TypeError: Mismatch between capability and arguments
|
||||
:raises curses.error: :func:`curses.tparm` raised an exception
|
||||
:rtype: :class:`FormattingString` or :class:`NullCallableString`
|
||||
:returns: Callable string for given parameters
|
||||
"""
|
||||
try:
|
||||
# Re-encode the cap, because tparm() takes a bytestring in Python
|
||||
# 3. However, appear to be a plain Unicode string otherwise so
|
||||
# concats work.
|
||||
attr = curses.tparm(self.encode('latin1'), *args).decode('latin1')
|
||||
return FormattingString(attr, self._normal)
|
||||
except TypeError as err:
|
||||
# If the first non-int (i.e. incorrect) arg was a string, suggest
|
||||
# something intelligent:
|
||||
if args and isinstance(args[0], six.string_types):
|
||||
raise TypeError(
|
||||
"Unknown terminal capability, %r, or, TypeError "
|
||||
"for arguments %r: %s" % (self._name, args, err))
|
||||
# Somebody passed a non-string; I don't feel confident
|
||||
# guessing what they were trying to do.
|
||||
raise
|
||||
except curses.error as err:
|
||||
# ignore 'tparm() returned NULL', you won't get any styling,
|
||||
# even if does_styling is True. This happens on win32 platforms
|
||||
# with http://www.lfd.uci.edu/~gohlke/pythonlibs/#curses installed
|
||||
if "tparm() returned NULL" not in six.text_type(err):
|
||||
raise
|
||||
return NullCallableString()
|
||||
|
||||
|
||||
class ParameterizingProxyString(six.text_type):
|
||||
r"""
|
||||
A Unicode string which can be called to proxy missing termcap entries.
|
||||
|
||||
This class supports the function :func:`get_proxy_string`, and mirrors
|
||||
the behavior of :class:`ParameterizingString`, except that instead of
|
||||
a capability name, receives a format string, and callable to filter the
|
||||
given positional ``*args`` of :meth:`ParameterizingProxyString.__call__`
|
||||
into a terminal sequence.
|
||||
|
||||
For example::
|
||||
|
||||
>>> from blessed import Terminal
|
||||
>>> term = Terminal('screen')
|
||||
>>> hpa = ParameterizingString(term.hpa, term.normal, 'hpa')
|
||||
>>> hpa(9)
|
||||
u''
|
||||
>>> fmt = u'\x1b[{0}G'
|
||||
>>> fmt_arg = lambda *arg: (arg[0] + 1,)
|
||||
>>> hpa = ParameterizingProxyString((fmt, fmt_arg), term.normal, 'hpa')
|
||||
>>> hpa(9)
|
||||
u'\x1b[10G'
|
||||
"""
|
||||
|
||||
def __new__(cls, fmt_pair, normal=u'', name=u'<not specified>'):
|
||||
# pylint: disable = missing-return-doc, missing-return-type-doc
|
||||
"""
|
||||
Class constructor accepting 4 positional arguments.
|
||||
|
||||
:arg tuple fmt_pair: Two element tuple containing:
|
||||
- format string suitable for displaying terminal sequences
|
||||
- callable suitable for receiving __call__ arguments for formatting string
|
||||
:arg str normal: terminating sequence for this capability (optional).
|
||||
:arg str name: name of this terminal capability (optional).
|
||||
"""
|
||||
assert isinstance(fmt_pair, tuple), fmt_pair
|
||||
assert callable(fmt_pair[1]), fmt_pair[1]
|
||||
new = six.text_type.__new__(cls, fmt_pair[0])
|
||||
new._fmt_args = fmt_pair[1]
|
||||
new._normal = normal
|
||||
new._name = name
|
||||
return new
|
||||
|
||||
def __call__(self, *args):
|
||||
"""
|
||||
Returning :class:`FormattingString` instance for given parameters.
|
||||
|
||||
Arguments are determined by the capability. For example, ``hpa``
|
||||
(move_x) receives only a single integer, whereas ``cup`` (move)
|
||||
receives two integers. See documentation in terminfo(5) for the
|
||||
given capability.
|
||||
|
||||
:rtype: FormattingString
|
||||
:returns: Callable string for given parameters
|
||||
"""
|
||||
return FormattingString(self.format(*self._fmt_args(*args)),
|
||||
self._normal)
|
||||
|
||||
|
||||
class FormattingString(six.text_type):
|
||||
r"""
|
||||
A Unicode string which doubles as a callable.
|
||||
|
||||
This is used for terminal attributes, so that it may be used both
|
||||
directly, or as a callable. When used directly, it simply emits
|
||||
the given terminal sequence. When used as a callable, it wraps the
|
||||
given (string) argument with the 2nd argument used by the class
|
||||
constructor::
|
||||
|
||||
>>> from blessed import Terminal
|
||||
>>> term = Terminal()
|
||||
>>> style = FormattingString(term.bright_blue, term.normal)
|
||||
>>> print(repr(style))
|
||||
u'\x1b[94m'
|
||||
>>> style('Big Blue')
|
||||
u'\x1b[94mBig Blue\x1b(B\x1b[m'
|
||||
"""
|
||||
|
||||
def __new__(cls, sequence, normal=u''):
|
||||
# pylint: disable = missing-return-doc, missing-return-type-doc
|
||||
"""
|
||||
Class constructor accepting 2 positional arguments.
|
||||
|
||||
:arg str sequence: terminal attribute sequence.
|
||||
:arg str normal: terminating sequence for this attribute (optional).
|
||||
"""
|
||||
new = six.text_type.__new__(cls, sequence)
|
||||
new._normal = normal
|
||||
return new
|
||||
|
||||
def __call__(self, *args):
|
||||
"""
|
||||
Return ``text`` joined by ``sequence`` and ``normal``.
|
||||
|
||||
:raises TypeError: Not a string type
|
||||
:rtype: str
|
||||
:returns: Arguments wrapped in sequence and normal
|
||||
"""
|
||||
# Jim Allman brings us this convenience of allowing existing
|
||||
# unicode strings to be joined as a call parameter to a formatting
|
||||
# string result, allowing nestation:
|
||||
#
|
||||
# >>> t.red('This is ', t.bold('extremely'), ' dangerous!')
|
||||
for idx, ucs_part in enumerate(args):
|
||||
if not isinstance(ucs_part, six.string_types):
|
||||
expected_types = ', '.join(_type.__name__ for _type in six.string_types)
|
||||
raise TypeError(
|
||||
"TypeError for FormattingString argument, "
|
||||
"%r, at position %s: expected type %s, "
|
||||
"got %s" % (ucs_part, idx, expected_types,
|
||||
type(ucs_part).__name__))
|
||||
postfix = u''
|
||||
if self and self._normal:
|
||||
postfix = self._normal
|
||||
_refresh = self._normal + self
|
||||
args = [_refresh.join(ucs_part.split(self._normal))
|
||||
for ucs_part in args]
|
||||
|
||||
return self + u''.join(args) + postfix
|
||||
|
||||
|
||||
class FormattingOtherString(six.text_type):
|
||||
r"""
|
||||
A Unicode string which doubles as a callable for another sequence when called.
|
||||
|
||||
This is used for the :meth:`~.Terminal.move_up`, ``down``, ``left``, and ``right()``
|
||||
family of functions::
|
||||
|
||||
>>> from blessed import Terminal
|
||||
>>> term = Terminal()
|
||||
>>> move_right = FormattingOtherString(term.cuf1, term.cuf)
|
||||
>>> print(repr(move_right))
|
||||
u'\x1b[C'
|
||||
>>> print(repr(move_right(666)))
|
||||
u'\x1b[666C'
|
||||
>>> print(repr(move_right()))
|
||||
u'\x1b[C'
|
||||
"""
|
||||
|
||||
def __new__(cls, direct, target):
|
||||
# pylint: disable = missing-return-doc, missing-return-type-doc
|
||||
"""
|
||||
Class constructor accepting 2 positional arguments.
|
||||
|
||||
:arg str direct: capability name for direct formatting, eg ``('x' + term.right)``.
|
||||
:arg str target: capability name for callable, eg ``('x' + term.right(99))``.
|
||||
"""
|
||||
new = six.text_type.__new__(cls, direct)
|
||||
new._callable = target
|
||||
return new
|
||||
|
||||
def __getnewargs__(self):
|
||||
# return arguments used for the __new__ method upon unpickling.
|
||||
return six.text_type.__new__(six.text_type, self), self._callable
|
||||
|
||||
def __call__(self, *args):
|
||||
"""Return ``text`` by ``target``."""
|
||||
return self._callable(*args) if args else self
|
||||
|
||||
|
||||
class NullCallableString(six.text_type):
|
||||
"""
|
||||
A dummy callable Unicode alternative to :class:`FormattingString`.
|
||||
|
||||
This is used for colors on terminals that do not support colors, it is just a basic form of
|
||||
unicode that may also act as a callable.
|
||||
"""
|
||||
|
||||
def __new__(cls):
|
||||
"""Class constructor."""
|
||||
return six.text_type.__new__(cls, u'')
|
||||
|
||||
def __call__(self, *args):
|
||||
"""
|
||||
Allow empty string to be callable, returning given string, if any.
|
||||
|
||||
When called with an int as the first arg, return an empty Unicode. An
|
||||
int is a good hint that I am a :class:`ParameterizingString`, as there
|
||||
are only about half a dozen string-returning capabilities listed in
|
||||
terminfo(5) which accept non-int arguments, they are seldom used.
|
||||
|
||||
When called with a non-int as the first arg (no no args at all), return
|
||||
the first arg, acting in place of :class:`FormattingString` without
|
||||
any attributes.
|
||||
"""
|
||||
if not args or isinstance(args[0], int):
|
||||
# As a NullCallableString, even when provided with a parameter,
|
||||
# such as t.color(5), we must also still be callable, fe:
|
||||
#
|
||||
# >>> t.color(5)('shmoo')
|
||||
#
|
||||
# is actually simplified result of NullCallable()() on terminals
|
||||
# without color support, so turtles all the way down: we return
|
||||
# another instance.
|
||||
return NullCallableString()
|
||||
return u''.join(args)
|
||||
|
||||
|
||||
def get_proxy_string(term, attr):
|
||||
"""
|
||||
Proxy and return callable string for proxied attributes.
|
||||
|
||||
:arg Terminal term: :class:`~.Terminal` instance.
|
||||
:arg str attr: terminal capability name that may be proxied.
|
||||
:rtype: None or :class:`ParameterizingProxyString`.
|
||||
:returns: :class:`ParameterizingProxyString` for some attributes
|
||||
of some terminal types that support it, where the terminfo(5)
|
||||
database would otherwise come up empty, such as ``move_x``
|
||||
attribute for ``term.kind`` of ``screen``. Otherwise, None.
|
||||
"""
|
||||
# normalize 'screen-256color', or 'ansi.sys' to its basic names
|
||||
term_kind = next(iter(_kind for _kind in ('screen', 'ansi',)
|
||||
if term.kind.startswith(_kind)), term)
|
||||
_proxy_table = { # pragma: no cover
|
||||
'screen': {
|
||||
# proxy move_x/move_y for 'screen' terminal type, used by tmux(1).
|
||||
'hpa': ParameterizingProxyString(
|
||||
(u'\x1b[{0}G', lambda *arg: (arg[0] + 1,)), term.normal, attr),
|
||||
'vpa': ParameterizingProxyString(
|
||||
(u'\x1b[{0}d', lambda *arg: (arg[0] + 1,)), term.normal, attr),
|
||||
},
|
||||
'ansi': {
|
||||
# proxy show/hide cursor for 'ansi' terminal type. There is some
|
||||
# demand for a richly working ANSI terminal type for some reason.
|
||||
'civis': ParameterizingProxyString(
|
||||
(u'\x1b[?25l', lambda *arg: ()), term.normal, attr),
|
||||
'cnorm': ParameterizingProxyString(
|
||||
(u'\x1b[?25h', lambda *arg: ()), term.normal, attr),
|
||||
'hpa': ParameterizingProxyString(
|
||||
(u'\x1b[{0}G', lambda *arg: (arg[0] + 1,)), term.normal, attr),
|
||||
'vpa': ParameterizingProxyString(
|
||||
(u'\x1b[{0}d', lambda *arg: (arg[0] + 1,)), term.normal, attr),
|
||||
'sc': '\x1b[s',
|
||||
'rc': '\x1b[u',
|
||||
}
|
||||
}
|
||||
return _proxy_table.get(term_kind, {}).get(attr, None)
|
||||
|
||||
|
||||
def split_compound(compound):
|
||||
"""
|
||||
Split compound formating string into segments.
|
||||
|
||||
>>> split_compound('bold_underline_bright_blue_on_red')
|
||||
['bold', 'underline', 'bright_blue', 'on_red']
|
||||
|
||||
:arg str compound: a string that may contain compounds, separated by
|
||||
underline (``_``).
|
||||
:rtype: list
|
||||
:returns: List of formating string segments
|
||||
"""
|
||||
merged_segs = []
|
||||
# These occur only as prefixes, so they can always be merged:
|
||||
mergeable_prefixes = ['on', 'bright', 'on_bright']
|
||||
for segment in compound.split('_'):
|
||||
if merged_segs and merged_segs[-1] in mergeable_prefixes:
|
||||
merged_segs[-1] += '_' + segment
|
||||
else:
|
||||
merged_segs.append(segment)
|
||||
return merged_segs
|
||||
|
||||
|
||||
def resolve_capability(term, attr):
|
||||
"""
|
||||
Resolve a raw terminal capability using :func:`tigetstr`.
|
||||
|
||||
:arg Terminal term: :class:`~.Terminal` instance.
|
||||
:arg str attr: terminal capability name.
|
||||
:returns: string of the given terminal capability named by ``attr``,
|
||||
which may be empty (u'') if not found or not supported by the
|
||||
given :attr:`~.Terminal.kind`.
|
||||
:rtype: str
|
||||
"""
|
||||
if not term.does_styling:
|
||||
return u''
|
||||
val = curses.tigetstr(term._sugar.get(attr, attr)) # pylint: disable=protected-access
|
||||
# Decode sequences as latin1, as they are always 8-bit bytes, so when
|
||||
# b'\xff' is returned, this is decoded as u'\xff'.
|
||||
return u'' if val is None else val.decode('latin1')
|
||||
|
||||
|
||||
def resolve_color(term, color):
|
||||
"""
|
||||
Resolve a simple color name to a callable capability.
|
||||
|
||||
This function supports :func:`resolve_attribute`.
|
||||
|
||||
:arg Terminal term: :class:`~.Terminal` instance.
|
||||
:arg str color: any string found in set :const:`COLORS`.
|
||||
:returns: a string class instance which emits the terminal sequence
|
||||
for the given color, and may be used as a callable to wrap the
|
||||
given string with such sequence.
|
||||
:returns: :class:`NullCallableString` when
|
||||
:attr:`~.Terminal.number_of_colors` is 0,
|
||||
otherwise :class:`FormattingString`.
|
||||
:rtype: :class:`NullCallableString` or :class:`FormattingString`
|
||||
"""
|
||||
# pylint: disable=protected-access
|
||||
if term.number_of_colors == 0:
|
||||
return NullCallableString()
|
||||
|
||||
# fg/bg capabilities terminals that support 0-256+ colors.
|
||||
vga_color_cap = (term._background_color if 'on_' in color else
|
||||
term._foreground_color)
|
||||
|
||||
base_color = color.rsplit('_', 1)[-1]
|
||||
if base_color in CGA_COLORS:
|
||||
# curses constants go up to only 7, so add an offset to get at the
|
||||
# bright colors at 8-15:
|
||||
offset = 8 if 'bright_' in color else 0
|
||||
base_color = color.rsplit('_', 1)[-1]
|
||||
attr = 'COLOR_%s' % (base_color.upper(),)
|
||||
fmt_attr = vga_color_cap(getattr(curses, attr) + offset)
|
||||
return FormattingString(fmt_attr, term.normal)
|
||||
|
||||
assert base_color in X11_COLORNAMES_TO_RGB, (
|
||||
'color not known', base_color)
|
||||
rgb = X11_COLORNAMES_TO_RGB[base_color]
|
||||
|
||||
# downconvert X11 colors to CGA, EGA, or VGA color spaces
|
||||
if term.number_of_colors <= 256:
|
||||
fmt_attr = vga_color_cap(term.rgb_downconvert(*rgb))
|
||||
return FormattingString(fmt_attr, term.normal)
|
||||
|
||||
# Modern 24-bit color terminals are written pretty basically. The
|
||||
# foreground and background sequences are:
|
||||
# - ^[38;2;<r>;<g>;<b>m
|
||||
# - ^[48;2;<r>;<g>;<b>m
|
||||
fgbg_seq = ('48' if 'on_' in color else '38')
|
||||
assert term.number_of_colors == 1 << 24
|
||||
fmt_attr = u'\x1b[' + fgbg_seq + ';2;{0};{1};{2}m'
|
||||
return FormattingString(fmt_attr.format(*rgb), term.normal)
|
||||
|
||||
|
||||
def resolve_attribute(term, attr):
|
||||
"""
|
||||
Resolve a terminal attribute name into a capability class.
|
||||
|
||||
:arg Terminal term: :class:`~.Terminal` instance.
|
||||
:arg str attr: Sugary, ordinary, or compound formatted terminal
|
||||
capability, such as "red_on_white", "normal", "red", or
|
||||
"bold_on_black".
|
||||
:returns: a string class instance which emits the terminal sequence
|
||||
for the given terminal capability, or may be used as a callable to
|
||||
wrap the given string with such sequence.
|
||||
:returns: :class:`NullCallableString` when
|
||||
:attr:`~.Terminal.number_of_colors` is 0,
|
||||
otherwise :class:`FormattingString`.
|
||||
:rtype: :class:`NullCallableString` or :class:`FormattingString`
|
||||
"""
|
||||
if attr in COLORS:
|
||||
return resolve_color(term, attr)
|
||||
|
||||
# A direct compoundable, such as `bold' or `on_red'.
|
||||
if attr in COMPOUNDABLES:
|
||||
sequence = resolve_capability(term, attr)
|
||||
return FormattingString(sequence, term.normal)
|
||||
|
||||
# Given `bold_on_red', resolve to ('bold', 'on_red'), RECURSIVE
|
||||
# call for each compounding section, joined and returned as
|
||||
# a completed completed FormattingString.
|
||||
formatters = split_compound(attr)
|
||||
if all((fmt in COLORS or fmt in COMPOUNDABLES) for fmt in formatters):
|
||||
resolution = (resolve_attribute(term, fmt) for fmt in formatters)
|
||||
return FormattingString(u''.join(resolution), term.normal)
|
||||
|
||||
# otherwise, this is our end-game: given a sequence such as 'csr'
|
||||
# (change scrolling region), return a ParameterizingString instance,
|
||||
# that when called, performs and returns the final string after curses
|
||||
# capability lookup is performed.
|
||||
tparm_capseq = resolve_capability(term, attr)
|
||||
if not tparm_capseq:
|
||||
# and, for special terminals, such as 'screen', provide a Proxy
|
||||
# ParameterizingString for attributes they do not claim to support,
|
||||
# but actually do! (such as 'hpa' and 'vpa').
|
||||
proxy = get_proxy_string(term,
|
||||
term._sugar.get(attr, attr)) # pylint: disable=protected-access
|
||||
if proxy is not None:
|
||||
return proxy
|
||||
|
||||
return ParameterizingString(tparm_capseq, term.normal, attr)
|
||||
70
venv/lib/python3.11/site-packages/blessed/formatters.pyi
Normal file
70
venv/lib/python3.11/site-packages/blessed/formatters.pyi
Normal file
@@ -0,0 +1,70 @@
|
||||
# std imports
|
||||
from typing import (Any,
|
||||
Set,
|
||||
List,
|
||||
Type,
|
||||
Tuple,
|
||||
Union,
|
||||
TypeVar,
|
||||
Callable,
|
||||
NoReturn,
|
||||
Optional,
|
||||
overload)
|
||||
|
||||
# local
|
||||
from .terminal import Terminal
|
||||
|
||||
COLORS: Set[str]
|
||||
COMPOUNDABLES: Set[str]
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
class ParameterizingString(str):
|
||||
def __new__(cls: Type[_T], cap: str, normal: str = ..., name: str = ...) -> _T: ...
|
||||
@overload
|
||||
def __call__(
|
||||
self, *args: int
|
||||
) -> Union["FormattingString", "NullCallableString"]: ...
|
||||
@overload
|
||||
def __call__(self, *args: str) -> NoReturn: ...
|
||||
|
||||
class ParameterizingProxyString(str):
|
||||
def __new__(
|
||||
cls: Type[_T],
|
||||
fmt_pair: Tuple[str, Callable[..., Tuple[object, ...]]],
|
||||
normal: str = ...,
|
||||
name: str = ...,
|
||||
) -> _T: ...
|
||||
def __call__(self, *args: Any) -> "FormattingString": ...
|
||||
|
||||
class FormattingString(str):
|
||||
def __new__(cls: Type[_T], sequence: str, normal: str = ...) -> _T: ...
|
||||
@overload
|
||||
def __call__(self, *args: int) -> NoReturn: ...
|
||||
@overload
|
||||
def __call__(self, *args: str) -> str: ...
|
||||
|
||||
class FormattingOtherString(str):
|
||||
def __new__(
|
||||
cls: Type[_T], direct: ParameterizingString, target: ParameterizingString = ...
|
||||
) -> _T: ...
|
||||
def __call__(self, *args: Union[int, str]) -> str: ...
|
||||
|
||||
class NullCallableString(str):
|
||||
def __new__(cls: Type[_T]) -> _T: ...
|
||||
@overload
|
||||
def __call__(self, *args: int) -> "NullCallableString": ...
|
||||
@overload
|
||||
def __call__(self, *args: str) -> str: ...
|
||||
|
||||
def get_proxy_string(
|
||||
term: Terminal, attr: str
|
||||
) -> Optional[ParameterizingProxyString]: ...
|
||||
def split_compound(compound: str) -> List[str]: ...
|
||||
def resolve_capability(term: Terminal, attr: str) -> str: ...
|
||||
def resolve_color(
|
||||
term: Terminal, color: str
|
||||
) -> Union[NullCallableString, FormattingString]: ...
|
||||
def resolve_attribute(
|
||||
term: Terminal, attr: str
|
||||
) -> Union[ParameterizingString, FormattingString]: ...
|
||||
451
venv/lib/python3.11/site-packages/blessed/keyboard.py
Normal file
451
venv/lib/python3.11/site-packages/blessed/keyboard.py
Normal file
@@ -0,0 +1,451 @@
|
||||
"""Sub-module providing 'keyboard awareness'."""
|
||||
|
||||
# std imports
|
||||
import re
|
||||
import time
|
||||
import platform
|
||||
from collections import OrderedDict
|
||||
|
||||
# 3rd party
|
||||
import six
|
||||
|
||||
# isort: off
|
||||
# curses
|
||||
if platform.system() == 'Windows':
|
||||
# pylint: disable=import-error
|
||||
import jinxed as curses
|
||||
from jinxed.has_key import _capability_names as capability_names
|
||||
else:
|
||||
import curses
|
||||
from curses.has_key import _capability_names as capability_names
|
||||
|
||||
|
||||
class Keystroke(six.text_type):
|
||||
"""
|
||||
A unicode-derived class for describing a single keystroke.
|
||||
|
||||
A class instance describes a single keystroke received on input,
|
||||
which may contain multiple characters as a multibyte sequence,
|
||||
which is indicated by properties :attr:`is_sequence` returning
|
||||
``True``.
|
||||
|
||||
When the string is a known sequence, :attr:`code` matches terminal
|
||||
class attributes for comparison, such as ``term.KEY_LEFT``.
|
||||
|
||||
The string-name of the sequence, such as ``u'KEY_LEFT'`` is accessed
|
||||
by property :attr:`name`, and is used by the :meth:`__repr__` method
|
||||
to display a human-readable form of the Keystroke this class
|
||||
instance represents. It may otherwise by joined, split, or evaluated
|
||||
just as as any other unicode string.
|
||||
"""
|
||||
|
||||
def __new__(cls, ucs='', code=None, name=None):
|
||||
"""Class constructor."""
|
||||
new = six.text_type.__new__(cls, ucs)
|
||||
new._name = name
|
||||
new._code = code
|
||||
return new
|
||||
|
||||
@property
|
||||
def is_sequence(self):
|
||||
"""Whether the value represents a multibyte sequence (bool)."""
|
||||
return self._code is not None
|
||||
|
||||
def __repr__(self):
|
||||
"""Docstring overwritten."""
|
||||
return (six.text_type.__repr__(self) if self._name is None else
|
||||
self._name)
|
||||
__repr__.__doc__ = six.text_type.__doc__
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""String-name of key sequence, such as ``u'KEY_LEFT'`` (str)."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def code(self):
|
||||
"""Integer keycode value of multibyte sequence (int)."""
|
||||
return self._code
|
||||
|
||||
|
||||
def get_curses_keycodes():
|
||||
"""
|
||||
Return mapping of curses key-names paired by their keycode integer value.
|
||||
|
||||
:rtype: dict
|
||||
:returns: Dictionary of (name, code) pairs for curses keyboard constant
|
||||
values and their mnemonic name. Such as code ``260``, with the value of
|
||||
its key-name identity, ``u'KEY_LEFT'``.
|
||||
"""
|
||||
_keynames = [attr for attr in dir(curses)
|
||||
if attr.startswith('KEY_')]
|
||||
return {keyname: getattr(curses, keyname) for keyname in _keynames}
|
||||
|
||||
|
||||
def get_keyboard_codes():
|
||||
"""
|
||||
Return mapping of keycode integer values paired by their curses key-name.
|
||||
|
||||
:rtype: dict
|
||||
:returns: Dictionary of (code, name) pairs for curses keyboard constant
|
||||
values and their mnemonic name. Such as key ``260``, with the value of
|
||||
its identity, ``u'KEY_LEFT'``.
|
||||
|
||||
These keys are derived from the attributes by the same of the curses module,
|
||||
with the following exceptions:
|
||||
|
||||
* ``KEY_DELETE`` in place of ``KEY_DC``
|
||||
* ``KEY_INSERT`` in place of ``KEY_IC``
|
||||
* ``KEY_PGUP`` in place of ``KEY_PPAGE``
|
||||
* ``KEY_PGDOWN`` in place of ``KEY_NPAGE``
|
||||
* ``KEY_ESCAPE`` in place of ``KEY_EXIT``
|
||||
* ``KEY_SUP`` in place of ``KEY_SR``
|
||||
* ``KEY_SDOWN`` in place of ``KEY_SF``
|
||||
|
||||
This function is the inverse of :func:`get_curses_keycodes`. With the
|
||||
given override "mixins" listed above, the keycode for the delete key will
|
||||
map to our imaginary ``KEY_DELETE`` mnemonic, effectively erasing the
|
||||
phrase ``KEY_DC`` from our code vocabulary for anyone that wishes to use
|
||||
the return value to determine the key-name by keycode.
|
||||
"""
|
||||
keycodes = OrderedDict(get_curses_keycodes())
|
||||
keycodes.update(CURSES_KEYCODE_OVERRIDE_MIXIN)
|
||||
# merge _CURSES_KEYCODE_ADDINS added to our module space
|
||||
keycodes.update(
|
||||
(name, value) for name, value in globals().copy().items() if name.startswith('KEY_')
|
||||
)
|
||||
|
||||
# invert dictionary (key, values) => (values, key), preferring the
|
||||
# last-most inserted value ('KEY_DELETE' over 'KEY_DC').
|
||||
return dict(zip(keycodes.values(), keycodes.keys()))
|
||||
|
||||
|
||||
def _alternative_left_right(term):
|
||||
r"""
|
||||
Determine and return mapping of left and right arrow keys sequences.
|
||||
|
||||
:arg blessed.Terminal term: :class:`~.Terminal` instance.
|
||||
:rtype: dict
|
||||
:returns: Dictionary of sequences ``term._cuf1``, and ``term._cub1``,
|
||||
valued as ``KEY_RIGHT``, ``KEY_LEFT`` (when appropriate).
|
||||
|
||||
This function supports :func:`get_terminal_sequences` to discover
|
||||
the preferred input sequence for the left and right application keys.
|
||||
|
||||
It is necessary to check the value of these sequences to ensure we do not
|
||||
use ``u' '`` and ``u'\b'`` for ``KEY_RIGHT`` and ``KEY_LEFT``,
|
||||
preferring their true application key sequence, instead.
|
||||
"""
|
||||
# pylint: disable=protected-access
|
||||
keymap = {}
|
||||
if term._cuf1 and term._cuf1 != u' ':
|
||||
keymap[term._cuf1] = curses.KEY_RIGHT
|
||||
if term._cub1 and term._cub1 != u'\b':
|
||||
keymap[term._cub1] = curses.KEY_LEFT
|
||||
return keymap
|
||||
|
||||
|
||||
def get_keyboard_sequences(term):
|
||||
r"""
|
||||
Return mapping of keyboard sequences paired by keycodes.
|
||||
|
||||
:arg blessed.Terminal term: :class:`~.Terminal` instance.
|
||||
:returns: mapping of keyboard unicode sequences paired by keycodes
|
||||
as integer. This is used as the argument ``mapper`` to
|
||||
the supporting function :func:`resolve_sequence`.
|
||||
:rtype: OrderedDict
|
||||
|
||||
Initialize and return a keyboard map and sequence lookup table,
|
||||
(sequence, keycode) from :class:`~.Terminal` instance ``term``,
|
||||
where ``sequence`` is a multibyte input sequence of unicode
|
||||
characters, such as ``u'\x1b[D'``, and ``keycode`` is an integer
|
||||
value, matching curses constant such as term.KEY_LEFT.
|
||||
|
||||
The return value is an OrderedDict instance, with their keys
|
||||
sorted longest-first.
|
||||
"""
|
||||
# A small gem from curses.has_key that makes this all possible,
|
||||
# _capability_names: a lookup table of terminal capability names for
|
||||
# keyboard sequences (fe. kcub1, key_left), keyed by the values of
|
||||
# constants found beginning with KEY_ in the main curses module
|
||||
# (such as KEY_LEFT).
|
||||
#
|
||||
# latin1 encoding is used so that bytes in 8-bit range of 127-255
|
||||
# have equivalent chr() and unichr() values, so that the sequence
|
||||
# of a kermit or avatar terminal, for example, remains unchanged
|
||||
# in its byte sequence values even when represented by unicode.
|
||||
#
|
||||
sequence_map = dict((
|
||||
(seq.decode('latin1'), val)
|
||||
for (seq, val) in (
|
||||
(curses.tigetstr(cap), val)
|
||||
for (val, cap) in capability_names.items()
|
||||
) if seq
|
||||
) if term.does_styling else ())
|
||||
|
||||
sequence_map.update(_alternative_left_right(term))
|
||||
sequence_map.update(DEFAULT_SEQUENCE_MIXIN)
|
||||
|
||||
# This is for fast lookup matching of sequences, preferring
|
||||
# full-length sequence such as ('\x1b[D', KEY_LEFT)
|
||||
# over simple sequences such as ('\x1b', KEY_EXIT).
|
||||
return OrderedDict((
|
||||
(seq, sequence_map[seq]) for seq in sorted(
|
||||
sequence_map.keys(), key=len, reverse=True)))
|
||||
|
||||
|
||||
def get_leading_prefixes(sequences):
|
||||
"""
|
||||
Return a set of proper prefixes for given sequence of strings.
|
||||
|
||||
:arg iterable sequences
|
||||
:rtype: set
|
||||
:return: Set of all string prefixes
|
||||
|
||||
Given an iterable of strings, all textparts leading up to the final
|
||||
string is returned as a unique set. This function supports the
|
||||
:meth:`~.Terminal.inkey` method by determining whether the given
|
||||
input is a sequence that **may** lead to a final matching pattern.
|
||||
|
||||
>>> prefixes(['abc', 'abdf', 'e', 'jkl'])
|
||||
set([u'a', u'ab', u'abd', u'j', u'jk'])
|
||||
"""
|
||||
return {seq[:i] for seq in sequences for i in range(1, len(seq))}
|
||||
|
||||
|
||||
def resolve_sequence(text, mapper, codes):
|
||||
r"""
|
||||
Return a single :class:`Keystroke` instance for given sequence ``text``.
|
||||
|
||||
:arg str text: string of characters received from terminal input stream.
|
||||
:arg OrderedDict mapper: unicode multibyte sequences, such as ``u'\x1b[D'``
|
||||
paired by their integer value (260)
|
||||
:arg dict codes: a :type:`dict` of integer values (such as 260) paired
|
||||
by their mnemonic name, such as ``'KEY_LEFT'``.
|
||||
:rtype: Keystroke
|
||||
:returns: Keystroke instance for the given sequence
|
||||
|
||||
The given ``text`` may extend beyond a matching sequence, such as
|
||||
``u\x1b[Dxxx`` returns a :class:`Keystroke` instance of attribute
|
||||
:attr:`Keystroke.sequence` valued only ``u\x1b[D``. It is up to
|
||||
calls to determine that ``xxx`` remains unresolved.
|
||||
"""
|
||||
for sequence, code in mapper.items():
|
||||
if text.startswith(sequence):
|
||||
return Keystroke(ucs=sequence, code=code, name=codes[code])
|
||||
return Keystroke(ucs=text and text[0] or u'')
|
||||
|
||||
|
||||
def _time_left(stime, timeout):
|
||||
"""
|
||||
Return time remaining since ``stime`` before given ``timeout``.
|
||||
|
||||
This function assists determining the value of ``timeout`` for
|
||||
class method :meth:`~.Terminal.kbhit` and similar functions.
|
||||
|
||||
:arg float stime: starting time for measurement
|
||||
:arg float timeout: timeout period, may be set to None to
|
||||
indicate no timeout (where None is always returned).
|
||||
:rtype: float or int
|
||||
:returns: time remaining as float. If no time is remaining,
|
||||
then the integer ``0`` is returned.
|
||||
"""
|
||||
return max(0, timeout - (time.time() - stime)) if timeout else timeout
|
||||
|
||||
|
||||
def _read_until(term, pattern, timeout):
|
||||
"""
|
||||
Convenience read-until-pattern function, supporting :meth:`~.get_location`.
|
||||
|
||||
:arg blessed.Terminal term: :class:`~.Terminal` instance.
|
||||
:arg float timeout: timeout period, may be set to None to indicate no
|
||||
timeout (where 0 is always returned).
|
||||
:arg str pattern: target regular expression pattern to seek.
|
||||
:rtype: tuple
|
||||
:returns: tuple in form of ``(match, str)``, *match*
|
||||
may be :class:`re.MatchObject` if pattern is discovered
|
||||
in input stream before timeout has elapsed, otherwise
|
||||
None. ``str`` is any remaining text received exclusive
|
||||
of the matching pattern).
|
||||
|
||||
The reason a tuple containing non-matching data is returned, is that the
|
||||
consumer should push such data back into the input buffer by
|
||||
:meth:`~.Terminal.ungetch` if any was received.
|
||||
|
||||
For example, when a user is performing rapid input keystrokes while its
|
||||
terminal emulator surreptitiously responds to this in-band sequence, we
|
||||
must ensure any such keyboard data is well-received by the next call to
|
||||
term.inkey() without delay.
|
||||
"""
|
||||
stime = time.time()
|
||||
match, buf = None, u''
|
||||
|
||||
# first, buffer all pending data. pexpect library provides a
|
||||
# 'searchwindowsize' attribute that limits this memory region. We're not
|
||||
# concerned about OOM conditions: only (human) keyboard input and terminal
|
||||
# response sequences are expected.
|
||||
|
||||
while True: # pragma: no branch
|
||||
# block as long as necessary to ensure at least one character is
|
||||
# received on input or remaining timeout has elapsed.
|
||||
ucs = term.inkey(timeout=_time_left(stime, timeout))
|
||||
# while the keyboard buffer is "hot" (has input), we continue to
|
||||
# aggregate all awaiting data. We do this to ensure slow I/O
|
||||
# calls do not unnecessarily give up within the first 'while' loop
|
||||
# for short timeout periods.
|
||||
while ucs:
|
||||
buf += ucs
|
||||
ucs = term.inkey(timeout=0)
|
||||
|
||||
match = re.search(pattern=pattern, string=buf)
|
||||
if match is not None:
|
||||
# match
|
||||
break
|
||||
|
||||
if timeout is not None and not _time_left(stime, timeout):
|
||||
# timeout
|
||||
break
|
||||
|
||||
return match, buf
|
||||
|
||||
|
||||
#: Though we may determine *keynames* and codes for keyboard input that
|
||||
#: generate multibyte sequences, it is also especially useful to aliases
|
||||
#: a few basic ASCII characters such as ``KEY_TAB`` instead of ``u'\t'`` for
|
||||
#: uniformity.
|
||||
#:
|
||||
#: Furthermore, many key-names for application keys enabled only by context
|
||||
#: manager :meth:`~.Terminal.keypad` are surprisingly absent. We inject them
|
||||
#: here directly into the curses module.
|
||||
_CURSES_KEYCODE_ADDINS = (
|
||||
'TAB',
|
||||
'KP_MULTIPLY',
|
||||
'KP_ADD',
|
||||
'KP_SEPARATOR',
|
||||
'KP_SUBTRACT',
|
||||
'KP_DECIMAL',
|
||||
'KP_DIVIDE',
|
||||
'KP_EQUAL',
|
||||
'KP_0',
|
||||
'KP_1',
|
||||
'KP_2',
|
||||
'KP_3',
|
||||
'KP_4',
|
||||
'KP_5',
|
||||
'KP_6',
|
||||
'KP_7',
|
||||
'KP_8',
|
||||
'KP_9')
|
||||
|
||||
_LASTVAL = max(get_curses_keycodes().values())
|
||||
for keycode_name in _CURSES_KEYCODE_ADDINS:
|
||||
_LASTVAL += 1
|
||||
globals()['KEY_' + keycode_name] = _LASTVAL
|
||||
|
||||
#: In a perfect world, terminal emulators would always send exactly what
|
||||
#: the terminfo(5) capability database plans for them, accordingly by the
|
||||
#: value of the ``TERM`` name they declare.
|
||||
#:
|
||||
#: But this isn't a perfect world. Many vt220-derived terminals, such as
|
||||
#: those declaring 'xterm', will continue to send vt220 codes instead of
|
||||
#: their native-declared codes, for backwards-compatibility.
|
||||
#:
|
||||
#: This goes for many: rxvt, putty, iTerm.
|
||||
#:
|
||||
#: These "mixins" are used for *all* terminals, regardless of their type.
|
||||
#:
|
||||
#: Furthermore, curses does not provide sequences sent by the keypad,
|
||||
#: at least, it does not provide a way to distinguish between keypad 0
|
||||
#: and numeric 0.
|
||||
DEFAULT_SEQUENCE_MIXIN = (
|
||||
# these common control characters (and 127, ctrl+'?') mapped to
|
||||
# an application key definition.
|
||||
(six.unichr(10), curses.KEY_ENTER),
|
||||
(six.unichr(13), curses.KEY_ENTER),
|
||||
(six.unichr(8), curses.KEY_BACKSPACE),
|
||||
(six.unichr(9), KEY_TAB), # noqa # pylint: disable=undefined-variable
|
||||
(six.unichr(27), curses.KEY_EXIT),
|
||||
(six.unichr(127), curses.KEY_BACKSPACE),
|
||||
|
||||
(u"\x1b[A", curses.KEY_UP),
|
||||
(u"\x1b[B", curses.KEY_DOWN),
|
||||
(u"\x1b[C", curses.KEY_RIGHT),
|
||||
(u"\x1b[D", curses.KEY_LEFT),
|
||||
(u"\x1b[1;2A", curses.KEY_SR),
|
||||
(u"\x1b[1;2B", curses.KEY_SF),
|
||||
(u"\x1b[1;2C", curses.KEY_SRIGHT),
|
||||
(u"\x1b[1;2D", curses.KEY_SLEFT),
|
||||
(u"\x1b[F", curses.KEY_END),
|
||||
(u"\x1b[H", curses.KEY_HOME),
|
||||
# not sure where these are from .. please report
|
||||
(u"\x1b[K", curses.KEY_END),
|
||||
(u"\x1b[U", curses.KEY_NPAGE),
|
||||
(u"\x1b[V", curses.KEY_PPAGE),
|
||||
|
||||
# keys sent after term.smkx (keypad_xmit) is emitted, source:
|
||||
# http://www.xfree86.org/current/ctlseqs.html#PC-Style%20Function%20Keys
|
||||
# http://fossies.org/linux/rxvt/doc/rxvtRef.html#KeyCodes
|
||||
#
|
||||
# keypad, numlock on
|
||||
(u"\x1bOM", curses.KEY_ENTER), # noqa return
|
||||
(u"\x1bOj", KEY_KP_MULTIPLY), # noqa * # pylint: disable=undefined-variable
|
||||
(u"\x1bOk", KEY_KP_ADD), # noqa + # pylint: disable=undefined-variable
|
||||
(u"\x1bOl", KEY_KP_SEPARATOR), # noqa , # pylint: disable=undefined-variable
|
||||
(u"\x1bOm", KEY_KP_SUBTRACT), # noqa - # pylint: disable=undefined-variable
|
||||
(u"\x1bOn", KEY_KP_DECIMAL), # noqa . # pylint: disable=undefined-variable
|
||||
(u"\x1bOo", KEY_KP_DIVIDE), # noqa / # pylint: disable=undefined-variable
|
||||
(u"\x1bOX", KEY_KP_EQUAL), # noqa = # pylint: disable=undefined-variable
|
||||
(u"\x1bOp", KEY_KP_0), # noqa 0 # pylint: disable=undefined-variable
|
||||
(u"\x1bOq", KEY_KP_1), # noqa 1 # pylint: disable=undefined-variable
|
||||
(u"\x1bOr", KEY_KP_2), # noqa 2 # pylint: disable=undefined-variable
|
||||
(u"\x1bOs", KEY_KP_3), # noqa 3 # pylint: disable=undefined-variable
|
||||
(u"\x1bOt", KEY_KP_4), # noqa 4 # pylint: disable=undefined-variable
|
||||
(u"\x1bOu", KEY_KP_5), # noqa 5 # pylint: disable=undefined-variable
|
||||
(u"\x1bOv", KEY_KP_6), # noqa 6 # pylint: disable=undefined-variable
|
||||
(u"\x1bOw", KEY_KP_7), # noqa 7 # pylint: disable=undefined-variable
|
||||
(u"\x1bOx", KEY_KP_8), # noqa 8 # pylint: disable=undefined-variable
|
||||
(u"\x1bOy", KEY_KP_9), # noqa 9 # pylint: disable=undefined-variable
|
||||
|
||||
# keypad, numlock off
|
||||
(u"\x1b[1~", curses.KEY_FIND), # find
|
||||
(u"\x1b[2~", curses.KEY_IC), # insert (0)
|
||||
(u"\x1b[3~", curses.KEY_DC), # delete (.), "Execute"
|
||||
(u"\x1b[4~", curses.KEY_SELECT), # select
|
||||
(u"\x1b[5~", curses.KEY_PPAGE), # pgup (9)
|
||||
(u"\x1b[6~", curses.KEY_NPAGE), # pgdown (3)
|
||||
(u"\x1b[7~", curses.KEY_HOME), # home
|
||||
(u"\x1b[8~", curses.KEY_END), # end
|
||||
(u"\x1b[OA", curses.KEY_UP), # up (8)
|
||||
(u"\x1b[OB", curses.KEY_DOWN), # down (2)
|
||||
(u"\x1b[OC", curses.KEY_RIGHT), # right (6)
|
||||
(u"\x1b[OD", curses.KEY_LEFT), # left (4)
|
||||
(u"\x1b[OF", curses.KEY_END), # end (1)
|
||||
(u"\x1b[OH", curses.KEY_HOME), # home (7)
|
||||
|
||||
# The vt220 placed F1-F4 above the keypad, in place of actual
|
||||
# F1-F4 were local functions (hold screen, print screen,
|
||||
# set up, data/talk, break).
|
||||
(u"\x1bOP", curses.KEY_F1),
|
||||
(u"\x1bOQ", curses.KEY_F2),
|
||||
(u"\x1bOR", curses.KEY_F3),
|
||||
(u"\x1bOS", curses.KEY_F4),
|
||||
)
|
||||
|
||||
#: Override mixins for a few curses constants with easier
|
||||
#: mnemonics: there may only be a 1:1 mapping when only a
|
||||
#: keycode (int) is given, where these phrases are preferred.
|
||||
CURSES_KEYCODE_OVERRIDE_MIXIN = (
|
||||
('KEY_DELETE', curses.KEY_DC),
|
||||
('KEY_INSERT', curses.KEY_IC),
|
||||
('KEY_PGUP', curses.KEY_PPAGE),
|
||||
('KEY_PGDOWN', curses.KEY_NPAGE),
|
||||
('KEY_ESCAPE', curses.KEY_EXIT),
|
||||
('KEY_SUP', curses.KEY_SR),
|
||||
('KEY_SDOWN', curses.KEY_SF),
|
||||
('KEY_UP_LEFT', curses.KEY_A1),
|
||||
('KEY_UP_RIGHT', curses.KEY_A3),
|
||||
('KEY_CENTER', curses.KEY_B2),
|
||||
('KEY_BEGIN', curses.KEY_BEG),
|
||||
)
|
||||
|
||||
__all__ = ('Keystroke', 'get_keyboard_codes', 'get_keyboard_sequences',)
|
||||
28
venv/lib/python3.11/site-packages/blessed/keyboard.pyi
Normal file
28
venv/lib/python3.11/site-packages/blessed/keyboard.pyi
Normal file
@@ -0,0 +1,28 @@
|
||||
# std imports
|
||||
from typing import Set, Dict, Type, Mapping, TypeVar, Iterable, Optional, OrderedDict
|
||||
|
||||
# local
|
||||
from .terminal import Terminal
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
class Keystroke(str):
|
||||
def __new__(
|
||||
cls: Type[_T],
|
||||
ucs: str = ...,
|
||||
code: Optional[int] = ...,
|
||||
name: Optional[str] = ...,
|
||||
) -> _T: ...
|
||||
@property
|
||||
def is_sequence(self) -> bool: ...
|
||||
@property
|
||||
def name(self) -> Optional[str]: ...
|
||||
@property
|
||||
def code(self) -> Optional[int]: ...
|
||||
|
||||
def get_keyboard_codes() -> Dict[int, str]: ...
|
||||
def get_keyboard_sequences(term: Terminal) -> OrderedDict[str, int]: ...
|
||||
def get_leading_prefixes(sequences: Iterable[str]) -> Set[str]: ...
|
||||
def resolve_sequence(
|
||||
text: str, mapper: Mapping[str, int], codes: Mapping[int, str]
|
||||
) -> Keystroke: ...
|
||||
0
venv/lib/python3.11/site-packages/blessed/py.typed
Normal file
0
venv/lib/python3.11/site-packages/blessed/py.typed
Normal file
461
venv/lib/python3.11/site-packages/blessed/sequences.py
Normal file
461
venv/lib/python3.11/site-packages/blessed/sequences.py
Normal file
@@ -0,0 +1,461 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Module providing 'sequence awareness'."""
|
||||
# std imports
|
||||
import re
|
||||
import math
|
||||
import textwrap
|
||||
|
||||
# 3rd party
|
||||
import six
|
||||
from wcwidth import wcwidth
|
||||
|
||||
# local
|
||||
from blessed._capabilities import CAPABILITIES_CAUSE_MOVEMENT
|
||||
|
||||
__all__ = ('Sequence', 'SequenceTextWrapper', 'iter_parse', 'measure_length')
|
||||
|
||||
|
||||
class Termcap(object):
|
||||
"""Terminal capability of given variable name and pattern."""
|
||||
|
||||
def __init__(self, name, pattern, attribute):
|
||||
"""
|
||||
Class initializer.
|
||||
|
||||
:arg str name: name describing capability.
|
||||
:arg str pattern: regular expression string.
|
||||
:arg str attribute: :class:`~.Terminal` attribute used to build
|
||||
this terminal capability.
|
||||
"""
|
||||
self.name = name
|
||||
self.pattern = pattern
|
||||
self.attribute = attribute
|
||||
self._re_compiled = None
|
||||
|
||||
def __repr__(self):
|
||||
# pylint: disable=redundant-keyword-arg
|
||||
return '<Termcap {self.name}:{self.pattern!r}>'.format(self=self)
|
||||
|
||||
@property
|
||||
def named_pattern(self):
|
||||
"""Regular expression pattern for capability with named group."""
|
||||
# pylint: disable=redundant-keyword-arg
|
||||
return '(?P<{self.name}>{self.pattern})'.format(self=self)
|
||||
|
||||
@property
|
||||
def re_compiled(self):
|
||||
"""Compiled regular expression pattern for capability."""
|
||||
if self._re_compiled is None:
|
||||
self._re_compiled = re.compile(self.pattern)
|
||||
return self._re_compiled
|
||||
|
||||
@property
|
||||
def will_move(self):
|
||||
"""Whether capability causes cursor movement."""
|
||||
return self.name in CAPABILITIES_CAUSE_MOVEMENT
|
||||
|
||||
def horizontal_distance(self, text):
|
||||
"""
|
||||
Horizontal carriage adjusted by capability, may be negative.
|
||||
|
||||
:rtype: int
|
||||
:arg str text: for capabilities *parm_left_cursor*,
|
||||
*parm_right_cursor*, provide the matching sequence
|
||||
text, its interpreted distance is returned.
|
||||
|
||||
:returns: 0 except for matching '
|
||||
"""
|
||||
value = {
|
||||
'cursor_left': -1,
|
||||
'backspace': -1,
|
||||
'cursor_right': 1,
|
||||
'tab': 8,
|
||||
'ascii_tab': 8,
|
||||
}.get(self.name)
|
||||
if value is not None:
|
||||
return value
|
||||
|
||||
unit = {
|
||||
'parm_left_cursor': -1,
|
||||
'parm_right_cursor': 1
|
||||
}.get(self.name)
|
||||
if unit is not None:
|
||||
value = int(self.re_compiled.match(text).group(1))
|
||||
return unit * value
|
||||
|
||||
return 0
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
@classmethod
|
||||
def build(cls, name, capability, attribute, nparams=0,
|
||||
numeric=99, match_grouped=False, match_any=False,
|
||||
match_optional=False):
|
||||
r"""
|
||||
Class factory builder for given capability definition.
|
||||
|
||||
:arg str name: Variable name given for this pattern.
|
||||
:arg str capability: A unicode string representing a terminal
|
||||
capability to build for. When ``nparams`` is non-zero, it
|
||||
must be a callable unicode string (such as the result from
|
||||
``getattr(term, 'bold')``.
|
||||
:arg str attribute: The terminfo(5) capability name by which this
|
||||
pattern is known.
|
||||
:arg int nparams: number of positional arguments for callable.
|
||||
:arg int numeric: Value to substitute into capability to when generating pattern
|
||||
:arg bool match_grouped: If the numeric pattern should be
|
||||
grouped, ``(\d+)`` when ``True``, ``\d+`` default.
|
||||
:arg bool match_any: When keyword argument ``nparams`` is given,
|
||||
*any* numeric found in output is suitable for building as
|
||||
pattern ``(\d+)``. Otherwise, only the first matching value of
|
||||
range *(numeric - 1)* through *(numeric + 1)* will be replaced by
|
||||
pattern ``(\d+)`` in builder.
|
||||
:arg bool match_optional: When ``True``, building of numeric patterns
|
||||
containing ``(\d+)`` will be built as optional, ``(\d+)?``.
|
||||
:rtype: blessed.sequences.Termcap
|
||||
:returns: Terminal capability instance for given capability definition
|
||||
"""
|
||||
_numeric_regex = r'\d+'
|
||||
if match_grouped:
|
||||
_numeric_regex = r'(\d+)'
|
||||
if match_optional:
|
||||
_numeric_regex = r'(\d+)?'
|
||||
numeric = 99 if numeric is None else numeric
|
||||
|
||||
# basic capability attribute, not used as a callable
|
||||
if nparams == 0:
|
||||
return cls(name, re.escape(capability), attribute)
|
||||
|
||||
# a callable capability accepting numeric argument
|
||||
_outp = re.escape(capability(*(numeric,) * nparams))
|
||||
if not match_any:
|
||||
for num in range(numeric - 1, numeric + 2):
|
||||
if str(num) in _outp:
|
||||
pattern = _outp.replace(str(num), _numeric_regex)
|
||||
return cls(name, pattern, attribute)
|
||||
|
||||
if match_grouped:
|
||||
pattern = re.sub(r'(\d+)', lambda x: _numeric_regex, _outp)
|
||||
else:
|
||||
pattern = re.sub(r'\d+', lambda x: _numeric_regex, _outp)
|
||||
return cls(name, pattern, attribute)
|
||||
|
||||
|
||||
class SequenceTextWrapper(textwrap.TextWrapper):
|
||||
"""Docstring overridden."""
|
||||
|
||||
def __init__(self, width, term, **kwargs):
|
||||
"""
|
||||
Class initializer.
|
||||
|
||||
This class supports the :meth:`~.Terminal.wrap` method.
|
||||
"""
|
||||
self.term = term
|
||||
textwrap.TextWrapper.__init__(self, width, **kwargs)
|
||||
|
||||
def _wrap_chunks(self, chunks):
|
||||
"""
|
||||
Sequence-aware variant of :meth:`textwrap.TextWrapper._wrap_chunks`.
|
||||
|
||||
:raises ValueError: ``self.width`` is not a positive integer
|
||||
:rtype: list
|
||||
:returns: text chunks adjusted for width
|
||||
|
||||
This simply ensures that word boundaries are not broken mid-sequence, as standard python
|
||||
textwrap would incorrectly determine the length of a string containing sequences, and may
|
||||
also break consider sequences part of a "word" that may be broken by hyphen (``-``), where
|
||||
this implementation corrects both.
|
||||
"""
|
||||
lines = []
|
||||
if self.width <= 0 or not isinstance(self.width, int):
|
||||
raise ValueError(
|
||||
"invalid width {0!r}({1!r}) (must be integer > 0)"
|
||||
.format(self.width, type(self.width)))
|
||||
|
||||
term = self.term
|
||||
drop_whitespace = not hasattr(self, 'drop_whitespace'
|
||||
) or self.drop_whitespace
|
||||
chunks.reverse()
|
||||
while chunks:
|
||||
cur_line = []
|
||||
cur_len = 0
|
||||
indent = self.subsequent_indent if lines else self.initial_indent
|
||||
width = self.width - len(indent)
|
||||
if drop_whitespace and (
|
||||
Sequence(chunks[-1], term).strip() == '' and lines):
|
||||
del chunks[-1]
|
||||
while chunks:
|
||||
chunk_len = Sequence(chunks[-1], term).length()
|
||||
if cur_len + chunk_len > width:
|
||||
break
|
||||
cur_line.append(chunks.pop())
|
||||
cur_len += chunk_len
|
||||
if chunks and Sequence(chunks[-1], term).length() > width:
|
||||
self._handle_long_word(chunks, cur_line, cur_len, width)
|
||||
if drop_whitespace and (
|
||||
cur_line and Sequence(cur_line[-1], term).strip() == ''):
|
||||
del cur_line[-1]
|
||||
if cur_line:
|
||||
lines.append(indent + u''.join(cur_line))
|
||||
return lines
|
||||
|
||||
def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
|
||||
"""
|
||||
Sequence-aware :meth:`textwrap.TextWrapper._handle_long_word`.
|
||||
|
||||
This simply ensures that word boundaries are not broken mid-sequence, as standard python
|
||||
textwrap would incorrectly determine the length of a string containing sequences, and may
|
||||
also break consider sequences part of a "word" that may be broken by hyphen (``-``), where
|
||||
this implementation corrects both.
|
||||
"""
|
||||
# Figure out when indent is larger than the specified width, and make
|
||||
# sure at least one character is stripped off on every pass
|
||||
space_left = 1 if width < 1 else width - cur_len
|
||||
# If we're allowed to break long words, then do so: put as much
|
||||
# of the next chunk onto the current line as will fit.
|
||||
|
||||
if self.break_long_words:
|
||||
term = self.term
|
||||
chunk = reversed_chunks[-1]
|
||||
idx = nxt = 0
|
||||
for text, _ in iter_parse(term, chunk):
|
||||
nxt += len(text)
|
||||
if Sequence(chunk[:nxt], term).length() > space_left:
|
||||
break
|
||||
idx = nxt
|
||||
cur_line.append(chunk[:idx])
|
||||
reversed_chunks[-1] = chunk[idx:]
|
||||
|
||||
# Otherwise, we have to preserve the long word intact. Only add
|
||||
# it to the current line if there's nothing already there --
|
||||
# that minimizes how much we violate the width constraint.
|
||||
elif not cur_line:
|
||||
cur_line.append(reversed_chunks.pop())
|
||||
|
||||
# If we're not allowed to break long words, and there's already
|
||||
# text on the current line, do nothing. Next time through the
|
||||
# main loop of _wrap_chunks(), we'll wind up here again, but
|
||||
# cur_len will be zero, so the next line will be entirely
|
||||
# devoted to the long word that we can't handle right now.
|
||||
|
||||
|
||||
SequenceTextWrapper.__doc__ = textwrap.TextWrapper.__doc__
|
||||
|
||||
|
||||
class Sequence(six.text_type):
|
||||
"""
|
||||
A "sequence-aware" version of the base :class:`str` class.
|
||||
|
||||
This unicode-derived class understands the effect of escape sequences
|
||||
of printable length, allowing a properly implemented :meth:`rjust`,
|
||||
:meth:`ljust`, :meth:`center`, and :meth:`length`.
|
||||
"""
|
||||
|
||||
def __new__(cls, sequence_text, term):
|
||||
# pylint: disable = missing-return-doc, missing-return-type-doc
|
||||
"""
|
||||
Class constructor.
|
||||
|
||||
:arg str sequence_text: A string that may contain sequences.
|
||||
:arg blessed.Terminal term: :class:`~.Terminal` instance.
|
||||
"""
|
||||
new = six.text_type.__new__(cls, sequence_text)
|
||||
new._term = term
|
||||
return new
|
||||
|
||||
def ljust(self, width, fillchar=u' '):
|
||||
"""
|
||||
Return string containing sequences, left-adjusted.
|
||||
|
||||
:arg int width: Total width given to left-adjust ``text``. If
|
||||
unspecified, the width of the attached terminal is used (default).
|
||||
:arg str fillchar: String for padding right-of ``text``.
|
||||
:returns: String of ``text``, left-aligned by ``width``.
|
||||
:rtype: str
|
||||
"""
|
||||
rightside = fillchar * int(
|
||||
(max(0.0, float(width.__index__() - self.length()))) / float(len(fillchar)))
|
||||
return u''.join((self, rightside))
|
||||
|
||||
def rjust(self, width, fillchar=u' '):
|
||||
"""
|
||||
Return string containing sequences, right-adjusted.
|
||||
|
||||
:arg int width: Total width given to right-adjust ``text``. If
|
||||
unspecified, the width of the attached terminal is used (default).
|
||||
:arg str fillchar: String for padding left-of ``text``.
|
||||
:returns: String of ``text``, right-aligned by ``width``.
|
||||
:rtype: str
|
||||
"""
|
||||
leftside = fillchar * int(
|
||||
(max(0.0, float(width.__index__() - self.length()))) / float(len(fillchar)))
|
||||
return u''.join((leftside, self))
|
||||
|
||||
def center(self, width, fillchar=u' '):
|
||||
"""
|
||||
Return string containing sequences, centered.
|
||||
|
||||
:arg int width: Total width given to center ``text``. If
|
||||
unspecified, the width of the attached terminal is used (default).
|
||||
:arg str fillchar: String for padding left and right-of ``text``.
|
||||
:returns: String of ``text``, centered by ``width``.
|
||||
:rtype: str
|
||||
"""
|
||||
split = max(0.0, float(width.__index__()) - self.length()) / 2
|
||||
leftside = fillchar * int(
|
||||
(max(0.0, math.floor(split))) / float(len(fillchar)))
|
||||
rightside = fillchar * int(
|
||||
(max(0.0, math.ceil(split))) / float(len(fillchar)))
|
||||
return u''.join((leftside, self, rightside))
|
||||
|
||||
def truncate(self, width):
|
||||
"""
|
||||
Truncate a string in a sequence-aware manner.
|
||||
|
||||
Any printable characters beyond ``width`` are removed, while all
|
||||
sequences remain in place. Horizontal Sequences are first expanded
|
||||
by :meth:`padd`.
|
||||
|
||||
:arg int width: The printable width to truncate the string to.
|
||||
:rtype: str
|
||||
:returns: String truncated to at most ``width`` printable characters.
|
||||
"""
|
||||
output = ""
|
||||
current_width = 0
|
||||
target_width = width.__index__()
|
||||
parsed_seq = iter_parse(self._term, self.padd())
|
||||
|
||||
# Retain all text until non-cap width reaches desired width
|
||||
for text, cap in parsed_seq:
|
||||
if not cap:
|
||||
# use wcwidth clipped to 0 because it can sometimes return -1
|
||||
current_width += max(wcwidth(text), 0)
|
||||
if current_width > target_width:
|
||||
break
|
||||
output += text
|
||||
|
||||
# Return with remaining caps appended
|
||||
return output + ''.join(text for text, cap in parsed_seq if cap)
|
||||
|
||||
def length(self):
|
||||
r"""
|
||||
Return the printable length of string containing sequences.
|
||||
|
||||
Strings containing ``term.left`` or ``\b`` will cause "overstrike",
|
||||
but a length less than 0 is not ever returned. So ``_\b+`` is a
|
||||
length of 1 (displays as ``+``), but ``\b`` alone is simply a
|
||||
length of 0.
|
||||
|
||||
Some characters may consume more than one cell, mainly those CJK
|
||||
Unified Ideographs (Chinese, Japanese, Korean) defined by Unicode
|
||||
as half or full-width characters.
|
||||
|
||||
For example:
|
||||
|
||||
>>> from blessed import Terminal
|
||||
>>> from blessed.sequences import Sequence
|
||||
>>> term = Terminal()
|
||||
>>> msg = term.clear + term.red(u'コンニチハ')
|
||||
>>> Sequence(msg, term).length()
|
||||
10
|
||||
|
||||
.. note:: Although accounted for, strings containing sequences such
|
||||
as ``term.clear`` will not give accurate returns, it is not
|
||||
considered lengthy (a length of 0).
|
||||
"""
|
||||
# because control characters may return -1, "clip" their length to 0.
|
||||
return sum(max(wcwidth(w_char), 0) for w_char in self.padd(strip=True))
|
||||
|
||||
def strip(self, chars=None):
|
||||
"""
|
||||
Return string of sequences, leading and trailing whitespace removed.
|
||||
|
||||
:arg str chars: Remove characters in chars instead of whitespace.
|
||||
:rtype: str
|
||||
:returns: string of sequences with leading and trailing whitespace removed.
|
||||
"""
|
||||
return self.strip_seqs().strip(chars)
|
||||
|
||||
def lstrip(self, chars=None):
|
||||
"""
|
||||
Return string of all sequences and leading whitespace removed.
|
||||
|
||||
:arg str chars: Remove characters in chars instead of whitespace.
|
||||
:rtype: str
|
||||
:returns: string of sequences with leading removed.
|
||||
"""
|
||||
return self.strip_seqs().lstrip(chars)
|
||||
|
||||
def rstrip(self, chars=None):
|
||||
"""
|
||||
Return string of all sequences and trailing whitespace removed.
|
||||
|
||||
:arg str chars: Remove characters in chars instead of whitespace.
|
||||
:rtype: str
|
||||
:returns: string of sequences with trailing removed.
|
||||
"""
|
||||
return self.strip_seqs().rstrip(chars)
|
||||
|
||||
def strip_seqs(self):
|
||||
"""
|
||||
Return ``text`` stripped of only its terminal sequences.
|
||||
|
||||
:rtype: str
|
||||
:returns: Text with terminal sequences removed
|
||||
"""
|
||||
return self.padd(strip=True)
|
||||
|
||||
def padd(self, strip=False):
|
||||
"""
|
||||
Return non-destructive horizontal movement as destructive spacing.
|
||||
|
||||
:arg bool strip: Strip terminal sequences
|
||||
:rtype: str
|
||||
:returns: Text adjusted for horizontal movement
|
||||
"""
|
||||
outp = ''
|
||||
for text, cap in iter_parse(self._term, self):
|
||||
if not cap:
|
||||
outp += text
|
||||
continue
|
||||
|
||||
value = cap.horizontal_distance(text)
|
||||
if value > 0:
|
||||
outp += ' ' * value
|
||||
elif value < 0:
|
||||
outp = outp[:value]
|
||||
elif not strip:
|
||||
outp += text
|
||||
return outp
|
||||
|
||||
|
||||
def iter_parse(term, text):
|
||||
"""
|
||||
Generator yields (text, capability) for characters of ``text``.
|
||||
|
||||
value for ``capability`` may be ``None``, where ``text`` is
|
||||
:class:`str` of length 1. Otherwise, ``text`` is a full
|
||||
matching sequence of given capability.
|
||||
"""
|
||||
for match in term._caps_compiled_any.finditer(text): # pylint: disable=protected-access
|
||||
name = match.lastgroup
|
||||
value = match.group(name)
|
||||
if name == 'MISMATCH':
|
||||
yield (value, None)
|
||||
else:
|
||||
yield value, term.caps[name]
|
||||
|
||||
|
||||
def measure_length(text, term):
|
||||
"""
|
||||
.. deprecated:: 1.12.0.
|
||||
|
||||
:rtype: int
|
||||
:returns: Length of the first sequence in the string
|
||||
"""
|
||||
try:
|
||||
text, capability = next(iter_parse(term, text))
|
||||
if capability:
|
||||
return len(text)
|
||||
except StopIteration:
|
||||
return 0
|
||||
return 0
|
||||
55
venv/lib/python3.11/site-packages/blessed/sequences.pyi
Normal file
55
venv/lib/python3.11/site-packages/blessed/sequences.pyi
Normal file
@@ -0,0 +1,55 @@
|
||||
# std imports
|
||||
import textwrap
|
||||
from typing import Any, Type, Tuple, Pattern, TypeVar, Iterator, Optional, SupportsIndex
|
||||
|
||||
# local
|
||||
from .terminal import Terminal
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
class Termcap:
|
||||
name: str = ...
|
||||
pattern: str = ...
|
||||
attribute: str = ...
|
||||
def __init__(self, name: str, pattern: str, attribute: str) -> None: ...
|
||||
@property
|
||||
def named_pattern(self) -> str: ...
|
||||
@property
|
||||
def re_compiled(self) -> Pattern[str]: ...
|
||||
@property
|
||||
def will_move(self) -> bool: ...
|
||||
def horizontal_distance(self, text: str) -> int: ...
|
||||
@classmethod
|
||||
def build(
|
||||
cls,
|
||||
name: str,
|
||||
capability: str,
|
||||
attribute: str,
|
||||
nparams: int = ...,
|
||||
numeric: int = ...,
|
||||
match_grouped: bool = ...,
|
||||
match_any: bool = ...,
|
||||
match_optional: bool = ...,
|
||||
) -> "Termcap": ...
|
||||
|
||||
class SequenceTextWrapper(textwrap.TextWrapper):
|
||||
term: Terminal = ...
|
||||
def __init__(self, width: int, term: Terminal, **kwargs: Any) -> None: ...
|
||||
|
||||
class Sequence(str):
|
||||
def __new__(cls: Type[_T], sequence_text: str, term: Terminal) -> _T: ...
|
||||
def ljust(self, width: SupportsIndex, fillchar: str = ...) -> str: ...
|
||||
def rjust(self, width: SupportsIndex, fillchar: str = ...) -> str: ...
|
||||
def center(self, width: SupportsIndex, fillchar: str = ...) -> str: ...
|
||||
def truncate(self, width: SupportsIndex) -> str: ...
|
||||
def length(self) -> int: ...
|
||||
def strip(self, chars: Optional[str] = ...) -> str: ...
|
||||
def lstrip(self, chars: Optional[str] = ...) -> str: ...
|
||||
def rstrip(self, chars: Optional[str] = ...) -> str: ...
|
||||
def strip_seqs(self) -> str: ...
|
||||
def padd(self, strip: bool = ...) -> str: ...
|
||||
|
||||
def iter_parse(
|
||||
term: Terminal, text: str
|
||||
) -> Iterator[Tuple[str, Optional[Termcap]]]: ...
|
||||
def measure_length(text: str, term: Terminal) -> int: ...
|
||||
1552
venv/lib/python3.11/site-packages/blessed/terminal.py
Normal file
1552
venv/lib/python3.11/site-packages/blessed/terminal.py
Normal file
File diff suppressed because it is too large
Load Diff
108
venv/lib/python3.11/site-packages/blessed/terminal.pyi
Normal file
108
venv/lib/python3.11/site-packages/blessed/terminal.pyi
Normal file
@@ -0,0 +1,108 @@
|
||||
# std imports
|
||||
from typing import IO, Any, List, Tuple, Union, Optional, OrderedDict, SupportsIndex, ContextManager
|
||||
|
||||
# local
|
||||
from .keyboard import Keystroke
|
||||
from .sequences import Termcap
|
||||
from .formatters import (FormattingString,
|
||||
NullCallableString,
|
||||
ParameterizingString,
|
||||
FormattingOtherString)
|
||||
|
||||
HAS_TTY: bool
|
||||
|
||||
class Terminal:
|
||||
caps: OrderedDict[str, Termcap]
|
||||
errors: List[str] = ...
|
||||
def __init__(
|
||||
self,
|
||||
kind: Optional[str] = ...,
|
||||
stream: Optional[IO[str]] = ...,
|
||||
force_styling: bool = ...,
|
||||
) -> None: ...
|
||||
def __getattr__(
|
||||
self, attr: str
|
||||
) -> Union[NullCallableString, ParameterizingString, FormattingString]: ...
|
||||
@property
|
||||
def kind(self) -> str: ...
|
||||
@property
|
||||
def does_styling(self) -> bool: ...
|
||||
@property
|
||||
def is_a_tty(self) -> bool: ...
|
||||
@property
|
||||
def height(self) -> int: ...
|
||||
@property
|
||||
def width(self) -> int: ...
|
||||
@property
|
||||
def pixel_height(self) -> int: ...
|
||||
@property
|
||||
def pixel_width(self) -> int: ...
|
||||
def location(
|
||||
self, x: Optional[int] = ..., y: Optional[int] = ...
|
||||
) -> ContextManager[None]: ...
|
||||
def get_location(self, timeout: Optional[float] = ...) -> Tuple[int, int]: ...
|
||||
def get_fgcolor(self, timeout: Optional[float] = ...) -> Tuple[int, int, int]: ...
|
||||
def get_bgcolor(self, timeout: Optional[float] = ...) -> Tuple[int, int, int]: ...
|
||||
def fullscreen(self) -> ContextManager[None]: ...
|
||||
def hidden_cursor(self) -> ContextManager[None]: ...
|
||||
def move_xy(self, x: int, y: int) -> ParameterizingString: ...
|
||||
def move_yx(self, y: int, x: int) -> ParameterizingString: ...
|
||||
@property
|
||||
def move_left(self) -> FormattingOtherString: ...
|
||||
@property
|
||||
def move_right(self) -> FormattingOtherString: ...
|
||||
@property
|
||||
def move_up(self) -> FormattingOtherString: ...
|
||||
@property
|
||||
def move_down(self) -> FormattingOtherString: ...
|
||||
@property
|
||||
def color(self) -> Union[NullCallableString, ParameterizingString]: ...
|
||||
def color_rgb(self, red: int, green: int, blue: int) -> FormattingString: ...
|
||||
@property
|
||||
def on_color(self) -> Union[NullCallableString, ParameterizingString]: ...
|
||||
def on_color_rgb(self, red: int, green: int, blue: int) -> FormattingString: ...
|
||||
def formatter(self, value: str) -> Union[NullCallableString, FormattingString]: ...
|
||||
def rgb_downconvert(self, red: int, green: int, blue: int) -> int: ...
|
||||
@property
|
||||
def normal(self) -> str: ...
|
||||
def link(self, url: str, text: str, url_id: str = ...) -> str: ...
|
||||
@property
|
||||
def stream(self) -> IO[str]: ...
|
||||
@property
|
||||
def number_of_colors(self) -> int: ...
|
||||
@number_of_colors.setter
|
||||
def number_of_colors(self, value: int) -> None: ...
|
||||
@property
|
||||
def color_distance_algorithm(self) -> str: ...
|
||||
@color_distance_algorithm.setter
|
||||
def color_distance_algorithm(self, value: str) -> None: ...
|
||||
def ljust(
|
||||
self, text: str, width: Optional[SupportsIndex] = ..., fillchar: str = ...
|
||||
) -> str: ...
|
||||
def rjust(
|
||||
self, text: str, width: Optional[SupportsIndex] = ..., fillchar: str = ...
|
||||
) -> str: ...
|
||||
def center(
|
||||
self, text: str, width: Optional[SupportsIndex] = ..., fillchar: str = ...
|
||||
) -> str: ...
|
||||
def truncate(self, text: str, width: Optional[SupportsIndex] = ...) -> str: ...
|
||||
def length(self, text: str) -> int: ...
|
||||
def strip(self, text: str, chars: Optional[str] = ...) -> str: ...
|
||||
def rstrip(self, text: str, chars: Optional[str] = ...) -> str: ...
|
||||
def lstrip(self, text: str, chars: Optional[str] = ...) -> str: ...
|
||||
def strip_seqs(self, text: str) -> str: ...
|
||||
def split_seqs(self, text: str, maxsplit: int) -> List[str]: ...
|
||||
def wrap(
|
||||
self, text: str, width: Optional[int] = ..., **kwargs: Any
|
||||
) -> List[str]: ...
|
||||
def getch(self) -> str: ...
|
||||
def ungetch(self, text: str) -> None: ...
|
||||
def kbhit(self, timeout: Optional[float] = ...) -> bool: ...
|
||||
def cbreak(self) -> ContextManager[None]: ...
|
||||
def raw(self) -> ContextManager[None]: ...
|
||||
def keypad(self) -> ContextManager[None]: ...
|
||||
def inkey(
|
||||
self, timeout: Optional[float] = ..., esc_delay: float = ...
|
||||
) -> Keystroke: ...
|
||||
|
||||
class WINSZ: ...
|
||||
163
venv/lib/python3.11/site-packages/blessed/win_terminal.py
Normal file
163
venv/lib/python3.11/site-packages/blessed/win_terminal.py
Normal file
@@ -0,0 +1,163 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Module containing Windows version of :class:`Terminal`."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
# std imports
|
||||
import time
|
||||
import msvcrt # pylint: disable=import-error
|
||||
import contextlib
|
||||
|
||||
# 3rd party
|
||||
from jinxed import win32 # pylint: disable=import-error
|
||||
|
||||
# local
|
||||
from .terminal import WINSZ
|
||||
from .terminal import Terminal as _Terminal
|
||||
|
||||
|
||||
class Terminal(_Terminal):
|
||||
"""Windows subclass of :class:`Terminal`."""
|
||||
|
||||
def getch(self):
|
||||
r"""
|
||||
Read, decode, and return the next byte from the keyboard stream.
|
||||
|
||||
:rtype: unicode
|
||||
:returns: a single unicode character, or ``u''`` if a multi-byte
|
||||
sequence has not yet been fully received.
|
||||
|
||||
For versions of Windows 10.0.10586 and later, the console is expected
|
||||
to be in ENABLE_VIRTUAL_TERMINAL_INPUT mode and the default method is
|
||||
called.
|
||||
|
||||
For older versions of Windows, msvcrt.getwch() is used. If the received
|
||||
character is ``\x00`` or ``\xe0``, the next character is
|
||||
automatically retrieved.
|
||||
"""
|
||||
if win32.VTMODE_SUPPORTED:
|
||||
return super(Terminal, self).getch()
|
||||
|
||||
rtn = msvcrt.getwch()
|
||||
if rtn in ('\x00', '\xe0'):
|
||||
rtn += msvcrt.getwch()
|
||||
return rtn
|
||||
|
||||
def kbhit(self, timeout=None):
|
||||
"""
|
||||
Return whether a keypress has been detected on the keyboard.
|
||||
|
||||
This method is used by :meth:`inkey` to determine if a byte may
|
||||
be read using :meth:`getch` without blocking. This is implemented
|
||||
by wrapping msvcrt.kbhit() in a timeout.
|
||||
|
||||
:arg float timeout: When ``timeout`` is 0, this call is
|
||||
non-blocking, otherwise blocking indefinitely until keypress
|
||||
is detected when None (default). When ``timeout`` is a
|
||||
positive number, returns after ``timeout`` seconds have
|
||||
elapsed (float).
|
||||
:rtype: bool
|
||||
:returns: True if a keypress is awaiting to be read on the keyboard
|
||||
attached to this terminal.
|
||||
"""
|
||||
end = time.time() + (timeout or 0)
|
||||
while True:
|
||||
|
||||
if msvcrt.kbhit():
|
||||
return True
|
||||
|
||||
if timeout is not None and end < time.time():
|
||||
break
|
||||
|
||||
time.sleep(0.01) # Sleep to reduce CPU load
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _winsize(fd):
|
||||
"""
|
||||
Return named tuple describing size of the terminal by ``fd``.
|
||||
|
||||
:arg int fd: file descriptor queries for its window size.
|
||||
:rtype: WINSZ
|
||||
:returns: named tuple describing size of the terminal
|
||||
|
||||
WINSZ is a :class:`collections.namedtuple` instance, whose structure
|
||||
directly maps to the return value of the :const:`termios.TIOCGWINSZ`
|
||||
ioctl return value. The return parameters are:
|
||||
|
||||
- ``ws_row``: width of terminal by its number of character cells.
|
||||
- ``ws_col``: height of terminal by its number of character cells.
|
||||
- ``ws_xpixel``: width of terminal by pixels (not accurate).
|
||||
- ``ws_ypixel``: height of terminal by pixels (not accurate).
|
||||
"""
|
||||
window = win32.get_terminal_size(fd)
|
||||
return WINSZ(ws_row=window.lines, ws_col=window.columns,
|
||||
ws_xpixel=0, ws_ypixel=0)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def cbreak(self):
|
||||
"""
|
||||
Allow each keystroke to be read immediately after it is pressed.
|
||||
|
||||
This is a context manager for ``jinxed.w32.setcbreak()``.
|
||||
|
||||
.. note:: You must explicitly print any user input you would like
|
||||
displayed. If you provide any kind of editing, you must handle
|
||||
backspace and other line-editing control functions in this mode
|
||||
as well!
|
||||
|
||||
**Normally**, characters received from the keyboard cannot be read
|
||||
by Python until the *Return* key is pressed. Also known as *cooked* or
|
||||
*canonical input* mode, it allows the tty driver to provide
|
||||
line-editing before shuttling the input to your program and is the
|
||||
(implicit) default terminal mode set by most unix shells before
|
||||
executing programs.
|
||||
"""
|
||||
if self._keyboard_fd is not None:
|
||||
|
||||
filehandle = msvcrt.get_osfhandle(self._keyboard_fd)
|
||||
|
||||
# Save current terminal mode:
|
||||
save_mode = win32.get_console_mode(filehandle)
|
||||
save_line_buffered = self._line_buffered
|
||||
win32.setcbreak(filehandle)
|
||||
try:
|
||||
self._line_buffered = False
|
||||
yield
|
||||
finally:
|
||||
win32.set_console_mode(filehandle, save_mode)
|
||||
self._line_buffered = save_line_buffered
|
||||
|
||||
else:
|
||||
yield
|
||||
|
||||
@contextlib.contextmanager
|
||||
def raw(self):
|
||||
"""
|
||||
A context manager for ``jinxed.w32.setcbreak()``.
|
||||
|
||||
Although both :meth:`break` and :meth:`raw` modes allow each keystroke
|
||||
to be read immediately after it is pressed, Raw mode disables
|
||||
processing of input and output.
|
||||
|
||||
In cbreak mode, special input characters such as ``^C`` are
|
||||
interpreted by the terminal driver and excluded from the stdin stream.
|
||||
In raw mode these values are receive by the :meth:`inkey` method.
|
||||
"""
|
||||
if self._keyboard_fd is not None:
|
||||
|
||||
filehandle = msvcrt.get_osfhandle(self._keyboard_fd)
|
||||
|
||||
# Save current terminal mode:
|
||||
save_mode = win32.get_console_mode(filehandle)
|
||||
save_line_buffered = self._line_buffered
|
||||
win32.setraw(filehandle)
|
||||
try:
|
||||
self._line_buffered = False
|
||||
yield
|
||||
finally:
|
||||
win32.set_console_mode(filehandle, save_mode)
|
||||
self._line_buffered = save_line_buffered
|
||||
|
||||
else:
|
||||
yield
|
||||
11
venv/lib/python3.11/site-packages/blessed/win_terminal.pyi
Normal file
11
venv/lib/python3.11/site-packages/blessed/win_terminal.pyi
Normal file
@@ -0,0 +1,11 @@
|
||||
# std imports
|
||||
from typing import Optional, ContextManager
|
||||
|
||||
# local
|
||||
from .terminal import Terminal as _Terminal
|
||||
|
||||
class Terminal(_Terminal):
|
||||
def getch(self) -> str: ...
|
||||
def kbhit(self, timeout: Optional[float] = ...) -> bool: ...
|
||||
def cbreak(self) -> ContextManager[None]: ...
|
||||
def raw(self) -> ContextManager[None]: ...
|
||||
Reference in New Issue
Block a user