aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/shell-integration/elvish/lib
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/elvish/lib
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/shell-integration/elvish/lib')
-rw-r--r--vendor/libghostty-vt/src/shell-integration/elvish/lib/ghostty-integration.elv190
1 files changed, 190 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/shell-integration/elvish/lib/ghostty-integration.elv b/vendor/libghostty-vt/src/shell-integration/elvish/lib/ghostty-integration.elv
new file mode 100644
index 00000000..31ebf094
--- /dev/null
+++ b/vendor/libghostty-vt/src/shell-integration/elvish/lib/ghostty-integration.elv
@@ -0,0 +1,190 @@
+{
+ use platform
+ use str
+
+ # Clean up XDG_DATA_DIRS by removing GHOSTTY_SHELL_INTEGRATION_XDG_DIR
+ if (and (has-env GHOSTTY_SHELL_INTEGRATION_XDG_DIR) (has-env XDG_DATA_DIRS)) {
+ set-env XDG_DATA_DIRS (str:replace $E:GHOSTTY_SHELL_INTEGRATION_XDG_DIR":" "" $E:XDG_DATA_DIRS)
+ unset-env GHOSTTY_SHELL_INTEGRATION_XDG_DIR
+ }
+
+ # List of enabled shell integration features
+ var features = [(str:split ',' $E:GHOSTTY_SHELL_FEATURES)]
+
+ # State tracking for semantic prompt sequences
+ # Values: 'prompt-start', 'pre-exec', 'post-exec'
+ fn set-prompt-state {|new| set-env __ghostty_prompt_state $new }
+
+ fn mark-prompt-start {
+ if (not-eq $E:__ghostty_prompt_state 'prompt-start') {
+ printf "\e]133;D;aid="$pid"\a"
+ }
+ set-prompt-state 'prompt-start'
+ printf "\e]133;A;aid="$pid"\a"
+ }
+
+ fn mark-output-start {|_|
+ set-prompt-state 'pre-exec'
+ printf "\e]133;C\a"
+ }
+
+ fn mark-output-end {|cmd-info|
+ set-prompt-state 'post-exec'
+
+ var exit-status = 0
+
+ # in case of error: retrieve exit status,
+ # unless does not exist (= builtin function failure), then default to 1
+ if (not-eq $nil $cmd-info[error]) {
+ set exit-status = 1
+
+ if (has-key $cmd-info[error] reason) {
+ if (has-key $cmd-info[error][reason] exit-status) {
+ set exit-status = $cmd-info[error][reason][exit-status]
+ }
+ }
+ }
+
+ printf "\e]133;D;"$exit-status";aid="$pid"\a"
+ }
+
+ # NOTE: OSC 133;B (end of prompt, start of input) cannot be reliably
+ # implemented at the script level in Elvish. The prompt function's output is
+ # escaped, and writing to /dev/tty has timing issues because Elvish renders
+ # its prompts on a background thread. Full semantic prompt support requires a
+ # native implementation: https://github.com/elves/elvish/pull/1917
+
+ fn sudo-with-terminfo {|@args|
+ var sudoedit = $false
+ for arg $args {
+ if (str:has-prefix $arg --) {
+ if (eq $arg --edit) {
+ set sudoedit = $true
+ break
+ }
+ } elif (str:has-prefix $arg -) {
+ if (str:contains (str:trim-prefix $arg -) e) {
+ set sudoedit = $true
+ break
+ }
+ } elif (not (str:contains $arg =)) {
+ break
+ }
+ }
+
+ if (not $sudoedit) { set args = [ --preserve-env=TERMINFO $@args ] }
+ (external sudo) $@args
+ }
+
+ fn ssh-integration {|@args|
+ var ssh-term = "xterm-256color"
+ var ssh-opts = []
+
+ # Configure environment variables for remote session
+ if (has-value $features ssh-env) {
+ set ssh-opts = (conj $ssh-opts ^
+ -o "SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION")
+ }
+
+ if (has-value $features ssh-terminfo) {
+ var ssh-user = ""
+ var ssh-hostname = ""
+
+ # Parse ssh config
+ for line [((external ssh) -G $@args)] {
+ var parts = [(str:fields $line)]
+ if (> (count $parts) 1) {
+ var ssh-key = $parts[0]
+ var ssh-value = $parts[1]
+ if (eq $ssh-key user) {
+ set ssh-user = $ssh-value
+ } elif (eq $ssh-key hostname) {
+ set ssh-hostname = $ssh-value
+ }
+ if (and (not-eq $ssh-user "") (not-eq $ssh-hostname "")) {
+ break
+ }
+ }
+ }
+
+ if (not-eq $ssh-hostname "") {
+ var ghostty = $E:GHOSTTY_BIN_DIR/"ghostty"
+ var ssh-target = $ssh-user"@"$ssh-hostname
+
+ # Check if terminfo is already cached
+ if (bool ?($ghostty +ssh-cache --host=$ssh-target)) {
+ set ssh-term = "xterm-ghostty"
+ } elif (has-external infocmp) {
+ var ssh-terminfo = ((external infocmp) -0 -x xterm-ghostty 2>/dev/null | slurp)
+
+ if (not-eq $ssh-terminfo "") {
+ echo "Setting up xterm-ghostty terminfo on "$ssh-hostname"..." >&2
+
+ use os
+ var ssh-cpath-dir = (os:temp-dir "ghostty-ssh-"$ssh-user".*")
+ var ssh-cpath = $ssh-cpath-dir"/socket"
+
+ if (bool ?(echo $ssh-terminfo | (external ssh) $@ssh-opts -o ControlMaster=yes -o ControlPath=$ssh-cpath -o ControlPersist=60s $@args '
+ 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 ssh-opts = (conj $ssh-opts -o ControlPath=$ssh-cpath)
+
+ # Cache successful installation
+ $ghostty +ssh-cache --add=$ssh-target >/dev/null
+ } else {
+ echo "Warning: Failed to install terminfo." >&2
+ }
+ } else {
+ echo "Warning: Could not generate terminfo data." >&2
+ }
+ } else {
+ echo "Warning: ghostty command not available for cache management." >&2
+ }
+ }
+ }
+
+ with [E:TERM = $ssh-term E:COLORTERM = truecolor] {
+ (external ssh) $@ssh-opts $@args
+ }
+ }
+
+ defer {
+ mark-prompt-start
+ }
+
+ set edit:before-readline = (conj $edit:before-readline $mark-prompt-start~)
+ set edit:after-readline = (conj $edit:after-readline $mark-output-start~)
+ set edit:after-command = (conj $edit:after-command $mark-output-end~)
+
+ if (str:contains $E:GHOSTTY_SHELL_FEATURES "cursor") {
+ var cursor = "5" # blinking bar
+ if (has-value $features cursor:steady) {
+ set cursor = "6" # steady bar
+ }
+
+ fn beam { printf "\e["$cursor" q" }
+ fn reset { printf "\e[0 q" }
+ set edit:before-readline = (conj $edit:before-readline $beam~)
+ set edit:after-readline = (conj $edit:after-readline {|_| reset })
+ }
+ if (and (has-value $features path) (has-env GHOSTTY_BIN_DIR)) {
+ if (not (has-value $paths $E:GHOSTTY_BIN_DIR)) {
+ set paths = [$@paths $E:GHOSTTY_BIN_DIR]
+ }
+ }
+ if (and (has-value $features sudo) (not-eq "" $E:TERMINFO) (has-external sudo)) {
+ edit:add-var sudo~ $sudo-with-terminfo~
+ }
+ if (and (str:contains $E:GHOSTTY_SHELL_FEATURES ssh-) (has-external ssh)) {
+ edit:add-var ssh~ $ssh-integration~
+ }
+
+ # Report changes to the current directory.
+ fn report-pwd { printf "\e]7;kitty-shell-cwd://%s%s\a" (platform:hostname) $pwd }
+ set after-chdir = (conj $after-chdir {|_| report-pwd })
+ report-pwd
+}