Add an env var that can be used to eval an expression at startup of shell
This will come in handy to implement serialization as session with running of current foreground command.
This commit is contained in:
parent
0fb1835af1
commit
337cbf1435
6 changed files with 35 additions and 2 deletions
|
|
@ -224,6 +224,14 @@ Variables that kitty sets when running child programs
|
||||||
Set when enabling :ref:`shell_integration`. It is automatically removed by
|
Set when enabling :ref:`shell_integration`. It is automatically removed by
|
||||||
the shell integration scripts.
|
the shell integration scripts.
|
||||||
|
|
||||||
|
.. envvar:: KITTY_SI_RUN_COMMAND_AT_STARTUP
|
||||||
|
|
||||||
|
Set this to an expression that the kitty shell integration scripts will
|
||||||
|
``eval`` after the shell is started. Note that this environment variable
|
||||||
|
is ignored when present in the environment in which kitty itself is launched
|
||||||
|
in. It is most useful with the ``--env`` flag for the :doc:`launch <launch>`
|
||||||
|
action.
|
||||||
|
|
||||||
.. envvar:: ZDOTDIR
|
.. envvar:: ZDOTDIR
|
||||||
|
|
||||||
Set when enabling :ref:`shell_integration` with :program:`zsh`, allowing
|
Set when enabling :ref:`shell_integration` with :program:`zsh`, allowing
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,7 @@ def process_env(env: Mapping[str, str] | None = None) -> dict[str, str]:
|
||||||
ans.pop(ssl_env_var, None)
|
ans.pop(ssl_env_var, None)
|
||||||
ans.pop('XDG_ACTIVATION_TOKEN', None)
|
ans.pop('XDG_ACTIVATION_TOKEN', None)
|
||||||
ans.pop('VTE_VERSION', None) # Used by the stupid VTE shell integration script that is installed system wide, sigh
|
ans.pop('VTE_VERSION', None) # Used by the stupid VTE shell integration script that is installed system wide, sigh
|
||||||
|
ans.pop('KITTY_SI_RUN_COMMAND_AT_STARTUP', None)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,12 +86,14 @@ class ShellIntegration(BaseTest):
|
||||||
with_kitten = False
|
with_kitten = False
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def run_shell(self, shell='zsh', rc='', cmd='', setup_env=None):
|
def run_shell(self, shell='zsh', rc='', cmd='', setup_env=None, extra_env=None):
|
||||||
home_dir = self.home_dir = os.path.realpath(tempfile.mkdtemp())
|
home_dir = self.home_dir = os.path.realpath(tempfile.mkdtemp())
|
||||||
cmd = cmd or shell
|
cmd = cmd or shell
|
||||||
cmd = shlex.split(cmd.format(**locals()))
|
cmd = shlex.split(cmd.format(**locals()))
|
||||||
env = (setup_env or safe_env_for_running_shell)(cmd, home_dir, rc=rc, shell=shell, with_kitten=self.with_kitten)
|
env = (setup_env or safe_env_for_running_shell)(cmd, home_dir, rc=rc, shell=shell, with_kitten=self.with_kitten)
|
||||||
env['KITTY_RUNNING_SHELL_INTEGRATION_TEST'] = '1'
|
env['KITTY_RUNNING_SHELL_INTEGRATION_TEST'] = '1'
|
||||||
|
if extra_env:
|
||||||
|
env.update(extra_env)
|
||||||
try:
|
try:
|
||||||
if self.with_kitten:
|
if self.with_kitten:
|
||||||
cmd = [kitten_exe(), 'run-shell', '--shell', shlex.join(cmd)]
|
cmd = [kitten_exe(), 'run-shell', '--shell', shlex.join(cmd)]
|
||||||
|
|
@ -183,6 +185,10 @@ def redrawn():
|
||||||
self.assert_command(pty)
|
self.assert_command(pty)
|
||||||
env = pty.callbacks.clone_cmds[0].env
|
env = pty.callbacks.clone_cmds[0].env
|
||||||
self.ae(env.get('ES'), 'a\n b c\nd')
|
self.ae(env.get('ES'), 'a\n b c\nd')
|
||||||
|
with self.run_shell(rc='PS1=XXX', extra_env={'KITTY_SI_RUN_COMMAND_AT_STARTUP': 'echo pre-start'}) as pty:
|
||||||
|
pty.wait_till(lambda: 'XXX' in pty.screen_contents())
|
||||||
|
self.assertIn('pre-start', pty.screen_contents())
|
||||||
|
self.assertTrue(pty.screen_contents().startswith('pre-start'))
|
||||||
|
|
||||||
@unittest.skipUnless(shutil.which('fish'), 'fish not installed')
|
@unittest.skipUnless(shutil.which('fish'), 'fish not installed')
|
||||||
def test_fish_integration(self):
|
def test_fish_integration(self):
|
||||||
|
|
@ -190,6 +196,7 @@ def test_fish_integration(self):
|
||||||
completions_dir = os.path.join(kitty_base_dir, 'shell-integration', 'fish', 'vendor_completions.d')
|
completions_dir = os.path.join(kitty_base_dir, 'shell-integration', 'fish', 'vendor_completions.d')
|
||||||
with self.run_shell(
|
with self.run_shell(
|
||||||
shell='fish',
|
shell='fish',
|
||||||
|
extra_env={'KITTY_SI_RUN_COMMAND_AT_STARTUP': 'echo XXX'},
|
||||||
rc=f'''
|
rc=f'''
|
||||||
set -g fish_greeting
|
set -g fish_greeting
|
||||||
function fish_prompt; echo -n "{fish_prompt}"; end
|
function fish_prompt; echo -n "{fish_prompt}"; end
|
||||||
|
|
@ -198,7 +205,7 @@ def test_fish_integration(self):
|
||||||
function _set_key; set -g fish_key_bindings fish_$argv[1]_key_bindings; end
|
function _set_key; set -g fish_key_bindings fish_$argv[1]_key_bindings; end
|
||||||
function _set_status_prompt; function fish_prompt; echo -n "$pipestatus $status {fish_prompt}"; end; end
|
function _set_status_prompt; function fish_prompt; echo -n "$pipestatus $status {fish_prompt}"; end; end
|
||||||
''') as pty:
|
''') as pty:
|
||||||
q = fish_prompt + ' ' * (pty.screen.columns - len(fish_prompt) - len(right_prompt)) + right_prompt
|
q = 'XXX\n' + fish_prompt + ' ' * (pty.screen.columns - len(fish_prompt) - len(right_prompt)) + right_prompt
|
||||||
pty.wait_till(lambda: pty.screen_contents().count(right_prompt) == 1)
|
pty.wait_till(lambda: pty.screen_contents().count(right_prompt) == 1)
|
||||||
self.ae(pty.screen_contents(), q)
|
self.ae(pty.screen_contents(), q)
|
||||||
|
|
||||||
|
|
@ -366,6 +373,10 @@ def redrawn():
|
||||||
self.ae(ps1.splitlines()[-1] + 'echo $COLUMNS', str(pty.screen.line(pty.screen.cursor.y - 1 - len(ps1.splitlines()))))
|
self.ae(ps1.splitlines()[-1] + 'echo $COLUMNS', str(pty.screen.line(pty.screen.cursor.y - 1 - len(ps1.splitlines()))))
|
||||||
self.assert_command(pty, 'echo $COLUMNS')
|
self.assert_command(pty, 'echo $COLUMNS')
|
||||||
|
|
||||||
|
with self.run_shell(shell='bash', rc='PS1=XXX', extra_env={'KITTY_SI_RUN_COMMAND_AT_STARTUP': 'echo pre-start'}) as pty:
|
||||||
|
pty.wait_till(lambda: 'XXX' in pty.screen_contents())
|
||||||
|
self.assertIn('pre-start', pty.screen_contents())
|
||||||
|
self.assertTrue(pty.screen_contents().startswith('pre-start'))
|
||||||
# test startup file sourcing
|
# test startup file sourcing
|
||||||
|
|
||||||
def setup_env(excluded, argv, home_dir, rc='', shell='bash', with_kitten=self.with_kitten):
|
def setup_env(excluded, argv, home_dir, rc='', shell='bash', with_kitten=self.with_kitten):
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,8 @@ _ksi_main() {
|
||||||
fi
|
fi
|
||||||
builtin unset SSH_KITTEN_KITTY_DIR
|
builtin unset SSH_KITTEN_KITTY_DIR
|
||||||
fi
|
fi
|
||||||
|
builtin local krcs="$KITTY_SI_RUN_COMMAND_AT_STARTUP"
|
||||||
|
builtin unset KITTY_SI_RUN_COMMAND_AT_STARTUP
|
||||||
|
|
||||||
_ksi_debug_print() {
|
_ksi_debug_print() {
|
||||||
# print a line to STDERR of parent kitty process
|
# print a line to STDERR of parent kitty process
|
||||||
|
|
@ -351,6 +353,7 @@ _ksi_main() {
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
builtin unset KITTY_IS_CLONE_LAUNCH KITTY_CLONE_SOURCE_STRATEGIES
|
builtin unset KITTY_IS_CLONE_LAUNCH KITTY_CLONE_SOURCE_STRATEGIES
|
||||||
|
if [[ -n "$krcs" ]]; then builtin eval "$krcs"; fi
|
||||||
}
|
}
|
||||||
_ksi_main
|
_ksi_main
|
||||||
builtin unset -f _ksi_main
|
builtin unset -f _ksi_main
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ function __ksi_schedule --on-event fish_prompt -d "Setup kitty integration after
|
||||||
end
|
end
|
||||||
set --erase SSH_KITTEN_KITTY_DIR
|
set --erase SSH_KITTEN_KITTY_DIR
|
||||||
end
|
end
|
||||||
|
set --local krcs "$KITTY_SI_RUN_COMMAND_AT_STARTUP"
|
||||||
|
set --erase KITTY_SI_RUN_COMMAND_AT_STARTUP
|
||||||
|
|
||||||
# Enable cursor shape changes for default mode and vi mode
|
# Enable cursor shape changes for default mode and vi mode
|
||||||
if not contains "no-cursor" $_ksi
|
if not contains "no-cursor" $_ksi
|
||||||
|
|
@ -201,6 +203,9 @@ function __ksi_schedule --on-event fish_prompt -d "Setup kitty integration after
|
||||||
test (count $new_path) -eq (count $PATH)
|
test (count $new_path) -eq (count $PATH)
|
||||||
or set --global --export --path PATH $new_path
|
or set --global --export --path PATH $new_path
|
||||||
end
|
end
|
||||||
|
if test -n "$krcs"
|
||||||
|
eval "$krcs"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function edit-in-kitty --wraps "kitten edit-in-kitty" -d "Edit the specified file in a kitty overlay window with your locally installed editor"
|
function edit-in-kitty --wraps "kitten edit-in-kitty" -d "Edit the specified file in a kitty overlay window with your locally installed editor"
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,8 @@ _ksi_deferred_init() {
|
||||||
builtin local -a opt
|
builtin local -a opt
|
||||||
opt=(${(s: :)KITTY_SHELL_INTEGRATION})
|
opt=(${(s: :)KITTY_SHELL_INTEGRATION})
|
||||||
builtin unset KITTY_SHELL_INTEGRATION
|
builtin unset KITTY_SHELL_INTEGRATION
|
||||||
|
builtin local krcs="$KITTY_SI_RUN_COMMAND_AT_STARTUP"
|
||||||
|
builtin unset KITTY_SI_RUN_COMMAND_AT_STARTUP
|
||||||
|
|
||||||
if [[ -n "$SSH_KITTEN_KITTY_DIR" ]]; then
|
if [[ -n "$SSH_KITTEN_KITTY_DIR" ]]; then
|
||||||
if [[ ! "$PATH" =~ (^|:)${SSH_KITTEN_KITTY_DIR}(:|$) ]] && [[ -z "$(builtin command -v kitten)" ]]; then
|
if [[ ! "$PATH" =~ (^|:)${SSH_KITTEN_KITTY_DIR}(:|$) ]] && [[ -z "$(builtin command -v kitten)" ]]; then
|
||||||
|
|
@ -424,6 +426,9 @@ _ksi_deferred_init() {
|
||||||
# kitty-integration though because decent public functions aren't supposed to
|
# kitty-integration though because decent public functions aren't supposed to
|
||||||
# to unfunction themselves when invoked. Unfunctioning is done by calling code.
|
# to unfunction themselves when invoked. Unfunctioning is done by calling code.
|
||||||
builtin unfunction _ksi_deferred_init
|
builtin unfunction _ksi_deferred_init
|
||||||
|
|
||||||
|
# run startup command
|
||||||
|
if [[ -n "$krcs" ]]; then builtin eval "$krcs"; fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_ksi_transmit_data() {
|
_ksi_transmit_data() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue