diff --git a/docs/changelog.rst b/docs/changelog.rst index 5e4841f32..263fa3d35 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -37,6 +37,9 @@ To update |kitty|, :doc:`follow the instructions `. - Marks: Fix marks not handling wide characters and tab characters correctly (:iss:`2534`) +- Add a new :opt:`listen_on` option in kitty.conf to set :option:`kitty --listen-on` + globally. Also allow using environment variables in this option (:iss:`2569`). + - Allow sending mouse events in kittens (:pull:`2538`) - icat kitten: Fix display of 16-bit depth images (:iss:`2542`) diff --git a/kitty/cli.py b/kitty/cli.py index 6175f9664..41ddeae1b 100644 --- a/kitty/cli.py +++ b/kitty/cli.py @@ -624,12 +624,15 @@ Tell kitty to listen on the specified address for control messages. For example, :option:`{appname} --listen-on`=unix:/tmp/mykitty or :option:`{appname} --listen-on`=tcp:localhost:12345. On Linux systems, you can also use abstract UNIX sockets, not associated with a file, like this: -:option:`{appname} --listen-on`=unix:@mykitty. To control kitty, you can send +:option:`{appname} --listen-on`=unix:@mykitty. Environment variables +in the setting are expanded and relative paths are resolved with +respect to the temporary directory. To control kitty, you can send it commands with :italic:`kitty @` using the :option:`kitty @ --to` option to specify this address. This option will be ignored, unless you set :opt:`allow_remote_control` to yes in :file:`kitty.conf`. Note that if you run :italic:`kitty @` within a kitty window, there is no need to specify the :italic:`--to` -option as it is read automatically from the environment. +option as it is read automatically from the environment. For UNIX sockets, this +can also be specified in :file:`kitty.conf`. --start-as diff --git a/kitty/config.py b/kitty/config.py index aeaa8e87a..63127009f 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -576,7 +576,7 @@ def handle_deprecated_macos_show_window_title_in_menubar_alias(key: str, val: st ans['macos_show_window_title_in'] = macos_show_window_title_in -def expandvars(val: str, env: Dict[str, str]) -> str: +def expandvars(val: str, env: Dict[str, str] = {}) -> str: def sub(m: Match) -> str: key = m.group(1) diff --git a/kitty/config_data.py b/kitty/config_data.py index c183f15db..3d05a41a3 100644 --- a/kitty/config_data.py +++ b/kitty/config_data.py @@ -1012,6 +1012,20 @@ you want to prevent programs running on a remote computer over ssh from controlling kitty. ''')) + +o('listen_on', 'none', long_text=_(''' +Tell kitty to listen to the specified unix/tcp socket for remote control +connections. Note that this will apply to all kitty instances. It can be +overridden by the :option:`kitty --listen-on` command line flag. This +option accepts only UNIX sockets, such as unix:${TEMP}/mykitty or (on Linux) +unix:@mykitty. Environment variables are expanded. If {kitty_pid} is present +then it is replaced by the PID of the kitty process, otherwise the PID of the kitty +process is appended to the value, with a hyphen. This option is ignored unless +you also set :opt:`allow_remote_control` to enable remote control. See the +help for :option:`kitty --listen-on` for more details. +''')) + + o( '+env', '', add_to_default=False, diff --git a/kitty/main.py b/kitty/main.py index cf2987f3f..7e9a62441 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -15,7 +15,7 @@ from .child import set_default_env from .cli import create_opts, parse_args from .cli_stub import CLIOptions from .conf.utils import BadLine -from .config import cached_values_for, initial_window_size_func +from .config import cached_values_for, initial_window_size_func, expandvars from .constants import ( appname, beam_cursor_data_file, config_dir, glfw_path, is_macos, is_wayland, kitty_exe, logo_data_file, running_in_kitty @@ -230,6 +230,22 @@ def get_editor_from_env(shell_env: Mapping[str, str]) -> Optional[str]: return editor +def expand_listen_on(listen_on: str, from_config_file: bool) -> str: + listen_on = expandvars(listen_on) + if '{kitty_pid}' not in listen_on and from_config_file: + listen_on += '-{kitty_pid}' + listen_on = listen_on.replace('{kitty_pid}', str(os.getpid())) + if listen_on.startswith('unix:'): + path = listen_on[len('unix:'):] + if not path.startswith('@'): + if path.startswith('~'): + listen_on = f'unix:{os.path.expanduser(path)}' + elif not os.path.isabs(path): + import tempfile + listen_on = f'unix:{os.path.join(tempfile.gettempdir(), path)}' + return listen_on + + def setup_environment(opts: OptionsStub, cli_opts: CLIOptions) -> None: extra_env = opts.env.copy() if opts.editor == '.': @@ -241,7 +257,12 @@ def setup_environment(opts: OptionsStub, cli_opts: CLIOptions) -> None: os.environ['EDITOR'] = editor else: os.environ['EDITOR'] = opts.editor - if cli_opts.listen_on: + from_config_file = False + if not cli_opts.listen_on and opts.listen_on.startswith('unix:'): + cli_opts.listen_on = opts.listen_on + from_config_file = True + if cli_opts.listen_on and opts.allow_remote_control != 'n': + cli_opts.listen_on = expand_listen_on(cli_opts.listen_on, from_config_file) os.environ['KITTY_LISTEN_ON'] = cli_opts.listen_on set_default_env(extra_env)