Skip to content

Commit b87010c

Browse files
authored
Merge pull request #954 from akinomyoga/_parse_help-1
refactor: `_parse_{help,usage}` => `_comp_compgen_help`
2 parents 581d160 + b196116 commit b87010c

File tree

265 files changed

+500
-476
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

265 files changed

+500
-476
lines changed

bash_completion

+109-86
Original file line numberDiff line numberDiff line change
@@ -1189,10 +1189,52 @@ _comp_initialize()
11891189
return 0
11901190
}
11911191

1192-
# Helper function for _parse_help and _parse_usage.
1192+
# Helper function for _comp_compgen_help and _comp_compgen_usage.
1193+
# Obtain the help output based on the arguments.
1194+
# @param $@ args Arguments specified to the caller.
1195+
# @var[out] _lines
1196+
# @return 2 if the usage is wrong, 1 if no output is obtained, or otherwise 0.
1197+
_comp_compgen_help__get_help_lines()
1198+
{
1199+
local -a help_cmd
1200+
case ${1-} in
1201+
-)
1202+
if (($# > 1)); then
1203+
printf 'bash_completion: %s -: extra arguments for -\n' "${FUNCNAME[1]}" >&2
1204+
printf 'usage: %s -\n' "${FUNCNAME[1]}" >&2
1205+
printf 'usage: %s -c cmd args...\n' "${FUNCNAME[1]}" >&2
1206+
printf 'usage: %s [-- args...]\n' "${FUNCNAME[1]}" >&2
1207+
return 2
1208+
fi
1209+
help_cmd=(exec cat)
1210+
;;
1211+
-c)
1212+
if (($# < 2)); then
1213+
printf 'bash_completion: %s -c: no command is specified\n' "${FUNCNAME[1]}" >&2
1214+
printf 'usage: %s -\n' "${FUNCNAME[1]}" >&2
1215+
printf 'usage: %s -c cmd args...\n' "${FUNCNAME[1]}" >&2
1216+
printf 'usage: %s [-- args...]\n' "${FUNCNAME[1]}" >&2
1217+
return 2
1218+
fi
1219+
help_cmd=("${@:2}")
1220+
;;
1221+
--) shift 1 ;&
1222+
*)
1223+
local ret
1224+
_comp_dequote "${comp_args[0]-}" || ret=${comp_args[0]-}
1225+
help_cmd=("${ret:-false}" "$@")
1226+
;;
1227+
esac
1228+
1229+
local ret
1230+
_comp_split -l ret "$(LC_ALL=C "${help_cmd[@]}" 2>&1)" &&
1231+
_lines=("${ret[@]}")
1232+
}
1233+
1234+
# Helper function for _comp_compgen_help and _comp_compgen_usage.
1235+
# @var[in,out] _options Add options
11931236
# @return True (0) if an option was found, False (> 0) otherwise
1194-
# TODO: rename per API conventions, rework to use vars rather than outputting
1195-
__parse_options()
1237+
_comp_compgen_help__parse()
11961238
{
11971239
local option option2 i
11981240

@@ -1218,108 +1260,89 @@ __parse_options()
12181260
if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
12191261
option2=${option/"${BASH_REMATCH[1]}"/}
12201262
option2=${option2%%[<{().[]*}
1221-
printf '%s\n' "${option2/=*/=}"
1263+
_options+=("${option2/=*/=}")
12221264
option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"}
12231265
fi
12241266
12251267
option=${option%%[<{().[]*}
12261268
option=${option/=*/=}
12271269
[[ $option ]] || return 1
12281270
1229-
printf '%s\n' "$option"
1271+
_options+=("$option")
12301272
}
12311273
1232-
# Parse GNU style help output of the given command.
1233-
# @param $1 command; if "-", read from stdin and ignore rest of args
1234-
# @param $2 command options (default: --help)
1274+
# Parse GNU style help output of the given command and generate and store
1275+
# completions in an array. The help output is produced in the way depending on
1276+
# the usage:
1277+
# usage: _comp_compgen_help - # read from stdin
1278+
# usage: _comp_compgen_help -c cmd args... # run "cmd args..."
1279+
# usage: _comp_compgen_help [[--] args...] # run "${comp_args[0]} args..."
1280+
# When no arguments are specified, `--help` is assumed.
12351281
#
1236-
# TODO: rename per API conventions, rework to use vars rather than outputting
1237-
_parse_help()
1282+
# @var[in] comp_args[0]
1283+
_comp_compgen_help()
12381284
{
1239-
local IFS=$' \t\n'
1240-
local reset_monitor=$(shopt -po monitor) reset_lastpipe=$(shopt -p lastpipe) reset_noglob=$(shopt -po noglob)
1241-
set +o monitor
1242-
shopt -s lastpipe
1243-
set -o noglob
1285+
(($#)) || set -- -- --help
12441286

1245-
local cmd=$1
1246-
local line rc=1
1247-
(
1248-
case $cmd in
1249-
-) exec cat ;;
1250-
*)
1251-
# shellcheck disable=SC2086
1252-
_comp_dequote "$cmd" && LC_ALL=C "$ret" ${2:---help} 2>&1
1253-
;;
1254-
esac
1255-
) |
1256-
while read -r line; do
1257-
1258-
[[ $line == *([[:blank:]])-* ]] || continue
1259-
# transform "-f FOO, --foo=FOO" to "-f , --foo=FOO" etc
1260-
while [[ $line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+([,_-]+[A-Z0-9]+)?(\.\.+)?\]? ]]; do
1261-
line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"}
1262-
done
1263-
__parse_options "${line// or /, }" && rc=0
1287+
local -a _lines
1288+
_comp_compgen_help__get_help_lines "$@" || return "$?"
12641289

1290+
local -a _options=()
1291+
local _line
1292+
for _line in "${_lines[@]}"; do
1293+
[[ $_line == *([[:blank:]])-* ]] || continue
1294+
# transform "-f FOO, --foo=FOO" to "-f , --foo=FOO" etc
1295+
while [[ $_line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+([,_-]+[A-Z0-9]+)?(\.\.+)?\]? ]]; do
1296+
_line=${_line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"}
12651297
done
1298+
_comp_compgen_help__parse "${_line// or /, }"
1299+
done
1300+
((${#_options[@]})) || return 1
12661301

1267-
$reset_monitor
1268-
$reset_lastpipe
1269-
$reset_noglob
1270-
return $rc
1302+
_comp_compgen -- -W '"${_options[@]}"'
1303+
return 0
12711304
}
12721305

1273-
# Parse BSD style usage output (options in brackets) of the given command.
1274-
# @param $1 command; if "-", read from stdin and ignore rest of args
1275-
# @param $2 command options (default: --usage)
1276-
#
1277-
# TODO: rename per API conventions, rework to use vars rather than outputting
1278-
_parse_usage()
1279-
{
1280-
local IFS=$' \t\n'
1281-
local reset_monitor=$(shopt -po monitor) reset_lastpipe=$(shopt -p lastpipe) reset_noglob=$(shopt -po noglob)
1282-
set +o monitor
1283-
shopt -s lastpipe
1284-
set -o noglob
1285-
1286-
local cmd=$1
1287-
local line match option i char rc=1
1288-
(
1289-
case $cmd in
1290-
-) exec cat ;;
1291-
*)
1292-
# shellcheck disable=SC2086
1293-
_comp_dequote "$cmd" && LC_ALL=C "$ret" ${2:---usage} 2>&1
1294-
;;
1295-
esac
1296-
) |
1297-
while read -r line; do
1298-
1299-
while [[ $line =~ \[[[:space:]]*(-[^]]+)[[:space:]]*\] ]]; do
1300-
match=${BASH_REMATCH[0]}
1301-
option=${BASH_REMATCH[1]}
1302-
case $option in
1303-
-?(\[)+([a-zA-Z0-9?]))
1304-
# Treat as bundled short options
1305-
for ((i = 1; i < ${#option}; i++)); do
1306-
char=${option:i:1}
1307-
[[ $char != '[' ]] && printf '%s\n' -"$char" && rc=0
1308-
done
1309-
;;
1310-
*)
1311-
__parse_options "$option" && rc=0
1312-
;;
1313-
esac
1314-
line=${line#*"$match"}
1315-
done
1316-
1306+
# Parse BSD style usage output (options in brackets) of the given command. The
1307+
# help output is produced in the way depending on the usage:
1308+
# usage: _comp_compgen_usage - # read from stdin
1309+
# usage: _comp_compgen_usage -c cmd args... # run "cmd args..."
1310+
# usage: _comp_compgen_usage [[--] args...] # run "${comp_args[0]} args..."
1311+
# When no arguments are specified, `--usage` is assumed.
1312+
#
1313+
# @var[in] comp_args[0]
1314+
_comp_compgen_usage()
1315+
{
1316+
(($#)) || set -- -- --usage
1317+
1318+
local -a _lines
1319+
_comp_compgen_help__get_help_lines "$@" || return "$?"
1320+
1321+
local -a _options=()
1322+
local _line _match _option _i _char
1323+
for _line in "${_lines[@]}"; do
1324+
while [[ $_line =~ \[[[:space:]]*(-[^]]+)[[:space:]]*\] ]]; do
1325+
_match=${BASH_REMATCH[0]}
1326+
_option=${BASH_REMATCH[1]}
1327+
case $_option in
1328+
-?(\[)+([a-zA-Z0-9?]))
1329+
# Treat as bundled short options
1330+
for ((_i = 1; _i < ${#_option}; _i++)); do
1331+
_char=${_option:_i:1}
1332+
[[ $_char != '[' ]] && _options+=("-$_char")
1333+
done
1334+
;;
1335+
*)
1336+
_comp_compgen_help__parse "$_option"
1337+
;;
1338+
esac
1339+
_line=${_line#*"$_match"}
13171340
done
1341+
done
1342+
((${#_options[@]})) || return 1
13181343

1319-
$reset_monitor
1320-
$reset_lastpipe
1321-
$reset_noglob
1322-
return $rc
1344+
_comp_compgen -- -W '"${_options[@]}"'
1345+
return 0
13231346
}
13241347

13251348
# This function completes on signal names (minus the SIG prefix)

bash_completion.d/000_bash_completion_compat.bash

+58
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,62 @@ _tilde()
276276
! _comp_compgen -c "$1" tilde
277277
}
278278

279+
# Helper function for _parse_help and _parse_usage.
280+
# @return True (0) if an option was found, False (> 0) otherwise
281+
# @deprecated Use _comp_compgen_help__parse
282+
__parse_options()
283+
{
284+
local -a _options=()
285+
_comp_compgen_help__parse "$1"
286+
printf '%s\n' "${_options[@]}"
287+
}
288+
289+
# Parse GNU style help output of the given command.
290+
# @param $1 command; if "-", read from stdin and ignore rest of args
291+
# @param $2 command options (default: --help)
292+
# @deprecated Use `_comp_compgen_help`. `COMPREPLY=($(compgen -W
293+
# '$(_parse_help "$1" ...)' -- "$cur"))` can be replaced with
294+
# `_comp_compgen_help [-- ...]`. Also, `var=($(_parse_help "$1" ...))` can
295+
# be replaced with `_comp_compgen -Rv var help [-- ...]`.
296+
_parse_help()
297+
{
298+
local -a args
299+
if [[ $1 == - ]]; then
300+
args=(-)
301+
else
302+
local ret opt IFS=$' \t\n'
303+
_comp_dequote "$1"
304+
_comp_split opt "${2:---help}"
305+
args=(-c "$ret" ${opt[@]+"${opt[@]}"})
306+
fi
307+
local -a ret=()
308+
_comp_compgen -Rv ret help "${args[@]}" || return 1
309+
((${#ret[@]})) && printf '%s\n' "${ret[@]}"
310+
return 0
311+
}
312+
313+
# Parse BSD style usage output (options in brackets) of the given command.
314+
# @param $1 command; if "-", read from stdin and ignore rest of args
315+
# @param $2 command options (default: --usage)
316+
# @deprecated Use `_comp_compgen_usage`. `COMPREPLY=($(compgen -W
317+
# '$(_parse_usage "$1" ...)' -- "$cur"))` can be replaced with
318+
# `_comp_compgen_usage [-- ...]`. `var=($(_parse_usage "$1" ...))` can be
319+
# replaced with `_comp_compgen -Rv var usage [-- ...]`.
320+
_parse_usage()
321+
{
322+
local -a args
323+
if [[ $1 == - ]]; then
324+
args=(-)
325+
else
326+
local ret opt IFS=$' \t\n'
327+
_comp_dequote "$1"
328+
_comp_split opt "${2:---usage}"
329+
args=(-c "$ret" ${opt[@]+"${opt[@]}"})
330+
fi
331+
local -a ret=()
332+
_comp_compgen -Rv ret usage "${args[@]}" || return 1
333+
((${#ret[@]})) && printf '%s\n' "${ret[@]}"
334+
return 0
335+
}
336+
279337
# ex: filetype=sh

completions/2to3

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ _comp_cmd_2to3()
2727
[[ $was_split ]] && return
2828

2929
if [[ $cur == -* ]]; then
30-
COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur"))
30+
_comp_compgen_help
3131
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
3232
return
3333
fi

completions/_adb

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ _comp_cmd_adb()
3737
if [[ ! $has_cmd ]]; then
3838
local tmp=()
3939
if [[ ! $cur || $cur == -* ]]; then
40-
tmp+=($(compgen -W '$(_parse_help "$1" help)' -- "$cur"))
40+
_comp_compgen -av tmp help -- help
4141
fi
4242
if [[ ! $cur || $cur != -* ]]; then
4343
tmp+=($("$1" help 2>&1 | awk '$1 == "adb" { print $2 }'))

completions/_cal

+1-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ _comp_cmd_cal()
2424
esac
2525

2626
if [[ $cur == -* ]]; then
27-
COMPREPLY=($(
28-
compgen -W '$(_parse_help "$1" || _parse_usage "$1")' -- "$cur"
29-
))
27+
_comp_compgen_help || _comp_compgen_usage
3028
return
3129
fi
3230

completions/_chsh

+1-3
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ _comp_cmd_chsh()
3232
esac
3333

3434
if [[ $cur == -* ]]; then
35-
COMPREPLY=($(
36-
compgen -W '$(_parse_help "$1" || _parse_usage "$1")' -- "$cur"
37-
))
35+
_comp_compgen_help || _comp_compgen_usage
3836
else
3937
_allowed_users
4038
fi

completions/_dmesg

+1-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ _comp_cmd_dmesg()
2525
;;
2626
esac
2727

28-
COMPREPLY=($(
29-
compgen -W '$(_parse_help "$1" || _parse_usage "$1")' -- "$cur"
30-
))
28+
_comp_compgen_help || _comp_compgen_usage
3129
} &&
3230
complete -F _comp_cmd_dmesg dmesg
3331

completions/_eject

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ _comp_cmd_eject()
1919
esac
2020

2121
if [[ $cur == -* ]]; then
22-
COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur"))
22+
_comp_compgen_help
2323
return
2424
elif [[ $prev == @(-d|--default) ]]; then
2525
return

completions/_hexdump

+1-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ _comp_cmd_hexdump()
1919
esac
2020

2121
if [[ $cur == -* ]]; then
22-
COMPREPLY=($(
23-
compgen -W '$(_parse_help "$1" || _parse_usage "$1")' -- "$cur"
24-
))
22+
_comp_compgen_help || _comp_compgen_usage
2523
return
2624
fi
2725

completions/_ionice

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ _comp_cmd_ionice()
5151
esac
5252

5353
if [[ $cur == -* ]]; then
54-
COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur"))
54+
_comp_compgen_help -- -h
5555
return
5656
fi
5757
} &&

completions/_mock

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ _comp_cmd_mock()
5858
[[ $was_split ]] && return
5959

6060
if [[ $cur == -* ]]; then
61-
COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur"))
61+
_comp_compgen_help
6262
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
6363
else
6464
_comp_compgen_filedir '@(?(no)src.r|s)pm'

completions/_repomanage

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ _comp_cmd_repomanage()
1313
[[ $was_split ]] && return
1414

1515
if [[ $cur == -* ]]; then
16-
COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur"))
16+
_comp_compgen_help
1717
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
1818
else
1919
_comp_compgen_filedir -d

completions/_reptyr

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ _comp_cmd_reptyr()
1515
esac
1616

1717
if [[ $cur == -* ]]; then
18-
COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur"))
18+
_comp_compgen_help
1919
return
2020
fi
2121

0 commit comments

Comments
 (0)