move to new repo

This commit is contained in:
tumillanino
2026-03-24 20:17:22 +11:00
parent 083b57c87b
commit 35bcba335a
1910 changed files with 161640 additions and 41 deletions

View File

@@ -0,0 +1,694 @@
#!/bin/zsh
zmodload -F zsh/zpty b:zpty
zmodload -F zsh/parameter p:funcstack p:functions p:parameters
zmodload -F zsh/system b:sysopen p:sysparams
zmodload -F zsh/zselect b:zselect
zmodload -F zsh/terminfo b:echoti p:terminfo
zmodload -F zsh/zutil b:zparseopts
builtin autoload -RUz \
add-zle-hook-widget \
is-at-least
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=yes
typeset -g _autocomplete__overhead=0
${0}:precmd() {
[[ -v ZSH_AUTOSUGGEST_IGNORE_WIDGETS ]] &&
ZSH_AUTOSUGGEST_IGNORE_WIDGETS+=(
history-incremental-search-backward
recent-paths
.autocomplete:async:complete:fd-widget
)
# Start names with `.` to avoid getting wrapped by syntax highlighting.
builtin zle -N .autocomplete:async:pty:zle-widget
builtin zle -C .autocomplete:async:pty:completion-widget list-choices .autocomplete:async:pty:completion-widget
builtin zle -N .autocomplete:async:complete:fd-widget
builtin zle -N .autocomplete:async:wait:fd-widget
builtin zle -C ._list_choices list-choices .autocomplete:async:list-choices:completion-widget
builtin zle -N history-incremental-search-backward .autocomplete:async:toggle-context
builtin zle -N recent-paths .autocomplete:async:toggle-context
add-zle-hook-widget line-init .autocomplete:async:reset-context
add-zle-hook-widget line-pre-redraw .autocomplete:async:complete
add-zle-hook-widget line-finish .autocomplete:async:clear
add-zle-hook-widget isearch-update .autocomplete:async:isearch-update
add-zle-hook-widget isearch-exit .autocomplete:async:isearch-exit
}
.autocomplete:async:toggle-context() {
if [[ $curcontext == $WIDGET* ]]; then
unset curcontext
else
typeset -g curcontext=${WIDGET}:::
fi
zle .autocomplete:async:complete -w
}
.autocomplete:async:reset-context() {
.autocomplete:async:reset-state
typeset -g curcontext=
builtin zstyle -s :autocomplete: default-context curcontext
.autocomplete:async:complete
return 0
}
.autocomplete:async:isearch-update() {
typeset -gi _autocomplete__isearch=1
}
.autocomplete:async:isearch-exit() {
unset _autocomplete__isearch
}
.autocomplete:async:save-state() {
typeset -g \
_autocomplete__curcontext=$curcontext \
_autocomplete__lbuffer="$LBUFFER" \
_autocomplete__rbuffer="$RBUFFER"
}
.autocomplete:async:same-state() {
[[ -v _autocomplete__curcontext && $_autocomplete__curcontext == $curcontext &&
-v _autocomplete__lbuffer && $_autocomplete__lbuffer == $LBUFFER &&
-v _autocomplete__rbuffer && $_autocomplete__rbuffer == $RBUFFER ]]
}
.autocomplete:async:reset-state() {
unset \
_autocomplete__curcontext \
_autocomplete__lbuffer \
_autocomplete__rbuffer
}
.autocomplete:async:complete() {
if [[ -v _autocomplete__inserted ]]; then
unset _autocomplete__inserted
typeset -g curcontext=
builtin zstyle -s :autocomplete: default-context curcontext
fi
.autocomplete:async:save-state
.autocomplete__zle-flags ||
return 0
(( KEYS_QUEUED_COUNT || PENDING )) &&
return
[[ -v ZSH_AUTOSUGGEST_IGNORE_WIDGETS ]] && (( ZSH_AUTOSUGGEST_IGNORE_WIDGETS[(I)$LASTWIDGET] )) &&
unset POSTDISPLAY
# Don't get activated by asynchronous widgets.
[[ $LASTWIDGET == (autosuggest-suggest|.autocomplete:async:*:fd-widget) ]] &&
return 0
{
if (( REGION_ACTIVE )) ||
[[ -v _autocomplete__isearch && $LASTWIDGET == *(incremental|isearch)* ]]; then
builtin zle -Rc
return 0
fi
builtin zstyle -t ":autocomplete:${LASTWIDGET}:" ignore &&
return 0
local -Pa ignored=(
'_complete_help'
'(copy|insert)-*-word'
'describe-key-briefly'
'(|reverse-)menu-complete'
'what-cursor-position'
'where-is'
)
[[ ${LASTWIDGET##.} == (${(~j:|:)~ignored}) ]] &&
return 0
[[ $KEYS == ([\ -+*]|$'\e\t') ]] &&
builtin zle -Rc
# WORKAROUND: #549 Bug in zdharma/fast-syntax-highlighting.
[[ -v _FAST_MAIN_CACHE ]] &&
_zsh_highlight
typeset -ga _autocomplete__region_highlight=( "$region_highlight[@]" )
if [[ -v ZSH_AUTOSUGGEST_IGNORE_WIDGETS ]] &&
(( ZSH_AUTOSUGGEST_IGNORE_WIDGETS[(I)$LASTWIDGET] )); then
unset POSTDISPLAY
fi
.autocomplete:async:wait
}
return 0
}
.autocomplete:async:clear() {
unset curcontext _autocomplete__isearch
.autocomplete:async:reset-context
builtin zle -Rc
return 0
}
.autocomplete:async:wait() {
local fd=
sysopen -r -o cloexec -u fd <(
local -F seconds=
builtin zstyle -s :autocomplete: delay seconds ||
builtin zstyle -s :autocomplete: min-delay seconds ||
(( seconds = 0.05 ))
(( seconds = max( 0, seconds - _autocomplete__overhead ) ))
# Convert to 100ths of a second for `zselect -t`.
# WORKAROUND: #441 Directly using $(( [#10] … max( … ) )) leads to 0 in Zsh 5.9, as the result
# of max() gets converted to an integer _before_ being multiplied.
local -i timeout=$(( 100 * seconds ))
zselect -t $timeout
print
)
builtin zle -Fw "$fd" .autocomplete:async:wait:fd-widget
return 0
}
.autocomplete:async:wait:fd-widget() {
local -i fd=$1
{
builtin zle -F $fd # Unhook ourselves immediately, so we don't get called more than once.
if [[ -n $_autocomplete__zle_flags ]]; then
builtin zle -f $_autocomplete__zle_flags
[[ $_autocomplete__zle_flags == yank* ]] &&
return 0
fi
(( KEYS_QUEUED_COUNT || PENDING )) &&
return
{
.autocomplete:async:same-state &&
.autocomplete:async:start
}
} always {
exec {fd}<&-
}
return 0
}
.autocomplete:async:start() {
if [[ -v _autocomplete__async_fd && _autocomplete__async_fd -ge 10 ]]; then
# Unhook and close the previous fd. (If it no longer exists, then this will fail harmlessly.)
builtin zle -F "$_autocomplete__async_fd" 2>/dev/null
exec {_autocomplete__async_fd}<&- 2>/dev/null
fi
typeset -g _autocomplete__async_fd=
sysopen -r -o cloexec -u _autocomplete__async_fd <(
local +h PS4=$_autocomplete__ps4
.autocomplete:async:start:inner 2>>| $_autocomplete__log
)
builtin zle -Fw "$_autocomplete__async_fd" .autocomplete:async:complete:fd-widget
# WORKAROUND: https://github.com/zsh-users/zsh-autosuggestions/issues/364
# There's a weird bug in Zsh < 5.8, where ^C stops working unless we force a fork.
command true
}
.autocomplete:async:start:inner() {
{
typeset -F SECONDS=0
local -P hooks=( chpwd periodic precmd preexec zshaddhistory zshexit )
builtin unset ${^hooks}_functions &> /dev/null
$hooks[@] () { : }
local -P hook=
for hook in \
zle-{isearch-{exit,update},line-{pre-redraw,init,finish},history-line-set,keymap-select}
do
builtin zle -N $hook .autocomplete:async:pty:no-op
done
{
local REPLY=
zpty AUTOCOMPLETE .autocomplete:async:pty
local -Pi fd=$REPLY
zpty -w AUTOCOMPLETE $'\C-@'
local header=
zpty -r AUTOCOMPLETE header $'*\C-A'
local -a reply=()
local text=
local -F seconds=0.0
builtin zstyle -s ":autocomplete:${curcontext}" timeout seconds ||
(( seconds = 1.0 ))
(( seconds = max( 0, seconds - SECONDS ) ))
# Convert to 100ths of a second for `zselect -t`.
# WORKAROUND: #441 Directly using $(( [#10] … max( … ) )) leads to 0 in Zsh 5.9, as the result
# of max() gets converted to an integer _before_ being multiplied.
local -i timeout=$(( 100 * seconds ))
if zselect -rt $timeout "$fd"; then
zpty -r AUTOCOMPLETE text $'*\C-B'
else
# Press ^C twice: Once to abort completion, then once to abort the command line.
# Then exit the shell with ^D.
zpty -wn AUTOCOMPLETE $'\C-C\C-C\C-D'
fi
} always {
zpty -d AUTOCOMPLETE
}
} always {
# Always produce output, so we always reach the callback, so we can close
# the fd.
print -rNC1 -- "${text%$'\C-B'}"
}
}
.autocomplete:async:pty() {
typeset -g +h PS4=pty:$_autocomplete__ps4
# Force the shell to exit on timeout.
local -i seconds=
builtin zstyle -s ":autocomplete:${curcontext}" timeout seconds ||
seconds=1
TMOUT=$(( [#10] 1 + seconds ))
TRAPALRM() {
builtin exit
}
builtin bindkey $'\C-@' .autocomplete:async:pty:zle-widget
local __tmp__=
builtin vared __tmp__
} 2>>| $_autocomplete__log
.autocomplete:async:pty:no-op() {
:
}
.autocomplete:async:pty:zle-widget() {
setopt localoptions NO_banghist
local -a _autocomplete__comp_mesg=()
local -i _autocomplete__list_lines=0
local _autocomplete__mesg=
{
# The completion widget sometimes returns without calling its function. So, we need to print all
# our control characters here, to ensure we don't end up waiting endlessly to read them.
print -n -- '\C-A'
LBUFFER=$_autocomplete__lbuffer
RBUFFER=$_autocomplete__rbuffer
[[ -n $curcontext ]] &&
setopt $_autocomplete__ctxt_opts[@]
builtin zle .autocomplete:async:pty:completion-widget -w 2>>| $_autocomplete__log
} always {
print -rNC1 -- ${_autocomplete__list_lines:-0}$'\C-B'
builtin exit
}
} 2>>| $_autocomplete__log
.autocomplete:async:pty:completion-widget() {
setopt localoptions banghist
{
if ! .autocomplete:async:sufficient-input; then
return
fi
{
unfunction compadd 2> /dev/null
unset 'compstate[vared]'
.autocomplete:async:list-choices:main-complete
} always {
_autocomplete__list_lines=$compstate[list_lines]
}
}
} 2>>| $_autocomplete__log
.autocomplete:async:complete:fd-widget() {
setopt localoptions NO_banghist
local -i fd=$1
{
local +h -F SECONDS=0.0
{
builtin zle -F $fd # Unhook ourselves immediately, so we don't get called more than once.
if [[ -n $_autocomplete__zle_flags ]]; then
builtin zle -f $_autocomplete__zle_flags
[[ $_autocomplete__zle_flags == yank* ]] &&
return 0
fi
(( KEYS_QUEUED_COUNT || PENDING )) &&
return
.autocomplete:async:same-state ||
return 0
local -a reply=()
IFS=$'\0' read -rAu $fd
shift -p reply
(( SECONDS += reply[2] ))
} always {
exec {fd}<&-
[[ -v _autocomplete__async_fd && $_autocomplete__async_fd == $fd ]] &&
unset _autocomplete__async_fd
}
[[ -n $curcontext ]] &&
setopt $_autocomplete__ctxt_opts[@]
# If a widget can't be called, zle always returns true.
# Thus, we return false on purpose, so we can check if our widget got called.
local +h PS4=zle:$_autocomplete__ps4
if ! builtin zle ._list_choices -w "$reply[1]" 2>>| $_autocomplete__log; then
typeset -g _autocomplete__overhead=$SECONDS
typeset -g region_highlight=( "$_autocomplete__region_highlight[@]" )
# Need to call this here, because on line-pre-redraw, $POSTDISPLAY is empty.
[[ -v functions[_zsh_autosuggest_highlight_apply] ]] &&
_zsh_autosuggest_highlight_apply
# Refresh if and only if our widget got called. Otherwise, Zsh will crash (eventually).
builtin zle -R
fi
.autocomplete:async:reset-state
return 0
}
}
.autocomplete:async:sufficient-input() {
local min_input=
if ! builtin zstyle -s ":autocomplete:${curcontext}:" min-input min_input; then
if [[ -n $curcontext ]]; then
min_input=0
else
min_input=1
fi
fi
local ignored=
builtin zstyle -s ":autocomplete:${curcontext}:" ignored-input ignored
if (( ${#words[@]} == 1 && ${#words[CURRENT]} < min_input )) ||
[[ -n $ignored && $words[CURRENT] == $~ignored ]]; then
compstate[list]=
false
else
true
fi
}
.autocomplete:async:list-choices:completion-widget() {
local +h PS4=$_autocomplete__ps4
setopt localoptions banghist
if [[ $1 != <1-> ]]; then
compstate[list]=
return
fi
.autocomplete:async:sufficient-input ||
return 2
.autocomplete:async:list-choices:main-complete
# Workaround: In Zsh <= 5.9.0, comppostfuncs don't get called after completing subscripts.
unset MENUSELECT MENUMODE
compstate[insert]=
_lastcomp[insert]=
compstate[pattern_insert]=
_lastcomp[pattern_insert]=
if [[ -v _autocomplete__partial_list ]]; then
builtin compadd -J -last- -x '%F{0}%K{12}(MORE)%f%k'
_lastcomp[list_lines]=$compstate[list_lines]
fi
if [[ -n $compstate[exact_string] && -z $_lastcomp[tags] &&
compstate[nmatches] -eq 1 && compstate[list_lines] -eq 1 ]]; then
# WORKAROUND: _arguments adds $compstate[exact_string] as a completion w/out description.
compstate[list]=
_lastcomp[list]=
fi
return 2 # Don't return 1, to prevent beeping.
}
.autocomplete:async:list-choices:max-lines() {
local -Pi max_lines
builtin zstyle -s ":autocomplete:${curcontext}:" list-lines max_lines ||
max_lines=16
_autocomplete__max_lines=$(( min( max_lines, LINES - BUFFERLINES - 1 ) ))
}
.autocomplete:async:list-choices:main-complete() {
local -i _autocomplete__max_lines
case $curcontext in
*history-* )
setopt $_autocomplete__func_opts[@]
autocomplete:_main_complete:new - history-lines _autocomplete__history_lines
;;
recent-paths:* )
setopt $_autocomplete__func_opts[@]
autocomplete:_main_complete:new - recent-paths _autocomplete__recent_paths
;;
* )
{
() {
emulate -L zsh
setopt $_autocomplete__func_opts[@]
local curcontext=list-choices:::
.autocomplete:async:shadow compadd
autoload -Uz +X _describe
.autocomplete:async:shadow _describe
# functions -T compadd _describe _description
} "$@"
.autocomplete:async:list-choices:max-lines
autocomplete:_main_complete:new "$@"
} always {
unfunction compadd comptags 2> /dev/null
.autocomplete:async:unshadow compadd
.autocomplete:async:unshadow _describe
}
;;
esac
}
.autocomplete:async:shadow() {
[[ -v functions[$1] ]] &&
functions[autocomplete:async:${1}:old]="$functions[$1]"
functions[$1]="$functions[.autocomplete:async:$1]"
}
.autocomplete:async:unshadow() {
if [[ -v functions[autocomplete:async:${1}:old] ]]; then
functions[$1]="$functions[autocomplete:async:${1}:old]"
unfunction autocomplete:async:${1}:old
fi
}
.autocomplete:async:_describe() {
local -i _autocomplete__described_lines=1 # Assume we'll add a title.
autocomplete:async:_describe:old "$@"
}
.autocomplete:async:compadd() {
setopt localoptions multibyte
local -A _opts_=()
local -a _xopts_=() _displ_=() _matches_=()
local -P _displ_name_= _matches_name_=
zparseopts -A _opts_ -E -- D: E: O:
local -Pi _unused_lines_=$(( _autocomplete__max_lines - compstate[list_lines] ))
# If $_grp is not set, then _describe is adding completions in a normal way and we don't need to
# do all this.
if [[ -v _autocomplete__described_lines && -n $_grp ]]; then
# We cannot interfere when _describe is actually adding the completions or we risk breaking the
# layout.
if [[ -z $_opts_[-D] ]]; then
builtin compadd "$@"
return
fi
_displ_name_=$_opts_[-D]
_matches_name_=$_opts_[-O]
# We already ran out of space.
if [[ -v _autocomplete__partial_list ]]; then
set -A $_displ_name_
[[ -n $_matches_name_ ]] &&
set -A $_matches_name_
fi
builtin compadd "$@"
local -Pi _ret_=$?
local -i _ndisplay_=${(PA)#_displ_name_}
local -i _lines_left_for_describe_=$(( _unused_lines_ - _autocomplete__described_lines ))
# The number of lines that would be added is equal to the number of unique display strings.
if (( ${#${(u)${(PA)_displ_name_}[@]#*:}} > _lines_left_for_describe_ )); then
local -Pi _matches_to_remove=$(( _ndisplay_ - max( 0, _lines_left_for_describe_ ) ))
if (( _matches_to_remove < _ndisplay_ )); then
shift -p $_matches_to_remove $_displ_name_ $_matches_name_
else
set -A $_displ_name_
[[ -n $_matches_name_ ]] &&
set -A $_matches_name_
fi
_ndisplay_=${(PA)#_displ_name_}
.autocomplete:async:compadd:disable
fi
(( _autocomplete__described_lines += _ndisplay_ ))
return _ret_
fi
# We already ran out of space.
if [[ -v _autocomplete__partial_list ]]; then
[[ -n $_opts_[-D] ]] &&
set -A $_opts_[-D]
[[ -n $_opts_[-O] ]] &&
set -A $_opts_[-O]
return 1
fi
# If
if [[ -n $_opts_[-D]$_opts_[-O] ]]; then
builtin compadd "$@"
return
fi
local -i _old_total_lines=$compstate[list_lines]
# +: Keep all occurences. Otherwise, only last occurence is kept.
zparseopts -a _xopts_ -D -E -- X+: x+:
if (( $#_xopts_ )); then
# Use only the first one, because subsequent ones are ignored by compadd anyway.
local original="$_xopts_[2]"
local formatted="${(%g:ce:)original}"
# Trim text to one line and omit ANSI sequences to avoid crash in command substitution.
local ansi_start=${(M)formatted##($'\C-[['[;[:digit:]]#m)#}
local ansi_end=${(M)formatted%%($'\C-[['[;[:digit:]]#m)#}
local text=${${formatted#$ansi_start}%$ansi_end}
_xopts_=(
"$_xopts_[1]"
"${(mr:COLUMNS-1:)text%%[[:space:]]#}"
)
fi
local -Pi _total_new_lines_="$(
builtin compadd "$_xopts_[@]" "$@"
print -nr -- $(( $compstate[list_lines] - _old_total_lines ))
)"
if (( $#_xopts_ )); then
# Replace original text with trimmed text.
_xopts_[2]="${original/$text/$_xopts_[-1]}"
fi
# Everything fits.
if (( _total_new_lines_ + $compstate[list_lines] <= _autocomplete__max_lines )); then
builtin compadd "$_xopts_[@]" "$@"
return
fi
local -Pi _new_completion_lines_="$(
builtin compadd "$@"
print -nr -- $(( $compstate[list_lines] - _old_total_lines ))
)"
local -a _dopt_=()
zparseopts -a _dopt_ -D -E -- d: ld:
_displ_name_=$_dopt_[2]
# Collect all matching completions and their display strings (if any).
local -a _Dopt_=()
[[ -n $_displ_name_ ]] &&
_Dopt_=( -D $_displ_name_ )
builtin compadd -O _matches_ $_Dopt_ "$@"
# If we don't have an array with display strings, then create one.
if [[ -z $_displ_name_ ]]; then
_displ_name_=_displ_
_displ_=( "$_matches_[@]" )
_dopt_=( -d $_displ_name_ )
fi
local -Pi _nmatches_per_line_=$(( 1.0 * $#_matches_ / _new_completion_lines_ ))
# If we need more than one line per match, then make each match fit exactly one line.
if (( _nmatches_per_line_ < 1 )); then
# WORKAROUND: Zsh mistakenly treats display strings that are exactly $COLUMNS wide as not
# fitting on one line.
set -A $_displ_name_ ${(@mr:COLUMNS-1:)${(PA)_displ_name_}[@]//$'\n'/\n}
_dopt_=( -ld $_displ_name_ )
(( _nmatches_per_line_ = 1 ))
fi
local -Pi _new_heading_lines_=$(( _total_new_lines_ - _new_completion_lines_ ))
# Need to round this down _before_ subtracting it or it will effectively be rounded up.
local -Pi _nmatches_that_fit_=$((
( _unused_lines_ - _new_heading_lines_ ) * _nmatches_per_line_
))
local -Pi _nmatches_to_remove_=$(( $#_matches_ - max( 0, _nmatches_that_fit_ ) ))
if (( _nmatches_to_remove_ > 0 )); then
# If we're going to remove anything, then we need to make room for the `(MORE)` prompt.
(( _nmatches_to_remove_ = min( ++_nmatches_to_remove_, $#_matches_ ) ))
.autocomplete:async:compadd:disable
# Make sure we always add a headline, even when we don't add any matches, because a single
# '(MORE)' without other content doesn't make sense.
(( _nmatches_to_remove_ >= $#_matches_ )) && _xopts_[1]=-x
shift -p $_nmatches_to_remove_ _matches_ $_displ_name_
fi
_autocomplete__compadd_opts_len "$@"
builtin compadd "$_xopts_[@]" "$_dopt_[@]" -a "$@[1,?]" _matches_
}
.autocomplete:async:compadd:disable() {
typeset -g _autocomplete__partial_list=$curtag
comptags() { false } # Stop completion from trying more tags.
}

View File

@@ -0,0 +1,189 @@
#!/bin/zsh
zmodload -Fa zsh/files b:zf_rm
zmodload -F zsh/parameter p:funcstack p:functions
builtin autoload -Uz is-at-least
typeset -ga _autocomplete__compdef=()
compdef() {
typeset -ga _autocomplete__compdef=( $_autocomplete__compdef[@] "${(j: :)${(@q+)@}}" )
}
[[ -v functions[_bash_complete] ]] ||
_bash_complete compgen complete () {
unfunction _bash_complete compgen complete
builtin autoload +X -Uz bashcompinit
bashcompinit
bashcompinit() { : }
${(%):-%N} "$@"
}
${0}:precmd() {
emulate -L zsh \
# -x
setopt $_autocomplete__func_opts[@]
[[ -v CDPATH && -z $CDPATH ]] &&
unset CDPATH cdpath
# Decrease Oh My Zsh start-up time. See below.
local -Pa omzdump=()
[[ -v ZSH_COMPDUMP && -r $ZSH_COMPDUMP ]] &&
omzdump=( ${(f)"$( < $ZSH_COMPDUMP )"} )
typeset -g \
_comp_dumpfile=${_comp_dumpfile:-${ZSH_COMPDUMP:-${XDG_CACHE_HOME:-$HOME/.cache}/zsh/compdump}}
if [[ -v _comps[-command-] && $_comps[-command-] != _autocomplete__command ]]; then
zf_rm -f $_comp_dumpfile
else
# Check if our most recently modified completion function is newer than the comp dump file.
local -Pa newest=( ~autocomplete/Completions/_*~*.zwc(N-.omY1) )
if [[ $newest[1] -nt $_comp_dumpfile ]]; then
zf_rm -f $_comp_dumpfile
fi
fi
if [[ ! -v _comp_setup ]] || [[ ! -r $_comp_dumpfile ]]; then
unfunction compdef compinit 2> /dev/null
bindkey() { : }
{
builtin autoload +X -Uz compinit
local -a compargs=()
zstyle -a ':autocomplete::compinit' arguments compargs
compinit -d "$_comp_dumpfile" "$compargs[@]"
} always {
unfunction bindkey
}
bindkey '^Xh' _complete_help
# Prevent Oh My Zsh from deleting comp dump file.
(( ${#omzdump[@]} > 0 )) &&
tee -a "$ZSH_COMPDUMP" &> /dev/null <<EOF
$omzdump[-2]
$omzdump[-1]
EOF
fi
compinit() { : }
local -P args=
for args in "$_autocomplete__compdef[@]"; do
eval "compdef $args"
done
unset _autocomplete__compdef
(
local -a reply=()
local cache_dir=
if builtin zstyle -s ':completion:*' cache-path cache_dir; then
local -P src= bin=
for src in $cache_dir/*~**.zwc~**/.*(N-.); do
bin=$src.zwc
if [[ ! -e $bin || $bin -ot $src ]]; then
zcompile -Uz $src
fi
done
fi
) &|
# Workaround: Some other plugins rely on patching _main_complete, which can interfere with our completion.
.autocomplete__patch _main_complete
autocomplete:_main_complete:new() {
local -i _autocomplete__reserved_lines=0
local -Pi ret=1
unset _autocomplete__partial_list
compstate[insert]=automenu-unambiguous # To get `all-expansions` from _expand.
compstate[last_prompt]=yes # Completion doesn't stay on the same command line without this.
compstate[list]='list force packed' # Always use same defaults, regardless of widget.
unset 'compstate[vared]'
local +h -a compprefuncs=( autocomplete:_main_complete:new:pre "$compprefuncs[@]" )
local +h -a comppostfuncs=( autocomplete:_main_complete:new:post "$comppostfuncs[@]" )
# functions -T autocomplete:_main_complete:old
autocomplete:_main_complete:old "$@"
# functions +T _path_files
# print -nu2 ' after: '
# typeset -m compstate >&2
}
autocomplete:_main_complete:new:pre() {
unsetopt localtraps
trap -
TRAPINT() { # ^C
zle -M "${(F)funcfiletrace}"
zle -R
return 130
}
TRAPQUIT() { # ^\
zle -M "${(F)funcfiletrace}"
zle -R
return 131
}
}
autocomplete:_main_complete:new:post() {
[[ $WIDGET != _complete_help ]] &&
unfunction compadd 2> /dev/null
_autocomplete__unambiguous
compstate[list_max]=0
MENUSCROLL=0
}
.autocomplete__patch _complete
_complete() {
local -i nmatches=$compstate[nmatches]
PREFIX=$PREFIX$SUFFIX
SUFFIX=
autocomplete:_complete:old "$@"
# WORKAROUND: Some completion functions mistakenly don't return 0 when they have succeeded.
(( compstate[nmatches] > nmatches ))
}
##
# WORKAROUND: _approximate won't do corrections if there already is a function called 'compadd'.
#
.autocomplete__patch _approximate
_approximate() {
{
[[ -v functions[compadd] ]] &&
functions[autocomplete:compadd:old]="$functions[compadd]"
functions[compadd]="$functions[autocomplete:approximate:compadd]"
autocomplete:_approximate:old
} always {
unfunction compadd 2> /dev/null
if [[ -v functions[autocomplete:compadd:old] ]]; then
functions[compadd]="$functions[autocomplete:compadd:old]"
unfunction autocomplete:compadd:old
fi
}
}
autocomplete:approximate:compadd() {
local ppre="$argv[(I)-p]"
[[ ${argv[(I)-[a-zA-Z]#U[a-zA-Z]#]} -eq 0 &&
"${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return
if [[ "$PREFIX" = \~* && ( ppre -eq 0 || "$argv[ppre+1]" != \~* ) ]]; then
PREFIX="~(#a${_comp_correct})${PREFIX[2,-1]}"
else
PREFIX="(#a${_comp_correct})$PREFIX"
fi
if [[ -v functions[autocomplete:compadd:old] ]]; then
autocomplete:compadd:old "$@"
else
builtin compadd "$@"
fi
}
}

View File

@@ -0,0 +1,159 @@
#!/bin/zsh
zmodload -Fa zsh/zutil b:zstyle
typeset -g ZLE_REMOVE_SUFFIX_CHARS=$' /;\n\r\t'
typeset -g ZLE_SPACE_SUFFIX_CHARS='|&<>-+'
builtin zstyle ':completion:*' use-cache yes
builtin zstyle -e ':completion:*' cache-path autocomplete:config:cache-path
autocomplete:config:cache-path() {
typeset -ga reply=( "${XDG_CACHE_HOME:-$HOME/.cache}/zsh/compcache" )
}
builtin zstyle ':completion:*' completer \
_expand _complete _complete:-fuzzy _correct _approximate _ignored
builtin zstyle -e ':completion:*' max-errors autocomplete:config:max-errors
autocomplete:config:max-errors() {
typeset -ga reply=( $(( min( 2, ( $#PREFIX + $#SUFFIX ) / 3 ) )) )
}
# Order of matchers matters: m should come before r, which should come before l.
# Otherwise, the results are not as expected.
local lower_to_upper='m:{[:lower:]-}={[:upper:]_}'
local any_before_dot='r:|[.]=**'
local any_before_any='r:|?=**'
local nonseparators_after_any_before_separator='r:?||[-_ \]=*'
local any_before_word='l:|=*'
local separator_after_any='l:?|=[-_ \]'
builtin zstyle ':completion:*' matcher-list \
"$lower_to_upper $any_before_dot"
builtin zstyle ':completion:*-fuzzy:*' matcher-list \
"$lower_to_upper $any_before_dot $any_before_word" \
"+$nonseparators_after_any_before_separator $separator_after_any" \
"$lower_to_upper $any_before_any"
local minus_at_beginning_to_plus='b:-=+'
builtin zstyle ':completion:*:options' matcher $minus_at_beginning_to_plus
builtin zstyle ':completion:*' prefix-needed yes
builtin zstyle ':completion:*:functions' ignored-patterns '*.*' '*:*' '+*'
builtin zstyle ':completion:*:users' ignored-patterns '_*'
builtin zstyle ':completion:*:widgets' ignored-patterns '*.*' '*:*'
builtin zstyle ':completion:*' single-ignored ''
builtin zstyle ':completion:*:expand-alias:*' complete yes
builtin zstyle ':completion:*:expand:*' tag-order 'expansions all-expansions' -
builtin zstyle ':completion:*:expand:*' accept-exact continue
builtin zstyle ':completion:*:expand:*' add-space no
builtin zstyle ':completion:*:expand:*' glob yes
builtin zstyle ':completion:*:expand:*' keep-prefix no # Needed for file type highlighting
builtin zstyle ':completion:*:expand:*' substitute yes
builtin zstyle ':completion:*:expand:*' subst-globs-only yes
builtin zstyle -e ':completion:*:-command-:*' tag-order autocomplete:config:tag-order:command
autocomplete:config:tag-order:command() {
if [[ $PREFIX == (|.|*/*) ]]; then
typeset -ga reply=( 'suffix-aliases (|*-)directories executables (|*-)files' - )
else
typeset -ga reply=( 'aliases suffix-aliases functions reserved-words builtins' )
if (( path[(I).] )); then
reply[1]+=' (|*-)directories executables (|*-)files commands'
else
reply[1]+=' commands (|*-)directories executables (|*-)files'
fi
fi
}
builtin zstyle ':completion:*:-tilde-:*' tag-order directory-stack named-directories
builtin zstyle ':completion:*:(approximate|correct):*' tag-order '! original' -
# Complete options rather than directory stack. You can get directory stack by typing `~-` (tilde plus dash).
builtin zstyle ':completion:*:cd:*' complete-options yes
builtin zstyle ':completion:*:cd:*' tag-order '! directory-stack' -
# Don't show the giant list of history lines.
builtin zstyle ':completion:*:fc:*' tag-order options -
builtin zstyle -e ':completion:*:git-*:*' tag-order 'autocomplete:config:tag-order:git "$@"'
autocomplete:config:tag-order:git() {
reply=()
(( compstate[nmatches] )) &&
reply=(
'! heads(|-*) *-remote remote-* blob-*'
-
)
}
# Complete only the tail of a path.
builtin zstyle ':completion:*' ignore-parents 'parent pwd directory'
builtin zstyle ':completion:*:paths' expand suffix
builtin zstyle ':completion:*:paths' list-suffixes yes
builtin zstyle ':completion:*:paths' special-dirs no
builtin zstyle ':completion:*' group-name ''
builtin zstyle ':completion:*:-command-:*' group-name commands
builtin zstyle ':completion:*:all-expansions' group-name 'expansion'
builtin zstyle ':completion:*' group-order \
expansions all-expansions options \
aliases suffix-aliases functions reserved-words builtins commands \
remotes hosts recent-branches commits \
local-directories directories executables
builtin zstyle ':completion:*' file-patterns '*(-/):directories:directory %p(#q^-/):globbed-files'
builtin zstyle -e ':completion:*:-command-:*' file-patterns autocomplete:config:file-patterns:command
autocomplete:config:file-patterns:command() {
[[ $PREFIX$SUFFIX != */* ]] &&
typeset -ga reply=( '*(-/):directories:directory ./*(-*^/):executables:"executable file"' )
}
builtin zstyle ':completion:*:(.|source):*' file-patterns \
'%p(#q-/):directories:directory %p~*.zwc(-.^*):globbed-files' '%p~*.zwc(-^/):globbed-files'
# Don't combine parameters with same values.
builtin zstyle ':completion:*:parameters' list-grouped no
builtin zstyle -e ':completion:*:-command-:*' format autocomplete:config:format command
builtin zstyle -e ':completion:*:descriptions' format autocomplete:config:format %d
builtin zstyle -e ':completion:*:all-expansions' format autocomplete:config:format expansion
autocomplete:config:format() {
reply=( $'%{\e[0;1;2m%}'$1$'%{\e[0m%}' )
}
builtin zstyle -e ':completion:*:all-expansions' format autocomplete:config:format expansion
builtin zstyle -e ':completion:*:expansions' format autocomplete:config:format '"globbed files"'
builtin zstyle -e ':completion:*:warnings' format autocomplete:config:format:warnings
autocomplete:config:format:warnings() {
[[ $CURRENT == 1 && -z $PREFIX$SUFFIX ]] ||
autocomplete:config:format 'no matching %d completions'
}
builtin zstyle ':completion:*:messages' format '%F{9}%d%f'
builtin zstyle ':completion:*:history-lines' format ''
builtin zstyle ':completion:*' auto-description '%d'
builtin zstyle ':completion:*:parameters' extra-verbose yes
builtin zstyle ':completion:*:default' select-prompt '%F{black}%K{12}line %l %p%f%k'
builtin zstyle ':completion:*' insert-sections yes
builtin zstyle ':completion:*' separate-sections yes
# Needed for _gnu_generic to prevent descriptions from getting cropped.
is-at-least 5.9 ||
builtin zstyle ':completion:*' command '- COLUMNS=999'
${0}:precmd() {
typeset -g _comp_setup="$_comp_setup"';
[[ $_comp_caller_options[globdots] == yes ]] && setopt globdots'
# Remove incompatible settings.
local -P key= setting=
for key in menu list-prompt; do
for setting in ${(f)"$( zstyle -L '*' $key )"}; do
eval "${setting/zstyle(| -e)/zstyle -d}"
done
done
builtin zstyle ':completion:*:*:*:*:default' menu no no-select
unset LISTPROMPT
}

View File

@@ -0,0 +1,64 @@
#!/bin/zsh
zmodload zsh/complist
zmodload -F zsh/terminfo p:terminfo
local -Pa prefix=( '\e'{\[,O} )
local -Pa key_up=( ${^prefix}A )
local -Pa key_down=( ${^prefix}B )
local -Pa key_alt_up=( '\e'$^key_up '\e[1;3A' )
local -Pa key_alt_down=( '\e'$^key_down '\e[1;3B' )
local -A main=() emacs=() vicmd=() menukeys=()
${0}:bind() {
local -P key= widget=$1 menuwidget=$2
emacs[$3]=$widget
menukeys[$3]=$menuwidget
vicmd[$4]=$widget
key="^[$4"
menukeys[$key]=$menuwidget
shift 4
for key; do
main[$key]=$widget
menukeys[$key]=$menuwidget
done
}
${0}:bind up-line-or-search up-history '^P' 'k' $key_up[@]
${0}:bind down-line-or-select down-history '^N' 'j' $key_down[@]
${0}:bind history-search-backward vi-backward-blank-word '\ep' '^P' $key_alt_up[@]
${0}:bind menu-select vi-forward-blank-word '\en' '^N' $key_alt_down[@]
${0}:bind history-incremental-search-backward history-incremental-search-backward '^R' '/'
${0}:bind menu-search history-incremental-search-forward '^S' '?'
local backtab=$terminfo[kcbt]
menukeys+=(
'\t' menu-complete
"$backtab" reverse-menu-complete
'^@' accept-and-hold
'^[v' accept-and-hold
'^_' undo
'^[u' undo
"$terminfo[kpp]" backward-word
"$terminfo[knp]" forward-word
)
main+=(
'\t' complete-word
"$backtab" expand-word
)
emacs+=(
'^X/' recent-paths
)
bindkey -M main "${(kv@)main}"
bindkey -M emacs "${(kv@)emacs}"
bindkey -M vicmd "${(kv@)vicmd}"
bindkey -M menuselect "${(kv@)menukeys}"
unfunction ${0}:bind

View File

@@ -0,0 +1,95 @@
#!/bin/zsh
zmodload -Fa zsh/files b:zf_mkdir b:zf_rm
zmodload -F zsh/parameter p:functions
zmodload -F zsh/system p:sysparams
zmodload -F zsh/zleparameter p:widgets
zmodload -Fa zsh/zutil b:zstyle
builtin autoload +X -Uz add-zsh-hook zmathfunc
zmathfunc
typeset -ga _autocomplete__ctxt_opts=( completealiases completeinword )
typeset -ga _autocomplete__mods=( compinit config widgets key-bindings recent-dirs async )
typeset -gU FPATH fpath=( ~autocomplete/Completions $fpath[@] )
local -P xdg_data_home=${XDG_DATA_HOME:-$HOME/.local/share}
local -P zsh_data_dir=$xdg_data_home/zsh
[[ -d $zsh_data_dir ]] ||
zf_mkdir -pm 0700 $zsh_data_dir
local -P old_logdir=$xdg_data_home/zsh-autocomplete/log
[[ -d $old_logdir ]] &&
zf_rm -fr -- $old_logdir
local -P logdir=${XDG_STATE_HOME:-$HOME/.local/state}/zsh-autocomplete/log
local -P bug=
for bug in ${logdir} ${logdir:h}; do
[[ -d $bug ]] ||
zf_rm -f $bug
done
zf_mkdir -p -- $logdir
hash -d autocomplete-log=$logdir
local -Pa older_than_a_week=( $logdir/*(Nmd+7) )
(( $#older_than_a_week[@] )) &&
zf_rm -f -- $older_than_a_week[@]
typeset -g _autocomplete__log=${logdir}/${(%):-%D{%F}}.log
typeset -g _autocomplete__ps4=$'%D{%T.%.} %e:%N:%I\t%? %(1_,%_ ,)'
local -P zsh_cache_dir=${XDG_CACHE_HOME:-$HOME/.cache}/zsh
[[ -d $zsh_cache_dir ]] ||
zf_mkdir -pm 0700 $zsh_cache_dir
local -P mod=
for mod in $_autocomplete__mods; do
builtin zstyle -T ":autocomplete:$mod" enabled &&
.autocomplete__$mod "$@"
unfunction .autocomplete__$mod
done
add-zsh-hook precmd ${0}:precmd
# Make sure we always run before Autosuggest, so we don't overwrite its default ignore list.
typeset -gaU precmd_functions=( ${0}:precmd $precmd_functions )
${0}:precmd() {
# WORKAROUND: For hook functions in Zsh 5.8, $0 can be something else than the function name.
0=${(%):-%N}
add-zsh-hook -d precmd $0
unfunction $0
() {
emulate -L zsh \
# -x
setopt $_autocomplete__func_opts[@]
# Workaround for https://www.zsh.org/mla/workers/2021/msg01310.html
if builtin zstyle -L zle-hook types > /dev/null; then
local -P hook=
for hook in \
zle-{isearch-{exit,update},line-{pre-redraw,init,finish},history-line-set,keymap-select}
do
[[ -v widgets[$hook] &&
$widgets[$hook] == user:_zsh_highlight_widget_orig-s*-r<->-$hook ]] &&
builtin zle -N $hook azhw:$hook
done
fi
}
local -P mod=
for mod in $_autocomplete__mods; do
mod=.autocomplete__${mod}:precmd
if [[ -v functions[$mod] ]]; then
$mod
unfunction $mod
fi
done
true
}

View File

@@ -0,0 +1,21 @@
#!/bin/zsh
zmodload -Fa zsh/files b:zf_mv b:zf_mkdir
zmodload -F zsh/parameter p:commands p:dirstack p:functions
${0}:precmd() {
setopt autopushd pushdignoredups # Set *global* shell options.
builtin autoload -Uz chpwd_recent_dirs chpwd_recent_filehandler
local __=
builtin zstyle -s :chpwd: recent-dirs-file __ ||
builtin zstyle ':chpwd:*' recent-dirs-file \
${XDG_DATA_HOME:-$HOME/.local/share}/zsh/chpwd-recent-dirs
builtin zstyle -s :chpwd: recent-dirs-max __ ||
builtin zstyle ':chpwd:*' recent-dirs-max 0
local -a reply=()
chpwd_recent_filehandler
dirstack=( "$reply[@]" )
add-zsh-hook chpwd chpwd_recent_dirs
}

View File

@@ -0,0 +1,47 @@
#!/bin/zsh
zmodload zsh/complist
typeset -ga _autocomplete__suggest_ignore_widgets=()
typeset -g ZSH_AUTOSUGGEST_MANUAL_REBIND=1
typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=.autosuggest-orig-
${0}:c() {
_autocomplete__suggest_ignore_widgets+=( $1 )
builtin zle -C "$1" "$2" .autocomplete__${3}__completion-widget
}
${0}:z() {
builtin zle -N "$1" .autocomplete__${2}__zle-widget
}
${0}:z up-line-or-search{,}
${0}:z down-line-or-select{,}
${0}:z history-search{-backward,}
${0}:precmd() {
emulate -L zsh \
# -x
setopt $_autocomplete__func_opts[@]
0=${0%:*}
# Create all completion widgets here, to avoid getting them wrapped by
# Autosuggest or Syntax Highlighting.
local -P tab_style=
for tab_style in complete-word menu-complete menu-select; do
${0}:c "$tab_style" "$tab_style" complete-word
done
${0}:c {,}reverse-menu-complete complete-word
${0}:c insert-unambiguous-or-complete {,}complete-word
${0}:c menu-search menu-select complete-word
${0}:c history-search-backward menu-select history-search
# Autosuggestions otherwise makes $WIDGETSTYLE disappear
[[ -v ZSH_AUTOSUGGEST_IGNORE_WIDGETS ]] &&
ZSH_AUTOSUGGEST_IGNORE_WIDGETS+=(
$_autocomplete__suggest_ignore_widgets
)
unset _autocomplete__suggest_ignore_widgets
unfunction ${0}:{c,z}
}

View File

@@ -0,0 +1,8 @@
#!/bin/zsh
zmodload -F zsh/parameter p:functions
functions[autocomplete:${1}:old]="$(
unfunction $1 2> /dev/null
builtin autoload +X -Uz $1
print -r -- "$functions[$1]"
)"

View File

@@ -0,0 +1,28 @@
#!/bin/zsh
emulate -L zsh \
# -x
setopt $_autocomplete__func_opts[@]
typeset -g _autocomplete__last_cutbuffer
typeset -g _autocomplete__zle_flags=
{
if (( YANK_ACTIVE )); then
_autocomplete__zle_flags=yank
(( YANK_END <= CURSOR )) &&
_autocomplete__zle_flags+=before
return 1 # Tell caller to abort.
fi
[[ $_autocomplete__last_cutbuffer != $CUTBUFFER ]] &&
_autocomplete__zle_flags=kill
return 0
} always {
[[ -n $_autocomplete__zle_flags ]] &&
builtin zle -f $_autocomplete__zle_flags
typeset -g _autocomplete__last_cutbuffer=$CUTBUFFER
}
return 0

View File

@@ -0,0 +1,36 @@
#!/bin/zsh
setopt localoptions banghist
zmodload -F zsh/terminfo p:terminfo
local context=${curcontext:-${WIDGET}:::}
unset curcontext
local +h curcontext=$context
local +h -a comppostfuncs=( .autocomplete__complete-word__post "$comppostfuncs[@]" )
local -a compargs=()
case $curcontext in
( history-incremental-search* )
compargs=( - history-lines _autocomplete__history_lines )
;;
( recent-paths:* )
compargs=( - recent-paths _autocomplete__recent_paths )
;;
( * )
if [[ $WIDGET == spell-word ]] ||
[[ -v _autocomplete__partial_list && $WIDGETSTYLE == (|*-)(list|menu)(|-*) ]] ||
{ [[ $_lastcomp[unambiguous] != (|$PREFIX$SUFFIX) ]] &&
_autocomplete__should_insert_unambiguous }; then
compstate[old_list]=
fi
;;
esac
if [[ -n $compstate[old_list] ]]; then
compstate[old_list]=keep
compargs=( - )
fi
autocomplete:_main_complete:new "$compargs[@]"
(( _lastcomp[nmatches] > 0 ))

View File

@@ -0,0 +1,69 @@
#autoload
local -a match=() mbegin=() mend=() # `zstyle` for some reason assigns these.
unset MENUMODE MENUSELECT
local -i nmatches
if [[ $compstate[old_list] == keep ]]; then
(( nmatches = _lastcomp[nmatches] ))
else
(( nmatches = compstate[nmatches] ))
fi
[[ $WIDGETSTYLE == (|*-)menu(|-*) ]]
local -i is_menu=$(( ! ? ))
if (( is_menu )); then
compstate[list]='list force'
else
compstate[list]=
zle -Rc
fi
if [[ $compstate[old_list] == keep && $_lastcomp[completer] == prefix ]] ||
[[ $_completer == prefix ]]; then
compstate[to_end]=
else
compstate[to_end]='match'
fi
{
compstate[insert]=
if [[ $compstate[unambiguous] != (|$PREFIX$SUFFIX) ]] && _autocomplete__should_insert_unambiguous
then
(( is_menu )) &&
compstate[insert]='automenu-'
compstate[insert]+='unambiguous'
return
fi
if (( is_menu )); then
if [[ $WIDGETSTYLE == (|*-)select(|-*) ]]; then
typeset -gi MENUSELECT=0
if [[ $WIDGET == (|*-)search(|-*) ]]; then
typeset -g MENUMODE=search-forward
fi
fi
compstate[insert]='menu:'
fi
if [[ $WIDGET == (|.)reverse-* || $WIDGETSTYLE == (|.)reverse-menu-complete ]]; then
compstate[insert]+='0'
else
compstate[insert]+='1'
fi
if (( ! is_menu )) && _autocomplete__should_add_space; then
compstate[insert]+=' '
fi
return 0
} always {
if [[ -n $compstate[insert] ]]; then
typeset -g _autocomplete__inserted
else
unset _autocomplete__inserted
fi
}

View File

@@ -0,0 +1,7 @@
#!/bin/zsh
if [[ $RBUFFER == *$'\n'* ]]; then
builtin zle down-line
else
builtin zle menu-select -w
fi

View File

@@ -0,0 +1,22 @@
#!/bin/zsh
local 0=${(%):-%N}
${0}() {
typeset -g curcontext=${WIDGET}:::
local +h -a comppostfuncs=( ${(%):-%N}:post "$comppostfuncs[@]" )
compstate[old_list]=
autocomplete:_main_complete:new - history-lines _autocomplete__history_lines
unset curcontext
(( compstate[nmatches] ))
}
${0}:post() {
typeset -gi MENUSELECT=0
compstate[insert]='menu:0'
if (( compstate[nmatches] < 2 )); then
compstate[list]=
fi
}
${0} "$@"

View File

@@ -0,0 +1,9 @@
#!/bin/zsh
if [[ $LBUFFER == *$'\n'* ]]; then
builtin zle up-line
return
fi
builtin zle history-search-backward -w
(( $_lastcomp[nmatches] )) # WORKAROUND: Widget always beeps otherwise.