From 4a1ad7755a1ed9026a0d635c569acade396d482b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 15 Mar 2022 14:30:21 +0530 Subject: [PATCH] Enable CWD reporting in the zsh integration --- docs/shell-integration.rst | 3 +++ kitty/fast_data_types.pyi | 1 + kitty/options/utils.py | 2 +- kitty/screen.c | 3 ++- kitty_tests/shell_integration.py | 7 ++++++- shell-integration/zsh/kitty-integration | 9 ++++++++- 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/shell-integration.rst b/docs/shell-integration.rst index fb38efd18..006496662 100644 --- a/docs/shell-integration.rst +++ b/docs/shell-integration.rst @@ -67,6 +67,9 @@ no-title Note that for the ``fish`` shell kitty relies on fish's native title setting functionality instead. +no-cwd + Turn off reporting + no-prompt-mark Turn off marking of prompts. This disables jumping to prompt, browsing output of last command and click to move cursor functionality. diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index c17c11736..bd6f9215e 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1031,6 +1031,7 @@ class Screen: cursor_key_mode: bool auto_repeat_enabled: bool render_unfocused_cursor: int + last_reported_cwd: Optional[str] def __init__( self, diff --git a/kitty/options/utils.py b/kitty/options/utils.py index 07b711dca..62891c47c 100644 --- a/kitty/options/utils.py +++ b/kitty/options/utils.py @@ -800,7 +800,7 @@ def store_multiple(val: str, current_val: Container[str]) -> Iterable[Tuple[str, def shell_integration(x: str) -> FrozenSet[str]: - s = frozenset({'enabled', 'disabled', 'no-rc', 'no-cursor', 'no-title', 'no-prompt-mark', 'no-complete'}) + s = frozenset({'enabled', 'disabled', 'no-rc', 'no-cursor', 'no-title', 'no-prompt-mark', 'no-complete', 'no-cwd'}) q = frozenset(x.lower().split()) if not q.issubset(s): log_error(f'Invalid shell integration options: {q - s}, ignoring') diff --git a/kitty/screen.c b/kitty/screen.c index 9c128d393..df521d94f 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -154,6 +154,7 @@ void screen_reset(Screen *self) { if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self, true, true); if (self->overlay_line.is_active) deactivate_overlay_line(self); + Py_CLEAR(self->last_reported_cwd); self->render_unfocused_cursor = false; memset(self->main_key_encoding_flags, 0, sizeof(self->main_key_encoding_flags)); memset(self->alt_key_encoding_flags, 0, sizeof(self->alt_key_encoding_flags)); @@ -4001,7 +4002,7 @@ static PyGetSetDef getsetters[] = { static PyMemberDef members[] = { {"callbacks", T_OBJECT_EX, offsetof(Screen, callbacks), 0, "callbacks"}, {"cursor", T_OBJECT_EX, offsetof(Screen, cursor), READONLY, "cursor"}, - {"last_reported_cwd", T_OBJECT_EX, offsetof(Screen, last_reported_cwd), READONLY, "last_reported_cwd"}, + {"last_reported_cwd", T_OBJECT, offsetof(Screen, last_reported_cwd), READONLY, "last_reported_cwd"}, {"grman", T_OBJECT_EX, offsetof(Screen, grman), READONLY, "grman"}, {"color_profile", T_OBJECT_EX, offsetof(Screen, color_profile), READONLY, "color_profile"}, {"linebuf", T_OBJECT_EX, offsetof(Screen, linebuf), READONLY, "linebuf"}, diff --git a/kitty_tests/shell_integration.py b/kitty_tests/shell_integration.py index 9002ef90e..821225ab8 100644 --- a/kitty_tests/shell_integration.py +++ b/kitty_tests/shell_integration.py @@ -78,7 +78,7 @@ class ShellIntegration(BaseTest): @contextmanager def run_shell(self, shell='zsh', rc='', cmd='', setup_env=None): - home_dir = os.path.realpath(tempfile.mkdtemp()) + home_dir = self.home_dir = os.path.realpath(tempfile.mkdtemp()) cmd = cmd or shell cmd = shlex.split(cmd.format(**locals())) env = (setup_env or safe_env_for_running_shell)(cmd, home_dir, rc=rc, shell=shell) @@ -142,7 +142,12 @@ RPS1="{rps1}" pty.callbacks.clear() pty.send_cmd_to_child('printf "%s\x16\a%s" "a" "b"') pty.wait_till(lambda: 'ab' in pty.screen_contents()) + self.assertTrue(pty.screen.last_reported_cwd.endswith(self.home_dir)) self.assertIn('%s^G%s', pty.screen_contents()) + q = os.path.join(self.home_dir, 'testing-cwd-notification') + os.mkdir(q) + pty.send_cmd_to_child(f'cd {q}') + pty.wait_till(lambda: pty.screen.last_reported_cwd.endswith(q)) @unittest.skipUnless(shutil.which('fish'), 'fish not installed') def test_fish_integration(self): diff --git a/shell-integration/zsh/kitty-integration b/shell-integration/zsh/kitty-integration index 878efb0f3..188d99cd0 100644 --- a/shell-integration/zsh/kitty-integration +++ b/shell-integration/zsh/kitty-integration @@ -84,7 +84,7 @@ precmd_functions+=(_ksi_deferred_init) _ksi_deferred_init() { builtin emulate -L zsh -o no_warn_create_global -o no_aliases - # Recognized options: no-cursor, no-title, no-prompt-mark, no-complete. + # Recognized options: no-cursor, no-title, no-prompt-mark, no-complete, no-cwd. builtin local -a opt opt=(${(s: :)KITTY_SHELL_INTEGRATION}) builtin unset KITTY_SHELL_INTEGRATION @@ -224,6 +224,13 @@ _ksi_deferred_init() { # builtin print -nu "$_ksi_fd" "\\e]133;B\\a"' fi + # Enable reporting current working dir to terminal + if (( ! opt[(Ie)no-cwd] )); then + _ksi_report_pwd() { builtin print -nu $_ksi_fd '\e]7;kitty-shell-cwd://'"$HOST""$PWD"'\a'; } + chpwd_functions=(${chpwd_functions[@]} "_ksi_report_pwd") + _ksi_report_pwd + fi + # Enable terminal title changes. if (( ! opt[(Ie)no-title] )); then # We don't use `print -P` because it depends on prompt options, which