Allow defining aliases for more general actions, not just kittens

Fixes #4260
This commit is contained in:
Kovid Goyal 2021-11-22 19:52:43 +05:30
parent 727c69ffdd
commit aa4fa4cc85
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
16 changed files with 370 additions and 281 deletions

View File

@ -210,6 +210,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
--program` option work when using the ``self``
:option:`kitty +kitten hints --linenum-action` (:iss:`3931`)
- Allow defining aliases for more general actions, not just kittens
(:pull:`4260`)
0.22.2 [2021-08-02]
----------------------

View File

@ -38,6 +38,18 @@ To pass the contents of the current screen and scrollback to the started process
There are many more powerful options, refer to the complete list below.
.. note::
To avoid duplicating launch actions with frequently used parameters, you can
use :opt:`action_alias` to define launch action aliases. For example::
action_alias launch_tab launch --cwd=current --type=tab
map f1 launch_tab vim
map f2 launch_tab emacs
The :kbd:`F1` key will now open vim in a new tab with the current windows
working directory
The piping environment
--------------------------

View File

@ -58,6 +58,12 @@ some special variables, documented below:
``FRAGMENT``
The fragment (unquoted), if any of the URL or the empty string.
.. note::
You can use the :opt:`action_alias` option just as in kitty.conf to
define aliases for frequently used actions.
.. _matching_criteria:
Matching criteria

View File

@ -46,7 +46,7 @@ from .keys import get_shortcut, shortcut_matches
from .layout.base import set_layout_options
from .notify import notification_activated
from .options.types import Options
from .options.utils import MINIMUM_FONT_SIZE, SubSequenceMap
from .options.utils import MINIMUM_FONT_SIZE, KeyMap, SubSequenceMap
from .os_window_size import initial_window_size_func
from .rgb import color_from_int
from .session import Session, create_sessions, get_os_window_sizing_data
@ -62,7 +62,7 @@ from .utils import (
remove_socket_file, safe_print, set_primary_selection, single_instance,
startup_notification_handler
)
from .window import MatchPatternType, Window, CommandOutput
from .window import CommandOutput, MatchPatternType, Window
class OSWindowDict(TypedDict):
@ -238,7 +238,7 @@ class Boss:
self.current_visual_select: Optional[VisualSelect] = None
self.startup_cursor_text_color = opts.cursor_text_color
self.pending_sequences: Optional[SubSequenceMap] = None
self.default_pending_action: Optional[KeyAction] = None
self.default_pending_action: Tuple[KeyAction, ...] = ()
self.cached_values = cached_values
self.os_window_map: Dict[int, TabManager] = {}
self.os_window_death_actions: Dict[int, Callable[[], None]] = {}
@ -259,7 +259,7 @@ class Boss:
)
set_boss(self)
self.args = args
self.global_shortcuts_map = {v: KeyAction(k) for k, v in global_shortcuts.items()}
self.global_shortcuts_map: KeyMap = {v: (KeyAction(k),) for k, v in global_shortcuts.items()}
self.global_shortcuts = global_shortcuts
self.mouse_handler: Optional[Callable[[WindowSystemMouseEvent], None]] = None
self.update_keymap()
@ -895,7 +895,7 @@ class Boss:
t = self.active_tab
return None if t is None else t.active_window
def set_pending_sequences(self, sequences: SubSequenceMap, default_pending_action: Optional[KeyAction] = None) -> None:
def set_pending_sequences(self, sequences: SubSequenceMap, default_pending_action: Tuple[KeyAction, ...] = ()) -> None:
self.pending_sequences = sequences
self.default_pending_action = default_pending_action
set_in_sequence_mode(True)
@ -905,17 +905,18 @@ class Boss:
key_action = get_shortcut(self.keymap, ev)
if key_action is None:
sequences = get_shortcut(get_options().sequence_map, ev)
if sequences and not isinstance(sequences, KeyAction):
if sequences and not isinstance(sequences, tuple):
self.set_pending_sequences(sequences)
return True
if self.global_shortcuts_map and get_shortcut(self.global_shortcuts_map, ev):
return True
elif isinstance(key_action, KeyAction):
return self.dispatch_action(key_action)
elif isinstance(key_action, tuple):
return self.combine(key_action)
return False
def clear_pending_sequences(self) -> None:
self.pending_sequences = self.default_pending_action = None
self.pending_sequences = None
self.default_pending_action = ()
set_in_sequence_mode(False)
def process_sequence(self, ev: KeyEvent) -> None:
@ -939,7 +940,7 @@ class Boss:
matched_action = matched_action or self.default_pending_action
self.clear_pending_sequences()
if matched_action is not None:
self.dispatch_action(matched_action)
self.combine(matched_action)
def cancel_current_visual_select(self) -> None:
if self.current_visual_select:
@ -982,11 +983,11 @@ class Boss:
window.screen.set_window_char(ch)
self.current_visual_select.window_ids.append(window.id)
for mods in (0, GLFW_MOD_CONTROL, GLFW_MOD_CONTROL | GLFW_MOD_SHIFT, GLFW_MOD_SUPER, GLFW_MOD_ALT, GLFW_MOD_SHIFT):
pending_sequences[(SingleKey(mods=mods, key=ord(ch.lower())),)] = ac
pending_sequences[(SingleKey(mods=mods, key=ord(ch.lower())),)] = (ac,)
if ch in string.digits:
pending_sequences[(SingleKey(mods=mods, key=fmap[f'KP_{ch}']),)] = ac
pending_sequences[(SingleKey(mods=mods, key=fmap[f'KP_{ch}']),)] = (ac,)
if len(self.current_visual_select.window_ids) > 1:
self.set_pending_sequences(pending_sequences, default_pending_action=KeyAction('visual_window_select_action_trigger', (0,)))
self.set_pending_sequences(pending_sequences, default_pending_action=(KeyAction('visual_window_select_action_trigger', (0,)),))
redirect_mouse_handling(True)
self.mouse_handler = self.visual_window_select_mouse_handler
else:
@ -1130,9 +1131,12 @@ class Boss:
map kitty_mod+e combine : new_window : next_layout
''')
def combine(self, *actions: KeyAction) -> None:
def combine(self, actions: Tuple[KeyAction, ...], window_for_dispatch: Optional[Window] = None, dispatch_type: str = 'KeyPress') -> bool:
consumed = False
for key_action in actions:
self.dispatch_action(key_action)
if self.dispatch_action(key_action, window_for_dispatch, dispatch_type):
consumed = True
return consumed
def on_focus(self, os_window_id: int, focused: bool) -> None:
tm = self.os_window_map.get(os_window_id)
@ -1363,10 +1367,7 @@ class Boss:
return overlay_window
@ac('misc', 'Run the specified kitten. See :doc:`/kittens/custom` for details')
def kitten(self, kitten: str, *args: str) -> None:
import shlex
cmdline = args[0] if args else ''
kargs = shlex.split(cmdline) if cmdline else []
def kitten(self, kitten: str, *kargs: str) -> None:
self._run_kitten(kitten, kargs)
def run_kitten(self, kitten: str, *args: str) -> None:

View File

@ -11,7 +11,8 @@ from .conf.utils import BadLine, load_config as _load_config, parse_config_base
from .constants import cache_dir, defconf
from .options.types import Options, defaults, option_names
from .options.utils import (
KeyDefinition, KeyMap, MouseMap, MouseMapping, SequenceMap
ActionAlias, KeyDefinition, KeyMap, MouseMap, MouseMapping, SequenceMap,
build_action_aliases
)
from .typing import TypedDict
from .utils import log_error
@ -21,9 +22,6 @@ def option_names_for_completion() -> Tuple[str, ...]:
return option_names
no_op_actions = frozenset({'noop', 'no-op', 'no_op'})
def build_ansi_color_table(opts: Optional[Options] = None) -> int:
if opts is None:
opts = defaults
@ -93,18 +91,18 @@ def prepare_config_file_for_editing() -> str:
return defconf
def finalize_keys(opts: Options) -> None:
def finalize_keys(opts: Options, alias_map: Dict[str, ActionAlias]) -> None:
defns: List[KeyDefinition] = []
for d in opts.map:
if d is None: # clear_all_shortcuts
defns = [] # type: ignore
else:
defns.append(d.resolve_and_copy(opts.kitty_mod, opts.kitten_alias))
defns.append(d.resolve_and_copy(opts.kitty_mod, alias_map))
keymap: KeyMap = {}
sequence_map: SequenceMap = {}
for defn in defns:
is_no_op = defn.action.func in no_op_actions
is_no_op = defn.is_no_op
if defn.is_sequence:
keymap.pop(defn.trigger, None)
s = sequence_map.setdefault(defn.trigger, {})
@ -113,32 +111,32 @@ def finalize_keys(opts: Options) -> None:
if not s:
del sequence_map[defn.trigger]
else:
s[defn.rest] = defn.action
s[defn.rest] = defn.actions
else:
sequence_map.pop(defn.trigger, None)
if is_no_op:
keymap.pop(defn.trigger, None)
else:
keymap[defn.trigger] = defn.action
keymap[defn.trigger] = defn.actions
opts.keymap = keymap
opts.sequence_map = sequence_map
def finalize_mouse_mappings(opts: Options) -> None:
def finalize_mouse_mappings(opts: Options, alias_map: Dict[str, ActionAlias]) -> None:
defns: List[MouseMapping] = []
for d in opts.mouse_map:
if d is None: # clear_all_mouse_actions
defns = [] # type: ignore
else:
defns.append(d.resolve_and_copy(opts.kitty_mod, opts.kitten_alias))
defns.append(d.resolve_and_copy(opts.kitty_mod, alias_map))
mousemap: MouseMap = {}
for defn in defns:
is_no_op = defn.action.func in no_op_actions
is_no_op = defn.is_no_op
if is_no_op:
mousemap.pop(defn.trigger, None)
else:
mousemap[defn.trigger] = defn.action
mousemap[defn.trigger] = defn.actions
opts.mousemap = mousemap
@ -161,10 +159,13 @@ def load_config(*paths: str, overrides: Optional[Iterable[str]] = None, accumula
opts_dict, paths = _load_config(defaults, partial(parse_config, accumulate_bad_lines=accumulate_bad_lines), merge_result_dicts, *paths, overrides=overrides)
opts = Options(opts_dict)
finalize_keys(opts)
finalize_mouse_mappings(opts)
alias_map = build_action_aliases(opts.kitten_alias, 'kitten')
alias_map.update(build_action_aliases(opts.action_alias))
finalize_keys(opts, alias_map)
finalize_mouse_mappings(opts, alias_map)
# delete no longer needed definitions, replacing with empty placeholders
opts.kitten_alias = {}
opts.action_alias = {}
opts.mouse_map = []
opts.map = []
if opts.background_opacity < 1.0 and opts.macos_titlebar_color:

View File

@ -27,7 +27,7 @@ from .rgb import color_as_sharp
from .types import MouseEvent, SingleKey
from .typing import SequenceMap
ShortcutMap = Dict[Tuple[SingleKey, ...], KeyAction]
ShortcutMap = Dict[Tuple[SingleKey, ...], Tuple[KeyAction, ...]]
def green(x: str) -> str:
@ -54,7 +54,7 @@ def mod_to_names(mods: int) -> Generator[str, None, None]:
yield name
def print_shortcut(key_sequence: Iterable[SingleKey], action: KeyAction, print: Callable[..., None]) -> None:
def print_shortcut(key_sequence: Iterable[SingleKey], actions: Iterable[KeyAction], print: Callable[..., None]) -> None:
from .fast_data_types import glfw_get_key_name
keys = []
for key_spec in key_sequence:
@ -66,6 +66,7 @@ def print_shortcut(key_sequence: Iterable[SingleKey], action: KeyAction, print:
names.append(kname or f'{key}')
keys.append('+'.join(names))
for action in actions:
print('\t' + ' > '.join(keys), action)
@ -87,7 +88,7 @@ def compare_keymaps(final: ShortcutMap, initial: ShortcutMap, print: Callable[..
def flatten_sequence_map(m: SequenceMap) -> ShortcutMap:
ans: Dict[Tuple[SingleKey, ...], KeyAction] = {}
ans = {}
for key_spec, rest_map in m.items():
for r, action in rest_map.items():
ans[(key_spec,) + (r)] = action
@ -99,10 +100,11 @@ def compare_mousemaps(final: MouseMap, initial: MouseMap, print: Callable[..., N
removed = set(initial) - set(final)
changed = {k for k in set(final) & set(initial) if final[k] != initial[k]}
def print_mouse_action(trigger: MouseEvent, action: KeyAction) -> None:
def print_mouse_action(trigger: MouseEvent, actions: Tuple[KeyAction, ...]) -> None:
names = list(mod_to_names(trigger.mods)) + [f'b{trigger.button+1}']
when = {-1: 'repeat', 1: 'press', 2: 'doublepress', 3: 'triplepress'}.get(trigger.repeat_count, trigger.repeat_count)
grabbed = 'grabbed' if trigger.grabbed else 'ungrabbed'
for action in actions:
print('\t', '+'.join(names), when, grabbed, action)
def print_changes(defns: MouseMap, changes: Set[MouseEvent], text: str) -> None:

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from typing import Optional, Union
from typing import Optional, Union, Tuple
from .conf.utils import KeyAction
from .fast_data_types import (
@ -22,7 +22,7 @@ def keyboard_mode_name(screen: ScreenType) -> str:
return 'application' if screen.cursor_key_mode else 'normal'
def get_shortcut(keymap: Union[KeyMap, SequenceMap], ev: KeyEvent) -> Optional[Union[KeyAction, SubSequenceMap]]:
def get_shortcut(keymap: Union[KeyMap, SequenceMap], ev: KeyEvent) -> Optional[Union[Tuple[KeyAction, ...], SubSequenceMap]]:
mods = ev.mods & mod_mask
ans = keymap.get(SingleKey(mods, False, ev.key))
if ans is None and ev.shifted_key and mods & GLFW_MOD_SHIFT:

View File

@ -112,7 +112,9 @@ def get_macos_shortcut_for(opts: Options, function: str = 'new_os_window', args:
ans = None
candidates = []
for k, v in opts.keymap.items():
if v.func == function and v.args == args:
if len(v) == 1:
q = v[0]
if q.func == function and q.args == args:
candidates.append(k)
if candidates:
from .fast_data_types import cocoa_set_global_shortcut

View File

@ -6,14 +6,16 @@ import os
import posixpath
from contextlib import suppress
from typing import (
Any, Generator, Iterable, List, NamedTuple, Optional, Tuple, cast
Any, Dict, Iterable, Iterator, List, NamedTuple, Optional, Tuple, cast
)
from urllib.parse import ParseResult, unquote, urlparse
from .conf.utils import KeyAction, to_cmdline_implementation
from .constants import config_dir
from .guess_mime_type import guess_type
from .options.utils import parse_key_action
from .options.utils import (
ActionAlias, action_alias, parse_key_actions, resolve_aliases_in_action
)
from .types import run_once
from .typing import MatchType
from .utils import expandvars, log_error
@ -29,9 +31,11 @@ class OpenAction(NamedTuple):
actions: Tuple[KeyAction, ...]
def parse(lines: Iterable[str]) -> Generator[OpenAction, None, None]:
def parse(lines: Iterable[str]) -> Iterator[OpenAction]:
match_criteria: List[MatchCriteria] = []
actions: List[KeyAction] = []
alias_map: Dict[str, ActionAlias] = {}
entries = []
for line in lines:
line = line.strip()
@ -39,7 +43,7 @@ def parse(lines: Iterable[str]) -> Generator[OpenAction, None, None]:
continue
if not line:
if match_criteria and actions:
yield OpenAction(tuple(match_criteria), tuple(actions))
entries.append((tuple(match_criteria), tuple(actions)))
match_criteria = []
actions = []
continue
@ -50,18 +54,22 @@ def parse(lines: Iterable[str]) -> Generator[OpenAction, None, None]:
key = key.lower()
if key == 'action':
with to_cmdline_implementation.filter_env_vars('URL', 'FILE_PATH', 'FILE', 'FRAGMENT'):
x = parse_key_action(rest)
if x is not None:
for x in parse_key_actions(rest):
actions.append(x)
elif key in ('mime', 'ext', 'protocol', 'file', 'path', 'url', 'fragment_matches'):
if key != 'url':
rest = rest.lower()
match_criteria.append(MatchCriteria(cast(MatchType, key), rest))
elif key == 'action_alias':
for (alias_name, args) in action_alias(rest):
alias_map[alias_name] = ActionAlias(args[0], args=tuple(args[1:]))
else:
log_error(f'Ignoring malformed open actions line: {line}')
for (mc, ac) in entries:
yield OpenAction(mc, tuple(resolve_aliases_in_action(a, alias_map) for a in ac))
if match_criteria and actions:
yield OpenAction(tuple(match_criteria), tuple(actions))
yield OpenAction(tuple(match_criteria), tuple(resolve_aliases_in_action(a, alias_map) for a in actions))
def url_matches_criterion(purl: 'ParseResult', url: str, unquoted_path: str, mc: MatchCriteria) -> bool:
@ -142,7 +150,7 @@ def url_matches_criteria(purl: 'ParseResult', url: str, unquoted_path: str, crit
return True
def actions_for_url_from_list(url: str, actions: Iterable[OpenAction]) -> Generator[KeyAction, None, None]:
def actions_for_url_from_list(url: str, actions: Iterable[OpenAction]) -> Iterator[KeyAction]:
try:
purl = urlparse(url)
except Exception:
@ -184,7 +192,7 @@ def load_open_actions() -> Tuple[OpenAction, ...]:
return tuple(parse(f))
def actions_for_url(url: str, actions_spec: Optional[str] = None) -> Generator[KeyAction, None, None]:
def actions_for_url(url: str, actions_spec: Optional[str] = None) -> Iterator[KeyAction]:
if actions_spec is None:
actions = load_open_actions()
else:

View File

@ -2870,15 +2870,23 @@ for instance, to remove the default shortcuts.
'''
)
opt('+action_alias', 'launch_tab launch --type=tab --cwd=current',
option_type='action_alias',
add_to_default=False,
long_text='''
Define aliases to avoid repeating the same options in multiple mappings. Aliases
can be defined for the :ref:`launch <action-launch>`, :ref:`kitten <action-kitten>`
and :ref:`action-remote_control` actions. For example, the above alias allows you
to create mappings to launch a new tab without duplication::
map f1 launch_tab vim
map f2 launch_tab emacs
''')
opt('+kitten_alias', 'hints hints --hints-offset=0',
option_type='kitten_alias',
add_to_default=False,
long_text='''
You can create aliases for kitten names, this allows overriding the defaults for
kitten options and can also be used to shorten repeated mappings of the same
kitten with a specific group of options. For example, the above alias changes
the default value of :option:`kitty +kitten hints --hints-offset` to zero for
all mappings, including the builtin ones.
long_text='''Deprecated, use :opt:`action_alias` instead.
'''
)

13
kitty/options/parse.py generated
View File

@ -6,13 +6,13 @@ from kitty.conf.utils import (
unit_float
)
from kitty.options.utils import (
active_tab_title_template, adjust_baseline, adjust_line_height, allow_hyperlinks,
action_alias, active_tab_title_template, adjust_baseline, adjust_line_height, allow_hyperlinks,
allow_remote_control, box_drawing_scale, clear_all_mouse_actions, clear_all_shortcuts,
clipboard_control, config_or_absolute_path, copy_on_select, cursor_text_color,
deprecated_hide_window_decorations_aliases, deprecated_macos_show_window_title_in_menubar_alias,
deprecated_send_text, disable_ligatures, edge_width, env, font_features, hide_window_decorations,
kitten_alias, macos_option_as_alt, macos_titlebar_color, optional_edge_width, parse_map,
parse_mouse_map, resize_draw_strategy, scrollback_lines, scrollback_pager_history_size, symbol_map,
macos_option_as_alt, macos_titlebar_color, optional_edge_width, parse_map, parse_mouse_map,
resize_draw_strategy, scrollback_lines, scrollback_pager_history_size, symbol_map,
tab_activity_symbol, tab_bar_edge, tab_bar_margin_height, tab_bar_min_tabs, tab_fade,
tab_font_style, tab_separator, tab_title_template, to_cursor_shape, to_font_size, to_layout_names,
to_modifiers, url_prefixes, url_style, visual_window_select_characters, watcher,
@ -22,6 +22,10 @@ from kitty.options.utils import (
class Parser:
def action_alias(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
for k, v in action_alias(val):
ans["action_alias"][k] = v
def active_border_color(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['active_border_color'] = to_color_or_none(val)
@ -1006,7 +1010,7 @@ class Parser:
ans['italic_font'] = str(val)
def kitten_alias(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
for k, v in kitten_alias(val):
for k, v in action_alias(val):
ans["kitten_alias"][k] = v
def kitty_mod(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
@ -1309,6 +1313,7 @@ class Parser:
def create_result_dict() -> typing.Dict[str, typing.Any]:
return {
'action_alias': {},
'env': {},
'font_features': {},
'kitten_alias': {},

289
kitty/options/types.py generated
View File

@ -43,6 +43,7 @@ else:
choices_for_tab_switch_strategy = str
option_names = ( # {{{
'action_alias',
'active_border_color',
'active_tab_background',
'active_tab_font_style',
@ -583,6 +584,7 @@ class Options:
window_padding_width: FloatEdges = FloatEdges(left=0, top=0, right=0, bottom=0)
window_resize_step_cells: int = 2
window_resize_step_lines: int = 2
action_alias: typing.Dict[str, typing.List[str]] = {}
env: typing.Dict[str, str] = {}
font_features: typing.Dict[str, typing.Tuple[kitty.fonts.FontFeature, ...]] = {}
kitten_alias: typing.Dict[str, typing.List[str]] = {}
@ -698,6 +700,7 @@ class Options:
defaults = Options()
defaults.action_alias = {}
defaults.env = {}
defaults.font_features = {}
defaults.kitten_alias = {}
@ -705,252 +708,252 @@ defaults.symbol_map = {}
defaults.watcher = {}
defaults.map = [
# copy_to_clipboard
KeyDefinition(False, KeyAction('copy_to_clipboard'), 1024, False, 99, ()),
KeyDefinition(False, (KeyAction('copy_to_clipboard'),), 1024, False, 99, ()),
# paste_from_clipboard
KeyDefinition(False, KeyAction('paste_from_clipboard'), 1024, False, 118, ()),
KeyDefinition(False, (KeyAction('paste_from_clipboard'),), 1024, False, 118, ()),
# paste_from_selection
KeyDefinition(False, KeyAction('paste_from_selection'), 1024, False, 115, ()),
KeyDefinition(False, (KeyAction('paste_from_selection'),), 1024, False, 115, ()),
# paste_from_selection
KeyDefinition(False, KeyAction('paste_from_selection'), 1, False, 57348, ()),
KeyDefinition(False, (KeyAction('paste_from_selection'),), 1, False, 57348, ()),
# pass_selection_to_program
KeyDefinition(False, KeyAction('pass_selection_to_program'), 1024, False, 111, ()),
KeyDefinition(False, (KeyAction('pass_selection_to_program'),), 1024, False, 111, ()),
# scroll_line_up
KeyDefinition(False, KeyAction('scroll_line_up'), 1024, False, 57352, ()),
KeyDefinition(False, (KeyAction('scroll_line_up'),), 1024, False, 57352, ()),
# scroll_line_up
KeyDefinition(False, KeyAction('scroll_line_up'), 1024, False, 107, ()),
KeyDefinition(False, (KeyAction('scroll_line_up'),), 1024, False, 107, ()),
# scroll_line_down
KeyDefinition(False, KeyAction('scroll_line_down'), 1024, False, 57353, ()),
KeyDefinition(False, (KeyAction('scroll_line_down'),), 1024, False, 57353, ()),
# scroll_line_down
KeyDefinition(False, KeyAction('scroll_line_down'), 1024, False, 106, ()),
KeyDefinition(False, (KeyAction('scroll_line_down'),), 1024, False, 106, ()),
# scroll_page_up
KeyDefinition(False, KeyAction('scroll_page_up'), 1024, False, 57354, ()),
KeyDefinition(False, (KeyAction('scroll_page_up'),), 1024, False, 57354, ()),
# scroll_page_down
KeyDefinition(False, KeyAction('scroll_page_down'), 1024, False, 57355, ()),
KeyDefinition(False, (KeyAction('scroll_page_down'),), 1024, False, 57355, ()),
# scroll_home
KeyDefinition(False, KeyAction('scroll_home'), 1024, False, 57356, ()),
KeyDefinition(False, (KeyAction('scroll_home'),), 1024, False, 57356, ()),
# scroll_end
KeyDefinition(False, KeyAction('scroll_end'), 1024, False, 57357, ()),
KeyDefinition(False, (KeyAction('scroll_end'),), 1024, False, 57357, ()),
# scroll_to_previous_prompt
KeyDefinition(False, KeyAction('scroll_to_prompt', (-1,)), 1024, False, 122, ()),
KeyDefinition(False, (KeyAction('scroll_to_prompt', (-1,)),), 1024, False, 122, ()),
# scroll_to_next_prompt
KeyDefinition(False, KeyAction('scroll_to_prompt', (1,)), 1024, False, 120, ()),
KeyDefinition(False, (KeyAction('scroll_to_prompt', (1,)),), 1024, False, 120, ()),
# show_scrollback
KeyDefinition(False, KeyAction('show_scrollback'), 1024, False, 104, ()),
KeyDefinition(False, (KeyAction('show_scrollback'),), 1024, False, 104, ()),
# show_last_command_output
KeyDefinition(False, KeyAction('show_last_command_output'), 1024, False, 103, ()),
KeyDefinition(False, (KeyAction('show_last_command_output'),), 1024, False, 103, ()),
# new_window
KeyDefinition(False, KeyAction('new_window'), 1024, False, 57345, ()),
KeyDefinition(False, (KeyAction('new_window'),), 1024, False, 57345, ()),
# new_os_window
KeyDefinition(False, KeyAction('new_os_window'), 1024, False, 110, ()),
KeyDefinition(False, (KeyAction('new_os_window'),), 1024, False, 110, ()),
# close_window
KeyDefinition(False, KeyAction('close_window'), 1024, False, 119, ()),
KeyDefinition(False, (KeyAction('close_window'),), 1024, False, 119, ()),
# next_window
KeyDefinition(False, KeyAction('next_window'), 1024, False, 93, ()),
KeyDefinition(False, (KeyAction('next_window'),), 1024, False, 93, ()),
# previous_window
KeyDefinition(False, KeyAction('previous_window'), 1024, False, 91, ()),
KeyDefinition(False, (KeyAction('previous_window'),), 1024, False, 91, ()),
# move_window_forward
KeyDefinition(False, KeyAction('move_window_forward'), 1024, False, 102, ()),
KeyDefinition(False, (KeyAction('move_window_forward'),), 1024, False, 102, ()),
# move_window_backward
KeyDefinition(False, KeyAction('move_window_backward'), 1024, False, 98, ()),
KeyDefinition(False, (KeyAction('move_window_backward'),), 1024, False, 98, ()),
# move_window_to_top
KeyDefinition(False, KeyAction('move_window_to_top'), 1024, False, 96, ()),
KeyDefinition(False, (KeyAction('move_window_to_top'),), 1024, False, 96, ()),
# start_resizing_window
KeyDefinition(False, KeyAction('start_resizing_window'), 1024, False, 114, ()),
KeyDefinition(False, (KeyAction('start_resizing_window'),), 1024, False, 114, ()),
# first_window
KeyDefinition(False, KeyAction('first_window'), 1024, False, 49, ()),
KeyDefinition(False, (KeyAction('first_window'),), 1024, False, 49, ()),
# second_window
KeyDefinition(False, KeyAction('second_window'), 1024, False, 50, ()),
KeyDefinition(False, (KeyAction('second_window'),), 1024, False, 50, ()),
# third_window
KeyDefinition(False, KeyAction('third_window'), 1024, False, 51, ()),
KeyDefinition(False, (KeyAction('third_window'),), 1024, False, 51, ()),
# fourth_window
KeyDefinition(False, KeyAction('fourth_window'), 1024, False, 52, ()),
KeyDefinition(False, (KeyAction('fourth_window'),), 1024, False, 52, ()),
# fifth_window
KeyDefinition(False, KeyAction('fifth_window'), 1024, False, 53, ()),
KeyDefinition(False, (KeyAction('fifth_window'),), 1024, False, 53, ()),
# sixth_window
KeyDefinition(False, KeyAction('sixth_window'), 1024, False, 54, ()),
KeyDefinition(False, (KeyAction('sixth_window'),), 1024, False, 54, ()),
# seventh_window
KeyDefinition(False, KeyAction('seventh_window'), 1024, False, 55, ()),
KeyDefinition(False, (KeyAction('seventh_window'),), 1024, False, 55, ()),
# eighth_window
KeyDefinition(False, KeyAction('eighth_window'), 1024, False, 56, ()),
KeyDefinition(False, (KeyAction('eighth_window'),), 1024, False, 56, ()),
# ninth_window
KeyDefinition(False, KeyAction('ninth_window'), 1024, False, 57, ()),
KeyDefinition(False, (KeyAction('ninth_window'),), 1024, False, 57, ()),
# tenth_window
KeyDefinition(False, KeyAction('tenth_window'), 1024, False, 48, ()),
KeyDefinition(False, (KeyAction('tenth_window'),), 1024, False, 48, ()),
# focus_visible_window
KeyDefinition(False, KeyAction('focus_visible_window'), 1024, False, 57370, ()),
KeyDefinition(False, (KeyAction('focus_visible_window'),), 1024, False, 57370, ()),
# swap_with_window
KeyDefinition(False, KeyAction('swap_with_window'), 1024, False, 57371, ()),
KeyDefinition(False, (KeyAction('swap_with_window'),), 1024, False, 57371, ()),
# next_tab
KeyDefinition(False, KeyAction('next_tab'), 1024, False, 57351, ()),
KeyDefinition(False, (KeyAction('next_tab'),), 1024, False, 57351, ()),
# next_tab
KeyDefinition(False, KeyAction('next_tab'), 4, False, 57346, ()),
KeyDefinition(False, (KeyAction('next_tab'),), 4, False, 57346, ()),
# previous_tab
KeyDefinition(False, KeyAction('previous_tab'), 1024, False, 57350, ()),
KeyDefinition(False, (KeyAction('previous_tab'),), 1024, False, 57350, ()),
# previous_tab
KeyDefinition(False, KeyAction('previous_tab'), 5, False, 57346, ()),
KeyDefinition(False, (KeyAction('previous_tab'),), 5, False, 57346, ()),
# new_tab
KeyDefinition(False, KeyAction('new_tab'), 1024, False, 116, ()),
KeyDefinition(False, (KeyAction('new_tab'),), 1024, False, 116, ()),
# close_tab
KeyDefinition(False, KeyAction('close_tab'), 1024, False, 113, ()),
KeyDefinition(False, (KeyAction('close_tab'),), 1024, False, 113, ()),
# move_tab_forward
KeyDefinition(False, KeyAction('move_tab_forward'), 1024, False, 46, ()),
KeyDefinition(False, (KeyAction('move_tab_forward'),), 1024, False, 46, ()),
# move_tab_backward
KeyDefinition(False, KeyAction('move_tab_backward'), 1024, False, 44, ()),
KeyDefinition(False, (KeyAction('move_tab_backward'),), 1024, False, 44, ()),
# set_tab_title
KeyDefinition(False, KeyAction('set_tab_title'), 1026, False, 116, ()),
KeyDefinition(False, (KeyAction('set_tab_title'),), 1026, False, 116, ()),
# next_layout
KeyDefinition(False, KeyAction('next_layout'), 1024, False, 108, ()),
KeyDefinition(False, (KeyAction('next_layout'),), 1024, False, 108, ()),
# increase_font_size
KeyDefinition(False, KeyAction('change_font_size', (True, '+', 2.0)), 1024, False, 61, ()),
KeyDefinition(False, (KeyAction('change_font_size', (True, '+', 2.0)),), 1024, False, 61, ()),
# increase_font_size
KeyDefinition(False, KeyAction('change_font_size', (True, '+', 2.0)), 1024, False, 43, ()),
KeyDefinition(False, (KeyAction('change_font_size', (True, '+', 2.0)),), 1024, False, 43, ()),
# increase_font_size
KeyDefinition(False, KeyAction('change_font_size', (True, '+', 2.0)), 1024, False, 57413, ()),
KeyDefinition(False, (KeyAction('change_font_size', (True, '+', 2.0)),), 1024, False, 57413, ()),
# decrease_font_size
KeyDefinition(False, KeyAction('change_font_size', (True, '-', 2.0)), 1024, False, 45, ()),
KeyDefinition(False, (KeyAction('change_font_size', (True, '-', 2.0)),), 1024, False, 45, ()),
# decrease_font_size
KeyDefinition(False, KeyAction('change_font_size', (True, '-', 2.0)), 1024, False, 57412, ()),
KeyDefinition(False, (KeyAction('change_font_size', (True, '-', 2.0)),), 1024, False, 57412, ()),
# reset_font_size
KeyDefinition(False, KeyAction('change_font_size', (True, None, 0.0)), 1024, False, 57347, ()),
KeyDefinition(False, (KeyAction('change_font_size', (True, None, 0.0)),), 1024, False, 57347, ()),
# open_url
KeyDefinition(False, KeyAction('open_url_with_hints'), 1024, False, 101, ()),
KeyDefinition(False, (KeyAction('open_url_with_hints'),), 1024, False, 101, ()),
# insert_selected_path
KeyDefinition(True, KeyAction('kitten', ('hints', '--type path --program -')), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=102),)),
KeyDefinition(True, (KeyAction('kitten', ('hints', '--type', 'path', '--program', '-')),), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=102),)),
# open_selected_path
KeyDefinition(True, KeyAction('kitten', ('hints', '--type path')), 1024, False, 112, (SingleKey(mods=1, is_native=False, key=102),)),
KeyDefinition(True, (KeyAction('kitten', ('hints', '--type', 'path')),), 1024, False, 112, (SingleKey(mods=1, is_native=False, key=102),)),
# insert_selected_line
KeyDefinition(True, KeyAction('kitten', ('hints', '--type line --program -')), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=108),)),
KeyDefinition(True, (KeyAction('kitten', ('hints', '--type', 'line', '--program', '-')),), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=108),)),
# insert_selected_word
KeyDefinition(True, KeyAction('kitten', ('hints', '--type word --program -')), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=119),)),
KeyDefinition(True, (KeyAction('kitten', ('hints', '--type', 'word', '--program', '-')),), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=119),)),
# insert_selected_hash
KeyDefinition(True, KeyAction('kitten', ('hints', '--type hash --program -')), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=104),)),
KeyDefinition(True, (KeyAction('kitten', ('hints', '--type', 'hash', '--program', '-')),), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=104),)),
# goto_file_line
KeyDefinition(True, KeyAction('kitten', ('hints', '--type linenum')), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=110),)),
KeyDefinition(True, (KeyAction('kitten', ('hints', '--type', 'linenum')),), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=110),)),
# open_selected_hyperlink
KeyDefinition(True, KeyAction('kitten', ('hints', '--type hyperlink')), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=121),)),
KeyDefinition(True, (KeyAction('kitten', ('hints', '--type', 'hyperlink')),), 1024, False, 112, (SingleKey(mods=0, is_native=False, key=121),)),
# toggle_fullscreen
KeyDefinition(False, KeyAction('toggle_fullscreen'), 1024, False, 57374, ()),
KeyDefinition(False, (KeyAction('toggle_fullscreen'),), 1024, False, 57374, ()),
# toggle_maximized
KeyDefinition(False, KeyAction('toggle_maximized'), 1024, False, 57373, ()),
KeyDefinition(False, (KeyAction('toggle_maximized'),), 1024, False, 57373, ()),
# input_unicode_character
KeyDefinition(False, KeyAction('kitten', ('unicode_input',)), 1024, False, 117, ()),
KeyDefinition(False, (KeyAction('kitten', ('unicode_input',)),), 1024, False, 117, ()),
# edit_config_file
KeyDefinition(False, KeyAction('edit_config_file'), 1024, False, 57365, ()),
KeyDefinition(False, (KeyAction('edit_config_file'),), 1024, False, 57365, ()),
# kitty_shell
KeyDefinition(False, KeyAction('kitty_shell', ('window',)), 1024, False, 57344, ()),
KeyDefinition(False, (KeyAction('kitty_shell', ('window',)),), 1024, False, 57344, ()),
# increase_background_opacity
KeyDefinition(True, KeyAction('set_background_opacity', ('+0.1',)), 1024, False, 97, (SingleKey(mods=0, is_native=False, key=109),)),
KeyDefinition(True, (KeyAction('set_background_opacity', ('+0.1',)),), 1024, False, 97, (SingleKey(mods=0, is_native=False, key=109),)),
# decrease_background_opacity
KeyDefinition(True, KeyAction('set_background_opacity', ('-0.1',)), 1024, False, 97, (SingleKey(mods=0, is_native=False, key=108),)),
KeyDefinition(True, (KeyAction('set_background_opacity', ('-0.1',)),), 1024, False, 97, (SingleKey(mods=0, is_native=False, key=108),)),
# full_background_opacity
KeyDefinition(True, KeyAction('set_background_opacity', ('1',)), 1024, False, 97, (SingleKey(mods=0, is_native=False, key=49),)),
KeyDefinition(True, (KeyAction('set_background_opacity', ('1',)),), 1024, False, 97, (SingleKey(mods=0, is_native=False, key=49),)),
# reset_background_opacity
KeyDefinition(True, KeyAction('set_background_opacity', ('default',)), 1024, False, 97, (SingleKey(mods=0, is_native=False, key=100),)),
KeyDefinition(True, (KeyAction('set_background_opacity', ('default',)),), 1024, False, 97, (SingleKey(mods=0, is_native=False, key=100),)),
# reset_terminal
KeyDefinition(False, KeyAction('clear_terminal', ('reset', True)), 1024, False, 57349, ()),
KeyDefinition(False, (KeyAction('clear_terminal', ('reset', True)),), 1024, False, 57349, ()),
# reload_config_file
KeyDefinition(False, KeyAction('load_config_file'), 1024, False, 57368, ()),
KeyDefinition(False, (KeyAction('load_config_file'),), 1024, False, 57368, ()),
# debug_config
KeyDefinition(False, KeyAction('debug_config'), 1024, False, 57369, ()),
KeyDefinition(False, (KeyAction('debug_config'),), 1024, False, 57369, ()),
]
if is_macos:
defaults.map.append(KeyDefinition(False, KeyAction('copy_to_clipboard'), 8, False, 99, ()))
defaults.map.append(KeyDefinition(False, KeyAction('paste_from_clipboard'), 8, False, 118, ()))
defaults.map.append(KeyDefinition(False, KeyAction('scroll_line_up'), 10, False, 57354, ()))
defaults.map.append(KeyDefinition(False, KeyAction('scroll_line_up'), 8, False, 57352, ()))
defaults.map.append(KeyDefinition(False, KeyAction('scroll_line_down'), 10, False, 57355, ()))
defaults.map.append(KeyDefinition(False, KeyAction('scroll_line_down'), 8, False, 57353, ()))
defaults.map.append(KeyDefinition(False, KeyAction('scroll_page_up'), 8, False, 57354, ()))
defaults.map.append(KeyDefinition(False, KeyAction('scroll_page_down'), 8, False, 57355, ()))
defaults.map.append(KeyDefinition(False, KeyAction('scroll_home'), 8, False, 57356, ()))
defaults.map.append(KeyDefinition(False, KeyAction('scroll_end'), 8, False, 57357, ()))
defaults.map.append(KeyDefinition(False, KeyAction('new_window'), 8, False, 57345, ()))
defaults.map.append(KeyDefinition(False, KeyAction('new_os_window'), 8, False, 110, ()))
defaults.map.append(KeyDefinition(False, KeyAction('close_window'), 9, False, 100, ()))
defaults.map.append(KeyDefinition(False, KeyAction('start_resizing_window'), 8, False, 114, ()))
defaults.map.append(KeyDefinition(False, KeyAction('first_window'), 8, False, 49, ()))
defaults.map.append(KeyDefinition(False, KeyAction('second_window'), 8, False, 50, ()))
defaults.map.append(KeyDefinition(False, KeyAction('third_window'), 8, False, 51, ()))
defaults.map.append(KeyDefinition(False, KeyAction('fourth_window'), 8, False, 52, ()))
defaults.map.append(KeyDefinition(False, KeyAction('fifth_window'), 8, False, 53, ()))
defaults.map.append(KeyDefinition(False, KeyAction('sixth_window'), 8, False, 54, ()))
defaults.map.append(KeyDefinition(False, KeyAction('seventh_window'), 8, False, 55, ()))
defaults.map.append(KeyDefinition(False, KeyAction('eighth_window'), 8, False, 56, ()))
defaults.map.append(KeyDefinition(False, KeyAction('ninth_window'), 8, False, 57, ()))
defaults.map.append(KeyDefinition(False, KeyAction('next_tab'), 9, False, 93, ()))
defaults.map.append(KeyDefinition(False, KeyAction('previous_tab'), 9, False, 91, ()))
defaults.map.append(KeyDefinition(False, KeyAction('new_tab'), 8, False, 116, ()))
defaults.map.append(KeyDefinition(False, KeyAction('close_tab'), 8, False, 119, ()))
defaults.map.append(KeyDefinition(False, KeyAction('close_os_window'), 9, False, 119, ()))
defaults.map.append(KeyDefinition(False, KeyAction('set_tab_title'), 9, False, 105, ()))
defaults.map.append(KeyDefinition(False, KeyAction('change_font_size', (True, '+', 2.0)), 8, False, 43, ()))
defaults.map.append(KeyDefinition(False, KeyAction('change_font_size', (True, '+', 2.0)), 8, False, 61, ()))
defaults.map.append(KeyDefinition(False, KeyAction('change_font_size', (True, '+', 2.0)), 9, False, 61, ()))
defaults.map.append(KeyDefinition(False, KeyAction('change_font_size', (True, '-', 2.0)), 8, False, 45, ()))
defaults.map.append(KeyDefinition(False, KeyAction('change_font_size', (True, '-', 2.0)), 9, False, 45, ()))
defaults.map.append(KeyDefinition(False, KeyAction('change_font_size', (True, None, 0.0)), 8, False, 48, ()))
defaults.map.append(KeyDefinition(False, KeyAction('kitten', ('unicode_input',)), 12, False, 32, ()))
defaults.map.append(KeyDefinition(False, KeyAction('edit_config_file'), 8, False, 44, ()))
defaults.map.append(KeyDefinition(False, KeyAction('clear_terminal', ('reset', True)), 10, False, 114, ()))
defaults.map.append(KeyDefinition(False, KeyAction('load_config_file'), 12, False, 44, ()))
defaults.map.append(KeyDefinition(False, KeyAction('debug_config'), 10, False, 44, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('copy_to_clipboard'),), 8, False, 99, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('paste_from_clipboard'),), 8, False, 118, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('scroll_line_up'),), 10, False, 57354, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('scroll_line_up'),), 8, False, 57352, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('scroll_line_down'),), 10, False, 57355, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('scroll_line_down'),), 8, False, 57353, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('scroll_page_up'),), 8, False, 57354, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('scroll_page_down'),), 8, False, 57355, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('scroll_home'),), 8, False, 57356, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('scroll_end'),), 8, False, 57357, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('new_window'),), 8, False, 57345, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('new_os_window'),), 8, False, 110, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('close_window'),), 9, False, 100, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('start_resizing_window'),), 8, False, 114, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('first_window'),), 8, False, 49, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('second_window'),), 8, False, 50, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('third_window'),), 8, False, 51, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('fourth_window'),), 8, False, 52, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('fifth_window'),), 8, False, 53, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('sixth_window'),), 8, False, 54, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('seventh_window'),), 8, False, 55, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('eighth_window'),), 8, False, 56, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('ninth_window'),), 8, False, 57, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('next_tab'),), 9, False, 93, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('previous_tab'),), 9, False, 91, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('new_tab'),), 8, False, 116, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('close_tab'),), 8, False, 119, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('close_os_window'),), 9, False, 119, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('set_tab_title'),), 9, False, 105, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('change_font_size', (True, '+', 2.0)),), 8, False, 43, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('change_font_size', (True, '+', 2.0)),), 8, False, 61, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('change_font_size', (True, '+', 2.0)),), 9, False, 61, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('change_font_size', (True, '-', 2.0)),), 8, False, 45, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('change_font_size', (True, '-', 2.0)),), 9, False, 45, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('change_font_size', (True, None, 0.0)),), 8, False, 48, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('kitten', ('unicode_input',)),), 12, False, 32, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('edit_config_file'),), 8, False, 44, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('clear_terminal', ('reset', True)),), 10, False, 114, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('load_config_file'),), 12, False, 44, ()))
defaults.map.append(KeyDefinition(False, (KeyAction('debug_config'),), 10, False, 44, ()))
defaults.mouse_map = [
# click_url_or_select
MouseMapping(0, 0, -2, False, KeyAction('mouse_handle_click', ('selection', 'link', 'prompt'))),
MouseMapping(0, 0, -2, False, (KeyAction('mouse_handle_click', ('selection', 'link', 'prompt')),)),
# click_url_or_select_grabbed
MouseMapping(0, 1, -2, True, KeyAction('mouse_handle_click', ('selection', 'link', 'prompt'))),
MouseMapping(0, 1, -2, True, (KeyAction('mouse_handle_click', ('selection', 'link', 'prompt')),)),
# click_url_or_select_grabbed
MouseMapping(0, 1, -2, False, KeyAction('mouse_handle_click', ('selection', 'link', 'prompt'))),
MouseMapping(0, 1, -2, False, (KeyAction('mouse_handle_click', ('selection', 'link', 'prompt')),)),
# click_url
MouseMapping(0, 5, -1, True, KeyAction('mouse_handle_click', ('link',))),
MouseMapping(0, 5, -1, True, (KeyAction('mouse_handle_click', ('link',)),)),
# click_url
MouseMapping(0, 5, -1, False, KeyAction('mouse_handle_click', ('link',))),
MouseMapping(0, 5, -1, False, (KeyAction('mouse_handle_click', ('link',)),)),
# click_url_discard
MouseMapping(0, 5, 1, True, KeyAction('discard_event')),
MouseMapping(0, 5, 1, True, (KeyAction('discard_event'),)),
# paste_selection
MouseMapping(2, 0, -1, False, KeyAction('paste_from_selection')),
MouseMapping(2, 0, -1, False, (KeyAction('paste_from_selection'),)),
# start_simple_selection
MouseMapping(0, 0, 1, False, KeyAction('mouse_selection', (0,))),
MouseMapping(0, 0, 1, False, (KeyAction('mouse_selection', (0,)),)),
# start_rectangle_selection
MouseMapping(0, 6, 1, False, KeyAction('mouse_selection', (2,))),
MouseMapping(0, 6, 1, False, (KeyAction('mouse_selection', (2,)),)),
# select_word
MouseMapping(0, 0, 2, False, KeyAction('mouse_selection', (3,))),
MouseMapping(0, 0, 2, False, (KeyAction('mouse_selection', (3,)),)),
# select_line
MouseMapping(0, 0, 3, False, KeyAction('mouse_selection', (4,))),
MouseMapping(0, 0, 3, False, (KeyAction('mouse_selection', (4,)),)),
# select_line_from_point
MouseMapping(0, 6, 3, False, KeyAction('mouse_selection', (5,))),
MouseMapping(0, 6, 3, False, (KeyAction('mouse_selection', (5,)),)),
# extend_selection
MouseMapping(1, 0, 1, False, KeyAction('mouse_selection', (1,))),
MouseMapping(1, 0, 1, False, (KeyAction('mouse_selection', (1,)),)),
# paste_selection_grabbed
MouseMapping(2, 1, -1, True, KeyAction('paste_selection')),
MouseMapping(2, 1, -1, True, (KeyAction('paste_selection'),)),
# paste_selection_grabbed
MouseMapping(2, 1, -1, False, KeyAction('paste_selection')),
MouseMapping(2, 1, -1, False, (KeyAction('paste_selection'),)),
# paste_selection_grabbed
MouseMapping(2, 1, 1, True, KeyAction('discard_event')),
MouseMapping(2, 1, 1, True, (KeyAction('discard_event'),)),
# start_simple_selection_grabbed
MouseMapping(0, 1, 1, True, KeyAction('mouse_selection', (0,))),
MouseMapping(0, 1, 1, True, (KeyAction('mouse_selection', (0,)),)),
# start_simple_selection_grabbed
MouseMapping(0, 1, 1, False, KeyAction('mouse_selection', (0,))),
MouseMapping(0, 1, 1, False, (KeyAction('mouse_selection', (0,)),)),
# start_rectangle_selection_grabbed
MouseMapping(0, 7, 1, True, KeyAction('mouse_selection', (2,))),
MouseMapping(0, 7, 1, True, (KeyAction('mouse_selection', (2,)),)),
# start_rectangle_selection_grabbed
MouseMapping(0, 7, 1, False, KeyAction('mouse_selection', (2,))),
MouseMapping(0, 7, 1, False, (KeyAction('mouse_selection', (2,)),)),
# select_word_grabbed
MouseMapping(0, 1, 2, True, KeyAction('mouse_selection', (3,))),
MouseMapping(0, 1, 2, True, (KeyAction('mouse_selection', (3,)),)),
# select_word_grabbed
MouseMapping(0, 1, 2, False, KeyAction('mouse_selection', (3,))),
MouseMapping(0, 1, 2, False, (KeyAction('mouse_selection', (3,)),)),
# select_line_grabbed
MouseMapping(0, 1, 3, True, KeyAction('mouse_selection', (4,))),
MouseMapping(0, 1, 3, True, (KeyAction('mouse_selection', (4,)),)),
# select_line_grabbed
MouseMapping(0, 1, 3, False, KeyAction('mouse_selection', (4,))),
MouseMapping(0, 1, 3, False, (KeyAction('mouse_selection', (4,)),)),
# select_line_from_point_grabbed
MouseMapping(0, 7, 3, True, KeyAction('mouse_selection', (5,))),
MouseMapping(0, 7, 3, True, (KeyAction('mouse_selection', (5,)),)),
# select_line_from_point_grabbed
MouseMapping(0, 7, 3, False, KeyAction('mouse_selection', (5,))),
MouseMapping(0, 7, 3, False, (KeyAction('mouse_selection', (5,)),)),
# extend_selection_grabbed
MouseMapping(1, 1, 1, True, KeyAction('mouse_selection', (1,))),
MouseMapping(1, 1, 1, True, (KeyAction('mouse_selection', (1,)),)),
# extend_selection_grabbed
MouseMapping(1, 1, 1, False, KeyAction('mouse_selection', (1,))),
MouseMapping(1, 1, 1, False, (KeyAction('mouse_selection', (1,)),)),
# show_clicked_cmd_output_ungrabbed
MouseMapping(1, 5, 1, False, KeyAction('mouse_show_command_output')),
MouseMapping(1, 5, 1, False, (KeyAction('mouse_show_command_output'),)),
]

View File

@ -6,17 +6,19 @@ import os
import re
import sys
from typing import (
Any, Callable, Container, Dict, Iterable, List, NamedTuple, Optional,
Sequence, Tuple, Union
Any, Callable, Container, Dict, Iterable, Iterator, List, NamedTuple,
Optional, Sequence, Tuple, Union
)
import kitty.fast_data_types as defines
from kitty.conf.utils import (
KeyAction, KeyFuncWrapper, positive_float, positive_int,
python_string, to_bool, to_cmdline, to_color, uniq, unit_float
KeyAction, KeyFuncWrapper, positive_float, positive_int, python_string,
to_bool, to_cmdline, to_color, uniq, unit_float
)
from kitty.constants import config_dir, is_macos
from kitty.fast_data_types import CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE, Color
from kitty.fast_data_types import (
CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE, Color
)
from kitty.fonts import FontFeature
from kitty.key_names import (
character_key_name_aliases, functional_key_name_aliases,
@ -26,10 +28,10 @@ from kitty.rgb import color_as_int
from kitty.types import FloatEdges, MouseEvent, SingleKey
from kitty.utils import expandvars, log_error
KeyMap = Dict[SingleKey, KeyAction]
MouseMap = Dict[MouseEvent, KeyAction]
KeyMap = Dict[SingleKey, Tuple[KeyAction, ...]]
MouseMap = Dict[MouseEvent, Tuple[KeyAction, ...]]
KeySequence = Tuple[SingleKey, ...]
SubSequenceMap = Dict[KeySequence, KeyAction]
SubSequenceMap = Dict[KeySequence, Tuple[KeyAction, ...]]
SequenceMap = Dict[SingleKey, SubSequenceMap]
MINIMUM_FONT_SIZE = 4
default_tab_separator = ''
@ -58,14 +60,6 @@ def shlex_parse(func: str, rest: str) -> FuncArgsType:
return func, to_cmdline(rest)
@func_with_args('combine')
def combine_parse(func: str, rest: str) -> FuncArgsType:
sep, rest = rest.split(maxsplit=1)
parts = re.split(r'\s*' + re.escape(sep) + r'\s*', rest)
args = tuple(map(parse_key_action, filter(None, parts)))
return func, args
def parse_send_text_bytes(text: str) -> bytes:
return python_string(text).encode('utf-8')
@ -91,7 +85,7 @@ def kitten_parse(func: str, rest: str) -> FuncArgsType:
else:
args = rest.split(maxsplit=2)[1:]
func = 'kitten'
return func, args
return func, [args[0]] + (to_cmdline(args[1]) if len(args) > 1 else [])
@func_with_args('goto_tab')
@ -772,11 +766,14 @@ def watcher(val: str, current_val: Container[str]) -> Iterable[Tuple[str, str]]:
yield val, val
def kitten_alias(val: str) -> Iterable[Tuple[str, List[str]]]:
parts = val.split(maxsplit=2)
if len(parts) >= 2:
name = parts.pop(0)
yield name, parts
def action_alias(val: str) -> Iterable[Tuple[str, List[str]]]:
parts = val.split(maxsplit=1)
if len(parts) > 1:
alias_name, rest = parts
yield alias_name, to_cmdline(rest)
kitten_alias = action_alias
def symbol_map(val: str) -> Iterable[Tuple[Tuple[int, int], str]]:
@ -806,12 +803,24 @@ def symbol_map(val: str) -> Iterable[Tuple[Tuple[int, int], str]]:
yield (a, b), family
def parse_key_action(action: str, action_type: str = 'map') -> Optional[KeyAction]:
def parse_combine(rest: str, action_type: str = 'map') -> Iterator[KeyAction]:
sep, rest = rest.split(maxsplit=1)
parts = re.split(r'\s*' + re.escape(sep) + r'\s*', rest)
for x in parts:
if x:
yield from parse_key_actions(x, action_type)
def parse_key_actions(action: str, action_type: str = 'map') -> Iterator[KeyAction]:
parts = action.strip().split(maxsplit=1)
func = parts[0]
if len(parts) == 1:
return KeyAction(func, ())
yield KeyAction(func, ())
return
rest = parts[1]
if func == 'combine':
yield from parse_combine(rest, action_type)
else:
parser = func_with_args.get(func)
if parser is not None:
try:
@ -819,44 +828,64 @@ def parse_key_action(action: str, action_type: str = 'map') -> Optional[KeyActio
except Exception as err:
log_error(f'Ignoring invalid {action_type} action: {action} with err: {err}')
else:
return KeyAction(func, tuple(args))
yield KeyAction(func, tuple(args))
else:
log_error(f'Ignoring unknown {action_type} action: {action}')
return None
class ActionAlias(NamedTuple):
func_name: str
args: Tuple[str, ...]
second_arg_test: Optional[Callable[[Any], bool]] = None
def build_action_aliases(raw: Dict[str, List[str]], first_arg_replacement: str = '') -> Dict[str, List[ActionAlias]]:
ans: Dict[str, List[ActionAlias]] = {}
if first_arg_replacement:
for alias_name, args in raw.items():
ans.setdefault('kitten', []).append(ActionAlias('kitten', tuple(args), alias_name.__eq__))
else:
for alias_name, args in raw.items():
ans[alias_name] = [ActionAlias(args[0], tuple(args[1:]))]
return ans
def resolve_aliases_in_action(action: KeyAction, aliases: Dict[str, List[ActionAlias]]) -> KeyAction:
for alias in aliases.get(action.func, ()):
if alias.second_arg_test is None:
return action._replace(func=alias.func_name, args=alias.args)
if action.args and alias.second_arg_test(action.args[0]):
return action._replace(func=alias.func_name, args=alias.args)
return action
class BaseDefinition:
action: KeyAction
actions: Tuple[KeyAction, ...]
no_op_actions = frozenset(('noop', 'no-op', 'no_op'))
def resolve_kitten_aliases(self, aliases: Dict[str, List[str]]) -> KeyAction:
if not self.action.args or not aliases:
return self.action
kitten = self.action.args[0]
rest = str(self.action.args[1] if len(self.action.args) > 1 else '')
changed = False
for key, expanded in aliases.items():
if key == kitten:
changed = True
kitten = expanded[0]
if len(expanded) > 1:
rest = expanded[1] + ' ' + rest
return self.action._replace(args=(kitten, rest.rstrip())) if changed else self.action
@property
def is_no_op(self) -> bool:
return len(self.actions) == 1 and self.actions[0].func in self.no_op_actions
def resolve_aliases(self, aliases: Dict[str, List[ActionAlias]]) -> Tuple[KeyAction, ...]:
self.actions = tuple(resolve_aliases_in_action(a, aliases) for a in self.actions)
return self.actions
class MouseMapping(BaseDefinition):
def __init__(self, button: int, mods: int, repeat_count: int, grabbed: bool, action: KeyAction):
def __init__(self, button: int, mods: int, repeat_count: int, grabbed: bool, actions: Tuple[KeyAction, ...]):
self.button = button
self.mods = mods
self.repeat_count = repeat_count
self.grabbed = grabbed
self.action = action
self.actions = actions
def __repr__(self) -> str:
return f'MouseMapping({self.button}, {self.mods}, {self.repeat_count}, {self.grabbed}, {self.action})'
return f'MouseMapping({self.button}, {self.mods}, {self.repeat_count}, {self.grabbed}, {self.actions})'
def resolve_and_copy(self, kitty_mod: int, aliases: Dict[str, List[str]]) -> 'MouseMapping':
return MouseMapping(self.button, defines.resolve_key_mods(kitty_mod, self.mods), self.repeat_count, self.grabbed, self.resolve_kitten_aliases(aliases))
def resolve_and_copy(self, kitty_mod: int, aliases: Dict[str, List[ActionAlias]]) -> 'MouseMapping':
return MouseMapping(self.button, defines.resolve_key_mods(kitty_mod, self.mods), self.repeat_count, self.grabbed, self.resolve_aliases(aliases))
@property
def trigger(self) -> MouseEvent:
@ -865,21 +894,21 @@ class MouseMapping(BaseDefinition):
class KeyDefinition(BaseDefinition):
def __init__(self, is_sequence: bool, action: KeyAction, mods: int, is_native: bool, key: int, rest: Tuple[SingleKey, ...] = ()):
def __init__(self, is_sequence: bool, actions: Tuple[KeyAction, ...], mods: int, is_native: bool, key: int, rest: Tuple[SingleKey, ...] = ()):
self.is_sequence = is_sequence
self.action = action
self.actions = actions
self.trigger = SingleKey(mods, is_native, key)
self.rest = rest
def __repr__(self) -> str:
return f'KeyDefinition({self.is_sequence}, {self.action}, {self.trigger.mods}, {self.trigger.is_native}, {self.trigger.key}, {self.rest})'
return f'KeyDefinition({self.is_sequence}, {self.actions}, {self.trigger.mods}, {self.trigger.is_native}, {self.trigger.key}, {self.rest})'
def resolve_and_copy(self, kitty_mod: int, aliases: Dict[str, List[str]]) -> 'KeyDefinition':
def resolve_and_copy(self, kitty_mod: int, aliases: Dict[str, List[ActionAlias]]) -> 'KeyDefinition':
def r(k: SingleKey) -> SingleKey:
mods = defines.resolve_key_mods(kitty_mod, k.mods)
return k._replace(mods=mods)
return KeyDefinition(
self.is_sequence, self.resolve_kitten_aliases(aliases),
self.is_sequence, self.resolve_aliases(aliases),
defines.resolve_key_mods(kitty_mod, self.trigger.mods),
self.trigger.is_native, self.trigger.key, tuple(map(r, self.rest)))
@ -920,12 +949,11 @@ def parse_map(val: str) -> Iterable[KeyDefinition]:
log_error(f'Shortcut: {sc} has unknown key, ignoring')
return
try:
paction = parse_key_action(action)
paction = tuple(parse_key_actions(action))
except Exception:
log_error('Invalid shortcut action: {}. Ignoring.'.format(
action))
log_error(f'Invalid shortcut action: {action}. Ignoring.')
else:
if paction is not None:
if paction:
if is_sequence:
if trigger is not None:
yield KeyDefinition(True, paction, trigger[0], trigger[1], trigger[2], rest)
@ -965,11 +993,11 @@ def parse_mouse_map(val: str) -> Iterable[MouseMapping]:
log_error(f'Mouse modes: {modes} not recognized, ignoring')
return
try:
paction = parse_key_action(action, 'mouse_map')
paction = tuple(parse_key_actions(action, 'mouse_map'))
except Exception:
log_error(f'Invalid mouse action: {action}. Ignoring.')
return
if paction is None:
if not paction:
return
for mode in sorted(specified_modes):
yield MouseMapping(button, mods, count, mode == 'grabbed', paction)

View File

@ -646,7 +646,7 @@ class Window:
action = get_options().mousemap.get(ev)
if action is None:
return False
return get_boss().dispatch_action(action, window_for_dispatch=self, dispatch_type='MouseEvent')
return get_boss().combine(action, window_for_dispatch=self, dispatch_type='MouseEvent')
def open_url(self, url: str, hyperlink_id: int, cwd: Optional[str] = None) -> None:
opts = get_options()

View File

@ -69,10 +69,11 @@ class Callbacks:
def on_mouse_event(self, event):
ev = MouseEvent(**event)
action = self.opts.mousemap.get(ev)
if action is None:
actions = self.opts.mousemap.get(ev)
if not actions:
return False
self.current_mouse_button = ev.button
for action in actions:
getattr(self, action.func)(*action.args)
self.current_mouse_button = 0
return True
@ -115,8 +116,8 @@ class BaseTest(TestCase):
if options:
final_options.update(options)
options = Options(merge_result_dicts(defaults._asdict(), final_options))
finalize_keys(options)
finalize_mouse_mappings(options)
finalize_keys(options, {})
finalize_mouse_mappings(options, {})
set_options(options)
return options

View File

@ -31,7 +31,8 @@ class TestConfParsing(BaseTest):
return ans
def keys_for_func(opts, name):
for key, action in opts.keymap.items():
for key, actions in opts.keymap.items():
for action in actions:
if action.func == name:
yield key
@ -51,8 +52,16 @@ class TestConfParsing(BaseTest):
self.ae(opts.pointer_shape_when_grabbed, defaults.pointer_shape_when_grabbed)
opts = p('env A=1', 'env B=x$A', 'env C=', 'env D', 'clear_all_shortcuts y', 'kitten_alias a b --moo', 'map f1 kitten a')
self.ae(opts.env, {'A': '1', 'B': 'x1', 'C': '', 'D': DELETE_ENV_VAR})
ka = tuple(opts.keymap.values())[0]
ka = tuple(opts.keymap.values())[0][0]
self.ae(ka.func, 'kitten')
self.ae(ka.args, ('b', '--moo'))
opts = p('clear_all_shortcuts y', 'action_alias la launch --moo', 'map f1 la')
ka = tuple(opts.keymap.values())[0][0]
self.ae(ka.func, 'launch')
self.ae(ka.args, ('--moo',))
opts = p('clear_all_shortcuts y', 'action_alias la launch --moo', 'map f1 combine : new_window : la ')
ka = tuple(opts.keymap.values())[0]
self.ae((ka[0].func, ka[1].func), ('new_window', 'launch'))
opts = p('kitty_mod alt')
self.ae(opts.kitty_mod, to_modifiers('alt'))
self.ae(next(keys_for_func(opts, 'next_layout')).mods, opts.kitty_mod)