This commit is contained in:
Kovid Goyal 2022-03-07 11:18:15 +05:30
commit d4d4e00f9d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
7 changed files with 104 additions and 111 deletions

View File

@ -83,7 +83,7 @@ def make_tarfile(ssh_opts: SSHOptions, base_env: Dict[str, str]) -> bytes:
def filter_from_globs(*pats: str) -> Callable[[tarfile.TarInfo], Optional[tarfile.TarInfo]]:
def filter(tarinfo: tarfile.TarInfo) -> Optional[tarfile.TarInfo]:
for junk_dir in ('.DS_Store', '__pycache__'):
for pat in (f'*/{junk_dir}', '*/{junk_dir}/*'):
for pat in (f'*/{junk_dir}', f'*/{junk_dir}/*'):
if fnmatch.fnmatch(tarinfo.name, pat):
return None
for pat in pats:

View File

@ -213,16 +213,8 @@ function _set_status_prompt; function fish_prompt; echo -n "$pipestatus $status
pty.write_to_child('i')
pty.wait_till(lambda: pty.screen.cursor.shape == CURSOR_BEAM)
pty.send_cmd_to_child('_set_key default')
# pipestatus
pty.send_cmd_to_child('clear;false|true|false')
pty.send_cmd_to_child('echo $pipestatus $status')
pty.wait_till(lambda: pty.screen_contents().count(right_prompt) == 2)
self.ae(pty.last_cmd_output(), '1 0 1 1')
pty.send_cmd_to_child('_set_status_prompt')
pty.send_cmd_to_child('false|true|false')
pty.wait_till(lambda: pty.screen_contents().count(right_prompt) == 4)
self.assertTrue(str(pty.screen.line(pty.screen.cursor.y)).startswith(f'1 0 1 1 {fish_prompt}'))
pty.wait_till(lambda: pty.screen.cursor.shape == CURSOR_BEAM)
pty.send_cmd_to_child('exit')

View File

@ -155,8 +155,19 @@ _ksi_main() {
fi
if [[ "${_ksi_prompt[title]}" == "y" ]]; then
if [[ -n "$SSH_TTY$SSH2_TTY" ]]; then
_ksi_prompt[hostname_prefix]="\h: ";
if [[ -z "$KITTY_PID" ]]; then
if [[ -n "$SSH_TTY" || -n "$SSH2_TTY$KITTY_WINDOW_ID" ]]; then
# connected to most SSH servers
# or use ssh kitten to connected to some SSH servers that do not set SSH_TTY
_ksi_prompt[hostname_prefix]="\h: ";
else
if [[ -n "$(builtin command -v who)" && "$(builtin command who -m 2> /dev/null)" =~ "\([a-fA-F.:0-9]+\)$" ]]; then
# the shell integration script is installed manually on the remote system
# the environment variables are cleared after sudo
# OpenSSH's sshd creates entries in utmp for every login so use those
_ksi_prompt[hostname_prefix]="\h: ";
fi
fi
fi
# see https://www.gnu.org/software/bash/manual/html_node/Controlling-the-Prompt.html#Controlling-the-Prompt
# we use suffix here because some distros add title setting to their bashrc files by default

View File

@ -19,7 +19,7 @@ end
status is-interactive || exit 0
not functions -q __ksi_schedule || exit 0
# Check fish version 3.3.0+ efficiently and fallback to check the last working version 3.2.0, exit on outdated versions.
# Check fish version 3.3.0+ efficiently and fallback to check the minimum working version 3.2.0, exit on outdated versions.
# "Warning: Update fish to version 3.3.0+ to enable kitty shell integration.\n"
set -q fish_killring || set -q status_generation || string match -qnv "3.1.*" "$version"
or echo -en "\eP@kitty-print|V2FybmluZzogVXBkYXRlIGZpc2ggdG8gdmVyc2lvbiAzLjMuMCsgdG8gZW5hYmxlIGtpdHR5IHNoZWxsIGludGVncmF0aW9uLgo=\e\\" && exit 0 || exit 0
@ -80,21 +80,6 @@ function __ksi_schedule --on-event fish_prompt -d "Setup kitty integration after
end
__ksi_mark_prompt_start
functions -c fish_prompt __ksi_original_fish_prompt
function fish_prompt
# fish trims one trailing newline from the output of fish_prompt, so
# we need to do the same. See https://github.com/kovidgoyal/kitty/issues/4032
# op is a list because fish splits on newlines in command substitution
set --local op (__ksi_original_fish_prompt)
# print all but last element of the list, each followed by a new line
set -q op[2]
and printf '%s\n' $op[1..-2]
# print the last component without a newline
printf '%s' $op[-1]
set --global __ksi_prompt_state prompt-end
echo -en "\e]133;B\a"
end
function __ksi_mark_output_start --on-event fish_preexec
set --global __ksi_prompt_state pre-exec
echo -en "\e]133;C\a"

View File

@ -107,21 +107,20 @@ def move(src, base_dest):
def compile_terminfo(base):
if not shutil.which('tic'):
tic = shutil.which('tic')
if not tic:
return
tname = '.terminfo'
if os.path.exists('/usr/share/misc/terminfo.cdb'):
tname += '.cdb'
os.environ['TERMINFO'] = os.path.join(HOME, tname)
tic = shutil.which('tic')
if tic:
cp = subprocess.run(
[tic, '-x', '-o', os.path.join(base, tname), os.path.join(base, '.terminfo', 'kitty.terminfo')],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
if cp.returncode != 0:
sys.stderr.buffer.write(cp.stdout)
raise SystemExit('Failed to compile the terminfo database')
cp = subprocess.run(
[tic, '-x', '-o', os.path.join(base, tname), os.path.join(base, '.terminfo', 'kitty.terminfo')],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
if cp.returncode != 0:
sys.stderr.buffer.write(cp.stdout)
raise SystemExit('Failed to compile the terminfo database')
def get_data():
@ -164,15 +163,6 @@ def get_data():
move(tdir + '/root', '/')
def exec_bash_with_integration():
os.environ['ENV'] = os.path.join(shell_integration_dir, 'bash', 'kitty.bash')
os.environ['KITTY_BASH_INJECT'] = '1'
if not os.environ.get('HISTFILE'):
os.environ['HISTFILE'] = os.path.join(HOME, '.bash_history')
os.environ['KITTY_BASH_UNEXPORT_HISTFILE'] = '1'
os.execlp(login_shell, os.path.basename('login_shell'), '--posix')
def exec_zsh_with_integration():
zdotdir = os.environ.get('ZDOTDIR') or ''
if not zdotdir:
@ -180,8 +170,8 @@ def exec_zsh_with_integration():
os.environ.pop('KITTY_ORIG_ZDOTDIR', None) # ensure this is not propagated
else:
os.environ['KITTY_ORIG_ZDOTDIR'] = zdotdir
# dont prevent zsh-new-user from running
for q in '.zshrc .zshenv .zprofile .zlogin'.split():
# dont prevent zsh-newuser-install from running
for q in ('.zshrc', '.zshenv', '.zprofile', '.zlogin'):
if os.path.exists(os.path.join(HOME, q)):
os.environ['ZDOTDIR'] = shell_integration_dir + '/zsh'
os.execlp(login_shell, os.path.basename(login_shell), '-l')
@ -197,14 +187,23 @@ def exec_fish_with_integration():
os.execlp(login_shell, os.path.basename(login_shell), '-l')
def exec_bash_with_integration():
os.environ['ENV'] = os.path.join(shell_integration_dir, 'bash', 'kitty.bash')
os.environ['KITTY_BASH_INJECT'] = '1'
if not os.environ.get('HISTFILE'):
os.environ['HISTFILE'] = os.path.join(HOME, '.bash_history')
os.environ['KITTY_BASH_UNEXPORT_HISTFILE'] = '1'
os.execlp(login_shell, os.path.basename('login_shell'), '--posix')
def exec_with_shell_integration():
shell_name = os.path.basename(login_shell).lower()
if shell_name == 'bash':
exec_bash_with_integration()
if shell_name == 'zsh':
exec_zsh_with_integration()
if shell_name == 'fish':
exec_fish_with_integration()
if shell_name == 'bash':
exec_bash_with_integration()
def main():

View File

@ -81,7 +81,7 @@ if [ -z "$HOSTNAME" ]; then
if [ -z "$hostname" ]; then
hostname=$(command hostnamectl hostname 2> /dev/null)
if [ -z "$hostname" ]; then
hostname="_";
hostname="_"
fi
fi
else
@ -95,17 +95,17 @@ if [ -z "$USER" ]; then USER=$(command whoami 2> /dev/null); fi
# ask for the SSH data
leading_data=""
init_tty && trap 'cleanup_on_bootstrap_exit' EXIT
init_tty && trap "cleanup_on_bootstrap_exit" EXIT
[ "$tty_ok" = "y" ] && dcs_to_kitty "ssh" "id="REQUEST_ID":hostname="$hostname":pwfile="PASSWORD_FILENAME":user="$USER":pw="DATA_PASSWORD""
record_separator=$(printf "\036")
mv_files_and_dirs() {
cwd="$PWD";
cd "$1";
cwd="$PWD"
cd "$1"
command find . -type d -exec mkdir -p "$2/{}" ";"
command find . -type l -exec sh -c "tgt=\$(command readlink -n \"{}\"); command ln -sf \"\$tgt\" \"$2/{}\"; command rm -f \"{}\"" ";"
command find . -type f -exec mv "{}" "$2/{}" ";"
cd "$cwd";
cd "$cwd"
}
compile_terminfo() {
@ -130,18 +130,18 @@ untar_and_read_env() {
# extract the tar file atomically, in the sense that any file from the
# tarfile is only put into place after it has been fully written to disk
tdir=$(command mktemp -d "$HOME/.kitty-ssh-kitten-untar-XXXXXXXXXXXX");
[ $? = 0 ] || die "Creating temp directory failed";
read_n_bytes_from_tty "$1" | command base64 -d | command tar xjf - --no-same-owner -C "$tdir";
data_file="$tdir/data.sh";
[ -f "$data_file" ] && . "$data_file";
tdir=$(command mktemp -d "$HOME/.kitty-ssh-kitten-untar-XXXXXXXXXXXX")
[ $? = 0 ] || die "Creating temp directory failed"
read_n_bytes_from_tty "$1" | command base64 -d | command tar xjf - --no-same-owner -C "$tdir"
data_file="$tdir/data.sh"
[ -f "$data_file" ] && . "$data_file"
data_dir="$HOME/$KITTY_SSH_KITTEN_DATA_DIR"
compile_terminfo "$tdir/home"
mv_files_and_dirs "$tdir/home" "$HOME"
[ -e "$tdir/root" ] && mv_files_and_dirs "$tdir/root" ""
command rm -rf "$tdir";
[ -z "KITTY_SSH_KITTEN_DATA_DIR" ] && die "Failed to read SSH data from tty";
unset KITTY_SSH_KITTEN_DATA_DIR;
command rm -rf "$tdir"
[ -z "KITTY_SSH_KITTEN_DATA_DIR" ] && die "Failed to read SSH data from tty"
unset KITTY_SSH_KITTEN_DATA_DIR
}
read_record() {
@ -175,17 +175,15 @@ if [ "$tty_ok" = "y" ]; then
printf "\r\033[K" > /dev/tty
fi
shell_integration_dir="$data_dir/shell-integration"
[ -f "$HOME/.terminfo/kitty.terminfo" ] || die "Incomplete extraction of ssh data";
[ -f "$HOME/.terminfo/kitty.terminfo" ] || die "Incomplete extraction of ssh data"
fi
login_shell_is_ok() {
if [ -z "$login_shell" -o ! -x "$login_shell" ]; then return 1; fi
case "$login_shell" in
*sh) return 0;
esac
return 1;
return 1
}
detect_python() {
@ -193,7 +191,7 @@ detect_python() {
if [ -z "$python" ]; then python=$(command -v python2); fi
if [ -z "$python" ]; then python=$(command -v python); fi
if [ -z "$python" -o ! -x "$python" ]; then return 1; fi
return 0;
return 0
}
parse_passwd_record() {
@ -203,43 +201,43 @@ parse_passwd_record() {
using_getent() {
cmd=$(command -v getent)
if [ -n "$cmd" ]; then
output=$($cmd passwd $USER 2>/dev/null)
output=$(command $cmd passwd $USER 2>/dev/null)
if [ $? = 0 ]; then
login_shell=$(echo $output | parse_passwd_record);
login_shell=$(echo $output | parse_passwd_record)
if login_shell_is_ok; then return 0; fi
fi
fi
return 1;
return 1
}
using_id() {
cmd=$(command -v id)
if [ -n "$cmd" ]; then
output=$($cmd -P $USER 2>/dev/null)
output=$(command $cmd -P $USER 2>/dev/null)
if [ $? = 0 ]; then
login_shell=$(echo $output | parse_passwd_record);
login_shell=$(echo $output | parse_passwd_record)
if login_shell_is_ok; then return 0; fi
fi
fi
return 1;
}
using_passwd() {
if [ -f "/etc/passwd" -a -r "/etc/passwd" ]; then
output=$(command grep "^$USER:" /etc/passwd 2>/dev/null)
if [ $? = 0 ]; then
login_shell=$(echo $output | parse_passwd_record);
if login_shell_is_ok; then return 0; fi
fi
fi
return 1;
return 1
}
using_python() {
if detect_python; then
output=$(command $python -c "import pwd, os; print(pwd.getpwuid(os.geteuid()).pw_shell)")
if [ $? = 0 ]; then
login_shell=$output;
login_shell=$output
if login_shell_is_ok; then return 0; fi
fi
fi
return 1
}
using_passwd() {
if [ -f "/etc/passwd" -a -r "/etc/passwd" ]; then
output=$(command grep "^$USER:" /etc/passwd 2>/dev/null)
if [ $? = 0 ]; then
login_shell=$(echo $output | parse_passwd_record)
if login_shell_is_ok; then return 0; fi
fi
fi
@ -250,14 +248,14 @@ execute_with_python() {
if detect_python; then
exec $python -c "import os; os.execlp('$login_shell', '-' '$shell_name')"
fi
return 1;
return 1
}
if [ -n "$KITTY_LOGIN_SHELL" ]; then
login_shell="$KITTY_LOGIN_SHELL"
unset KITTY_LOGIN_SHELL
else
using_getent || using_id || using_python || using_passwd || die "Could not detect login shell";
using_getent || using_id || using_python || using_passwd || die "Could not detect login shell"
fi
shell_name=$(command basename $login_shell)
@ -272,17 +270,6 @@ if [ "$tty_ok" = "n" ]; then
fi
fi
exec_bash_with_integration() {
export ENV="$shell_integration_dir/bash/kitty.bash"
export KITTY_BASH_INJECT="1"
if [ -z "$HISTFILE" ]; then
export HISTFILE="$HOME/.bash_history"
export KITTY_BASH_UNEXPORT_HISTFILE="1"
fi
exec "$login_shell" "--posix"
}
exec_zsh_with_integration() {
zdotdir="$ZDOTDIR"
if [ -z "$zdotdir" ]; then
@ -290,7 +277,7 @@ exec_zsh_with_integration() {
else
export KITTY_ORIG_ZDOTDIR="$zdotdir"
fi
# dont prevent zsh-new-user from running
# dont prevent zsh-newuser-install from running
if [ -f "$zdotdir/.zshrc" -o -f "$zdotdir/.zshenv" -o -f "$zdotdir/.zprofile" -o -f "$zdotdir/.zlogin" ]; then
export ZDOTDIR="$shell_integration_dir/zsh"
exec "$login_shell" "-l"
@ -308,17 +295,27 @@ exec_fish_with_integration() {
exec "$login_shell" "-l"
}
exec_bash_with_integration() {
export ENV="$shell_integration_dir/bash/kitty.bash"
export KITTY_BASH_INJECT="1"
if [ -z "$HISTFILE" ]; then
export HISTFILE="$HOME/.bash_history"
export KITTY_BASH_UNEXPORT_HISTFILE="1"
fi
exec "$login_shell" "--posix"
}
exec_with_shell_integration() {
case "$shell_name" in
"zsh")
exec_zsh_with_integration
;;
"bash")
exec_bash_with_integration
;;
"fish")
exec_fish_with_integration
;;
"bash")
exec_bash_with_integration
;;
esac
}
@ -333,7 +330,7 @@ case "$KITTY_SHELL_INTEGRATION" in
(*)
# not blank
q=$(printf "%s" "$KITTY_SHELL_INTEGRATION" | command grep '\bno-rc\b')
if [ -z "$q" ]; then
if [ -z "$q" ]; then
exec_with_shell_integration
# exec failed, unset
unset KITTY_SHELL_INTEGRATION

View File

@ -55,9 +55,9 @@ builtin typeset -gi _ksi_state
# _ksi_deferred_init.
typeset -gi _ksi_fd
{
zmodload zsh/system && (( $+builtins[sysopen] )) && {
{ [[ -w $TTY ]] && sysopen -o cloexec -wu _ksi_fd -- $TTY } ||
{ [[ -w /dev/tty ]] && sysopen -o cloexec -wu _ksi_fd -- /dev/tty }
builtin zmodload zsh/system && (( $+builtins[sysopen] )) && {
{ [[ -w $TTY ]] && builtin sysopen -o cloexec -wu _ksi_fd -- $TTY } ||
{ [[ -w /dev/tty ]] && builtin sysopen -o cloexec -wu _ksi_fd -- /dev/tty }
}
} 2>/dev/null || (( _ksi_fd = 1 ))
@ -87,7 +87,7 @@ _ksi_deferred_init() {
# Recognized options: no-cursor, no-title, no-prompt-mark, no-complete.
builtin local -a opt
opt=(${(s: :)KITTY_SHELL_INTEGRATION})
unset KITTY_SHELL_INTEGRATION
builtin unset KITTY_SHELL_INTEGRATION
# The directory where kitty-integration is located: /.../shell-integration/zsh.
builtin local self_dir="${functions_source[_ksi_deferred_init]:A:h}"
@ -233,8 +233,17 @@ _ksi_deferred_init() {
# (LF becomes \n, etc.). This isn't necessary in precmd because (%) does it
# for us.
builtin local is_ssh_session="n"
if [[ -n "$SSH_TTY$SSH2_TTY" ]]; then
is_ssh_session="y";
if [[ -n "$KITTY_PID" ]]; then
# kitty running locally
elif [[ -n "$SSH_TTY" || -n "$SSH2_TTY$KITTY_WINDOW_ID" ]]; then
# connected to most SSH servers
# or use ssh kitten to connected to some SSH servers that do not set SSH_TTY
is_ssh_session="y"
elif [[ -n "$(builtin command -v who)" ]]; then
# the shell integration script is installed manually on the remote system
# the environment variables are cleared after sudo
# OpenSSH's sshd creates entries in utmp for every login so use those
[[ "$(builtin command who -m 2> /dev/null)" =~ "\([a-fA-F.:0-9]+\)$" ]] && is_ssh_session="y"
fi
if [[ "$is_ssh_session" == "y" ]]; then