[Bash-completion-commits] [SCM] bash-completion branch, master, updated. 1.3-241-g0a40e98
Ville Skyttä
ville.skytta at iki.fi
Mon May 2 12:23:09 UTC 2011
The following commit has been merged in the master branch:
commit 68f6f1c685fd9742b97b42d96739ebb52c1ffb35
Author: Ville Skyttä <ville.skytta at iki.fi>
Date: Mon May 2 13:34:56 2011 +0300
_parse_usage, _parse_help: Add _parse_usage, expand [no-] and [dont-?] as well in _parse_help.
diff --git a/bash_completion b/bash_completion
index 70591f1..77e76b3 100644
--- a/bash_completion
+++ b/bash_completion
@@ -747,40 +747,81 @@ _init_completion()
return 0
}
-# This function tries to parse the help output of the given command.
+# Helper function for _parse_help and _parse_usage.
+__parse_options()
+{
+ local option option2 i IFS=$' \t\n,/|'
+
+ # Take first found long option, or first one (short) if not found.
+ option=
+ for i in $1; do
+ case $i in
+ ---*) break ;;
+ --?*) option=$i ; break ;;
+ -?*) [[ $option ]] || option=$i ;;
+ *) break ;;
+ esac
+ done
+ [[ $option ]] || return
+
+ IFS=$' \t\n' # affects parsing of the regexps below...
+
+ # Expand --[no]foo to --foo and --nofoo etc
+ if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
+ option2=${option/"${BASH_REMATCH[1]}"/}
+ option2=${option2%%[<{[]*}
+ printf '%s\n' "${option2/=*/=}"
+ option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"}
+ fi
+
+ option=${option%%[<{[]*}
+ printf '%s\n' "${option/=*/=}"
+}
+
+# Parse GNU style help output of the given command.
# @param $1 command
# @param $2 command options (default: --help)
#
_parse_help()
{
eval local cmd=$1
- local line i option option2 IFS=$' \t\n,/|'
+ local line
"$cmd" ${2:---help} 2>&1 | while read line; do
[[ $line == *([ $'\t'])-* ]] || continue
+ __parse_options "$line"
- # Take first found long option, or first one (short) if not found.
- option=
- for i in $line; do
- case $i in
- ---*) break ;;
- --?*) option=$i ; break ;;
- -?*) [[ $option ]] || option=$i ;;
- *) break ;;
+ done
+}
+
+# Parse BSD style usage output (options in brackets) of the given command.
+# @param $1 command
+# @param $2 command options (default: --usage)
+#
+_parse_usage()
+{
+ eval local cmd=$1
+ local line match option i char
+ "$cmd" ${2:---usage} 2>&1 | while read -r line; do
+
+ while [[ $line =~ \[(-[^]]+)\] ]]; do
+ match=${BASH_REMATCH[0]}
+ option=${BASH_REMATCH[1]}
+ case $option in
+ -?(\[)+([a-zA-Z0-9?]))
+ # Treat as bundled short options
+ for (( i=1; i < ${#option}; i++ )); do
+ char=${option:i:1}
+ [[ $char != '[' ]] && printf '%s\n' -$char
+ done
+ ;;
+ *)
+ __parse_options "$option"
+ ;;
esac
+ line=${line#*"$match"}
done
- [[ $option ]] || continue
-
- # Expand --[no]foo to --foo and --nofoo
- if [[ $option == *\[no\]?* ]]; then
- option2=${option/\[no\]/}
- option2=${option2%%[<{[]*}
- printf '%s\n' "${option2/=*/=}"
- option=${option/\[no\]/no}
- fi
- option=${option%%[<{[]*}
- printf '%s\n' "${option/=*/=}"
done
}
diff --git a/test/unit/_parse_help.exp b/test/unit/_parse_help.exp
index c746b65..9c38dea 100644
--- a/test/unit/_parse_help.exp
+++ b/test/unit/_parse_help.exp
@@ -93,6 +93,22 @@ set cmd {fn() { printf '%s\n' "--[no]foo"; }; _parse_help fn}
assert_bash_list "--foo\n--nofoo" $cmd "long with \[no\]"
sync_after_int
+set cmd {fn() { printf '%s\n' "--[no-]bar[=quux]"; }; _parse_help fn}
+assert_bash_list "--bar\n--no-bar" $cmd "long with \[no-\] + optional arg"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "--[no-]bar=quux"; }; _parse_help fn}
+assert_bash_list "--bar=\n--no-bar=" $cmd "long with \[no-\] + required arg"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "--[dont-]foo"; }; _parse_help fn}
+assert_bash_list "--foo\n--dont-foo" $cmd "long with \[dont-\]"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "-[dont]x, --[dont]yy"; }; _parse_help fn}
+assert_bash_list "--yy\n--dontyy" $cmd "short and long with \[dont\]"
+sync_after_int
+
set cmd {fn() { printf '%s\n' "----\n---foo\n----- bar"; }; _parse_help fn}
assert_bash_list "" $cmd "more than two dashes"
sync_after_int
diff --git a/test/unit/_parse_usage.exp b/test/unit/_parse_usage.exp
new file mode 100644
index 0000000..6c7cd66
--- /dev/null
+++ b/test/unit/_parse_usage.exp
@@ -0,0 +1,51 @@
+proc setup {} {
+ save_env
+}
+
+proc teardown {} {
+ assert_env_unmodified {
+ /declare -f fn/d
+ }
+}
+
+setup
+
+
+set cmd {fn() { printf '%s\n' ""; }; _parse_usage fn}
+assert_bash_list "" $cmd "empty"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "no dashes here"; }; _parse_usage fn}
+assert_bash_list "" $cmd "no dashes"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "foo [-f]"; }; _parse_usage fn}
+assert_bash_list "-f" $cmd "simple"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "bar [-aBcD] [-e X]"; }; _parse_usage fn}
+assert_bash_list "-a -B -c -D -e" $cmd "bundled + separate 1 short"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "[-[XyZ]] [--long=arg]"; }; _parse_usage fn}
+assert_bash_list "-X -y -Z --long=" $cmd "bundled in brackets + separate long"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "[-s|--long]"; }; _parse_usage fn}
+assert_bash_list "--long" $cmd "short or long"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "[-s, --long=arg]"; }; _parse_usage fn}
+assert_bash_list "--long=" $cmd "short or long with arg, comma"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "[--long/-s] [-S/--longer]"; }; _parse_usage fn}
+assert_bash_list "--long\n--longer" $cmd "long or short, slash"
+sync_after_int
+
+set cmd {fn() { printf '%s\n' "----\n---foo\n----- bar"; }; _parse_usage fn}
+assert_bash_list "" $cmd "many dashes"
+sync_after_int
+
+
+teardown
--
bash-completion
More information about the Bash-completion-commits
mailing list