From 8218df82f28058cf2d9260ede8d9b1bacc646888 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 8 Nov 2021 11:11:16 +0530 Subject: [PATCH] Add function to get path to integration script for the current shell Makes setting up manual shell integration much easier. Also clean up integration docs. --- docs/shell-integration.rst | 93 +++++++++++--------------------------- kitty/child.py | 4 +- kitty/shell_integration.py | 18 ++++++++ 3 files changed, 48 insertions(+), 67 deletions(-) diff --git a/docs/shell-integration.rst b/docs/shell-integration.rst index 754729f72..a20bc2b5d 100644 --- a/docs/shell-integration.rst +++ b/docs/shell-integration.rst @@ -69,15 +69,24 @@ How it works ----------------- At startup kitty detects if the shell you have configured (either system wide -or in kitty.conf) is a supported shell. If so, kitty adds a couple of lines to -the bottom of the shell's rc files (in an atomic manner) to load the shell -integration code. +or in kitty.conf) is a supported shell. If so, kitty injects some shell specific +code into the shell, to enable shell integration. How it does so varies for +different shells. -For fish, to make it automatically load the configuration file provided by -kitty, the integration script directory path is prepended to the -:code:`XDG_DATA_DIRS` environment variable. This is only applied to the fish -process and will be cleaned up by the integration script after startup. No files -are added or modified. + +.. tab:: bash/zsh + + For these shells, kitty adds a couple of lines to + the bottom of the shell's rc files (in an atomic manner) to load the shell + integration code. + +.. tab:: fish + + For fish, to make it automatically load the integration code provided by + kitty, the integration script directory path is prepended to the + :code:`XDG_DATA_DIRS` environment variable. This is only applied to the fish + process and will be cleaned up by the integration script after startup. No files + are added or modified. Then, when launching the shell, kitty sets the environment variable :envvar:`KITTY_SHELL_INTEGRATION` to the value of the :opt:`shell_integration` @@ -131,22 +140,21 @@ want to setup shell integration for a remote system over SSH, in Then in your shell's rc file, add the lines: -.. code-block:: sh +.. tab:: bash/zsh - export KITTY_SHELL_INTEGRATION="enabled" - source /path/to/integration/script + .. code-block:: sh -For fish, add the lines: + export KITTY_SHELL_INTEGRATION="enabled" + source $(kitty +runpy "from kitty.shell_integration import script_path; print(script_path())") -.. code-block:: fish +.. tab:: fish - set --global KITTY_SHELL_INTEGRATION enabled - source /path/to/integration/script + .. code-block:: fish + + set --global KITTY_SHELL_INTEGRATION enabled + source (kitty +runpy "from kitty.shell_integration import script_path; print(script_path('fish'))") + set --prepend fish_complete_path (kitty +runpy "from kitty.shell_integration import fish_completions_dir; print(fish_completions_dir)") -Or create symbolic links for each of the two files in the fish integration -script directory and place them in :code:`~/.config/fish/completions/` and -:code:`~/.config/fish/conf.d/` respectively. You still need to configure -:envvar:`KITTY_SHELL_INTEGRATION` and set it to :code:`enabled` explicitly. You can get the path to the directory containing the various shell integration scripts by looking at the directory displayed by: @@ -160,53 +168,6 @@ The value of :envvar:`KITTY_SHELL_INTEGRATION` is the same as that for completely, in which case simply do not set the :envvar:`KITTY_SHELL_INTEGRATION` variable at all. -If you use the fish shell automatic integration, the script directory will be -removed from the :code:`XDG_DATA_DIRS` environment variable after startup. This -is to ensure that when this environment variable is empty, the software that -relies on it will correctly use the system default fallback path, such as -:code:`/usr/local/share:/usr/share` defined in the specification. Otherwise, -software may not work properly, for example, :code:`xdg-open` will not be able -to open your files. - -If you want to run fish in fish and enable automatic shell integration (e.g. -run :code:`fish --private`), you need to configure it manually and make sure -that :code:`XDG_DATA_DIRS` contains all the system data directory paths. - -In your :file:`kitty.conf` set: - -.. code-block:: conf - - shell_integration enabled - -For systems that already have the correct :code:`XDG_DATA_DIRS`, add the -following lines: - -.. code-block:: fish - - set --global KITTY_SHELL_INTEGRATION enabled - if set -q KITTY_FISH_XDG_DATA_DIR - set --erase KITTY_FISH_XDG_DATA_DIR - end - -For cases where :code:`XDG_DATA_DIRS` is not set or empty (e.g. not set by -default on macOS), you can set it in :file:`kitty.conf` via :opt:`env`. -Otherwise, you need to add all the data directory paths defined by your system -and package manager in your fish configuration. For example: - -.. code-block:: fish - - set --global KITTY_SHELL_INTEGRATION enabled - if set -q KITTY_FISH_XDG_DATA_DIR - set --global --export XDG_DATA_DIRS $KITTY_FISH_XDG_DATA_DIR:/opt/path/to/data/dirs:/usr/local/share:/usr/share - set --erase KITTY_FISH_XDG_DATA_DIR - end - -The benefit of using fish shell automatic integration is that the integration -script included with the current version of kitty will always be loaded -correctly. The installation path for kitty can be anywhere, not a hard-coded -location in your fish configuration. Your fish configuration files (a.k.a. -dotfiles) can also be shared between different system environments. - Notes for shell developers ----------------------------- diff --git a/kitty/child.py b/kitty/child.py index 7f568cab8..4948ac40d 100644 --- a/kitty/child.py +++ b/kitty/child.py @@ -23,7 +23,7 @@ except ImportError: if is_macos: from kitty.fast_data_types import ( - cmdline_of_process, cwd_of_process as _cwd, + cmdline_of_process as cmdline_, cwd_of_process as _cwd, environ_of_process as _environ_of_process, process_group_map as _process_group_map ) @@ -37,6 +37,8 @@ if is_macos: ans[pgid].append(pid) return ans + def cmdline_of_process(pid: int) -> List[str]: + return cmdline_(pid) else: def cmdline_of_process(pid: int) -> List[str]: diff --git a/kitty/shell_integration.py b/kitty/shell_integration.py index f8773436a..dce8046bb 100644 --- a/kitty/shell_integration.py +++ b/kitty/shell_integration.py @@ -16,6 +16,7 @@ posix_template = ''' if test -e {path}; then source {path}; fi # END_KITTY_SHELL_INTEGRATION ''' +fish_completions_dir = os.path.join(shell_integration_dir, 'fish', 'vendor_completions.d') def atomic_write(path: str, data: Union[str, bytes]) -> None: @@ -86,6 +87,7 @@ ENV_MODIFIERS = { def get_supported_shell_name(path: str) -> Optional[str]: name = os.path.basename(path).split('.')[0].lower() + name = name.replace('-', '') if name in SUPPORTED_SHELLS: return name return None @@ -131,3 +133,19 @@ def modify_shell_environ(argv0: str, opts: Options, env: Dict[str, str]) -> None traceback.print_exc() log_error(f'Failed to setup shell integration for: {shell}') return + + +def script_path(shell: str = '') -> str: + if not shell: + from .child import cmdline_of_process + cmd = cmdline_of_process(os.getppid()) + if not cmd: + return '' + shell = get_supported_shell_name(cmd[0]) or '' + if not shell: + return '' + if shell == 'fish': + f = 'fish/vendor_conf.d/kitty-shell-integration.fish' + else: + f = f'kitty.{shell}' + return os.path.join(shell_integration_dir, f)