aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/shell-integration/fish
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/shell-integration/fish
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/shell-integration/fish')
-rw-r--r--vendor/libghostty-vt/src/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish245
1 files changed, 245 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish b/vendor/libghostty-vt/src/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish
new file mode 100644
index 00000000..f8bfe091
--- /dev/null
+++ b/vendor/libghostty-vt/src/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish
@@ -0,0 +1,245 @@
+# This shell script aims to be written in a way where it can't really fail
+# or all failure scenarios are handled, so that we never leave the shell in
+# a weird state. If you find a way to break this, please report a bug!
+
+function ghostty_restore_xdg_data_dir -d "restore the original XDG_DATA_DIR value"
+ # If we don't have our own data dir then we don't need to do anything.
+ if not set -q GHOSTTY_SHELL_INTEGRATION_XDG_DIR
+ return
+ end
+
+ # If the data dir isn't set at all then we don't need to do anything.
+ if not set -q XDG_DATA_DIRS
+ return
+ end
+
+ # We need to do this so that XDG_DATA_DIRS turns into an array.
+ set --function --path xdg_data_dirs "$XDG_DATA_DIRS"
+
+ # If our data dir is in the list then remove it.
+ if set --function index (contains --index "$GHOSTTY_SHELL_INTEGRATION_XDG_DIR" $xdg_data_dirs)
+ set --erase --function xdg_data_dirs[$index]
+ end
+
+ # Re-export our data dir
+ if set -q xdg_data_dirs[1]
+ set --global --export --unpath XDG_DATA_DIRS "$xdg_data_dirs"
+ else
+ set --erase --global XDG_DATA_DIRS
+ end
+
+ set --erase GHOSTTY_SHELL_INTEGRATION_XDG_DIR
+end
+
+function ghostty_exit -d "exit the shell integration setup"
+ functions -e ghostty_restore_xdg_data_dir
+ functions -e ghostty_exit
+ exit 0
+end
+
+# We always try to restore the XDG data dir
+ghostty_restore_xdg_data_dir
+
+# If we aren't interactive or we've already run, don't run.
+status --is-interactive || ghostty_exit
+
+# We do the full setup on the first prompt render. We do this so that other
+# shell integrations that setup the prompt and modify things are able to run
+# first. We want to run _last_.
+function __ghostty_setup --on-event fish_prompt -d "Setup ghostty integration"
+ functions -e __ghostty_setup
+
+ set --local features (string split , $GHOSTTY_SHELL_FEATURES)
+
+ # Parse the fish version for feature detection.
+ # Default to 0.0 if version is unavailable or malformed.
+ set -l fish_major 0
+ set -l fish_minor 0
+ if set -q version[1]
+ set -l fish_ver (string match -r '(\d+)\.(\d+)' -- $version[1])
+ if set -q fish_ver[2]; and test -n "$fish_ver[2]"
+ set fish_major "$fish_ver[2]"
+ end
+ if set -q fish_ver[3]; and test -n "$fish_ver[3]"
+ set fish_minor "$fish_ver[3]"
+ end
+ end
+
+ # Our OSC133A (prompt start) sequence. If we're using Fish >= 4.1
+ # then it supports click_events so we enable that.
+ set -g __ghostty_prompt_start_mark "\e]133;A\a"
+ if test "$fish_major" -gt 4; or test "$fish_major" -eq 4 -a "$fish_minor" -ge 1
+ set -g __ghostty_prompt_start_mark "\e]133;A;click_events=1\a"
+ end
+
+ if string match -q 'cursor*' -- $features
+ set -l cursor 5 # blinking bar
+ contains cursor:steady $features && set cursor 6 # steady bar
+
+ # Change the cursor to a beam on prompt.
+ function __ghostty_set_cursor_beam --on-event fish_prompt -V cursor -d "Set cursor shape"
+ if not functions -q fish_vi_cursor_handle
+ echo -en "\e[$cursor q"
+ end
+ end
+ function __ghostty_reset_cursor --on-event fish_preexec -d "Reset cursor shape"
+ if not functions -q fish_vi_cursor_handle
+ echo -en "\e[0 q"
+ end
+ end
+ end
+
+ # Add Ghostty binary to PATH if the path feature is enabled
+ if contains path $features; and test -n "$GHOSTTY_BIN_DIR"
+ fish_add_path --global --path --append "$GHOSTTY_BIN_DIR"
+ end
+
+ # When using sudo shell integration feature, ensure $TERMINFO is set
+ # and `sudo` is not already a function or alias
+ if contains sudo $features; and test -n "$TERMINFO"; and test file = (type -t sudo 2> /dev/null; or echo "x")
+ # Wrap `sudo` command to ensure Ghostty terminfo is preserved
+ function sudo -d "Wrap sudo to preserve terminfo"
+ set --function sudo_has_sudoedit_flags no
+ for arg in $argv
+ # Check if argument is '-e' or '--edit' (sudoedit flags)
+ if string match -q -- -e "$arg"; or string match -q -- --edit "$arg"
+ set --function sudo_has_sudoedit_flags yes
+ break
+ end
+ # Check if argument is neither an option nor a key-value pair
+ if not string match -r -q -- "^-" "$arg"; and not string match -r -q -- "=" "$arg"
+ break
+ end
+ end
+ if test "$sudo_has_sudoedit_flags" = yes
+ command sudo $argv
+ else
+ command sudo --preserve-env=TERMINFO $argv
+ end
+ end
+ end
+
+ # SSH Integration
+ set -l features (string split ',' -- "$GHOSTTY_SHELL_FEATURES")
+ if contains ssh-env $features; or contains ssh-terminfo $features
+ function ssh --wraps=ssh --description "SSH wrapper with Ghostty integration"
+ set -l features (string split ',' -- "$GHOSTTY_SHELL_FEATURES")
+ set -l ssh_term xterm-256color
+ set -l ssh_opts
+
+ # Configure environment variables for remote session
+ if contains ssh-env $features
+ set -a ssh_opts -o "SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION"
+ end
+
+ # Install terminfo on remote host if needed
+ if contains ssh-terminfo $features
+ set -l ssh_user
+ set -l ssh_hostname
+
+ for line in (command ssh -G $argv 2>/dev/null)
+ set -l parts (string split ' ' -- $line)
+ if test (count $parts) -ge 2
+ switch $parts[1]
+ case user
+ set ssh_user $parts[2]
+ case hostname
+ set ssh_hostname $parts[2]
+ end
+ if test -n "$ssh_user"; and test -n "$ssh_hostname"
+ break
+ end
+ end
+ end
+
+ if test -n "$ssh_hostname"
+ set -l ssh_target "$ssh_user@$ssh_hostname"
+
+ # Check if terminfo is already cached
+ if test -x "$GHOSTTY_BIN_DIR/ghostty"; and "$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --host="$ssh_target" >/dev/null 2>&1
+ set ssh_term xterm-ghostty
+ else if command -q infocmp
+ set -l ssh_terminfo
+ set -l ssh_cpath_dir
+ set -l ssh_cpath
+
+ set ssh_terminfo "$(infocmp -0 -x xterm-ghostty 2>/dev/null)"
+
+ if test -n "$ssh_terminfo"
+ echo "Setting up xterm-ghostty terminfo on $ssh_hostname..." >&2
+
+ set ssh_cpath_dir (mktemp -d "/tmp/ghostty-ssh-$ssh_user.XXXXXX" 2>/dev/null; or echo "/tmp/ghostty-ssh-$ssh_user."(random))
+ set ssh_cpath "$ssh_cpath_dir/socket"
+
+ if echo "$ssh_terminfo" | command ssh $ssh_opts -o ControlMaster=yes -o ControlPath="$ssh_cpath" -o ControlPersist=60s $argv '
+ infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
+ command -v tic >/dev/null 2>&1 || exit 1
+ mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
+ exit 1
+ ' 2>/dev/null
+ set ssh_term xterm-ghostty
+ set -a ssh_opts -o "ControlPath=$ssh_cpath"
+
+ # Cache successful installation
+ if test -x "$GHOSTTY_BIN_DIR/ghostty"
+ "$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --add="$ssh_target" >/dev/null 2>&1; or true
+ end
+ else
+ echo "Warning: Failed to install terminfo." >&2
+ end
+ else
+ echo "Warning: Could not generate terminfo data." >&2
+ end
+ else
+ echo "Warning: ghostty command not available for cache management." >&2
+ end
+ end
+ end
+
+ # Execute SSH with TERM environment variable
+ TERM="$ssh_term" COLORTERM=truecolor command ssh $ssh_opts $argv
+ end
+ end
+
+ # Setup prompt marking
+ function __ghostty_mark_prompt_start --on-event fish_prompt --on-event fish_posterror
+ # If we never got the output end event, then we need to send it now.
+ if test "$__ghostty_prompt_state" != prompt-start
+ echo -en "\e]133;D\a"
+ end
+
+ set --global __ghostty_prompt_state prompt-start
+ echo -en $__ghostty_prompt_start_mark
+ end
+
+ function __ghostty_mark_output_start --on-event fish_preexec
+ set --global __ghostty_prompt_state pre-exec
+ echo -en "\e]133;C\a"
+ end
+
+ function __ghostty_mark_output_end --on-event fish_postexec
+ set --global __ghostty_prompt_state post-exec
+ echo -en "\e]133;D;$status\a"
+ end
+
+ # Report pwd. This is actually built-in to fish but only for terminals
+ # that match an allowlist and that isn't us.
+ function __update_cwd_osc --on-variable PWD -d 'Notify capable terminals when $PWD changes'
+ if status --is-command-substitution || set -q INSIDE_EMACS
+ return
+ end
+ printf \e\]7\;file://%s%s\a $hostname (string escape --style=url $PWD)
+ end
+
+ # Enable fish to handle reflow because Ghostty clears the prompt on resize.
+ set --global fish_handle_reflow 1
+
+ # Initial calls for first prompt
+ if string match -q 'cursor*' -- $features
+ __ghostty_set_cursor_beam
+ end
+ __ghostty_mark_prompt_start
+ __update_cwd_osc
+end
+
+ghostty_exit