25c2c3a4683be60c3526858be960ee6ce1249245

Author
Alexander Schlarb <alexander@ninetailed.ninja>
Committer
Marc Cornellà <hello@mcornella.com>
Date

Message

feat(lib): send OSC 7 on directory change for more supported terminals (#9914)

Previously this was only emitted on macOS with Apple's Terminal.app (and
compatible clones like iTerm2), but it is used by other terminal emulators
as well to obtain the actual current working directory wiht symlinks intact.
All non-supporting terminal emulators tested gracefully ignored this value,
so emit this on these as well in case they (or some other app masquarading
as them) add future support for this value.

Closes #9914

Co-authored-by: Marc Cornellà <hello@mcornella.com>

Diff

 1diff --git a/lib/termsupport.zsh b/lib/termsupport.zsh
 2index 5bc418761b7602304c254e2b987d282d21e6c160..cf8f08741a896db2b4a78ec268b643b802e37293 100644
 3--- a/lib/termsupport.zsh
 4+++ b/lib/termsupport.zsh
 5@@ -109,28 +109,52 @@ if [[ -z "$INSIDE_EMACS" || "$INSIDE_EMACS" = vterm ]]; then
 6   add-zsh-hook preexec omz_termsupport_preexec
 7 fi
 8 
 9-# Keep Apple Terminal.app's current working directory updated
10-# Based on this answer: https://superuser.com/a/315029
11-# With extra fixes to handle multibyte chars and non-UTF-8 locales
12-
13-if [[ "$TERM_PROGRAM" == "Apple_Terminal" ]] && [[ -z "$INSIDE_EMACS" ]]; then
14-  # Emits the control sequence to notify Terminal.app of the cwd
15-  # Identifies the directory using a file: URI scheme, including
16-  # the host name to disambiguate local vs. remote paths.
17-  function update_terminalapp_cwd() {
18-    emulate -L zsh
19-
20-    # Percent-encode the host and path names.
21-    local URL_HOST URL_PATH
22-    URL_HOST="$(omz_urlencode -P $HOST)" || return 1
23-    URL_PATH="$(omz_urlencode -P $PWD)" || return 1
24-
25-    # Undocumented Terminal.app-specific control sequence
26-    printf '\e]7;%s\a' "file://$URL_HOST$URL_PATH"
27-  }
28-
29-  # Use a precmd hook instead of a chpwd hook to avoid contaminating output
30-  add-zsh-hook precmd update_terminalapp_cwd
31-  # Run once to get initial cwd set
32-  update_terminalapp_cwd
33+# Keep terminal emulator's current working directory correct,
34+# even if the current working directory path contains symbolic links
35+#
36+# References:
37+# - Apple's Terminal.app: https://superuser.com/a/315029
38+# - iTerm2: https://iterm2.com/documentation-escape-codes.html (iTerm2 Extension / CurrentDir+RemoteHost)
39+# - Konsole: https://bugs.kde.org/show_bug.cgi?id=327720#c1
40+# - libvte (gnome-terminal, mate-terminal, …): https://bugzilla.gnome.org/show_bug.cgi?id=675987#c14
41+#   Apparently it had a bug before ~2012 were it would display the unknown OSC 7 code
42+#
43+# As of May 2021 mlterm, PuTTY, rxvt, screen, termux & xterm simply ignore the unknown OSC.
44+
45+# Don't define the function if we're inside Emacs
46+if [[ -n "$INSIDE_EMACS" ]]; then
47+  return
48 fi
49+
50+# Don't define the function if we're in an unsupported terminal
51+case "$TERM" in
52+  # all of these either process OSC 7 correctly or ignore entirely
53+  xterm*|putty*|rxvt*|konsole*|mlterm*|alacritty|screen*|tmux*) ;;
54+  contour*|foot*) ;;
55+  *)
56+    # Terminal.app and iTerm2 process OSC 7 correctly
57+    case "$TERM_PROGRAM" in
58+      Apple_Terminal|iTerm.app) ;;
59+      *) return ;;
60+    esac ;;
61+esac
62+
63+# Emits the control sequence to notify many terminal emulators
64+# of the cwd
65+#
66+# Identifies the directory using a file: URI scheme, including
67+# the host name to disambiguate local vs. remote paths.
68+function omz_termsupport_cwd {
69+  # Percent-encode the host and path names.
70+  local URL_HOST URL_PATH
71+  URL_HOST="$(omz_urlencode -P $HOST)" || return 1
72+  URL_PATH="$(omz_urlencode -P $PWD)" || return 1
73+
74+  # common control sequence (OSC 7) to set current host and path
75+  printf "\e]7;%s\a" "file://${URL_HOST}${URL_PATH}"
76+}
77+
78+# Use a precmd hook instead of a chpwd hook to avoid contaminating output
79+# i.e. when a script or function changes directory without `cd -q`, chpwd
80+# will be called the output may be swallowed by the script or function.
81+add-zsh-hook precmd omz_termsupport_cwd