Work on porting kittens to use new key infrastructure

Also move type definitions into their own module
This commit is contained in:
Kovid Goyal
2021-01-14 21:35:48 +05:30
parent 0714fd376b
commit 027c5a57f1
30 changed files with 524 additions and 721 deletions

View File

@@ -8,6 +8,7 @@ from typing import (
Any, Callable, ContextManager, Dict, Optional, Sequence, Type, Union
)
from kitty.types import ParsedShortcut
from kitty.typing import (
AbstractEventLoop, BossType, Debug, ImageManagerType, KeyEventType,
KittensKeyActionType, LoopType, MouseEvent, ScreenSize, TermManagerType
@@ -35,6 +36,7 @@ class Handler:
self.debug = debug
self.cmd = commander(self)
self._image_manager = image_manager
self._key_shortcuts: Dict[ParsedShortcut, KittensKeyActionType] = {}
@property
def image_manager(self) -> ImageManagerType:
@@ -45,18 +47,16 @@ class Handler:
def asyncio_loop(self) -> AbstractEventLoop:
return self._tui_loop.asycio_loop
def add_shortcut(self, action: KittensKeyActionType, key: str, mods: Optional[int] = None, is_text: Optional[bool] = False) -> None:
if not hasattr(self, '_text_shortcuts'):
self._text_shortcuts, self._key_shortcuts = {}, {}
if is_text:
self._text_shortcuts[key] = action
else:
self._key_shortcuts[(key, mods or 0)] = action
def add_shortcut(self, action: KittensKeyActionType, spec: Union[str, ParsedShortcut]) -> None:
if isinstance(spec, str):
from kitty.key_encoding import parse_shortcut
spec = parse_shortcut(spec)
self._key_shortcuts[spec] = action
def shortcut_action(self, key_event_or_text: Union[str, KeyEventType]) -> Optional[KittensKeyActionType]:
if isinstance(key_event_or_text, str):
return self._text_shortcuts.get(key_event_or_text)
return self._key_shortcuts.get((key_event_or_text.key, key_event_or_text.mods))
def shortcut_action(self, key_event: KeyEventType) -> Optional[KittensKeyActionType]:
for sc, action in self._key_shortcuts.items():
if key_event.matches(sc):
return action
def __enter__(self) -> None:
if self._image_manager is not None:
@@ -85,6 +85,12 @@ class Handler:
def on_term(self) -> None:
self._tui_loop.quit(1)
def on_key_event(self, key_event: KeyEventType, in_bracketed_paste: bool = False) -> None:
if key_event.text:
self.on_text(key_event.text, in_bracketed_paste)
else:
self.on_key(key_event)
def on_text(self, text: str, in_bracketed_paste: bool = False) -> None:
pass

View File

@@ -5,17 +5,10 @@
from typing import Callable, Tuple
from kitty.fast_data_types import truncate_point_for_length, wcswidth
from kitty.key_encoding import RELEASE, KeyEvent, key_defs as K
from kitty.key_encoding import EventType, KeyEvent
from .operations import RESTORE_CURSOR, SAVE_CURSOR, move_cursor_by
HOME = K['HOME']
END = K['END']
BACKSPACE = K['BACKSPACE']
DELETE = K['DELETE']
LEFT = K['LEFT']
RIGHT = K['RIGHT']
class LineEdit:
@@ -137,22 +130,22 @@ class LineEdit:
return self.cursor_pos != orig
def on_key(self, key_event: KeyEvent) -> bool:
if key_event.type is RELEASE:
if key_event.type is EventType.RELEASE:
return False
elif key_event.key is HOME:
if key_event.matches('home'):
return self.home()
elif key_event.key is END:
if key_event.matches('end'):
return self.end()
elif key_event.key is BACKSPACE:
if key_event.matches('backspace'):
self.backspace()
return True
elif key_event.key is DELETE:
if key_event.matches('delete'):
self.delete()
return True
elif key_event.key is LEFT:
if key_event.matches('left'):
self.left()
return True
elif key_event.key is RIGHT:
if key_event.matches('right'):
self.right()
return True
return False

View File

@@ -21,7 +21,7 @@ from kitty.fast_data_types import (
)
from kitty.key_encoding import (
ALT, CTRL, PRESS, RELEASE, REPEAT, SHIFT, backspace_key, decode_key_event,
enter_key, key_defs as K
enter_key
)
from kitty.typing import ImageManagerType, KeyEventType, Protocol
from kitty.utils import ScreenSizeGetter, screen_size_function, write_all
@@ -29,8 +29,6 @@ from kitty.utils import ScreenSizeGetter, screen_size_function, write_all
from .handler import Handler
from .operations import init_state, reset_state
C, D = K['C'], K['D']
class BinaryWrite(Protocol):
@@ -149,7 +147,7 @@ class UnhandledException(Handler):
self.write('Press the Enter key to quit')
def on_key(self, key_event: KeyEventType) -> None:
if key_event is enter_key:
if key_event.key == 'ENTER':
self.quit_loop(1)
def on_interrupt(self) -> None:
@@ -282,8 +280,23 @@ class Loop:
elif q == '~':
if csi == '200~':
self.in_bracketed_paste = True
return
elif csi == '201~':
self.in_bracketed_paste = False
return
elif q in 'u~ABCDHFPQRS':
try:
k = decode_key_event(csi[:-1], q)
except Exception:
pass
else:
if k.matches('ctrl+c'):
self.handler.on_interrupt()
return
if k.matches('ctrl+d'):
self.handler.on_eot()
return
self.handler.on_key_event(k)
def _on_pm(self, pm: str) -> None:
pass
@@ -300,21 +313,7 @@ class Loop:
self.handler.on_clipboard_response(standard_b64decode(rest).decode('utf-8'), from_primary)
def _on_apc(self, apc: str) -> None:
if apc.startswith('K'):
try:
k = decode_key_event(apc[1:])
except Exception:
pass
else:
if k.mods is CTRL and k.type is not RELEASE:
if k.key is C:
self.handler.on_interrupt()
return
if k.key is D:
self.handler.on_eot()
return
self.handler.on_key(k)
elif apc.startswith('G'):
if apc.startswith('G'):
if self.handler.image_manager is not None:
self.handler.image_manager.handle_response(apc)
# }}}

View File

@@ -40,7 +40,6 @@ MODES = dict(
MOUSE_URXVT_MODE=(1015, '?'),
ALTERNATE_SCREEN=(1049, '?'),
BRACKETED_PASTE=(2004, '?'),
EXTENDED_KEYBOARD=(2017, '?'),
)
F = TypeVar('F')
@@ -270,8 +269,8 @@ def init_state(alternate_screen: bool = True) -> str:
reset_mode('MOUSE_MOTION_TRACKING') + reset_mode('MOUSE_MOVE_TRACKING') +
reset_mode('FOCUS_TRACKING') + reset_mode('MOUSE_UTF8_MODE') +
reset_mode('MOUSE_SGR_MODE') + reset_mode('MOUSE_UTF8_MODE') +
set_mode('BRACKETED_PASTE') + set_mode('EXTENDED_KEYBOARD') +
SAVE_COLORS +
set_mode('BRACKETED_PASTE') + SAVE_COLORS +
'\033[>31u' + # extended keyboard mode
'\033[*x' # reset DECSACE to default region select
)
if alternate_screen:
@@ -287,6 +286,7 @@ def reset_state(normal_screen: bool = True) -> str:
ans += RESTORE_PRIVATE_MODE_VALUES
ans += RESTORE_CURSOR
ans += RESTORE_COLORS
ans += '\033[<u' # restore keyboard mode
return ans