Skip to content

Commit

Permalink
Rework zsh completion fallback
Browse files Browse the repository at this point in the history
Don't rely on internals from the git completion. Instead set up the
environment and then simply call _git and let it do the completion as
it see fit.

See yadm-dev#292.
  • Loading branch information
erijo committed Jan 6, 2021
1 parent 630bc69 commit f45ec2c
Showing 1 changed file with 24 additions and 62 deletions.
86 changes: 24 additions & 62 deletions completion/zsh/_yadm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#compdef yadm

# This completion tries to fallback to git's completion for git commands.
# It handles two different types of fallbacks:
# - The git completion shipped with git.
# - The git completion shipped with zsh.

zstyle ':completion:*:yadm:argument-1:descriptions' format '%d:'
zstyle ':completion:*:yadm:*:yadm' group-name ''

_yadm-alt() {
return 0
Expand Down Expand Up @@ -72,7 +72,9 @@ _yadm-transcrypt() {
}

_yadm-upgrade() {
return 0
_arguments \
'-f[force deinit of submodules]' \
': '
}

_yadm-version() {
Expand Down Expand Up @@ -100,36 +102,21 @@ _yadm_commands() {
version:'show yadm version'
)

integer _ret=1
local oldcontext="$curcontext"
local curcontext="${curcontext%:*:*}:git:"

if (( $+functions[_git_commands] )); then
zstyle ':completion:*:*:yadm:*' user-commands $commands
_call_function _ret _git_commands
zstyle -d ':completion:*:*:yadm:*' user-commands
else
local curcontext=${curcontext%:*:*}:git:
_tags common-commands alias-commands all-commands
while _tags; do
_requested common-commands && __git_zsh_cmd_common
_requested alias-commands && __git_zsh_cmd_alias
_requested all-commands && __git_zsh_cmd_all
let _ret || break
done
_describe "yadm commands" commands
fi
service=git _git

return _ret
curcontext="$oldcontext"
_describe -t yadm "yadm commands" commands

return 0
}

_yadm() {
local curcontext=$curcontext state state_descr line
declare -A opt_args

local -a orig_words=( ${words[@]} )
local cur=${words[CURRENT]}
local prev=${words[CURRENT-1]}
let cword=CURRENT-1

_arguments -C \
'(-Y --yadm-dir)'{-Y,--yadm-dir}'[override the standard yadm directory]: :_files -/' \
'--yadm-data[override the standard yadm data directory]: :_files -/' \
Expand All @@ -147,55 +134,30 @@ _yadm() {
(( $+opt_args[--yadm-repo] )) && repo_args+=(--yadm-repo "$opt_args[--yadm-repo]")
(( $+opt_args[--yadm-data] )) && repo_args+=(--yadm-data "$opt_args[--yadm-data]")
local -x GIT_DIR="$(_call_program gitdir yadm "${repo_args[@]}" introspect repo)"
local __git_dir="$GIT_DIR"
[[ -z "$GIT_DIR" ]] && return 1

integer _ret=1
case $state in
(command)
_yadm_commands && _ret=0
;;
(option-or-argument)
local command=$words[1]
curcontext=${curcontext%:*:*}:yadm-${words[1]}:
if ! _call_function _ret _yadm-${words[1]}; then

# First try to complete yadm commands
curcontext=${curcontext%:*:*}:yadm-$command:
if ! _call_function _ret _yadm-$command; then
# Translate gitconfig to use the regular completion for config
[[ $command = "gitconfig" ]] && command=config

# If is wasn't a valid command, try git's completion if available
if (( $+functions[__git_zsh_bash_func] )); then
words=( ${orig_words[@]} )
curcontext=${curcontext%:*:*}:git:

__git_zsh_bash_func $command
let _ret && _default && _ret=0
else
# If git's completion wasn't available, try zsh's
curcontext=${curcontext%:*:*}:git-$command:
if ! _call_function _ret _git-$command; then
if [[ $words[1] = \!* ]]; then
words[1]=${words[1]##\!}
_normal && _ret=0
elif zstyle -T :completion:$curcontext: use-fallback; then
_default && _ret=0
else
_message "unknown sub-command: $command"
fi
fi
fi
[[ ${words[1]} = "gitconfig" ]] && words[1]=config

words=("git" "${(@)words}")
CURRENT=$(( CURRENT + 1 ))

curcontext=${curcontext%:*:*}:git:
service=git _git && _ret=0
fi
;;
esac

return _ret
}

# Ignore call from _git when using git's completion
__yadm_zsh_main() {
_ret=0
}

# __git_zsh_bash_func comes from git's completion and _git_commands from zsh's
(( $+functions[__git_zsh_bash_func] + $+functions[_git_commands] )) || _git
_yadm
(( $+functions[_git] )) && _yadm

0 comments on commit f45ec2c

Please sign in to comment.