Merge branch 'zsh-integration' of https://github.com/romkatv/kitty
This commit is contained in:
commit
bcecc61b67
@ -1,11 +1,15 @@
|
|||||||
|
# This file can get sourced with aliases enabled. To avoid alias expansion
|
||||||
|
# we quote everything that can be quoted. Some aliases will still break us
|
||||||
|
# though.
|
||||||
|
|
||||||
# Don't use [[ -v ... ]] because it doesn't work in zsh < 5.4.
|
# Don't use [[ -v ... ]] because it doesn't work in zsh < 5.4.
|
||||||
if (( ${+KITTY_ORIG_ZDOTDIR} )); then
|
if [[ -n "${KITTY_ORIG_ZDOTDIR+X}" ]]; then
|
||||||
# Normally ZDOTDIR shouldn't be exported but it was in the environment
|
# Normally ZDOTDIR shouldn't be exported but it was in the environment
|
||||||
# of Kitty, so we export it.
|
# of Kitty, so we export it.
|
||||||
export ZDOTDIR=$KITTY_ORIG_ZDOTDIR
|
'builtin' 'export' ZDOTDIR="$KITTY_ORIG_ZDOTDIR"
|
||||||
unset KITTY_ORIG_ZDOTDIR
|
'builtin' 'unset' 'KITTY_ORIG_ZDOTDIR'
|
||||||
else
|
else
|
||||||
unset ZDOTDIR
|
'builtin' 'unset' 'ZDOTDIR'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use try-always to have the right error code.
|
# Use try-always to have the right error code.
|
||||||
@ -17,16 +21,19 @@ fi
|
|||||||
#
|
#
|
||||||
# Use typeset in case we are in a function with warn_create_global in
|
# Use typeset in case we are in a function with warn_create_global in
|
||||||
# effect. Unlikely but better safe than sorry.
|
# effect. Unlikely but better safe than sorry.
|
||||||
typeset _ksi_source=${ZDOTDIR-~}/.zshenv
|
'builtin' 'typeset' _ksi_file=${ZDOTDIR-~}"/.zshenv"
|
||||||
# Zsh ignores unreadable rc files. We do the same.
|
# Zsh ignores unreadable rc files. We do the same.
|
||||||
# Zsh ignores rc files that are directories, and so does source.
|
# Zsh ignores rc files that are directories, and so does source.
|
||||||
[[ ! -r $_ksi_source ]] || source -- "$_ksi_source"
|
[[ ! -r "$_ksi_file" ]] || 'builtin' 'source' '--' "$_ksi_file"
|
||||||
} always {
|
} always {
|
||||||
if [[ -o interactive ]]; then
|
if [[ -o 'interactive' && -n "${KITTY_SHELL_INTEGRATION-}" ]]; then
|
||||||
# ${(%):-%x} is the path to the current file.
|
# ${(%):-%x} is the path to the current file.
|
||||||
# On top of it we add :a:h to get the directory.
|
# On top of it we add :A:h to get the directory.
|
||||||
typeset _ksi_source=${${(%):-%x}:A:h}/kitty.zsh
|
'builtin' 'typeset' _ksi_file="${${(%):-%x}:A:h}"/kitty-integration
|
||||||
[[ ! -r $_ksi_source ]] || source -- "$_ksi_source"
|
if [[ -r "$_ksi_file" ]]; then
|
||||||
|
'builtin' 'autoload' '-Uz' '--' "$_ksi_file"
|
||||||
|
"${_ksi_file:t}"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
unset _ksi_source
|
'builtin' 'unset' '_ksi_file'
|
||||||
}
|
}
|
||||||
|
|||||||
7
shell-integration/zsh/completions/_kitty
Normal file
7
shell-integration/zsh/completions/_kitty
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#compdef kitty
|
||||||
|
|
||||||
|
(( ${+commands[kitty]} )) || builtin return
|
||||||
|
builtin local src cmd=${(F)words:0:$CURRENT}
|
||||||
|
# Send all words up to the word the cursor is currently on.
|
||||||
|
src=$(builtin command kitty +complete zsh "_matcher=$_matcher" <<<$cmd) || builtin return
|
||||||
|
builtin eval "$src"
|
||||||
266
shell-integration/zsh/kitty-integration
Normal file
266
shell-integration/zsh/kitty-integration
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
#!/bin/zsh
|
||||||
|
#
|
||||||
|
# Enables integration between zsh and Kitty based on KITTY_SHELL_INTEGRATION.
|
||||||
|
# The latter is set by Kitty based on kitty.conf.
|
||||||
|
#
|
||||||
|
# This is an autoloadable function. It's invoked automatically in shells
|
||||||
|
# directly spawned by Kitty but not in any other shells. For example, running
|
||||||
|
# `exec zsh`, `sudo -E zsh`, `tmux`, or plain `zsh` will create a shell where
|
||||||
|
# kitty-integration won't automatically run. Zsh users who want integration with
|
||||||
|
# Kitty in all shells should add the following lines to their .zshrc:
|
||||||
|
#
|
||||||
|
# if [[ -n $KITTY_INSTALLATION_DIR ]]; then
|
||||||
|
# autoload -Uz -- "$KITTY_INSTALLATION_DIR"/shell-integration/zsh/kitty-integration
|
||||||
|
# kitty-integration
|
||||||
|
# fi
|
||||||
|
#
|
||||||
|
# Implementation note: We can assume that alias expansion is disabled in this
|
||||||
|
# file, so no need to quote defensively. We still have to defensively prefix all
|
||||||
|
# builtins with `builtin` to avoid accidentally invoking user-defined functions.
|
||||||
|
# We avoid `function` reserved word as an additional defensive measure.
|
||||||
|
|
||||||
|
builtin emulate -L zsh -o no_warn_create_global
|
||||||
|
|
||||||
|
[[ -o interactive ]] || builtin return 0 # non-interactive shell
|
||||||
|
[[ -n $KITTY_SHELL_INTEGRATION ]] || builtin return 0 # integration disabled
|
||||||
|
(( ! _ksi_state )) || builtin return 0 # already initialized
|
||||||
|
|
||||||
|
if (( ! $+_ksi_state )); then
|
||||||
|
# 0: not initialized; deferred initialization can start now.
|
||||||
|
# 1: not initialized; waiting for deferred initialization.
|
||||||
|
# 2: initialized; no OSC 133 [AC] marks have been written yet.
|
||||||
|
# 3: initialized; the last written OSC 133 C has not been closed with D yet.
|
||||||
|
# 4: initialized; none of the above.
|
||||||
|
builtin typeset -gi _ksi_state=1
|
||||||
|
|
||||||
|
# Asks Kitty to print $@ to its stdout. This is for debugging.
|
||||||
|
_ksi_debug_print() {
|
||||||
|
builtin local data
|
||||||
|
data=$(command base64 <<<"${(j: :}@}") || builtin return
|
||||||
|
builtin printf '\eP@kitty-print|%s\e\\' "${data//$'\n'}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_ksi_deferred_init() {
|
||||||
|
(( _ksi_state = 0, 1 )) # `, 1` in case err_return is set
|
||||||
|
kitty-integration
|
||||||
|
}
|
||||||
|
|
||||||
|
# We defer initialization until precmd for several reasons:
|
||||||
|
#
|
||||||
|
# - Oh My Zsh and many other configs remove zle-line-init and
|
||||||
|
# zle-line-finish hooks when they initialize.
|
||||||
|
# - By deferring initialization we allow user rc files to opt out from some
|
||||||
|
# parts of integration. For example, if a zshrc theme prints OSC 133
|
||||||
|
# marks, it can append " no-prompt-mark" to KITTY_SHELL_INTEGRATION during
|
||||||
|
# intialization to avoid redundant marks from our code.
|
||||||
|
builtin typeset -ag precmd_functions
|
||||||
|
precmd_functions+=(_ksi_deferred_init)
|
||||||
|
builtin return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The rest of kitty-integration performs deferred initialization. We are being
|
||||||
|
# run from _ksi_deferred_init here.
|
||||||
|
|
||||||
|
(( _ksi_state = 2 ))
|
||||||
|
|
||||||
|
# Recognized options: no-cursor, no-title, no-prompt-mark, no-complete.
|
||||||
|
builtin local -a opt
|
||||||
|
opt=(${(s: :)KITTY_SHELL_INTEGRATION})
|
||||||
|
unset KITTY_SHELL_INTEGRATION
|
||||||
|
|
||||||
|
# The directory where kitty-integration is located: /.../shell-integration/zsh.
|
||||||
|
builtin local self_dir=${functions_source[kitty-integration]:A:h}
|
||||||
|
# The directory with _kitty. We store it in a directory of its own rather than
|
||||||
|
# in $self_dir because we are adding it to fpath and we don't want any other
|
||||||
|
# files to be accidentally autoloadable.
|
||||||
|
builtin local comp_dir=$self_dir/completions
|
||||||
|
|
||||||
|
# Enable completions for `kitty` command.
|
||||||
|
if (( ! opt[(Ie)no-complete] )) && [[ -r $comp_dir/_kitty ]]; then
|
||||||
|
if (( $+functions[compdef] )); then
|
||||||
|
# If compdef is defined, then either compinit has already run or it's
|
||||||
|
# a shim that records all calls for the purpose of replaying them after
|
||||||
|
# compinit. Either way we clobber the existing completion for kitty and
|
||||||
|
# install our own.
|
||||||
|
builtin unset "functions[_kitty]"
|
||||||
|
builtin autoload -Uz -- $comp_dir/_kitty
|
||||||
|
compdef _kitty kitty
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If compdef is not set, compinit has not run yet. In this case we must
|
||||||
|
# add our completions directory to fpath so that _kitty gets picked up by
|
||||||
|
# compinit.
|
||||||
|
#
|
||||||
|
# We extend fpath even if compinit has run because it might run again.
|
||||||
|
# Without our completions directory in fpath compinit would our _comp
|
||||||
|
# mapping.
|
||||||
|
builtin typeset -ga fpath
|
||||||
|
fpath=($comp_dir ${fpath:#$comp_dir})
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enable cursor shape changes depending on the current keymap.
|
||||||
|
if (( ! opt[(Ie)no-cursor] )); then
|
||||||
|
# This implementation leaks blinking block cursor into external commands
|
||||||
|
# executed from zle. For example, users of fzf-based widgets may find
|
||||||
|
# themselves with a blinking block cursor within fzf.
|
||||||
|
_ksi_zle_line_init _ksi_zle_line_finish _ksi_zle_keymap_select() {
|
||||||
|
case ${KEYMAP-} in
|
||||||
|
vicmd|visual) builtin print -n '\e[1 q';; # blinking block cursor
|
||||||
|
*) builtin print -n '\e[5 q';; # blinking bar cursor
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enable semantic markup with OSC 133.
|
||||||
|
if (( ! opt[(Ie)no-prompt-mark] )); then
|
||||||
|
_ksi_precmd() {
|
||||||
|
builtin local -i cmd_status=$?
|
||||||
|
builtin emulate -L zsh -o no_warn_create_global
|
||||||
|
|
||||||
|
# Don't write OSC 133 D when our precmd handler is invoked from zle.
|
||||||
|
# Some plugins do that to update prompt on cd.
|
||||||
|
if ! builtin zle; then
|
||||||
|
# This code works incorrectly in the presence of a precmd or chpwd
|
||||||
|
# hook that prints. For example, sindresorhus/pure prints an empty
|
||||||
|
# line on precmd and marlonrichert/zsh-snap prints $PWD on chpwd.
|
||||||
|
# We'll end up writing our OSC 133 D mark too late.
|
||||||
|
#
|
||||||
|
# Another failure mode is when the output of a command doesn't end
|
||||||
|
# with LF and prompst_sp is set (it is by default). In this case
|
||||||
|
# we'll incorrectly state that '%' from prompt_sp is a part of the
|
||||||
|
# command's output.
|
||||||
|
if (( _ksi_state == 3 )); then
|
||||||
|
# The last written OSC 133 C has not been closed with D yet.
|
||||||
|
# Close it and supply status.
|
||||||
|
builtin printf '\e]133;D;%s\a' $cmd_status
|
||||||
|
(( _ksi_state = 4 ))
|
||||||
|
elif (( _ksi_state == 4 )); then
|
||||||
|
# There might be an unclosed OSC 133 C. Close that.
|
||||||
|
builtin print -n '\e]133;D\a'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
builtin local mark1=$'%{\e]133;A\a%}'
|
||||||
|
if [[ -o prompt_percent ]]; then
|
||||||
|
builtin typeset -g precmd_functions
|
||||||
|
if [[ ${precmd_functions[-1]} == _ksi_precmd ]]; then
|
||||||
|
# This is the best case for us: we can add our marks to PS1 and
|
||||||
|
# PS2. This way our marks will be printed whenever zsh
|
||||||
|
# redisplays prompt: on reset-prompt, on SIGWINCH, and on
|
||||||
|
# SIGCHLD if notify is set. Themes that update prompt
|
||||||
|
# asynchronously from a `zle -F` handler might still remove our
|
||||||
|
# marks. Oh well.
|
||||||
|
builtin local mark2=$'%{\e]133;A;k=s\a%}'
|
||||||
|
# Add marks conditionally to avoid a situation where we have
|
||||||
|
# several marks in place. These conditions can have false
|
||||||
|
# positives and false negatives though.
|
||||||
|
#
|
||||||
|
# - False positive (with prompt_percent): PS1="%(?.$mark1.)"
|
||||||
|
# - False negative (with prompt_subst): PS1='$mark1'
|
||||||
|
[[ $PS1 == *$mark1* ]] || PS1=${mark1}${PS1}
|
||||||
|
[[ $PS2 == *$mark2* ]] || PS2=${mark2}${PS2}
|
||||||
|
(( _ksi_state = 4 ))
|
||||||
|
else
|
||||||
|
# If our precmd hook is not the last, we cannot rely on prompt
|
||||||
|
# changes to stick, so we don't even try. At least we can move
|
||||||
|
# our hook to the end to have better luck next time. If there is
|
||||||
|
# another piece of code that wants to take this privileged
|
||||||
|
# position, this won't work well. We'll break them as much as
|
||||||
|
# they are breaking us.
|
||||||
|
precmd_functions=(${precmd_functions:#_ksi_precmd} _ksi_precmd)
|
||||||
|
# Plugins that invoke precmd hooks from zle do that before zle
|
||||||
|
# is trashed. This means that the cursor is in the middle of
|
||||||
|
# BUFFER and we cannot print our mark there. Prompt might
|
||||||
|
# already have a mark, so the following reset-prompt will write
|
||||||
|
# it. If it doesn't, there is nothing we can do.
|
||||||
|
if ! builtin zle; then
|
||||||
|
builtin print -rn -- $mark1[3,-3]
|
||||||
|
(( _ksi_state = 4 ))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
elif ! builtin zle; then
|
||||||
|
# Without prompt_percent we cannot patch prompt. Just print the
|
||||||
|
# mark, except when we are invoked from zle. In the latter case we
|
||||||
|
# cannot do anything.
|
||||||
|
builtin print -rn -- $mark1[3,-3]
|
||||||
|
(( _ksi_state = 4 ))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_ksi_preexec() {
|
||||||
|
builtin emulate -L zsh -o no_warn_create_global
|
||||||
|
|
||||||
|
# This can potentially break user prompt. Oh well. The robustness of
|
||||||
|
# this code can be improved in the case prompt_subst is set because
|
||||||
|
# it'll allow us distinguish (not perfectly but close enough) between
|
||||||
|
# our own prompt, user prompt, and our own prompt with user additions on
|
||||||
|
# top. We cannot force prompt_subst on the user though, so we would
|
||||||
|
# still need this code for the no_prompt_subst case.
|
||||||
|
PS1=${PS1//$'%{\e]133;A\a%}'}
|
||||||
|
PS2=${PS2//$'%{\e]133;A;k=s\a%}'}
|
||||||
|
|
||||||
|
# This will work incorrectly in the presence of a preexec hook that
|
||||||
|
# prints. For example, if MichaelAquilina/zsh-you-should-use installs
|
||||||
|
# its preexec hook before us, we'll incorrectly mark its output as
|
||||||
|
# belonging to the command (as if the user typed it into zle) rather
|
||||||
|
# than command output.
|
||||||
|
builtin print -n '\e]133;C\a'
|
||||||
|
(( _ksi_state = 3 ))
|
||||||
|
}
|
||||||
|
|
||||||
|
functions[_ksi_zle_line_init]+='
|
||||||
|
builtin print -n "\\e]133;B\\a"'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enable terminal title changes.
|
||||||
|
if (( ! opt[(Ie)no-title] )); then
|
||||||
|
# We don't use `print -P` because it depends on prompt options, which
|
||||||
|
# we don't control and cannot change.
|
||||||
|
#
|
||||||
|
# We use (V) in preexec to convert control characters to something visible
|
||||||
|
# (LF becomes \n, etc.). This isn't necessary in precmd because (%) does it
|
||||||
|
# for us.
|
||||||
|
functions[_ksi_precmd]+='
|
||||||
|
builtin printf "\\e]2;%s\\a" "${(%):-%(4~|…/%3~|%~)}"'
|
||||||
|
functions[_ksi_preexec]+='
|
||||||
|
builtin printf "\\e]2;%s\\a" "${(V)1}"'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Some zsh users manually run `source ~/.zshrc` in order to apply rc file
|
||||||
|
# changes to the current shell. This is a terrible practice that breaks many
|
||||||
|
# things, including our shell integration. For example, Oh My Zsh and Prezto
|
||||||
|
# (both very popular among zsh users) will remove zle-line-init and
|
||||||
|
# zle-line-finish hooks if .zshrc is manually sourced. Prezto will also remove
|
||||||
|
# zle-keymap-select.
|
||||||
|
#
|
||||||
|
# Another common (and much more robust) way to apply rc file changes to the
|
||||||
|
# current shell is `exec zsh`. This will remove our integration from the shell
|
||||||
|
# unless it's explicitly invoked from .zshrc. This is not an issue with
|
||||||
|
# `exec zsh` but rather with our implementation of automatic shell integration.
|
||||||
|
builtin autoload -Uz add-zle-hook-widget
|
||||||
|
if (( $+functions[_ksi_zle_line_init] )); then
|
||||||
|
add-zle-hook-widget line-init _ksi_zle_line_init
|
||||||
|
fi
|
||||||
|
if (( $+functions[_ksi_zle_line_finish] )); then
|
||||||
|
add-zle-hook-widget line-finish _ksi_zle_line_finish
|
||||||
|
fi
|
||||||
|
if (( $+functions[_ksi_zle_keymap_select] )); then
|
||||||
|
add-zle-hook-widget keymap-select _ksi_zle_keymap_select
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( $+functions[_ksi_preexec] )); then
|
||||||
|
builtin typeset -ag preexec_functions
|
||||||
|
preexec_functions+=(_ksi_preexec)
|
||||||
|
fi
|
||||||
|
|
||||||
|
builtin typeset -ag precmd_functions
|
||||||
|
if (( $+functions[_ksi_precmd] )); then
|
||||||
|
precmd_functions=(${precmd_functions:/_ksi_deferred_init/_ksi_precmd})
|
||||||
|
_ksi_precmd
|
||||||
|
else
|
||||||
|
precmd_functions=(${precmd_functions:#_ksi_deferred_init})
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unfunction what we don't need to save memory.
|
||||||
|
builtin unfunction _ksi_deferred_init kitty-integration
|
||||||
|
builtin autoload -Uz -- $self_dir/kitty-integration
|
||||||
@ -1,151 +1,20 @@
|
|||||||
#!/bin/zsh
|
#!/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.
|
||||||
|
|
||||||
() {
|
# ${(%):-%x} is the path to the current file.
|
||||||
if [[ ! -o interactive ]]; then return; fi
|
# On top of it we add :A:h to get the directory.
|
||||||
if [[ -z "$KITTY_SHELL_INTEGRATION" ]]; then return; fi
|
'builtin' 'typeset' _ksi_file="${${(%):-%x}:A:h}"/kitty-integration
|
||||||
if [[ ! -z "$_ksi_prompt" ]]; then return; fi
|
if [[ -r "$_ksi_file" ]]; then
|
||||||
typeset -g -A _ksi_prompt
|
'builtin' 'autoload' '-Uz' '--' "$_ksi_file"
|
||||||
_ksi_prompt=(state first-run is_last_precmd y cursor y title y mark y complete y)
|
"${_ksi_file:t}"
|
||||||
for i in ${=KITTY_SHELL_INTEGRATION}; do
|
fi
|
||||||
if [[ "$i" == "no-cursor" ]]; then _ksi_prompt[cursor]='n'; fi
|
'builtin' 'unset' '_ksi_file'
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user