From f6e0eb40057827dcede90f2626de73dcc8d27273 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 27 Nov 2021 07:19:59 +0530 Subject: [PATCH] Shell integration: Dont modify ~/.zshrc Instead use the ZDOTDIR env var to load the shell integration code --- docs/build.rst | 8 +++++--- docs/shell-integration.rst | 29 ++++++++++++++++++--------- kitty/shell_integration.py | 17 +++++++++++----- shell-integration/zsh/.zshenv | 9 +++++++++ shell-integration/{ => zsh}/kitty.zsh | 0 5 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 shell-integration/zsh/.zshenv rename shell-integration/{ => zsh}/kitty.zsh (100%) diff --git a/docs/build.rst b/docs/build.rst index 05160e706c..0470fb89e6 100644 --- a/docs/build.rst +++ b/docs/build.rst @@ -189,8 +189,10 @@ update-checking ./setup.py linux-package --update-check-interval=0 shell-integration - |kitty| by default installs its :ref:`shell_integration` files into the user's - rc files. For a package, it might make more sense to distribute the shell + |kitty| by default injects its :ref:`shell_integration` code into the user's + shell using environment variables or (for bash only) modifying + the user's :file:`~/.bashrc` file. + For a package, it might make more sense to distribute the shell integration scripts into the system-wide shell vendor locations. The shell integration files are found in the :file:`shell-integration` directory. Copy them to the system wide shell vendor locations for each @@ -198,5 +200,5 @@ shell-integration ./setup.py linux-package --shell-integration=enabled\ no-rc - This will prevent kitty from modifying the user's shell rc files to load + This will prevent kitty from modifying the user's shell environment to load the integration scripts. diff --git a/docs/shell-integration.rst b/docs/shell-integration.rst index d93f4d1f99..9d2159103e 100644 --- a/docs/shell-integration.rst +++ b/docs/shell-integration.rst @@ -51,7 +51,7 @@ disabled turn off all shell integration no-rc - dont modify the shell's rc files to enable integration. Useful if you prefer + dont modify the shell's launch environment to enable integration. Useful if you prefer to :ref:`manually enable integration `. no-cursor @@ -116,17 +116,23 @@ define the following in :file:`kitty.conf`: How it works ----------------- -At startup kitty detects if the shell you have configured (either system wide +At startup, kitty detects if the shell you have configured (either system wide 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. -.. tab:: bash/zsh +.. tab:: zsh + + For zsh, kitty sets the ``ZDOTDIR`` environment variable to make zsh load + kitty's :file:`.zshenv` which in turn loads the shell integration code then + restores the original value of ``ZDOTDIR`` and finally sources the original + :file:`.zshenv`. The remainder of zsh's startup process proceeds as normal. - 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:: bash + + For bash, kitty adds a couple of lines to the bottom of :file:`~/.bashrc` + (in an atomic manner) to load the shell integration code. .. tab:: fish @@ -178,9 +184,12 @@ code used for each shell below: Manual shell integration ---------------------------- -If you do not want to rely on kitty's automatic shell integration or if you -want to setup shell integration for a remote system over SSH, in -:file:`kitty.conf` set: +The automatic shell integration is designed to be minimally intrusive, as such +it wont work for sub-shells, terminal multiplexers, containers, remote systems, etc. +For such systems, you should setup manual shell integration by adding some code +to your shells startup files to load the shell integration script. + +First, in :file:`kitty.conf` set: .. code-block:: conf @@ -203,7 +212,7 @@ Then in your shell's rc file, add the lines: if [[ ! -z "$KITTY_INSTALLATION_DIR" ]]; then export KITTY_SHELL_INTEGRATION="enabled" - source "$KITTY_INSTALLATION_DIR/shell-integration/kitty.zsh" + source "$KITTY_INSTALLATION_DIR/shell-integration/zsh/kitty.zsh" fi .. tab:: fish diff --git a/kitty/shell_integration.py b/kitty/shell_integration.py index 2deeea1d42..7a044f8566 100644 --- a/kitty/shell_integration.py +++ b/kitty/shell_integration.py @@ -49,10 +49,7 @@ def setup_integration(shell_name: str, rc_path: str, template: str = posix_templ def setup_zsh_integration(env: Dict[str, str]) -> None: - base = os.environ.get('ZDOTDIR', os.path.expanduser('~')) - rc = os.path.join(base, '.zshrc') - if os.path.exists(rc): # dont prevent zsh-newuser-install from running - setup_integration('zsh', rc) + pass # this is handled in the zsh env modifier def setup_bash_integration(env: Dict[str, str]) -> None: @@ -74,13 +71,23 @@ def setup_fish_env(env: Dict[str, str]) -> None: env['XDG_DATA_DIRS'] = os.pathsep.join(dirs) +def setup_zsh_env(env: Dict[str, str]) -> None: + zdotdir = os.environ.get('ZDOTDIR') + base = zdotdir or os.path.expanduser('~') + if zdotdir is not None: + env['KITTY_ORIG_ZDOTDIR'] = zdotdir + env['KITTY_ZSH_BASE'] = base + env['ZDOTDIR'] = os.path.join(shell_integration_dir, 'zsh') + + SUPPORTED_SHELLS = { 'zsh': setup_zsh_integration, 'bash': setup_bash_integration, 'fish': setup_fish_integration, } ENV_MODIFIERS = { - 'fish': setup_fish_env + 'fish': setup_fish_env, + 'zsh': setup_zsh_env, } diff --git a/shell-integration/zsh/.zshenv b/shell-integration/zsh/.zshenv new file mode 100644 index 0000000000..4682040261 --- /dev/null +++ b/shell-integration/zsh/.zshenv @@ -0,0 +1,9 @@ +if [[ -o interactive && -v ZDOTDIR && -r "$ZDOTDIR/kitty.zsh" ]]; then source "$ZDOTDIR/kitty.zsh"; fi +if [[ -v KITTY_ORIG_ZDOTDIR ]]; then + export ZDOTDIR="$KITTY_ORIG_ZDOTDIR" + unset KITTY_ORIG_ZDOTDIR +else + unset ZDOTDIR +fi +if [[ -v KITTY_ZSH_BASE && -r "$KITTY_ZSH_BASE/.zshenv" ]]; then source "$KITTY_ZSH_BASE/.zshenv"; fi +unset KITTY_ZSH_BASE diff --git a/shell-integration/kitty.zsh b/shell-integration/zsh/kitty.zsh similarity index 100% rename from shell-integration/kitty.zsh rename to shell-integration/zsh/kitty.zsh