A new show_key kitten

Fixes #3556
This commit is contained in:
Kovid Goyal 2021-04-29 13:10:20 +05:30
parent 3e00ee4155
commit 28b4fe5cb6
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
7 changed files with 98 additions and 27 deletions

View File

@ -4,6 +4,12 @@ Changelog
|kitty| is a feature-rich, cross-platform, *fast*, GPU based terminal. |kitty| is a feature-rich, cross-platform, *fast*, GPU based terminal.
To update |kitty|, :doc:`follow the instructions <binary>`. To update |kitty|, :doc:`follow the instructions <binary>`.
0.20.3 [future]
----------------------
- A new ``show_key`` kitten to easily see the bytes generated by the terminal
for key presses in the various keyboard modes (:pull:`3556`)
0.20.2 [2021-04-28] 0.20.2 [2021-04-28]
---------------------- ----------------------

View File

@ -229,23 +229,11 @@ For example::
map alt+s send_text all \x13 map alt+s send_text all \x13
This maps :kbd:`alt+s` to :kbd:`ctrl+s`. To figure out what bytes to use for This maps :kbd:`alt+s` to :kbd:`ctrl+s`. To figure out what bytes to use for
the :sc:`send_text <send_text>` you can use the ``showkey`` utility. Run:: the :sc:`send_text <send_text>` you can use the ``show_key`` kitten. Run::
showkey -a kitty +kitten show_key
Then press the key you want to emulate. On macOS, this utility is currently not Then press the key you want to emulate.
available. The manual way to figure it out is:
1. Look up your key's decimal value in the table at the bottom of `this
page <http://ascii-table.com/ansi-escape-sequences.php>`_ or any
ANSI escape sequence table. There are different modifiers for :kbd:`ctrl`,
:kbd:`alt`, etc. For e.g., for :kbd:`ctrl+s`, find the ``S`` row and look at
the third column value, ``19``.
2. Convert the decimal value to hex with ``kitty +runpy "print(hex(19))"``.
This shows the hex value, ``13`` in this case.
3. Use ``\x(hexval)`` in your ``send_text`` command in kitty. So in this example, ``\x13``
How do I open a new window or tab with the same working directory as the current window? How do I open a new window or tab with the same working directory as the current window?
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------

View File

@ -28,7 +28,7 @@ issues in that proposal, listed at the :ref:`bottom of this document
You can see this protocol with all enhancements in action by running:: You can see this protocol with all enhancements in action by running::
kitty +kitten key_demo kitty +kitten show_key -m kitty
inside the kitty terminal to report key events. inside the kitty terminal to report key events.

View File

@ -2,16 +2,13 @@
# vim:fileencoding=utf-8 # vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net> # License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import sys
from typing import List
from kitty.key_encoding import ( from kitty.key_encoding import (
ALT, CAPS_LOCK, CTRL, HYPER, META, NUM_LOCK, PRESS, RELEASE, REPEAT, SHIFT, ALT, CAPS_LOCK, CTRL, HYPER, META, NUM_LOCK, PRESS, RELEASE, REPEAT, SHIFT,
SUPER, KeyEvent, encode_key_event SUPER, KeyEvent, encode_key_event
) )
from ..tui.handler import Handler from kittens.tui.handler import Handler
from ..tui.loop import Loop from kittens.tui.loop import Loop
class KeysHandler(Handler): class KeysHandler(Handler):
@ -69,12 +66,8 @@ class KeysHandler(Handler):
self.quit_loop(0) self.quit_loop(0)
def main(args: List[str]) -> None: def main() -> None:
loop = Loop() loop = Loop()
handler = KeysHandler() handler = KeysHandler()
loop.loop(handler) loop.loop(handler)
raise SystemExit(loop.return_code) raise SystemExit(loop.return_code)
if __name__ == '__main__':
main(sys.argv)

81
kittens/show_key/main.py Normal file
View File

@ -0,0 +1,81 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
import os
import sys
from typing import List
from kitty.cli import parse_args
from kitty.cli_stub import ShowKeyCLIOptions
from kittens.tui.operations import raw_mode, styled
ctrl_keys = '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'
def print_key(raw: bytearray) -> None:
unix = ''
for ch in raw:
if ch < len(ctrl_keys):
unix += '^' + ctrl_keys[ch]
elif ch == 127:
unix += '^?'
else:
unix += chr(ch)
print(unix + '\t\t', end='')
for ch in raw:
x = chr(ch).encode('ascii')
print(styled(repr(x)[2:-1], fg='yellow'), end='')
print(end='\r\n', flush=True)
def read_keys() -> None:
fd = sys.stdin.fileno()
while True:
try:
raw = bytearray(os.read(fd, 64))
except OSError as err:
print(err, file=sys.stderr, flush=True)
break
if not raw:
break
print_key(raw)
if len(raw) == 1 and raw[0] == 4:
break
def legacy_main() -> None:
print('Press any keys - Ctrl-D will terminate this program', end='\r\n', flush=True)
print(styled('UNIX', italic=True, fg='green'), styled('send_text', italic=True, fg='green'), sep='\t\t', end='\r\n')
with raw_mode():
read_keys()
OPTIONS = r'''
--key-mode -m
default=normal
type=choices
choices=normal,application,kitty,unchanged
The keyboard mode to use when showing keys. "normal" mode is with DECCKM reset and "application" mode is with
DECCKM set. "kitty" is the full kitty extended keyboard protocol.
'''.format
def main(args: List[str]) -> None:
cli_opts, items = parse_args(args[1:], OPTIONS, '', '', 'kitty +kitten clipboard', result_class=ShowKeyCLIOptions)
if cli_opts.key_mode == 'kitty':
from .kitty_mode import main as kitty_main
return kitty_main()
if cli_opts.key_mode != 'unchanged':
print(end='\x1b[?1' + ('l' if cli_opts.key_mode == 'normal' else 'h'), flush=True)
try:
return legacy_main()
finally:
if cli_opts.key_mode != 'unchanged':
print(end='\x1b[?1l', flush=True)
if __name__ == '__main__':
main(sys.argv)

View File

@ -13,7 +13,7 @@ class CLIOptions:
LaunchCLIOptions = AskCLIOptions = ClipboardCLIOptions = DiffCLIOptions = CLIOptions LaunchCLIOptions = AskCLIOptions = ClipboardCLIOptions = DiffCLIOptions = CLIOptions
HintsCLIOptions = IcatCLIOptions = PanelCLIOptions = ResizeCLIOptions = CLIOptions HintsCLIOptions = IcatCLIOptions = PanelCLIOptions = ResizeCLIOptions = CLIOptions
ErrorCLIOptions = UnicodeCLIOptions = RCOptions = RemoteFileCLIOptions = CLIOptions ErrorCLIOptions = UnicodeCLIOptions = RCOptions = RemoteFileCLIOptions = CLIOptions
QueryTerminalCLIOptions = BroadcastCLIOptions = CLIOptions QueryTerminalCLIOptions = BroadcastCLIOptions = ShowKeyCLIOptions = CLIOptions
def generate_stub() -> None: def generate_stub() -> None:
@ -42,6 +42,9 @@ def generate_stub() -> None:
from kittens.clipboard.main import OPTIONS from kittens.clipboard.main import OPTIONS
do(OPTIONS(), 'ClipboardCLIOptions') do(OPTIONS(), 'ClipboardCLIOptions')
from kittens.show_key.main import OPTIONS
do(OPTIONS(), 'ShowKeyCLIOptions')
from kittens.diff.main import OPTIONS from kittens.diff.main import OPTIONS
do(OPTIONS(), 'DiffCLIOptions') do(OPTIONS(), 'DiffCLIOptions')