Skip to content

Commit 15b4a16

Browse files
szedergitster
authored andcommitted
completion: wrap __git_refs() for better option parsing
__git_refs() currently accepts two optional positional parameters: a remote and a flag for 'git checkout's tracking DWIMery. To fix a minor bug, and, more importantly, for faster refs completion, this series will add three more parameters: a prefix, the current word to be completed and a suffix, i.e. the options accepted by __gitcomp() & friends, and will change __git_refs() to list only refs matching that given current word and to add that given prefix and suffix to the listed refs. However, __git_refs() is the helper function that is most likely used in users' custom completion scriptlets for their own git commands, and we don't want to break those, so - we can't change __git_refs()'s default output format, i.e. we can't by default append a trailing space to every listed ref, meaning that the suffix parameter containing the default trailing space would have to be specified on every invocation, and - we can't change the position of existing positional parameters either, so there would have to be plenty of set-but-empty placeholder positional parameters all over the completion script. Furthermore, with five positional parameters it would be really hard to remember which position means what. To keep callsites simple, add the new wrapper function __git_complete_refs() around __git_refs(), which: - instead of positional parameters accepts real '--opt=val'-style options and with minimalistic option parsing translates them to __git_refs()'s and __gitcomp_nl()'s positional parameters, and - includes the '__gitcomp_nl "$(__git_refs ...)" ...' command substitution to make its behavior match its name and the behavior of other __git_complete_* functions, and to limit future changes in this series to __git_refs() and this new wrapper function. Call this wrapper function instead of __git_refs() wherever possible throughout the completion script, i.e. when __git_refs()'s output is fed to __gitcomp_nl() right away without further processing, which means all callsites except a single one in the __git_refs2() helper. Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent c977eef commit 15b4a16

File tree

2 files changed

+173
-35
lines changed

2 files changed

+173
-35
lines changed

contrib/completion/git-completion.bash

Lines changed: 67 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ __git_tags ()
354354
# Can be the name of a configured remote, a path, or a URL.
355355
# 2: In addition to local refs, list unique branches from refs/remotes/ for
356356
# 'git checkout's tracking DWIMery (optional; ignored, if set but empty).
357+
#
358+
# Use __git_complete_refs() instead.
357359
__git_refs ()
358360
{
359361
local i hash dir track="${2-}"
@@ -446,6 +448,36 @@ __git_refs ()
446448
esac
447449
}
448450

451+
# Completes refs, short and long, local and remote, symbolic and pseudo.
452+
#
453+
# Usage: __git_complete_refs [<option>]...
454+
# --remote=<remote>: The remote to list refs from, can be the name of a
455+
# configured remote, a path, or a URL.
456+
# --track: List unique remote branches for 'git checkout's tracking DWIMery.
457+
# --pfx=<prefix>: A prefix to be added to each ref.
458+
# --cur=<word>: The current ref to be completed. Defaults to the current
459+
# word to be completed.
460+
# --sfx=<suffix>: A suffix to be appended to each ref instead of the default
461+
# space.
462+
__git_complete_refs ()
463+
{
464+
local remote track pfx cur_="$cur" sfx=" "
465+
466+
while test $# != 0; do
467+
case "$1" in
468+
--remote=*) remote="${1##--remote=}" ;;
469+
--track) track="yes" ;;
470+
--pfx=*) pfx="${1##--pfx=}" ;;
471+
--cur=*) cur_="${1##--cur=}" ;;
472+
--sfx=*) sfx="${1##--sfx=}" ;;
473+
*) return 1 ;;
474+
esac
475+
shift
476+
done
477+
478+
__gitcomp_nl "$(__git_refs "$remote" "$track")" "$pfx" "$cur_" "$sfx"
479+
}
480+
449481
# __git_refs2 requires 1 argument (to pass to __git_refs)
450482
__git_refs2 ()
451483
{
@@ -554,15 +586,15 @@ __git_complete_revlist_file ()
554586
*...*)
555587
pfx="${cur_%...*}..."
556588
cur_="${cur_#*...}"
557-
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
589+
__git_complete_refs --pfx="$pfx" --cur="$cur_"
558590
;;
559591
*..*)
560592
pfx="${cur_%..*}.."
561593
cur_="${cur_#*..}"
562-
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
594+
__git_complete_refs --pfx="$pfx" --cur="$cur_"
563595
;;
564596
*)
565-
__gitcomp_nl "$(__git_refs)"
597+
__git_complete_refs
566598
;;
567599
esac
568600
}
@@ -649,21 +681,21 @@ __git_complete_remote_or_refspec ()
649681
if [ $lhs = 1 ]; then
650682
__gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_"
651683
else
652-
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
684+
__git_complete_refs --pfx="$pfx" --cur="$cur_"
653685
fi
654686
;;
655687
pull|remote)
656688
if [ $lhs = 1 ]; then
657-
__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
689+
__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"
658690
else
659-
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
691+
__git_complete_refs --pfx="$pfx" --cur="$cur_"
660692
fi
661693
;;
662694
push)
663695
if [ $lhs = 1 ]; then
664-
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
696+
__git_complete_refs --pfx="$pfx" --cur="$cur_"
665697
else
666-
__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
698+
__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"
667699
fi
668700
;;
669701
esac
@@ -1061,7 +1093,7 @@ _git_bisect ()
10611093

10621094
case "$subcommand" in
10631095
bad|good|reset|skip|start)
1064-
__gitcomp_nl "$(__git_refs)"
1096+
__git_complete_refs
10651097
;;
10661098
*)
10671099
;;
@@ -1083,7 +1115,7 @@ _git_branch ()
10831115

10841116
case "$cur" in
10851117
--set-upstream-to=*)
1086-
__gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}"
1118+
__git_complete_refs --cur="${cur##--set-upstream-to=}"
10871119
;;
10881120
--*)
10891121
__gitcomp "
@@ -1097,7 +1129,7 @@ _git_branch ()
10971129
if [ $only_local_ref = "y" -a $has_r = "n" ]; then
10981130
__gitcomp_nl "$(__git_heads)"
10991131
else
1100-
__gitcomp_nl "$(__git_refs)"
1132+
__git_complete_refs
11011133
fi
11021134
;;
11031135
esac
@@ -1140,18 +1172,18 @@ _git_checkout ()
11401172
*)
11411173
# check if --track, --no-track, or --no-guess was specified
11421174
# if so, disable DWIM mode
1143-
local flags="--track --no-track --no-guess" track=1
1175+
local flags="--track --no-track --no-guess" track_opt="--track"
11441176
if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
1145-
track=''
1177+
track_opt=''
11461178
fi
1147-
__gitcomp_nl "$(__git_refs '' $track)"
1179+
__git_complete_refs $track_opt
11481180
;;
11491181
esac
11501182
}
11511183

11521184
_git_cherry ()
11531185
{
1154-
__gitcomp_nl "$(__git_refs)"
1186+
__git_complete_refs
11551187
}
11561188

11571189
_git_cherry_pick ()
@@ -1166,7 +1198,7 @@ _git_cherry_pick ()
11661198
__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
11671199
;;
11681200
*)
1169-
__gitcomp_nl "$(__git_refs)"
1201+
__git_complete_refs
11701202
;;
11711203
esac
11721204
}
@@ -1216,7 +1248,7 @@ _git_commit ()
12161248
{
12171249
case "$prev" in
12181250
-c|-C)
1219-
__gitcomp_nl "$(__git_refs)"
1251+
__git_complete_refs
12201252
return
12211253
;;
12221254
esac
@@ -1229,7 +1261,7 @@ _git_commit ()
12291261
;;
12301262
--reuse-message=*|--reedit-message=*|\
12311263
--fixup=*|--squash=*)
1232-
__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
1264+
__git_complete_refs --cur="${cur#*=}"
12331265
return
12341266
;;
12351267
--untracked-files=*)
@@ -1267,7 +1299,7 @@ _git_describe ()
12671299
"
12681300
return
12691301
esac
1270-
__gitcomp_nl "$(__git_refs)"
1302+
__git_complete_refs
12711303
}
12721304

12731305
__git_diff_algorithms="myers minimal patience histogram"
@@ -1453,7 +1485,7 @@ _git_grep ()
14531485
;;
14541486
esac
14551487

1456-
__gitcomp_nl "$(__git_refs)"
1488+
__git_complete_refs
14571489
}
14581490

14591491
_git_help ()
@@ -1621,7 +1653,7 @@ _git_merge ()
16211653
--rerere-autoupdate --no-rerere-autoupdate --abort --continue"
16221654
return
16231655
esac
1624-
__gitcomp_nl "$(__git_refs)"
1656+
__git_complete_refs
16251657
}
16261658

16271659
_git_mergetool ()
@@ -1646,7 +1678,7 @@ _git_merge_base ()
16461678
return
16471679
;;
16481680
esac
1649-
__gitcomp_nl "$(__git_refs)"
1681+
__git_complete_refs
16501682
}
16511683

16521684
_git_mv ()
@@ -1684,7 +1716,7 @@ _git_notes ()
16841716
,*)
16851717
case "$prev" in
16861718
--ref)
1687-
__gitcomp_nl "$(__git_refs)"
1719+
__git_complete_refs
16881720
;;
16891721
*)
16901722
__gitcomp "$subcommands --ref"
@@ -1693,7 +1725,7 @@ _git_notes ()
16931725
;;
16941726
add,--reuse-message=*|append,--reuse-message=*|\
16951727
add,--reedit-message=*|append,--reedit-message=*)
1696-
__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
1728+
__git_complete_refs --cur="${cur#*=}"
16971729
;;
16981730
add,--*|append,--*)
16991731
__gitcomp '--file= --message= --reedit-message=
@@ -1712,7 +1744,7 @@ _git_notes ()
17121744
-m|-F)
17131745
;;
17141746
*)
1715-
__gitcomp_nl "$(__git_refs)"
1747+
__git_complete_refs
17161748
;;
17171749
esac
17181750
;;
@@ -1750,10 +1782,10 @@ __git_complete_force_with_lease ()
17501782
--*=)
17511783
;;
17521784
*:*)
1753-
__gitcomp_nl "$(__git_refs)" "" "${cur_#*:}"
1785+
__git_complete_refs --cur="${cur_#*:}"
17541786
;;
17551787
*)
1756-
__gitcomp_nl "$(__git_refs)" "" "$cur_"
1788+
__git_complete_refs --cur="$cur_"
17571789
;;
17581790
esac
17591791
}
@@ -1829,7 +1861,7 @@ _git_rebase ()
18291861

18301862
return
18311863
esac
1832-
__gitcomp_nl "$(__git_refs)"
1864+
__git_complete_refs
18331865
}
18341866

18351867
_git_reflog ()
@@ -1840,7 +1872,7 @@ _git_reflog ()
18401872
if [ -z "$subcommand" ]; then
18411873
__gitcomp "$subcommands"
18421874
else
1843-
__gitcomp_nl "$(__git_refs)"
1875+
__git_complete_refs
18441876
fi
18451877
}
18461878

@@ -1986,7 +2018,7 @@ _git_config ()
19862018
return
19872019
;;
19882020
branch.*.merge)
1989-
__gitcomp_nl "$(__git_refs)"
2021+
__git_complete_refs
19902022
return
19912023
;;
19922024
branch.*.rebase)
@@ -2460,7 +2492,7 @@ _git_remote ()
24602492

24612493
_git_replace ()
24622494
{
2463-
__gitcomp_nl "$(__git_refs)"
2495+
__git_complete_refs
24642496
}
24652497

24662498
_git_reset ()
@@ -2473,7 +2505,7 @@ _git_reset ()
24732505
return
24742506
;;
24752507
esac
2476-
__gitcomp_nl "$(__git_refs)"
2508+
__git_complete_refs
24772509
}
24782510

24792511
_git_revert ()
@@ -2489,7 +2521,7 @@ _git_revert ()
24892521
return
24902522
;;
24912523
esac
2492-
__gitcomp_nl "$(__git_refs)"
2524+
__git_complete_refs
24932525
}
24942526

24952527
_git_rm ()
@@ -2597,7 +2629,7 @@ _git_stash ()
25972629
;;
25982630
branch,*)
25992631
if [ $cword -eq 3 ]; then
2600-
__gitcomp_nl "$(__git_refs)";
2632+
__git_complete_refs
26012633
else
26022634
__gitcomp_nl "$(__git stash list \
26032635
| sed -n -e 's/:.*//p')"
@@ -2755,7 +2787,7 @@ _git_tag ()
27552787
fi
27562788
;;
27572789
*)
2758-
__gitcomp_nl "$(__git_refs)"
2790+
__git_complete_refs
27592791
;;
27602792
esac
27612793

0 commit comments

Comments
 (0)