Rewrite zsh integration
Note: - Very lightly tested. - Docs not updated.
This commit is contained in:
@@ -1,151 +1,20 @@
|
||||
#!/bin/zsh
|
||||
#
|
||||
# This file can get sourced with aliases enabled. Moreover, it be sourced from
|
||||
# zshrc, so the chance of having some aliases already defined is high. To avoid
|
||||
# alias expansion we quote everything that can be quoted. Some aliases will
|
||||
# still break us. For example:
|
||||
#
|
||||
# alias -g -- -r='$RANDOM'
|
||||
#
|
||||
# For this reason users are discouraged from sourcing kitty.zsh in favor of
|
||||
# invoking kitty-integration directly.
|
||||
|
||||
() {
|
||||
if [[ ! -o interactive ]]; then return; fi
|
||||
if [[ -z "$KITTY_SHELL_INTEGRATION" ]]; then return; fi
|
||||
if [[ ! -z "$_ksi_prompt" ]]; then return; fi
|
||||
typeset -g -A _ksi_prompt
|
||||
_ksi_prompt=(state first-run is_last_precmd y cursor y title y mark y complete y)
|
||||
for i in ${=KITTY_SHELL_INTEGRATION}; do
|
||||
if [[ "$i" == "no-cursor" ]]; then _ksi_prompt[cursor]='n'; fi
|
||||
if [[ "$i" == "no-title" ]]; then _ksi_prompt[title]='n'; fi
|
||||
if [[ "$i" == "no-prompt-mark" ]]; then _ksi_prompt[mark]='n'; fi
|
||||
if [[ "$i" == "no-complete" ]]; then _ksi_prompt[complete]='n'; fi
|
||||
done
|
||||
unset KITTY_SHELL_INTEGRATION
|
||||
|
||||
function _ksi_debug_print() {
|
||||
# print a line to STDOUT of parent kitty process
|
||||
local b=$(printf "%s\n" "$1" | base64 | tr -d \\n)
|
||||
printf "\eP@kitty-print|%s\e\\" "$b"
|
||||
}
|
||||
|
||||
function _ksi_change_cursor_shape () {
|
||||
# change cursor shape depending on mode
|
||||
if [[ "$_ksi_prompt[cursor]" == "y" ]]; then
|
||||
case $KEYMAP in
|
||||
vicmd | visual)
|
||||
# the command mode for vi
|
||||
printf "\e[1 q" # blinking block cursor
|
||||
;;
|
||||
*)
|
||||
printf "\e[5 q" # blinking bar cursor
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
function _ksi_osc() {
|
||||
printf "\e]%s\a" "$1"
|
||||
}
|
||||
|
||||
function _ksi_mark() {
|
||||
# tell kitty to mark the current cursor position using OSC 133
|
||||
if [[ "$_ksi_prompt[mark]" == "y" ]]; then _ksi_osc "133;$1"; fi
|
||||
}
|
||||
_ksi_prompt[start_mark]="%{$(_ksi_mark A)%}"
|
||||
_ksi_prompt[secondary_mark]="%{$(_ksi_mark 'A;k=s')%}"
|
||||
|
||||
function _ksi_set_title() {
|
||||
if [[ "$_ksi_prompt[title]" == "y" ]]; then _ksi_osc "2;$1"; fi
|
||||
}
|
||||
|
||||
function _ksi_install_completion() {
|
||||
if [[ "$_ksi_prompt[complete]" == "y" ]]; then
|
||||
# compdef is only defined if compinit has been called
|
||||
if whence compdef > /dev/null; then
|
||||
compdef _ksi_complete kitty
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function _ksi_precmd() {
|
||||
local cmd_status=$?
|
||||
# Set kitty window title to the cwd, appropriately shortened, see
|
||||
# https://unix.stackexchange.com/questions/273529/shorten-path-in-zsh-prompt
|
||||
_ksi_set_title $(print -P '%(4~|…/%3~|%~)')
|
||||
|
||||
# Prompt marking
|
||||
if [[ "$_ksi_prompt[mark]" == "y" ]]; then
|
||||
if [[ "$_ksi_prompt[state]" == "preexec" ]]; then
|
||||
_ksi_mark "D;$cmd_status"
|
||||
else
|
||||
if [[ "$_ksi_prompt[state]" != "first-run" ]]; then _ksi_mark "D"; fi
|
||||
fi
|
||||
# we must use PS1 to set the prompt start mark as precmd functions are
|
||||
# not called when the prompt is redrawn after a window resize or when a background
|
||||
# job finishes. However, if we are not the last function in precmd_functions which
|
||||
# can be the case on first run, PS1 might be broken by a following function, so
|
||||
# output the mark directly in that case
|
||||
if [[ "$_ksi_prompt[is_last_precmd]" != "y" ]]; then
|
||||
_ksi_mark "A";
|
||||
_ksi_prompt[is_last_precmd]="y";
|
||||
else
|
||||
if [[ "$PS1" != *"$_ksi_prompt[start_mark]"* ]]; then PS1="$_ksi_prompt[start_mark]$PS1" fi
|
||||
fi
|
||||
# PS2 is used for prompt continuation. On resize with a continued prompt only the last
|
||||
# prompt is redrawn so we need to mark it
|
||||
if [[ "$PS2" != *"$_ksi_prompt[secondary_mark]"* ]]; then PS2="$_ksi_prompt[secondary_mark]$PS2" fi
|
||||
fi
|
||||
_ksi_prompt[state]="precmd"
|
||||
}
|
||||
|
||||
function _ksi_zle_line_init() {
|
||||
if [[ "$_ksi_prompt[mark]" == "y" ]]; then _ksi_mark "B"; fi
|
||||
_ksi_change_cursor_shape
|
||||
_ksi_prompt[state]="line-init"
|
||||
}
|
||||
|
||||
function _ksi_zle_line_finish() {
|
||||
_ksi_change_cursor_shape
|
||||
_ksi_prompt[state]="line-finish"
|
||||
}
|
||||
|
||||
function _ksi_preexec() {
|
||||
if [[ "$_ksi_prompt[mark]" == "y" ]]; then
|
||||
_ksi_mark "C";
|
||||
# remove the prompt mark sequence while the command is executing as it could read/modify the value of PS1
|
||||
PS1="${PS1//$_ksi_prompt[start_mark]/}"
|
||||
PS2="${PS2//$_ksi_prompt[secondary_mark]/}"
|
||||
fi
|
||||
# Set kitty window title to the currently executing command
|
||||
_ksi_set_title "$1"
|
||||
_ksi_prompt[state]="preexec"
|
||||
}
|
||||
|
||||
function _ksi_first_run() {
|
||||
# We install the real precmd and preexec functions here and remove this function
|
||||
# from precmd_functions. This ensures that our functions are last. This is needed
|
||||
# because the zsh prompt_init package actually sets PS1 in a precmd function and the user
|
||||
# could have setup their own precmd function to set the prompt as well.
|
||||
_ksi_install_completion
|
||||
typeset -a -g precmd_functions
|
||||
local idx=$precmd_functions[(ie)_ksi_first_run]
|
||||
if [[ $idx -gt 0 ]]; then
|
||||
if [[ $idx -lt ${#precmd_functions[@]} ]]; then
|
||||
_ksi_prompt[is_last_precmd]="n"
|
||||
fi
|
||||
add-zsh-hook -d precmd _ksi_first_run
|
||||
add-zsh-hook precmd _ksi_precmd
|
||||
add-zsh-hook preexec _ksi_preexec
|
||||
add-zle-hook-widget keymap-select _ksi_change_cursor_shape
|
||||
add-zle-hook-widget line-init _ksi_zle_line_init
|
||||
add-zle-hook-widget line-finish _ksi_zle_line_finish
|
||||
_ksi_precmd
|
||||
fi
|
||||
}
|
||||
|
||||
# Completion for kitty
|
||||
_ksi_complete() {
|
||||
local src
|
||||
# Send all words up to the word the cursor is currently on
|
||||
src=$(printf "%s\n" "${(@)words[1,$CURRENT]}" | kitty +complete zsh "_matcher=$_matcher")
|
||||
if [[ $? == 0 ]]; then
|
||||
eval ${src}
|
||||
fi
|
||||
}
|
||||
|
||||
autoload -Uz add-zsh-hook
|
||||
autoload -Uz add-zle-hook-widget
|
||||
add-zsh-hook precmd _ksi_first_run
|
||||
}
|
||||
# ${(%):-%x} is the path to the current file.
|
||||
# On top of it we add :A:h to get the directory.
|
||||
'builtin' 'typeset' _ksi_file="${${(%):-%x}:A:h}"/kitty-integration
|
||||
if [[ -r "$_ksi_file" ]]; then
|
||||
'builtin' 'autoload' '-Uz' '--' "$_ksi_file"
|
||||
"${_ksi_file:t}"
|
||||
fi
|
||||
'builtin' 'unset' '_ksi_file'
|
||||
|
||||
Reference in New Issue
Block a user