Skip to content

Commit 247ba7b

Browse files
authored
Merge pull request #1362 from akinomyoga/tar-perf
perf(tar): cache the parse result of GNU tar help
2 parents c298dcf + d8d1d82 commit 247ba7b

File tree

1 file changed

+85
-21
lines changed

1 file changed

+85
-21
lines changed

completions/tar

+85-21
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
_comp_deprecate_var 2.12 \
6060
COMP_TAR_INTERNAL_PATHS BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS
6161

62-
_comp_cmd_gtar__parse_help_opt()
62+
_comp_cmd_gtar__init_parse_help_opt()
6363
{
6464
local opttype arg opt separator optvar
6565
opttype=long
@@ -98,7 +98,7 @@ _comp_cmd_gtar__parse_help_opt()
9898
eval "$optvar=\"\$$optvar$separator\"\"$opt\""
9999
}
100100

101-
_comp_cmd_gtar__parse_help_line()
101+
_comp_cmd_gtar__init_parse_help_line()
102102
{
103103
local i
104104
local -a tmp
@@ -107,7 +107,7 @@ _comp_cmd_gtar__parse_help_line()
107107
case "$i" in
108108
# regular options
109109
--* | -*)
110-
_comp_cmd_gtar__parse_help_opt "$i" "$2"
110+
_comp_cmd_gtar__init_parse_help_opt "$i" "$2"
111111
;;
112112

113113
# end once there is single non-option word
@@ -119,8 +119,21 @@ _comp_cmd_gtar__parse_help_line()
119119
done <<<"$1"
120120
}
121121

122-
_comp_cmd_gtar__parse_help()
122+
# Parse the output of "tar --help" with GNU tar and store the parse results
123+
# in a global variable.
124+
#
125+
# @var[out] _comp_cmd_gtar__saved_opts
126+
# The parse results are stored in this global variable in a form that can
127+
# be evaluated by the builtin "eval".
128+
_comp_cmd_gtar__init_parse_help()
123129
{
130+
local long_arg_none=""
131+
local long_arg_opt=""
132+
local long_arg_req=""
133+
local short_arg_none=""
134+
local short_arg_opt=""
135+
local short_arg_req=""
136+
124137
local str line arg
125138
while IFS= read -r line; do
126139
# Ok, this requires some comment probably. The GNU help output prints
@@ -141,14 +154,49 @@ _comp_cmd_gtar__parse_help()
141154
[[ ${BASH_REMATCH[1]} ]] && arg=opt || arg=req
142155
fi
143156

144-
_comp_cmd_gtar__parse_help_line "$str" "$arg"
157+
_comp_cmd_gtar__init_parse_help_line "$str" "$arg"
145158
fi
146159
done <<<"$(tar --help)"
147160

148-
long_opts="\
149-
$long_arg_none $long_arg_opt $long_arg_req"
161+
local long_opts="$long_arg_none $long_arg_opt $long_arg_req"
162+
163+
local short_opts="$short_arg_none$short_arg_opt$short_arg_req"
164+
165+
printf -v _comp_cmd_gtar__saved_opts '%s=%q ' \
166+
long_opts "$long_opts" \
167+
short_opts "$short_opts" \
168+
long_arg_none "$long_arg_none" \
169+
long_arg_opt "$long_arg_opt" \
170+
long_arg_req "$long_arg_req" \
171+
short_arg_none "$short_arg_none" \
172+
short_arg_opt "$short_arg_opt" \
173+
short_arg_req "$short_arg_req"
150174

151-
short_opts="$short_arg_none$short_arg_opt$short_arg_req"
175+
# Clean up functions only used in initialization
176+
unset -f _comp_cmd_gtar__init_parse_help
177+
unset -f _comp_cmd_gtar__init_parse_help_line
178+
unset -f _comp_cmd_gtar__init_parse_help_opt
179+
}
180+
_comp_cmd_gtar__init_parse_help
181+
182+
# Load the parse results of "tar --help" for GNU tar into variables.
183+
#
184+
# @var[out] long_opts
185+
# @var[out] short_opts
186+
# @var[out] long_arg_none
187+
# @var[out] long_arg_opt
188+
# @var[out] long_arg_req
189+
# @var[out] short_arg_none
190+
# @var[out] short_arg_opt
191+
# @var[out] short_arg_req
192+
# The parse results are returned in these variables.
193+
#
194+
# @var[in] _comp_cmd_gtar__saved_opts
195+
# The parse results are obtained by evaluating this variable with the
196+
# "eval" builtin.
197+
_comp_cmd_gtar__load_opts()
198+
{
199+
eval -- "$_comp_cmd_gtar__saved_opts"
152200
}
153201

154202
# Hack: parse --warning keywords from tar's error output
@@ -165,8 +213,15 @@ _comp_cmd_gtar__parse_warnings()
165213
_comp_compgen -- -W '"${warnings[@]}"'
166214
}
167215

216+
# @var[out] old_opt_progress
217+
# @var[out] old_opt_used
218+
# @var[out,array] old_opt_parsed
168219
_comp_cmd_tar__parse_old_opt()
169220
{
221+
old_opt_progress=""
222+
old_opt_used=""
223+
old_opt_parsed=()
224+
170225
local first_word char
171226

172227
# current word is the first word
@@ -193,6 +248,10 @@ _comp_cmd_tar__parse_old_opt()
193248
}
194249

195250
# Make the analysis of whole command line.
251+
#
252+
# @var[out] old_opt_progress
253+
# @var[out] old_opt_used
254+
# @var[out,array] old_opt_parsed
196255
_comp_cmd_tar__preparse_cmdline()
197256
{
198257
local first_arg=set i modes="ctxurdA"
@@ -507,11 +566,7 @@ _comp_cmd_tar__detect_ext()
507566

508567
_comp_cmd_tar__gnu()
509568
{
510-
local long_opts short_opts basic_tar="" \
511-
long_arg_none="" long_arg_opt="" long_arg_req="" \
512-
short_arg_none="" short_arg_opt="" short_arg_req="" \
513-
tar_mode tar_mode_arg old_opt_progress="" \
514-
old_opt_used="" old_opt_parsed=()
569+
local basic_tar=""
515570

516571
# Main mode, e.g. "x" or "c" or the long forms "extract" or "create"
517572
local tar_mode=none
@@ -528,12 +583,15 @@ _comp_cmd_tar__gnu()
528583
fi
529584

530585
local cur prev words cword was_split comp_args
531-
532586
_comp_initialize -s -- "$@" || return
533587

534588
# Fill the {long,short}_{opts,arg*}
535-
_comp_cmd_gtar__parse_help
589+
local long_opts short_opts \
590+
long_arg_none long_arg_opt long_arg_req \
591+
short_arg_none short_arg_opt short_arg_req
592+
_comp_cmd_gtar__load_opts
536593

594+
local old_opt_progress old_opt_used old_opt_parsed
537595
_comp_cmd_tar__preparse_cmdline "${words[@]}"
538596

539597
local ext
@@ -694,11 +752,7 @@ _comp_cmd_tar__posix_prev_handle()
694752

695753
_comp_cmd_tar__posix()
696754
{
697-
local long_opts short_opts basic_tar=set \
698-
long_arg_none="" long_arg_opt long_arg_req="" \
699-
short_arg_none short_arg_opt short_arg_req \
700-
tar_mode tar_mode_arg old_opt_progress="" \
701-
old_opt_used=set old_opt_parsed=()
755+
local basic_tar=set
702756

703757
# Main mode, e.g. -x or -c (extract/creation)
704758
local tar_mode=none
@@ -710,15 +764,25 @@ _comp_cmd_tar__posix()
710764
local tar_compression_mode=none
711765

712766
local cur prev words cword was_split comp_args
713-
714767
_comp_initialize -s -- "$@" || return
715768

769+
# Initialize option variables:
716770
# relatively compatible modes are {c,t,x}
717771
# relatively compatible options {b,f,m,v,w}
772+
# Note: long_{opts,arg_{none,opt}} and short_arg_opt are currently unused
773+
local long_opts short_opts \
774+
long_arg_none long_arg_opt long_arg_req \
775+
short_arg_none short_arg_opt short_arg_req
776+
long_arg_none=""
777+
long_arg_opt=""
778+
long_arg_req=""
779+
long_opts=""
718780
short_arg_req="fb"
781+
short_arg_opt=""
719782
short_arg_none="wmv"
720783
short_opts="$short_arg_req$short_arg_none"
721784

785+
local old_opt_progress old_opt_used old_opt_parsed
722786
_comp_cmd_tar__preparse_cmdline "${words[@]}"
723787

724788
local ext

0 commit comments

Comments
 (0)