Skip to content

Commit 691bc6b

Browse files
committed
Zsh improve completion for passthrough git options
Two main improvements: 1. Exclude already-provided git options from completions. E.g. `stg diff -O--word-diff -O--w<TAB>` will no longer offer `--word-diff` as a completion again. 2. Only complete *options* to the respective git commands and not arguments. This is done by pre-priming PREFIX with '-' if the user hasn't already started typing.
1 parent b062679 commit 691bc6b

File tree

1 file changed

+38
-32
lines changed

1 file changed

+38
-32
lines changed

completion/stgit.zsh

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,46 +1206,52 @@ __stg_add_args_trailers() {
12061206
)
12071207
}
12081208

1209-
__stg_git_diff_opts() {
1210-
words=('git' ${(@)__stg_C_args} 'diff-tree')
1211-
# Needs a way to know word indices for opt_args values to only provide through CURRENT.
1212-
#
1213-
# words+=(${(0)opt_args[-O]} ${(0)opt_args[--diff-opt]})
1214-
words+=("$PREFIX$SUFFIX")
1209+
__stg_complete_git_opts() {
1210+
local gitcmd short long
1211+
gitcmd=$1
1212+
short=$2
1213+
long=$3
1214+
1215+
# Parse short and long options (e.g. -O and --diff-opt) from $words.
1216+
declare -a gitopts
1217+
function {
1218+
zparseopts -E -D ${short}+:=gitopts -${long}+:=gitopts 2>/dev/null
1219+
} $words
1220+
1221+
# Compose git command line
1222+
words=('git' ${(@)__stg_C_args} ${gitcmd})
1223+
1224+
# The option values are at the even indexes in the gitopts array.
1225+
# The last option is skipped because it is the partially specified one being
1226+
# completed.
1227+
for i in $(seq 2 2 $(($#gitopts - 2))); do
1228+
# Need to strip any leading '=' because zparseopts will parse, for example,
1229+
# `--diff-opt=foo` as ('--diff-opt' '=foo').
1230+
words+=${gitopts[i]#=}
1231+
done
1232+
1233+
# If the user has not started typing the value, prime it with '-' to force
1234+
# completing only the options (and not arguments) to the git command.
1235+
if [ -z "$PREFIX" -a -z "$SUFFIX" ]; then
1236+
PREFIX='-'
1237+
fi
1238+
words+="$PREFIX$SUFFIX"
12151239
(( CURRENT = $#words ))
12161240

1217-
local _comp_command1 _comp_command2 _comp_command
1218-
_set_command
1219-
_message -e git-diff-option 'diff option' && \
1220-
_dispatch "$_comp_command" "$_comp_command1" "$_comp_command2" -default-
1241+
_message -e "git-$gitcmd-option" "git $gitcmd" &&
1242+
_dispatch git git $commands[git]
12211243
}
12221244

1223-
__stg_git_format_patch_opts() {
1224-
words=('git' ${(@)__stg_C_args} 'format-patch')
1225-
# Needs a way to know word indices for opt_args values to only provide through CURRENT.
1226-
#
1227-
# words+=(${(0)opt_args[-G]} ${(0)opt_args[--git-opt]})
1228-
words+=("$PREFIX$SUFFIX")
1229-
(( CURRENT = $#words ))
1245+
__stg_git_diff_opts() {
1246+
__stg_complete_git_opts diff-tree O diff-opt
1247+
}
12301248

1231-
local _comp_command1 _comp_command2 _comp_command
1232-
_set_command
1233-
_message -e git-format-patch-option 'format-patch option' && \
1234-
_dispatch "$_comp_command" "$_comp_command1" "$_comp_command2" -default-
1249+
__stg_git_format_patch_opts() {
1250+
__stg_complete_git_opts format-patch G git-opt
12351251
}
12361252

12371253
__stg_git_send_email_opts() {
1238-
words=('git' ${(@)__stg_C_args} 'send-email')
1239-
# Needs a way to know word indices for opt_args values to only provide through CURRENT.
1240-
#
1241-
# words+=(${(0)opt_args[-G]} ${(0)opt_args[--git-opt]})
1242-
words+=("$PREFIX$SUFFIX")
1243-
(( CURRENT = $#words ))
1244-
1245-
local _comp_command1 _comp_command2 _comp_command
1246-
_set_command
1247-
_message -e git-send-email-option 'send-email option' && \
1248-
_dispatch "$_comp_command" "$_comp_command1" "$_comp_command2" -default-
1254+
__stg_complete_git_opts send-email G git-opt
12491255
}
12501256

12511257
__stg_revisions () {

0 commit comments

Comments
 (0)