elvish: revise the ssh integration

The previous implementation wasn't quite working. This revision reworks
it in a few ways:

- Fix various syntax issues
- Redirect the `ssh` command to our 'ssh-integration' function
- Locate the `ghostty` binary using $GHOSTTY_BIN_DIR
- Use os:temp-dir to create our temporary directory

Also, consistently use 2-space indents, which is the Elvish standard.
This commit is contained in:
Jon Parise
2025-07-09 21:44:32 -04:00
parent d0c5191aef
commit 5cdfe3d70e
2 changed files with 77 additions and 85 deletions

View File

@ -1,6 +1,6 @@
root = true
[*.{sh,bash}]
[*.{sh,bash,elv}]
indent_size = 2
indent_style = space

View File

@ -38,6 +38,9 @@
{
use str
# List of enabled shell integration features
var features = [(str:split ',' $E:GHOSTTY_SHELL_FEATURES)]
# helper used by `mark-*` functions
fn set-prompt-state {|new| set-env __ghostty_prompt_state $new }
@ -98,93 +101,81 @@
(external sudo) $@args
}
# SSH Integration
use str
fn ssh-integration {|@args|
var ssh-term = "xterm-256color"
var ssh-opts = []
if (str:contains $E:GHOSTTY_SHELL_FEATURES ssh-) {
fn ssh {|@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")
}
# Configure environment variables for remote session
if (str:contains $E:GHOSTTY_SHELL_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
}
# Install terminfo on remote host if needed
if (str:contains $E:GHOSTTY_SHELL_FEATURES ssh-terminfo) {
var ssh-user = ""
var ssh-hostname = ""
# Parse ssh config
var ssh-config = (external ssh -G $@args 2>/dev/null | slurp)
for line (str:split "\n" $ssh-config) {
var parts = (str:split " " $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 ssh-target = $ssh-user"@"$ssh-hostname
# Check if terminfo is already cached
if (and (has-external ghostty) (bool ?(external ghostty +ssh-cache --host=$ssh-target >/dev/null 2>&1))) {
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
var ssh-cpath-dir = ""
try {
set ssh-cpath-dir = (external mktemp -d "/tmp/ghostty-ssh-"$ssh-user".XXXXXX" 2>/dev/null | slurp)
} catch {
set ssh-cpath-dir = "/tmp/ghostty-ssh-"$ssh-user"."(randint 10000 99999)
}
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
if (has-external ghostty) {
external ghostty +ssh-cache --add=$ssh-target >/dev/null 2>&1
}
} 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
}
}
if (and (not-eq $ssh-user "") (not-eq $ssh-hostname "")) {
break
}
# Execute SSH with TERM environment variable
external E:TERM=$ssh-term ssh $@ssh-opts $@args
}
}
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 {
@ -196,8 +187,6 @@
set edit:after-readline = (conj $edit:after-readline $mark-output-start~)
set edit:after-command = (conj $edit:after-command $mark-output-end~)
var features = [(str:split ',' $E:GHOSTTY_SHELL_FEATURES)]
if (has-value $features title) {
set after-chdir = (conj $after-chdir {|_| report-pwd })
}
@ -210,4 +199,7 @@
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~
}
}