diff --git a/docs/changelog.rst b/docs/changelog.rst index 3305c2002..185d152e1 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -14,6 +14,9 @@ To update |kitty|, :doc:`follow the instructions `. - Fix reverse video not being rendered correctly when using transparency or a background image (:iss:`2419`) +- Allow mapping arbitrary remote control commands to key presses in + :file:`kitty.conf` + - X11: Fix crash when doing drag and drop from some applications (:iss:`2505`) - Fix :option:`launch --stdin-add-formatting` not working (:iss:`2512`) diff --git a/docs/remote-control.rst b/docs/remote-control.rst index bfa4a6077..09a4e761b 100644 --- a/docs/remote-control.rst +++ b/docs/remote-control.rst @@ -134,6 +134,19 @@ still write to the pipes of any other program on the same computer and therefore can control |kitty|. It can, however, be useful to block programs running on other computers (for example, over ssh) or as other users. +Mapping key presses to remote control commands +-------------------------------------------------- + +If you wish to trigger a remote control command easily with just a keypress, +you can map it in :file:`kitty.conf`. For example:: + + map F1 remote_control set-spacing margin=30 + +Then pressing the :kbd:`F1` key will set the active window margins to 30. +The syntax for what follows :code:`remote_control` is exactly the same +as the syntax for what follows :code:`kitty @` above. + + Documentation for the remote control protocol ----------------------------------------------- diff --git a/kitty/boss.py b/kitty/boss.py index 214df48b0..64047c401 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -339,6 +339,21 @@ def _handle_remote_command(self, cmd: str, window: Optional[Window] = None, from response = {'ok': False, 'error': 'Remote control is disabled. Add allow_remote_control to your kitty.conf'} return response + def remote_control(self, *args: str) -> None: + from .remote_control import parse_rc_args + from .rc.base import command_for_name, parse_subcommand_cli, PayloadGetter + try: + global_opts, items = parse_rc_args(['@'] + list(args)) + if not items: + return + cmd = items[0] + c = command_for_name(cmd) + opts, items = parse_subcommand_cli(c, items) + payload = c.message_to_kitty(global_opts, opts, items) + c.response_from_kitty(self, self.active_window, PayloadGetter(c, payload if isinstance(payload, dict) else {})) + except (Exception, SystemExit) as e: + self.show_error(_('remote_control mapping failed'), str(e)) + def peer_message_received(self, msg_bytes: bytes) -> Optional[bytes]: msg = msg_bytes.decode('utf-8') cmd_prefix = '\x1bP@kitty-cmd' diff --git a/kitty/config.py b/kitty/config.py index fc3dde9e9..2faa08b64 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -240,6 +240,15 @@ def set_colors(func: str, rest: str) -> FuncArgsType: return func, r +@func_with_args('remote_control') +def remote_control(func: str, rest: str) -> FuncArgsType: + import shlex + r = shlex.split(rest) + if len(r) < 1: + log_error('Too few arguments to remote_control function') + return func, r + + @func_with_args('nth_window') def nth_window(func: str, rest: str) -> FuncArgsType: try: