| # Copyright 2000-2008 Michael Hudson-Doyle <micahel@gmail.com> |
| # Armin Rigo |
| # |
| # All Rights Reserved |
| # |
| # |
| # Permission to use, copy, modify, and distribute this software and |
| # its documentation for any purpose is hereby granted without fee, |
| # provided that the above copyright notice appear in all copies and |
| # that both that copyright notice and this permission notice appear in |
| # supporting documentation. |
| # |
| # THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO |
| # THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
| # AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, |
| # INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER |
| # RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF |
| # CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
| # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| from .terminfo import TermInfo |
| from .trace import trace |
| from .base_eventqueue import BaseEventQueue |
| from termios import tcgetattr, VERASE |
| import os |
| |
| |
| # Mapping of human-readable key names to their terminal-specific codes |
| TERMINAL_KEYNAMES = { |
| "delete": "kdch1", |
| "down": "kcud1", |
| "end": "kend", |
| "enter": "kent", |
| "home": "khome", |
| "insert": "kich1", |
| "left": "kcub1", |
| "page down": "knp", |
| "page up": "kpp", |
| "right": "kcuf1", |
| "up": "kcuu1", |
| } |
| |
| |
| # Function keys F1-F20 mapping |
| TERMINAL_KEYNAMES.update(("f%d" % i, "kf%d" % i) for i in range(1, 21)) |
| |
| # Known CTRL-arrow keycodes |
| CTRL_ARROW_KEYCODES= { |
| # for xterm, gnome-terminal, xfce terminal, etc. |
| b'\033[1;5D': 'ctrl left', |
| b'\033[1;5C': 'ctrl right', |
| # for rxvt |
| b'\033Od': 'ctrl left', |
| b'\033Oc': 'ctrl right', |
| } |
| |
| def get_terminal_keycodes(ti: TermInfo) -> dict[bytes, str]: |
| """ |
| Generates a dictionary mapping terminal keycodes to human-readable names. |
| """ |
| keycodes = {} |
| for key, terminal_code in TERMINAL_KEYNAMES.items(): |
| keycode = ti.get(terminal_code) |
| trace('key {key} tiname {terminal_code} keycode {keycode!r}', **locals()) |
| if keycode: |
| keycodes[keycode] = key |
| keycodes.update(CTRL_ARROW_KEYCODES) |
| return keycodes |
| |
| |
| class EventQueue(BaseEventQueue): |
| def __init__(self, fd: int, encoding: str, ti: TermInfo) -> None: |
| keycodes = get_terminal_keycodes(ti) |
| if os.isatty(fd): |
| backspace = tcgetattr(fd)[6][VERASE] |
| keycodes[backspace] = "backspace" |
| BaseEventQueue.__init__(self, encoding, keycodes) |