diff --git a/kitty_tests/shell_integration.py b/kitty_tests/shell_integration.py index 22aa97a66..2e6736da1 100644 --- a/kitty_tests/shell_integration.py +++ b/kitty_tests/shell_integration.py @@ -8,6 +8,7 @@ import shutil import tempfile import unittest from contextlib import contextmanager +from functools import partial from kitty.constants import is_macos, kitty_base_dir, terminfo_dir from kitty.fast_data_types import CURSOR_BEAM @@ -16,7 +17,7 @@ from kitty.shell_integration import setup_bash_env, setup_zsh_env from . import BaseTest -def safe_env_for_running_shell(argv, home_dir, rc='', shell='zsh'): +def basic_shell_env(home_dir): ans = { 'PATH': os.environ['PATH'], 'HOME': home_dir, @@ -28,6 +29,11 @@ def safe_env_for_running_shell(argv, home_dir, rc='', shell='zsh'): for x in ('USER', 'LANG'): if os.environ.get(x): ans[x] = os.environ[x] + return ans + + +def safe_env_for_running_shell(argv, home_dir, rc='', shell='zsh'): + ans = basic_shell_env(home_dir) if shell == 'zsh': ans['ZLE_RPROMPT_INDENT'] = '0' with open(os.path.join(home_dir, '.zshenv'), 'w') as f: @@ -50,11 +56,11 @@ def safe_env_for_running_shell(argv, home_dir, rc='', shell='zsh'): class ShellIntegration(BaseTest): @contextmanager - def run_shell(self, shell='zsh', rc='', cmd=''): + def run_shell(self, shell='zsh', rc='', cmd='', setup_env=None): home_dir = os.path.realpath(tempfile.mkdtemp()) cmd = cmd or shell cmd = shlex.split(cmd.format(**locals())) - env = safe_env_for_running_shell(cmd, home_dir, rc=rc, shell=shell) + env = (setup_env or safe_env_for_running_shell)(cmd, home_dir, rc=rc, shell=shell) try: pty = self.create_pty(cmd, cwd=home_dir, env=env) i = 10 @@ -175,3 +181,26 @@ PS1="{ps1}" pty.wait_till(lambda: pty.screen_contents().count(ps1) == 3) self.ae('40', str(pty.screen.line(pty.screen.cursor.y - len(ps1.splitlines())))) self.ae(ps1.splitlines()[-1] + 'echo $COLUMNS', str(pty.screen.line(pty.screen.cursor.y - 1 - len(ps1.splitlines())))) + + # test startup file sourcing + + def setup_env(excluded, argv, home_dir, rc='', shell='bash'): + ans = basic_shell_env(home_dir) + setup_bash_env(ans, argv) + for x in {'profile', 'bash.bashrc', '.bash_profile', '.bash_login', '.profile', '.bashrc'} - excluded: + with open(os.path.join(home_dir, x), 'w') as f: + print(f'echo {x}', file=f) + ans['KITTY_BASH_ETC_LOCATION'] = home_dir + return ans + + def run_test(argv, *expected, excluded=()): + with self.subTest(argv=argv), self.run_shell(shell='bash', setup_env=partial(setup_env, set(excluded)), cmd=argv) as pty: + pty.wait_till(lambda: '$' in pty.screen_contents()) + q = pty.screen_contents() + for x in expected: + self.assertIn(x, q) + + run_test('bash', 'bash.bashrc', '.bashrc') + run_test('bash -l', 'profile', '.bash_profile') + run_test('bash -l', 'profile', '.bash_login', excluded=('.bash_profile',)) + run_test('bash -l', 'profile', '.profile', excluded=('.bash_profile', '.bash_login')) diff --git a/shell-integration/bash/kitty.bash b/shell-integration/bash/kitty.bash index e726b12d0..466cee7b0 100644 --- a/shell-integration/bash/kitty.bash +++ b/shell-integration/bash/kitty.bash @@ -35,6 +35,8 @@ _ksi_main() { if [[ -n "$KITTY_BASH_INJECT" ]]; then builtin unset ENV; + if [[ -z "$HOME" ]]; then HOME=~; fi + if [[ -z "$KITTY_BASH_ETC_LOCATION" ]]; then KITTY_BASH_ETC_LOCATION="/etc"; fi if [[ "$KITTY_BASH_INJECT" == *"posix"* ]]; then _ksi_safe_source "$KITTY_BASH_POSIX_ENV" && builtin export ENV="$KITTY_BASH_POSIX_ENV"; else @@ -42,14 +44,14 @@ _ksi_main() { # See run_startup_files() in shell.c in the BASH source code if builtin shopt -q login_shell; then if [[ "$KITTY_BASH_INJECT" != *"no-profile"* ]]; then - _ksi_safe_source "/etc/profile"; + _ksi_safe_source "$KITTY_BASH_ETC_LOCATION/profile"; _ksi_safe_source "$HOME/.bash_profile" || _ksi_safe_source "$HOME/.bash_login" || _ksi_safe_source "$HOME/.profile"; fi else if [[ "$KITTY_BASH_INJECT" != *"no-rc"* ]]; then # Linux distros build bash with -DSYS_BASHRC. Unfortunately, there is # no way to to probe bash for it and different distros use different files - _ksi_safe_source "/etc/bash.bashrc" # Arch, Debian, Ubuntu + _ksi_safe_source "$KITTY_BASH_ETC_LOCATION/bash.bashrc" # Arch, Debian, Ubuntu # Fedora uses /etc/bashrc sourced from ~/.bashrc instead of SYS_BASHRC if [[ -z "$KITTY_BASH_RCFILE" ]]; then KITTY_BASH_RCFILE="$HOME/.bashrc"; fi _ksi_safe_source "$KITTY_BASH_RCFILE"; @@ -59,6 +61,7 @@ _ksi_main() { builtin unset KITTY_BASH_RCFILE; builtin unset KITTY_BASH_POSIX_ENV; builtin unset KITTY_BASH_INJECT; + builtin unset KITTY_BASH_ETC_LOCATION; fi builtin unset -f _ksi_safe_source