ce173ebbdf
War durch .gitignore-Regel *.app/ ausgeschlossen; make-ghostty-app.sh braucht es aber als Basis. Explizit per git add -f aufgenommen.
192 lines
6.2 KiB
Plaintext
192 lines
6.2 KiB
Plaintext
{
|
|
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 "SetEnv COLORTERM=truecolor" ^
|
|
-o "SendEnv 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] {
|
|
(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
|
|
}
|