diff options
author | Nikita Slyusarev <nslus@yandex-team.com> | 2022-02-10 16:46:52 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:52 +0300 |
commit | cd77cecfc03a3eaf87816af28a33067c4f0cdb59 (patch) | |
tree | 1308e0bae862d52e0020d881fe758080437fe389 /contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal | |
parent | cdae02d225fb5b3afbb28990e79a7ac6c9125327 (diff) | |
download | ydb-cd77cecfc03a3eaf87816af28a33067c4f0cdb59.tar.gz |
Restoring authorship annotation for Nikita Slyusarev <nslus@yandex-team.com>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal')
5 files changed, 646 insertions, 646 deletions
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py index 16b7bde8f3..1b7e69fbd4 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/conemu_output.py @@ -32,8 +32,8 @@ class ConEmuOutput(object): def __getattr__(self, name): if name in ('get_size', 'get_rows_below_cursor_position', 'enable_mouse_support', 'disable_mouse_support', - 'scroll_buffer_to_prompt', 'get_win32_screen_buffer_info', - 'enable_bracketed_paste', 'disable_bracketed_paste'): + 'scroll_buffer_to_prompt', 'get_win32_screen_buffer_info', + 'enable_bracketed_paste', 'disable_bracketed_paste'): return getattr(self.win32_output, name) else: return getattr(self.vt100_output, name) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py index 74841312fa..a66afc28c6 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_input.py @@ -9,8 +9,8 @@ import six import termios import tty -from six.moves import range - +from six.moves import range + from ..keys import Keys from ..key_binding.input_processor import KeyPress @@ -93,7 +93,7 @@ ANSI_SEQUENCES = { '\x1bOF': Keys.End, '\x1b[3~': Keys.Delete, '\x1b[3;2~': Keys.ShiftDelete, # xterm, gnome-terminal. - '\x1b[3;5~': Keys.ControlDelete, # xterm, gnome-terminal. + '\x1b[3;5~': Keys.ControlDelete, # xterm, gnome-terminal. '\x1b[1~': Keys.Home, # tmux '\x1b[4~': Keys.End, # tmux '\x1b[5~': Keys.PageUp, @@ -107,11 +107,11 @@ ANSI_SEQUENCES = { '\x1bOQ': Keys.F2, '\x1bOR': Keys.F3, '\x1bOS': Keys.F4, - '\x1b[[A': Keys.F1, # Linux console. - '\x1b[[B': Keys.F2, # Linux console. - '\x1b[[C': Keys.F3, # Linux console. - '\x1b[[D': Keys.F4, # Linux console. - '\x1b[[E': Keys.F5, # Linux console. + '\x1b[[A': Keys.F1, # Linux console. + '\x1b[[B': Keys.F2, # Linux console. + '\x1b[[C': Keys.F3, # Linux console. + '\x1b[[D': Keys.F4, # Linux console. + '\x1b[[E': Keys.F5, # Linux console. '\x1b[11~': Keys.F1, # rxvt-unicode '\x1b[12~': Keys.F2, # rxvt-unicode '\x1b[13~': Keys.F3, # rxvt-unicode @@ -132,39 +132,39 @@ ANSI_SEQUENCES = { '\x1b[32~': Keys.F18, '\x1b[33~': Keys.F19, '\x1b[34~': Keys.F20, - - # Xterm - '\x1b[1;2P': Keys.F13, - '\x1b[1;2Q': Keys.F14, - # '\x1b[1;2R': Keys.F15, # Conflicts with CPR response. - '\x1b[1;2S': Keys.F16, - '\x1b[15;2~': Keys.F17, - '\x1b[17;2~': Keys.F18, - '\x1b[18;2~': Keys.F19, - '\x1b[19;2~': Keys.F20, - '\x1b[20;2~': Keys.F21, - '\x1b[21;2~': Keys.F22, - '\x1b[23;2~': Keys.F23, - '\x1b[24;2~': Keys.F24, - + + # Xterm + '\x1b[1;2P': Keys.F13, + '\x1b[1;2Q': Keys.F14, + # '\x1b[1;2R': Keys.F15, # Conflicts with CPR response. + '\x1b[1;2S': Keys.F16, + '\x1b[15;2~': Keys.F17, + '\x1b[17;2~': Keys.F18, + '\x1b[18;2~': Keys.F19, + '\x1b[19;2~': Keys.F20, + '\x1b[20;2~': Keys.F21, + '\x1b[21;2~': Keys.F22, + '\x1b[23;2~': Keys.F23, + '\x1b[24;2~': Keys.F24, + '\x1b[1;5A': Keys.ControlUp, # Cursor Mode '\x1b[1;5B': Keys.ControlDown, # Cursor Mode '\x1b[1;5C': Keys.ControlRight, # Cursor Mode '\x1b[1;5D': Keys.ControlLeft, # Cursor Mode - '\x1b[1;2A': Keys.ShiftUp, - '\x1b[1;2B': Keys.ShiftDown, - '\x1b[1;2C': Keys.ShiftRight, - '\x1b[1;2D': Keys.ShiftLeft, - - # Tmux sends following keystrokes when control+arrow is pressed, but for - # Emacs ansi-term sends the same sequences for normal arrow keys. Consider - # it a normal arrow press, because that's more important. - '\x1bOA': Keys.Up, - '\x1bOB': Keys.Down, - '\x1bOC': Keys.Right, - '\x1bOD': Keys.Left, - + '\x1b[1;2A': Keys.ShiftUp, + '\x1b[1;2B': Keys.ShiftDown, + '\x1b[1;2C': Keys.ShiftRight, + '\x1b[1;2D': Keys.ShiftLeft, + + # Tmux sends following keystrokes when control+arrow is pressed, but for + # Emacs ansi-term sends the same sequences for normal arrow keys. Consider + # it a normal arrow press, because that's more important. + '\x1bOA': Keys.Up, + '\x1bOB': Keys.Down, + '\x1bOC': Keys.Right, + '\x1bOD': Keys.Left, + '\x1b[5A': Keys.ControlUp, '\x1b[5B': Keys.ControlDown, '\x1b[5C': Keys.ControlRight, @@ -188,11 +188,11 @@ ANSI_SEQUENCES = { '\x1b[1;3C': (Keys.Escape, Keys.Right), '\x1b[1;3A': (Keys.Escape, Keys.Up), '\x1b[1;3B': (Keys.Escape, Keys.Down), - - # Sequences generated by numpad 5. Not sure what it means. (It doesn't - # appear in 'infocmp'. Just ignore. - '\x1b[E': Keys.Ignore, # Xterm. - '\x1b[G': Keys.Ignore, # Linux console. + + # Sequences generated by numpad 5. Not sure what it means. (It doesn't + # appear in 'infocmp'. Just ignore. + '\x1b[E': Keys.Ignore, # Xterm. + '\x1b[G': Keys.Ignore, # Linux console. } @@ -367,11 +367,11 @@ class InputStream(object): # Quit bracketed paste mode and handle remaining input. self._in_bracketed_paste = False - remaining = self._paste_buffer[end_index + len(end_mark):] + remaining = self._paste_buffer[end_index + len(end_mark):] self._paste_buffer = '' - self.feed(remaining) - + self.feed(remaining) + # Handle normal input character by character. else: for i, c in enumerate(data): @@ -383,16 +383,16 @@ class InputStream(object): else: # Replace \r by \n. (Some clients send \r instead of \n # when enter is pressed. E.g. telnet and some other - # terminals.) - - # XXX: We should remove this in a future version. It *is* - # now possible to recognise the difference. - # (We remove ICRNL/INLCR/IGNCR below.) - # However, this breaks IPython and maybe other applications, - # because they bind ControlJ (\n) for handling the Enter key. - - # When this is removed, replace Enter=ControlJ by - # Enter=ControlM in keys.py. + # terminals.) + + # XXX: We should remove this in a future version. It *is* + # now possible to recognise the difference. + # (We remove ICRNL/INLCR/IGNCR below.) + # However, this breaks IPython and maybe other applications, + # because they bind ControlJ (\n) for handling the Enter key. + + # When this is removed, replace Enter=ControlJ by + # Enter=ControlM in keys.py. if c == '\r': c = '\n' self._input_parser.send(c) @@ -425,40 +425,40 @@ class raw_mode(object): with raw_mode(stdin): ''' the pseudo-terminal stdin is now used in raw mode ''' - - We ignore errors when executing `tcgetattr` fails. + + We ignore errors when executing `tcgetattr` fails. """ - # There are several reasons for ignoring errors: - # 1. To avoid the "Inappropriate ioctl for device" crash if somebody would - # execute this code (In a Python REPL, for instance): - # - # import os; f = open(os.devnull); os.dup2(f.fileno(), 0) - # - # The result is that the eventloop will stop correctly, because it has - # to logic to quit when stdin is closed. However, we should not fail at - # this point. See: - # https://github.com/jonathanslenders/python-prompt-toolkit/pull/393 - # https://github.com/jonathanslenders/python-prompt-toolkit/issues/392 - - # 2. Related, when stdin is an SSH pipe, and no full terminal was allocated. - # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/165 + # There are several reasons for ignoring errors: + # 1. To avoid the "Inappropriate ioctl for device" crash if somebody would + # execute this code (In a Python REPL, for instance): + # + # import os; f = open(os.devnull); os.dup2(f.fileno(), 0) + # + # The result is that the eventloop will stop correctly, because it has + # to logic to quit when stdin is closed. However, we should not fail at + # this point. See: + # https://github.com/jonathanslenders/python-prompt-toolkit/pull/393 + # https://github.com/jonathanslenders/python-prompt-toolkit/issues/392 + + # 2. Related, when stdin is an SSH pipe, and no full terminal was allocated. + # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/165 def __init__(self, fileno): self.fileno = fileno - try: - self.attrs_before = termios.tcgetattr(fileno) - except termios.error: - # Ignore attribute errors. - self.attrs_before = None + try: + self.attrs_before = termios.tcgetattr(fileno) + except termios.error: + # Ignore attribute errors. + self.attrs_before = None def __enter__(self): # NOTE: On os X systems, using pty.setraw() fails. Therefor we are using this: - try: - newattr = termios.tcgetattr(self.fileno) - except termios.error: - pass - else: - newattr[tty.LFLAG] = self._patch_lflag(newattr[tty.LFLAG]) - newattr[tty.IFLAG] = self._patch_iflag(newattr[tty.IFLAG]) + try: + newattr = termios.tcgetattr(self.fileno) + except termios.error: + pass + else: + newattr[tty.LFLAG] = self._patch_lflag(newattr[tty.LFLAG]) + newattr[tty.IFLAG] = self._patch_iflag(newattr[tty.IFLAG]) # VMIN defines the number of characters read at a time in # non-canonical mode. It seems to default to 1 on Linux, but on @@ -467,54 +467,54 @@ class raw_mode(object): # defaults to ASCII EOT = Ctrl-D = 4.) newattr[tty.CC][termios.VMIN] = 1 - termios.tcsetattr(self.fileno, termios.TCSANOW, newattr) + termios.tcsetattr(self.fileno, termios.TCSANOW, newattr) - # Put the terminal in cursor mode. (Instead of application mode.) - os.write(self.fileno, b'\x1b[?1l') + # Put the terminal in cursor mode. (Instead of application mode.) + os.write(self.fileno, b'\x1b[?1l') - @classmethod - def _patch_lflag(cls, attrs): + @classmethod + def _patch_lflag(cls, attrs): return attrs & ~(termios.ECHO | termios.ICANON | termios.IEXTEN | termios.ISIG) - @classmethod - def _patch_iflag(cls, attrs): - return attrs & ~( - # Disable XON/XOFF flow control on output and input. - # (Don't capture Ctrl-S and Ctrl-Q.) - # Like executing: "stty -ixon." - termios.IXON | termios.IXOFF | - - # Don't translate carriage return into newline on input. - termios.ICRNL | termios.INLCR | termios.IGNCR - ) - + @classmethod + def _patch_iflag(cls, attrs): + return attrs & ~( + # Disable XON/XOFF flow control on output and input. + # (Don't capture Ctrl-S and Ctrl-Q.) + # Like executing: "stty -ixon." + termios.IXON | termios.IXOFF | + + # Don't translate carriage return into newline on input. + termios.ICRNL | termios.INLCR | termios.IGNCR + ) + def __exit__(self, *a, **kw): - if self.attrs_before is not None: - try: - termios.tcsetattr(self.fileno, termios.TCSANOW, self.attrs_before) - except termios.error: - pass + if self.attrs_before is not None: + try: + termios.tcsetattr(self.fileno, termios.TCSANOW, self.attrs_before) + except termios.error: + pass - # # Put the terminal in application mode. - # self._stdout.write('\x1b[?1h') + # # Put the terminal in application mode. + # self._stdout.write('\x1b[?1h') class cooked_mode(raw_mode): """ - The opposide of ``raw_mode``, used when we need cooked mode inside a - `raw_mode` block. Used in `CommandLineInterface.run_in_terminal`.:: + The opposide of ``raw_mode``, used when we need cooked mode inside a + `raw_mode` block. Used in `CommandLineInterface.run_in_terminal`.:: with cooked_mode(stdin): ''' the pseudo-terminal stdin is now used in cooked mode. ''' """ - @classmethod - def _patch_lflag(cls, attrs): + @classmethod + def _patch_lflag(cls, attrs): return attrs | (termios.ECHO | termios.ICANON | termios.IEXTEN | termios.ISIG) - - @classmethod - def _patch_iflag(cls, attrs): - # Turn the ICRNL flag back on. (Without this, calling `input()` in - # run_in_terminal doesn't work and displays ^M instead. Ptpython - # evaluates commands using `run_in_terminal`, so it's important that - # they translate ^M back into ^J.) - return attrs | termios.ICRNL + + @classmethod + def _patch_iflag(cls, attrs): + # Turn the ICRNL flag back on. (Without this, calling `input()` in + # run_in_terminal doesn't work and displays ^M instead. Ptpython + # evaluates commands using `run_in_terminal`, so it's important that + # they translate ^M back into ^J.) + return attrs | termios.ICRNL diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py index b800aaacec..f9ebbcbb24 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/vt100_output.py @@ -1,22 +1,22 @@ -""" -Output for vt100 terminals. - -A lot of thanks, regarding outputting of colors, goes to the Pygments project: -(We don't rely on Pygments anymore, because many things are very custom, and -everything has been highly optimized.) -http://pygments.org/ -""" +""" +Output for vt100 terminals. + +A lot of thanks, regarding outputting of colors, goes to the Pygments project: +(We don't rely on Pygments anymore, because many things are very custom, and +everything has been highly optimized.) +http://pygments.org/ +""" from __future__ import unicode_literals -from prompt_toolkit.filters import to_simple_filter, Condition +from prompt_toolkit.filters import to_simple_filter, Condition from prompt_toolkit.layout.screen import Size from prompt_toolkit.renderer import Output from prompt_toolkit.styles import ANSI_COLOR_NAMES -from six.moves import range +from six.moves import range import array import errno -import os +import os import six __all__ = ( @@ -25,219 +25,219 @@ __all__ = ( FG_ANSI_COLORS = { - 'ansidefault': 39, + 'ansidefault': 39, # Low intensity. 'ansiblack': 30, - 'ansidarkred': 31, - 'ansidarkgreen': 32, - 'ansibrown': 33, - 'ansidarkblue': 34, - 'ansipurple': 35, - 'ansiteal': 36, + 'ansidarkred': 31, + 'ansidarkgreen': 32, + 'ansibrown': 33, + 'ansidarkblue': 34, + 'ansipurple': 35, + 'ansiteal': 36, 'ansilightgray': 37, # High intensity. 'ansidarkgray': 90, - 'ansired': 91, - 'ansigreen': 92, - 'ansiyellow': 93, - 'ansiblue': 94, - 'ansifuchsia': 95, - 'ansiturquoise': 96, + 'ansired': 91, + 'ansigreen': 92, + 'ansiyellow': 93, + 'ansiblue': 94, + 'ansifuchsia': 95, + 'ansiturquoise': 96, 'ansiwhite': 97, } BG_ANSI_COLORS = { - 'ansidefault': 49, + 'ansidefault': 49, # Low intensity. 'ansiblack': 40, - 'ansidarkred': 41, - 'ansidarkgreen': 42, - 'ansibrown': 43, - 'ansidarkblue': 44, - 'ansipurple': 45, - 'ansiteal': 46, + 'ansidarkred': 41, + 'ansidarkgreen': 42, + 'ansibrown': 43, + 'ansidarkblue': 44, + 'ansipurple': 45, + 'ansiteal': 46, 'ansilightgray': 47, # High intensity. 'ansidarkgray': 100, - 'ansired': 101, - 'ansigreen': 102, - 'ansiyellow': 103, - 'ansiblue': 104, - 'ansifuchsia': 105, - 'ansiturquoise': 106, + 'ansired': 101, + 'ansigreen': 102, + 'ansiyellow': 103, + 'ansiblue': 104, + 'ansifuchsia': 105, + 'ansiturquoise': 106, 'ansiwhite': 107, } - -ANSI_COLORS_TO_RGB = { - 'ansidefault': (0x00, 0x00, 0x00), # Don't use, 'default' doesn't really have a value. - 'ansiblack': (0x00, 0x00, 0x00), - 'ansidarkgray': (0x7f, 0x7f, 0x7f), - 'ansiwhite': (0xff, 0xff, 0xff), - 'ansilightgray': (0xe5, 0xe5, 0xe5), - - # Low intensity. - 'ansidarkred': (0xcd, 0x00, 0x00), - 'ansidarkgreen': (0x00, 0xcd, 0x00), - 'ansibrown': (0xcd, 0xcd, 0x00), - 'ansidarkblue': (0x00, 0x00, 0xcd), - 'ansipurple': (0xcd, 0x00, 0xcd), - 'ansiteal': (0x00, 0xcd, 0xcd), - - # High intensity. - 'ansired': (0xff, 0x00, 0x00), - 'ansigreen': (0x00, 0xff, 0x00), - 'ansiyellow': (0xff, 0xff, 0x00), - 'ansiblue': (0x00, 0x00, 0xff), - 'ansifuchsia': (0xff, 0x00, 0xff), - 'ansiturquoise': (0x00, 0xff, 0xff), -} - - + +ANSI_COLORS_TO_RGB = { + 'ansidefault': (0x00, 0x00, 0x00), # Don't use, 'default' doesn't really have a value. + 'ansiblack': (0x00, 0x00, 0x00), + 'ansidarkgray': (0x7f, 0x7f, 0x7f), + 'ansiwhite': (0xff, 0xff, 0xff), + 'ansilightgray': (0xe5, 0xe5, 0xe5), + + # Low intensity. + 'ansidarkred': (0xcd, 0x00, 0x00), + 'ansidarkgreen': (0x00, 0xcd, 0x00), + 'ansibrown': (0xcd, 0xcd, 0x00), + 'ansidarkblue': (0x00, 0x00, 0xcd), + 'ansipurple': (0xcd, 0x00, 0xcd), + 'ansiteal': (0x00, 0xcd, 0xcd), + + # High intensity. + 'ansired': (0xff, 0x00, 0x00), + 'ansigreen': (0x00, 0xff, 0x00), + 'ansiyellow': (0xff, 0xff, 0x00), + 'ansiblue': (0x00, 0x00, 0xff), + 'ansifuchsia': (0xff, 0x00, 0xff), + 'ansiturquoise': (0x00, 0xff, 0xff), +} + + assert set(FG_ANSI_COLORS) == set(ANSI_COLOR_NAMES) assert set(BG_ANSI_COLORS) == set(ANSI_COLOR_NAMES) -assert set(ANSI_COLORS_TO_RGB) == set(ANSI_COLOR_NAMES) - - -def _get_closest_ansi_color(r, g, b, exclude=()): - """ - Find closest ANSI color. Return it by name. - - :param r: Red (Between 0 and 255.) - :param g: Green (Between 0 and 255.) - :param b: Blue (Between 0 and 255.) - :param exclude: A tuple of color names to exclude. (E.g. ``('ansired', )``.) - """ - assert isinstance(exclude, tuple) - - # When we have a bit of saturation, avoid the gray-like colors, otherwise, - # too often the distance to the gray color is less. - saturation = abs(r - g) + abs(g - b) + abs(b - r) # Between 0..510 - - if saturation > 30: - exclude += ('ansilightgray', 'ansidarkgray', 'ansiwhite', 'ansiblack') - - # Take the closest color. - # (Thanks to Pygments for this part.) - distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff) - match = 'ansidefault' - - for name, (r2, g2, b2) in ANSI_COLORS_TO_RGB.items(): - if name != 'ansidefault' and name not in exclude: - d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2 - - if d < distance: - match = name - distance = d - - return match - - -class _16ColorCache(dict): - """ - Cache which maps (r, g, b) tuples to 16 ansi colors. - - :param bg: Cache for background colors, instead of foreground. - """ - def __init__(self, bg=False): - assert isinstance(bg, bool) - self.bg = bg - - def get_code(self, value, exclude=()): - """ - Return a (ansi_code, ansi_name) tuple. (E.g. ``(44, 'ansiblue')``.) for - a given (r,g,b) value. - """ - key = (value, exclude) - if key not in self: - self[key] = self._get(value, exclude) - return self[key] - - def _get(self, value, exclude=()): - r, g, b = value - match = _get_closest_ansi_color(r, g, b, exclude=exclude) - - # Turn color name into code. - if self.bg: - code = BG_ANSI_COLORS[match] - else: - code = FG_ANSI_COLORS[match] - - self[value] = code - return code, match - - -class _256ColorCache(dict): - """ - Cach which maps (r, g, b) tuples to 256 colors. - """ - def __init__(self): - # Build color table. - colors = [] - - # colors 0..15: 16 basic colors - colors.append((0x00, 0x00, 0x00)) # 0 - colors.append((0xcd, 0x00, 0x00)) # 1 - colors.append((0x00, 0xcd, 0x00)) # 2 - colors.append((0xcd, 0xcd, 0x00)) # 3 - colors.append((0x00, 0x00, 0xee)) # 4 - colors.append((0xcd, 0x00, 0xcd)) # 5 - colors.append((0x00, 0xcd, 0xcd)) # 6 - colors.append((0xe5, 0xe5, 0xe5)) # 7 - colors.append((0x7f, 0x7f, 0x7f)) # 8 - colors.append((0xff, 0x00, 0x00)) # 9 - colors.append((0x00, 0xff, 0x00)) # 10 - colors.append((0xff, 0xff, 0x00)) # 11 - colors.append((0x5c, 0x5c, 0xff)) # 12 - colors.append((0xff, 0x00, 0xff)) # 13 - colors.append((0x00, 0xff, 0xff)) # 14 - colors.append((0xff, 0xff, 0xff)) # 15 - - # colors 16..232: the 6x6x6 color cube - valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff) - - for i in range(217): - r = valuerange[(i // 36) % 6] - g = valuerange[(i // 6) % 6] - b = valuerange[i % 6] - colors.append((r, g, b)) - - # colors 233..253: grayscale - for i in range(1, 22): - v = 8 + i * 10 - colors.append((v, v, v)) - - self.colors = colors - - def __missing__(self, value): - r, g, b = value - - # Find closest color. - # (Thanks to Pygments for this!) - distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff) - match = 0 - - for i, (r2, g2, b2) in enumerate(self.colors): - d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2 - - if d < distance: - match = i - distance = d - - # Turn color name into code. - self[value] = match - return match - - -_16_fg_colors = _16ColorCache(bg=False) -_16_bg_colors = _16ColorCache(bg=True) -_256_colors = _256ColorCache() - - +assert set(ANSI_COLORS_TO_RGB) == set(ANSI_COLOR_NAMES) + + +def _get_closest_ansi_color(r, g, b, exclude=()): + """ + Find closest ANSI color. Return it by name. + + :param r: Red (Between 0 and 255.) + :param g: Green (Between 0 and 255.) + :param b: Blue (Between 0 and 255.) + :param exclude: A tuple of color names to exclude. (E.g. ``('ansired', )``.) + """ + assert isinstance(exclude, tuple) + + # When we have a bit of saturation, avoid the gray-like colors, otherwise, + # too often the distance to the gray color is less. + saturation = abs(r - g) + abs(g - b) + abs(b - r) # Between 0..510 + + if saturation > 30: + exclude += ('ansilightgray', 'ansidarkgray', 'ansiwhite', 'ansiblack') + + # Take the closest color. + # (Thanks to Pygments for this part.) + distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff) + match = 'ansidefault' + + for name, (r2, g2, b2) in ANSI_COLORS_TO_RGB.items(): + if name != 'ansidefault' and name not in exclude: + d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2 + + if d < distance: + match = name + distance = d + + return match + + +class _16ColorCache(dict): + """ + Cache which maps (r, g, b) tuples to 16 ansi colors. + + :param bg: Cache for background colors, instead of foreground. + """ + def __init__(self, bg=False): + assert isinstance(bg, bool) + self.bg = bg + + def get_code(self, value, exclude=()): + """ + Return a (ansi_code, ansi_name) tuple. (E.g. ``(44, 'ansiblue')``.) for + a given (r,g,b) value. + """ + key = (value, exclude) + if key not in self: + self[key] = self._get(value, exclude) + return self[key] + + def _get(self, value, exclude=()): + r, g, b = value + match = _get_closest_ansi_color(r, g, b, exclude=exclude) + + # Turn color name into code. + if self.bg: + code = BG_ANSI_COLORS[match] + else: + code = FG_ANSI_COLORS[match] + + self[value] = code + return code, match + + +class _256ColorCache(dict): + """ + Cach which maps (r, g, b) tuples to 256 colors. + """ + def __init__(self): + # Build color table. + colors = [] + + # colors 0..15: 16 basic colors + colors.append((0x00, 0x00, 0x00)) # 0 + colors.append((0xcd, 0x00, 0x00)) # 1 + colors.append((0x00, 0xcd, 0x00)) # 2 + colors.append((0xcd, 0xcd, 0x00)) # 3 + colors.append((0x00, 0x00, 0xee)) # 4 + colors.append((0xcd, 0x00, 0xcd)) # 5 + colors.append((0x00, 0xcd, 0xcd)) # 6 + colors.append((0xe5, 0xe5, 0xe5)) # 7 + colors.append((0x7f, 0x7f, 0x7f)) # 8 + colors.append((0xff, 0x00, 0x00)) # 9 + colors.append((0x00, 0xff, 0x00)) # 10 + colors.append((0xff, 0xff, 0x00)) # 11 + colors.append((0x5c, 0x5c, 0xff)) # 12 + colors.append((0xff, 0x00, 0xff)) # 13 + colors.append((0x00, 0xff, 0xff)) # 14 + colors.append((0xff, 0xff, 0xff)) # 15 + + # colors 16..232: the 6x6x6 color cube + valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff) + + for i in range(217): + r = valuerange[(i // 36) % 6] + g = valuerange[(i // 6) % 6] + b = valuerange[i % 6] + colors.append((r, g, b)) + + # colors 233..253: grayscale + for i in range(1, 22): + v = 8 + i * 10 + colors.append((v, v, v)) + + self.colors = colors + + def __missing__(self, value): + r, g, b = value + + # Find closest color. + # (Thanks to Pygments for this!) + distance = 257*257*3 # "infinity" (>distance from #000000 to #ffffff) + match = 0 + + for i, (r2, g2, b2) in enumerate(self.colors): + d = (r - r2) ** 2 + (g - g2) ** 2 + (b - b2) ** 2 + + if d < distance: + match = i + distance = d + + # Turn color name into code. + self[value] = match + return match + + +_16_fg_colors = _16ColorCache(bg=False) +_16_bg_colors = _16ColorCache(bg=True) +_256_colors = _256ColorCache() + + class _EscapeCodeCache(dict): """ Cache for VT100 escape codes. It maps @@ -245,17 +245,17 @@ class _EscapeCodeCache(dict): :param true_color: When True, use 24bit colors instead of 256 colors. """ - def __init__(self, true_color=False, ansi_colors_only=False): + def __init__(self, true_color=False, ansi_colors_only=False): assert isinstance(true_color, bool) self.true_color = true_color - self.ansi_colors_only = to_simple_filter(ansi_colors_only) + self.ansi_colors_only = to_simple_filter(ansi_colors_only) def __missing__(self, attrs): fgcolor, bgcolor, bold, underline, italic, blink, reverse = attrs parts = [] - parts.extend(self._colors_to_code(fgcolor, bgcolor)) - + parts.extend(self._colors_to_code(fgcolor, bgcolor)) + if bold: parts.append('1') if italic: @@ -275,72 +275,72 @@ class _EscapeCodeCache(dict): self[attrs] = result return result - def _color_name_to_rgb(self, color): - " Turn 'ffffff', into (0xff, 0xff, 0xff). " - try: - rgb = int(color, 16) - except ValueError: - raise - else: + def _color_name_to_rgb(self, color): + " Turn 'ffffff', into (0xff, 0xff, 0xff). " + try: + rgb = int(color, 16) + except ValueError: + raise + else: r = (rgb >> 16) & 0xff g = (rgb >> 8) & 0xff b = rgb & 0xff - return r, g, b - - def _colors_to_code(self, fg_color, bg_color): - " Return a tuple with the vt100 values that represent this color. " - # When requesting ANSI colors only, and both fg/bg color were converted - # to ANSI, ensure that the foreground and background color are not the - # same. (Unless they were explicitely defined to be the same color.) - fg_ansi = [()] - - def get(color, bg): - table = BG_ANSI_COLORS if bg else FG_ANSI_COLORS - - if color is None: - return () - - # 16 ANSI colors. (Given by name.) - elif color in table: - return (table[color], ) - - # RGB colors. (Defined as 'ffffff'.) - else: - try: - rgb = self._color_name_to_rgb(color) - except ValueError: - return () - - # When only 16 colors are supported, use that. - if self.ansi_colors_only(): - if bg: # Background. - if fg_color != bg_color: - exclude = (fg_ansi[0], ) - else: - exclude = () - code, name = _16_bg_colors.get_code(rgb, exclude=exclude) - return (code, ) - else: # Foreground. - code, name = _16_fg_colors.get_code(rgb) - fg_ansi[0] = name - return (code, ) - - # True colors. (Only when this feature is enabled.) - elif self.true_color: - r, g, b = rgb - return (48 if bg else 38, 2, r, g, b) - - # 256 RGB colors. - else: - return (48 if bg else 38, 5, _256_colors[rgb]) - - result = [] - result.extend(get(fg_color, False)) - result.extend(get(bg_color, True)) - - return map(six.text_type, result) - - + return r, g, b + + def _colors_to_code(self, fg_color, bg_color): + " Return a tuple with the vt100 values that represent this color. " + # When requesting ANSI colors only, and both fg/bg color were converted + # to ANSI, ensure that the foreground and background color are not the + # same. (Unless they were explicitely defined to be the same color.) + fg_ansi = [()] + + def get(color, bg): + table = BG_ANSI_COLORS if bg else FG_ANSI_COLORS + + if color is None: + return () + + # 16 ANSI colors. (Given by name.) + elif color in table: + return (table[color], ) + + # RGB colors. (Defined as 'ffffff'.) + else: + try: + rgb = self._color_name_to_rgb(color) + except ValueError: + return () + + # When only 16 colors are supported, use that. + if self.ansi_colors_only(): + if bg: # Background. + if fg_color != bg_color: + exclude = (fg_ansi[0], ) + else: + exclude = () + code, name = _16_bg_colors.get_code(rgb, exclude=exclude) + return (code, ) + else: # Foreground. + code, name = _16_fg_colors.get_code(rgb) + fg_ansi[0] = name + return (code, ) + + # True colors. (Only when this feature is enabled.) + elif self.true_color: + r, g, b = rgb + return (48 if bg else 38, 2, r, g, b) + + # 256 RGB colors. + else: + return (48 if bg else 38, 5, _256_colors[rgb]) + + result = [] + result.extend(get(fg_color, False)) + result.extend(get(bg_color, True)) + + return map(six.text_type, result) + + def _get_size(fileno): # Thanks to fabric (fabfile.org), and # http://sqizit.bartletts.id.au/2011/02/14/pseudo-terminals-in-python/ @@ -356,13 +356,13 @@ def _get_size(fileno): import termios # Buffer for the C call - buf = array.array(b'h' if six.PY2 else u'h', [0, 0, 0, 0]) + buf = array.array(b'h' if six.PY2 else u'h', [0, 0, 0, 0]) # Do TIOCGWINSZ (Get) - # Note: We should not pass 'True' as a fourth parameter to 'ioctl'. (True - # is the default.) This causes segmentation faults on some systems. - # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/364 - fcntl.ioctl(fileno, termios.TIOCGWINSZ, buf) + # Note: We should not pass 'True' as a fourth parameter to 'ioctl'. (True + # is the default.) This causes segmentation faults on some systems. + # See: https://github.com/jonathanslenders/python-prompt-toolkit/pull/364 + fcntl.ioctl(fileno, termios.TIOCGWINSZ, buf) # Return rows, cols return buf[0], buf[1] @@ -371,74 +371,74 @@ def _get_size(fileno): class Vt100_Output(Output): """ :param get_size: A callable which returns the `Size` of the output terminal. - :param stdout: Any object with has a `write` and `flush` method + an 'encoding' property. + :param stdout: Any object with has a `write` and `flush` method + an 'encoding' property. :param true_color: Use 24bit color instead of 256 colors. (Can be a :class:`SimpleFilter`.) - When `ansi_colors_only` is set, only 16 colors are used. - :param ansi_colors_only: Restrict to 16 ANSI colors only. - :param term: The terminal environment variable. (xterm, xterm-256color, linux, ...) - :param write_binary: Encode the output before writing it. If `True` (the - default), the `stdout` object is supposed to expose an `encoding` attribute. + When `ansi_colors_only` is set, only 16 colors are used. + :param ansi_colors_only: Restrict to 16 ANSI colors only. + :param term: The terminal environment variable. (xterm, xterm-256color, linux, ...) + :param write_binary: Encode the output before writing it. If `True` (the + default), the `stdout` object is supposed to expose an `encoding` attribute. """ - def __init__(self, stdout, get_size, true_color=False, - ansi_colors_only=None, term=None, write_binary=True): - assert callable(get_size) - assert term is None or isinstance(term, six.text_type) - assert all(hasattr(stdout, a) for a in ('write', 'flush')) - - if write_binary: - assert hasattr(stdout, 'encoding') - + def __init__(self, stdout, get_size, true_color=False, + ansi_colors_only=None, term=None, write_binary=True): + assert callable(get_size) + assert term is None or isinstance(term, six.text_type) + assert all(hasattr(stdout, a) for a in ('write', 'flush')) + + if write_binary: + assert hasattr(stdout, 'encoding') + self._buffer = [] self.stdout = stdout - self.write_binary = write_binary + self.write_binary = write_binary self.get_size = get_size self.true_color = to_simple_filter(true_color) - self.term = term or 'xterm' - - # ANSI colors only? - if ansi_colors_only is None: - # When not given, use the following default. - ANSI_COLORS_ONLY = bool(os.environ.get( - 'PROMPT_TOOLKIT_ANSI_COLORS_ONLY', False)) - - @Condition - def ansi_colors_only(): - return ANSI_COLORS_ONLY or term in ('linux', 'eterm-color') - else: - ansi_colors_only = to_simple_filter(ansi_colors_only) - - self.ansi_colors_only = ansi_colors_only - - # Cache for escape codes. - self._escape_code_cache = _EscapeCodeCache(ansi_colors_only=ansi_colors_only) - self._escape_code_cache_true_color = _EscapeCodeCache( - true_color=True, ansi_colors_only=ansi_colors_only) - + self.term = term or 'xterm' + + # ANSI colors only? + if ansi_colors_only is None: + # When not given, use the following default. + ANSI_COLORS_ONLY = bool(os.environ.get( + 'PROMPT_TOOLKIT_ANSI_COLORS_ONLY', False)) + + @Condition + def ansi_colors_only(): + return ANSI_COLORS_ONLY or term in ('linux', 'eterm-color') + else: + ansi_colors_only = to_simple_filter(ansi_colors_only) + + self.ansi_colors_only = ansi_colors_only + + # Cache for escape codes. + self._escape_code_cache = _EscapeCodeCache(ansi_colors_only=ansi_colors_only) + self._escape_code_cache_true_color = _EscapeCodeCache( + true_color=True, ansi_colors_only=ansi_colors_only) + @classmethod - def from_pty(cls, stdout, true_color=False, ansi_colors_only=None, term=None): + def from_pty(cls, stdout, true_color=False, ansi_colors_only=None, term=None): """ Create an Output class from a pseudo terminal. (This will take the dimensions by reading the pseudo terminal attributes.) """ - assert stdout.isatty() + assert stdout.isatty() def get_size(): rows, columns = _get_size(stdout.fileno()) # If terminal (incorrectly) reports its size as 0, pick a reasonable default. # See https://github.com/ipython/ipython/issues/10071 return Size(rows=(rows or 24), columns=(columns or 80)) - return cls(stdout, get_size, true_color=true_color, - ansi_colors_only=ansi_colors_only, term=term) - - def fileno(self): - " Return file descriptor. " - return self.stdout.fileno() - - def encoding(self): - " Return encoding used for stdout. " - return self.stdout.encoding - + return cls(stdout, get_size, true_color=true_color, + ansi_colors_only=ansi_colors_only, term=term) + + def fileno(self): + " Return file descriptor. " + return self.stdout.fileno() + + def encoding(self): + " Return encoding used for stdout. " + return self.stdout.encoding + def write_raw(self, data): """ Write raw data to output. @@ -456,8 +456,8 @@ class Vt100_Output(Output): """ Set terminal title. """ - if self.term not in ('linux', 'eterm-color'): # Not supported by the Linux console. - self.write_raw('\x1b]2;%s\x07' % title.replace('\x1b', '').replace('\x07', '')) + if self.term not in ('linux', 'eterm-color'): # Not supported by the Linux console. + self.write_raw('\x1b]2;%s\x07' % title.replace('\x1b', '').replace('\x07', '')) def clear_title(self): self.set_title('') @@ -514,10 +514,10 @@ class Vt100_Output(Output): :param attrs: `Attrs` instance. """ - if self.true_color() and not self.ansi_colors_only(): - self.write_raw(self._escape_code_cache_true_color[attrs]) + if self.true_color() and not self.ansi_colors_only(): + self.write_raw(self._escape_code_cache_true_color[attrs]) else: - self.write_raw(self._escape_code_cache[attrs]) + self.write_raw(self._escape_code_cache[attrs]) def disable_autowrap(self): self.write_raw('\x1b[?7l') @@ -537,7 +537,7 @@ class Vt100_Output(Output): def cursor_up(self, amount): if amount == 0: - pass + pass elif amount == 1: self.write_raw('\x1b[A') else: @@ -545,7 +545,7 @@ class Vt100_Output(Output): def cursor_down(self, amount): if amount == 0: - pass + pass elif amount == 1: # Note: Not the same as '\n', '\n' can cause the window content to # scroll. @@ -555,7 +555,7 @@ class Vt100_Output(Output): def cursor_forward(self, amount): if amount == 0: - pass + pass elif amount == 1: self.write_raw('\x1b[C') else: @@ -563,7 +563,7 @@ class Vt100_Output(Output): def cursor_backward(self, amount): if amount == 0: - pass + pass elif amount == 1: self.write_raw('\b') # '\x1b[D' else: @@ -590,11 +590,11 @@ class Vt100_Output(Output): # UnicodeEncodeError crashes. E.g. u'\xb7' does not appear in 'ascii'.) # My Arch Linux installation of july 2015 reported 'ANSI_X3.4-1968' # for sys.stdout.encoding in xterm. - if self.write_binary: - if hasattr(self.stdout, 'buffer'): - out = self.stdout.buffer # Py3. - else: - out = self.stdout + if self.write_binary: + if hasattr(self.stdout, 'buffer'): + out = self.stdout.buffer # Py3. + else: + out = self.stdout out.write(data.encode(self.stdout.encoding or 'utf-8', 'replace')) else: self.stdout.write(data) diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py index 410e5fa517..74a7decd61 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_input.py @@ -1,18 +1,18 @@ -from __future__ import unicode_literals +from __future__ import unicode_literals from ctypes import windll, pointer from ctypes.wintypes import DWORD, HANDLE -from six.moves import range +from six.moves import range from prompt_toolkit.key_binding.input_processor import KeyPress from prompt_toolkit.keys import Keys -from prompt_toolkit.mouse_events import MouseEventType +from prompt_toolkit.mouse_events import MouseEventType from prompt_toolkit.win32_types import EventTypes, KEY_EVENT_RECORD, MOUSE_EVENT_RECORD, INPUT_RECORD, STD_INPUT_HANDLE -import msvcrt -import os -import sys -import six - +import msvcrt +import os +import sys +import six + __all__ = ( 'ConsoleInputReader', 'raw_mode', @@ -21,10 +21,10 @@ __all__ = ( class ConsoleInputReader(object): - """ - :param recognize_paste: When True, try to discover paste actions and turn - the event into a BracketedPaste. - """ + """ + :param recognize_paste: When True, try to discover paste actions and turn + the event into a BracketedPaste. + """ # Keys with character data. mappings = { b'\x1b': Keys.Escape, @@ -104,70 +104,70 @@ class ConsoleInputReader(object): LEFT_CTRL_PRESSED = 0x0008 RIGHT_CTRL_PRESSED = 0x0004 - def __init__(self, recognize_paste=True): - self._fdcon = None - self.recognize_paste = recognize_paste + def __init__(self, recognize_paste=True): + self._fdcon = None + self.recognize_paste = recognize_paste - # When stdin is a tty, use that handle, otherwise, create a handle from - # CONIN$. - if sys.stdin.isatty(): + # When stdin is a tty, use that handle, otherwise, create a handle from + # CONIN$. + if sys.stdin.isatty(): self.handle = HANDLE(windll.kernel32.GetStdHandle(STD_INPUT_HANDLE)) - else: - self._fdcon = os.open('CONIN$', os.O_RDWR | os.O_BINARY) + else: + self._fdcon = os.open('CONIN$', os.O_RDWR | os.O_BINARY) self.handle = HANDLE(msvcrt.get_osfhandle(self._fdcon)) - - def close(self): - " Close fdcon. " - if self._fdcon is not None: - os.close(self._fdcon) - + + def close(self): + " Close fdcon. " + if self._fdcon is not None: + os.close(self._fdcon) + def read(self): """ - Return a list of `KeyPress` instances. It won't return anything when - there was nothing to read. (This function doesn't block.) + Return a list of `KeyPress` instances. It won't return anything when + there was nothing to read. (This function doesn't block.) http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx """ - max_count = 2048 # Max events to read at the same time. + max_count = 2048 # Max events to read at the same time. read = DWORD(0) arrtype = INPUT_RECORD * max_count input_records = arrtype() # Get next batch of input event. - windll.kernel32.ReadConsoleInputW( - self.handle, pointer(input_records), max_count, pointer(read)) - - # First, get all the keys from the input buffer, in order to determine - # whether we should consider this a paste event or not. - all_keys = list(self._get_keys(read, input_records)) - - if self.recognize_paste and self._is_paste(all_keys): - gen = iter(all_keys) - for k in gen: - # Pasting: if the current key consists of text or \n, turn it - # into a BracketedPaste. - data = [] - while k and (isinstance(k.key, six.text_type) or - k.key == Keys.ControlJ): - data.append(k.data) - try: - k = next(gen) - except StopIteration: - k = None - - if data: - yield KeyPress(Keys.BracketedPaste, ''.join(data)) - if k is not None: - yield k - else: - for k in all_keys: - yield k - - def _get_keys(self, read, input_records): - """ - Generator that yields `KeyPress` objects from the input records. - """ + windll.kernel32.ReadConsoleInputW( + self.handle, pointer(input_records), max_count, pointer(read)) + + # First, get all the keys from the input buffer, in order to determine + # whether we should consider this a paste event or not. + all_keys = list(self._get_keys(read, input_records)) + + if self.recognize_paste and self._is_paste(all_keys): + gen = iter(all_keys) + for k in gen: + # Pasting: if the current key consists of text or \n, turn it + # into a BracketedPaste. + data = [] + while k and (isinstance(k.key, six.text_type) or + k.key == Keys.ControlJ): + data.append(k.data) + try: + k = next(gen) + except StopIteration: + k = None + + if data: + yield KeyPress(Keys.BracketedPaste, ''.join(data)) + if k is not None: + yield k + else: + for k in all_keys: + yield k + + def _get_keys(self, read, input_records): + """ + Generator that yields `KeyPress` objects from the input records. + """ for i in range(read.value): ir = input_records[i] @@ -181,35 +181,35 @@ class ConsoleInputReader(object): # Process if this is a key event. (We also have mouse, menu and # focus events.) if type(ev) == KEY_EVENT_RECORD and ev.KeyDown: - for key_press in self._event_to_key_presses(ev): - yield key_press + for key_press in self._event_to_key_presses(ev): + yield key_press elif type(ev) == MOUSE_EVENT_RECORD: - for key_press in self._handle_mouse(ev): - yield key_press - - @staticmethod - def _is_paste(keys): - """ - Return `True` when we should consider this list of keys as a paste - event. Pasted text on windows will be turned into a - `Keys.BracketedPaste` event. (It's not 100% correct, but it is probably - the best possible way to detect pasting of text and handle that - correctly.) - """ - # Consider paste when it contains at least one newline and at least one - # other character. - text_count = 0 - newline_count = 0 - - for k in keys: - if isinstance(k.key, six.text_type): - text_count += 1 - if k.key == Keys.ControlJ: - newline_count += 1 - - return newline_count >= 1 and text_count > 1 - + for key_press in self._handle_mouse(ev): + yield key_press + + @staticmethod + def _is_paste(keys): + """ + Return `True` when we should consider this list of keys as a paste + event. Pasted text on windows will be turned into a + `Keys.BracketedPaste` event. (It's not 100% correct, but it is probably + the best possible way to detect pasting of text and handle that + correctly.) + """ + # Consider paste when it contains at least one newline and at least one + # other character. + text_count = 0 + newline_count = 0 + + for k in keys: + if isinstance(k.key, six.text_type): + text_count += 1 + if k.key == Keys.ControlJ: + newline_count += 1 + + return newline_count >= 1 and text_count > 1 + def _event_to_key_presses(self, ev): """ For this `KEY_EVENT_RECORD`, return a list of `KeyPress` instances. @@ -219,20 +219,20 @@ class ConsoleInputReader(object): result = None u_char = ev.uChar.UnicodeChar - ascii_char = u_char.encode('utf-8') - - # NOTE: We don't use `ev.uChar.AsciiChar`. That appears to be latin-1 - # encoded. See also: - # https://github.com/ipython/ipython/issues/10004 - # https://github.com/jonathanslenders/python-prompt-toolkit/issues/389 + ascii_char = u_char.encode('utf-8') + # NOTE: We don't use `ev.uChar.AsciiChar`. That appears to be latin-1 + # encoded. See also: + # https://github.com/ipython/ipython/issues/10004 + # https://github.com/jonathanslenders/python-prompt-toolkit/issues/389 + if u_char == '\x00': if ev.VirtualKeyCode in self.keycodes: result = KeyPress(self.keycodes[ev.VirtualKeyCode], '') else: if ascii_char in self.mappings: - if self.mappings[ascii_char] == Keys.ControlJ: - u_char = '\n' # Windows sends \n, turn into \r for unix compatibility. + if self.mappings[ascii_char] == Keys.ControlJ: + u_char = '\n' # Windows sends \n, turn into \r for unix compatibility. result = KeyPress(self.mappings[ascii_char], u_char) else: result = KeyPress(u_char, u_char) @@ -299,7 +299,7 @@ class ConsoleInputReader(object): # Check event type. if ev.ButtonState == FROM_LEFT_1ST_BUTTON_PRESSED: # On a key press, generate both the mouse down and up event. - for event_type in [MouseEventType.MOUSE_DOWN, MouseEventType.MOUSE_UP]: + for event_type in [MouseEventType.MOUSE_DOWN, MouseEventType.MOUSE_UP]: data = ';'.join([ event_type, str(ev.MousePosition.X), diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py index d4dddbab42..577c61c130 100644 --- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py +++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/terminal/win32_output.py @@ -7,7 +7,7 @@ from prompt_toolkit.renderer import Output from prompt_toolkit.styles import ANSI_COLOR_NAMES from prompt_toolkit.win32_types import CONSOLE_SCREEN_BUFFER_INFO, STD_OUTPUT_HANDLE, STD_INPUT_HANDLE, COORD, SMALL_RECT -import os +import os import six __all__ = ( @@ -40,26 +40,26 @@ _DEBUG_RENDER_OUTPUT = False _DEBUG_RENDER_OUTPUT_FILENAME = r'prompt-toolkit-windows-output.log' -class NoConsoleScreenBufferError(Exception): - """ - Raised when the application is not running inside a Windows Console, but - the user tries to instantiate Win32Output. - """ - def __init__(self): - # Are we running in 'xterm' on Windows, like git-bash for instance? - xterm = 'xterm' in os.environ.get('TERM', '') - - if xterm: - message = ('Found %s, while expecting a Windows console. ' - 'Maybe try to run this program using "winpty" ' - 'or run it in cmd.exe instead. Or otherwise, ' - 'in case of Cygwin, use the Python executable ' - 'that is compiled for Cygwin.' % os.environ['TERM']) - else: - message = 'No Windows console found. Are you running cmd.exe?' - super(NoConsoleScreenBufferError, self).__init__(message) - - +class NoConsoleScreenBufferError(Exception): + """ + Raised when the application is not running inside a Windows Console, but + the user tries to instantiate Win32Output. + """ + def __init__(self): + # Are we running in 'xterm' on Windows, like git-bash for instance? + xterm = 'xterm' in os.environ.get('TERM', '') + + if xterm: + message = ('Found %s, while expecting a Windows console. ' + 'Maybe try to run this program using "winpty" ' + 'or run it in cmd.exe instead. Or otherwise, ' + 'in case of Cygwin, use the Python executable ' + 'that is compiled for Cygwin.' % os.environ['TERM']) + else: + message = 'No Windows console found. Are you running cmd.exe?' + super(NoConsoleScreenBufferError, self).__init__(message) + + class Win32Output(Output): """ I/O abstraction for rendering to Windows consoles. @@ -76,21 +76,21 @@ class Win32Output(Output): self.color_lookup_table = ColorLookupTable() - # Remember the default console colors. - info = self.get_win32_screen_buffer_info() - self.default_attrs = info.wAttributes if info else 15 - + # Remember the default console colors. + info = self.get_win32_screen_buffer_info() + self.default_attrs = info.wAttributes if info else 15 + if _DEBUG_RENDER_OUTPUT: self.LOG = open(_DEBUG_RENDER_OUTPUT_FILENAME, 'ab') - def fileno(self): - " Return file descriptor. " - return self.stdout.fileno() - - def encoding(self): - " Return encoding used for stdout. " - return self.stdout.encoding - + def fileno(self): + " Return file descriptor. " + return self.stdout.fileno() + + def encoding(self): + " Return encoding used for stdout. " + return self.stdout.encoding + def write(self, data): self._buffer.append(data) @@ -168,8 +168,8 @@ class Win32Output(Output): if success: return sbinfo - else: - raise NoConsoleScreenBufferError + else: + raise NoConsoleScreenBufferError def set_title(self, title): """ @@ -221,31 +221,31 @@ class Win32Output(Output): byref(chars_written)) def reset_attributes(self): - " Reset the console foreground/background color. " - self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole, - self.default_attrs) + " Reset the console foreground/background color. " + self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole, + self.default_attrs) def set_attributes(self, attrs): fgcolor, bgcolor, bold, underline, italic, blink, reverse = attrs - # Start from the default attributes. - attrs = self.default_attrs - - # Override the last four bits: foreground color. - if fgcolor is not None: - attrs = attrs & ~0xf - attrs |= self.color_lookup_table.lookup_fg_color(fgcolor) - - # Override the next four bits: background color. - if bgcolor is not None: - attrs = attrs & ~0xf0 - attrs |= self.color_lookup_table.lookup_bg_color(bgcolor) - - # Reverse: swap these four bits groups. + # Start from the default attributes. + attrs = self.default_attrs + + # Override the last four bits: foreground color. + if fgcolor is not None: + attrs = attrs & ~0xf + attrs |= self.color_lookup_table.lookup_fg_color(fgcolor) + + # Override the next four bits: background color. + if bgcolor is not None: + attrs = attrs & ~0xf0 + attrs |= self.color_lookup_table.lookup_bg_color(bgcolor) + + # Reverse: swap these four bits groups. if reverse: - attrs = (attrs & ~0xff) | ((attrs & 0xf) << 4) | ((attrs & 0xf0) >> 4) + attrs = (attrs & ~0xff) | ((attrs & 0xf) << 4) | ((attrs & 0xf0) >> 4) - self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole, attrs) + self._winapi(windll.kernel32.SetConsoleTextAttribute, self.hconsole, attrs) def disable_autowrap(self): # Not supported by Windows. @@ -327,11 +327,11 @@ class Win32Output(Output): # Scroll vertical win_height = sr.Bottom - sr.Top - if 0 < sr.Bottom - cursor_pos.Y < win_height - 1: - # no vertical scroll if cursor already on the screen - result.Bottom = sr.Bottom - else: - result.Bottom = max(win_height, cursor_pos.Y) + if 0 < sr.Bottom - cursor_pos.Y < win_height - 1: + # no vertical scroll if cursor already on the screen + result.Bottom = sr.Bottom + else: + result.Bottom = max(win_height, cursor_pos.Y) result.Top = result.Bottom - win_height # Scroll API @@ -429,27 +429,27 @@ class BACKROUND_COLOR: def _create_ansi_color_dict(color_cls): " Create a table that maps the 16 named ansi colors to their Windows code. " return { - 'ansidefault': color_cls.BLACK, - 'ansiblack': color_cls.BLACK, - 'ansidarkgray': color_cls.BLACK | color_cls.INTENSITY, - 'ansilightgray': color_cls.GRAY, - 'ansiwhite': color_cls.GRAY | color_cls.INTENSITY, - + 'ansidefault': color_cls.BLACK, + 'ansiblack': color_cls.BLACK, + 'ansidarkgray': color_cls.BLACK | color_cls.INTENSITY, + 'ansilightgray': color_cls.GRAY, + 'ansiwhite': color_cls.GRAY | color_cls.INTENSITY, + # Low intensity. - 'ansidarkred': color_cls.RED, - 'ansidarkgreen': color_cls.GREEN, - 'ansibrown': color_cls.YELLOW, - 'ansidarkblue': color_cls.BLUE, - 'ansipurple': color_cls.MAGENTA, - 'ansiteal': color_cls.CYAN, + 'ansidarkred': color_cls.RED, + 'ansidarkgreen': color_cls.GREEN, + 'ansibrown': color_cls.YELLOW, + 'ansidarkblue': color_cls.BLUE, + 'ansipurple': color_cls.MAGENTA, + 'ansiteal': color_cls.CYAN, # High intensity. - 'ansired': color_cls.RED | color_cls.INTENSITY, - 'ansigreen': color_cls.GREEN | color_cls.INTENSITY, - 'ansiyellow': color_cls.YELLOW | color_cls.INTENSITY, - 'ansiblue': color_cls.BLUE | color_cls.INTENSITY, - 'ansifuchsia': color_cls.MAGENTA | color_cls.INTENSITY, - 'ansiturquoise': color_cls.CYAN | color_cls.INTENSITY, + 'ansired': color_cls.RED | color_cls.INTENSITY, + 'ansigreen': color_cls.GREEN | color_cls.INTENSITY, + 'ansiyellow': color_cls.YELLOW | color_cls.INTENSITY, + 'ansiblue': color_cls.BLUE | color_cls.INTENSITY, + 'ansifuchsia': color_cls.MAGENTA | color_cls.INTENSITY, + 'ansiturquoise': color_cls.CYAN | color_cls.INTENSITY, } FG_ANSI_COLORS = _create_ansi_color_dict(FOREGROUND_COLOR) @@ -492,7 +492,7 @@ class ColorLookupTable(object): (0xff, 0x44, 0xff, FG.MAGENTA | FG.INTENSITY, BG.MAGENTA | BG.INTENSITY), (0xff, 0xff, 0x44, FG.YELLOW | FG.INTENSITY, BG.YELLOW | BG.INTENSITY), - (0x44, 0x44, 0x44, FG.BLACK | FG.INTENSITY, BG.BLACK | BG.INTENSITY), + (0x44, 0x44, 0x44, FG.BLACK | FG.INTENSITY, BG.BLACK | BG.INTENSITY), (0xff, 0xff, 0xff, FG.GRAY | FG.INTENSITY, BG.GRAY | BG.INTENSITY), ] @@ -529,7 +529,7 @@ class ColorLookupTable(object): self.best_match[color] = indexes return indexes - def lookup_fg_color(self, fg_color): + def lookup_fg_color(self, fg_color): """ Return the color for use in the `windll.kernel32.SetConsoleTextAttribute` API call. @@ -538,19 +538,19 @@ class ColorLookupTable(object): """ # Foreground. if fg_color in FG_ANSI_COLORS: - return FG_ANSI_COLORS[fg_color] + return FG_ANSI_COLORS[fg_color] else: - return self._color_indexes(fg_color)[0] - - def lookup_bg_color(self, bg_color): - """ - Return the color for use in the - `windll.kernel32.SetConsoleTextAttribute` API call. - - :param bg_color: Background as text. E.g. 'ffffff' or 'red' - """ + return self._color_indexes(fg_color)[0] + + def lookup_bg_color(self, bg_color): + """ + Return the color for use in the + `windll.kernel32.SetConsoleTextAttribute` API call. + + :param bg_color: Background as text. E.g. 'ffffff' or 'red' + """ # Background. if bg_color in BG_ANSI_COLORS: - return BG_ANSI_COLORS[bg_color] + return BG_ANSI_COLORS[bg_color] else: - return self._color_indexes(bg_color)[1] + return self._color_indexes(bg_color)[1] |