gsu: Overhaul of the rexexp matching for help commands.
authorAndre Noll <maan@systemlinux.org>
Thu, 29 Sep 2011 13:12:33 +0000 (15:12 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Fri, 29 Aug 2014 19:39:58 +0000 (21:39 +0200)
The old sed scripts were unreadable and broken on non-gnu systems
since they made use of some gnuisms of grep and sed like \+ in regular
expressions to match at least one character or sed's T command which
jumps to a label if no substitution has been made since the most
recent reading of an input line.

This patch switches to extended regular expressions and replaces all
broken sed scripts by portable ones, which are known to work at least
on FreeBSD and MacOS. The new scripts are commented verbosely so that
any subsequent changes do not require a full rewrite, hopefully.

misc/gsu/subcommand

index f5f4745a8856920a0203b02039eadce46f4bf2ef..a688ed5855c60c47e099b723bf8b060487a7669a 100644 (file)
@@ -11,16 +11,33 @@ _gsu_usage()
        gsu_short_msg "# Usage: $_gsu_self command [options]"
 }
 
-# Each line matching this is recognized as a subcommand. The name
-# of the subcommand is the first subexpression.
-export gsu_command_regex='^com_\([-a-zA-Z_0-9]\+\)()'
+# Each line matching this is recognized as a subcommand. The name of the may be
+# given as $1. In any case the subcommand is the first subexpression.
+_gsu_get_command_regex()
+{
+       local cmd="${1:-[-a-zA-Z_0-9]+}"
+       result="^com_($cmd)\(\)"
+}
 
 _gsu_available_commands()
 {
+       local ere
+
+       _gsu_get_command_regex
+       ere="$result"
        result="$({
                printf "help\nman\nprefs\ncomplete\n"
-               sed -ne "s/$gsu_command_regex/\1/g;T;p" $0
-               } | sort | tr '\n' ' ')"
+               sed -Ee '
+                       # if line matches, isolate command name
+                       s/'"$ere"'/\1/g
+
+                       # if there is a match, (print it and) start next cycle
+                       t
+
+                       # otherwise delete it
+                       d
+               ' $0
+       } | sort | tr '\n' ' ')"
 }
 
 _gsu_print_available_commands()
@@ -194,7 +211,11 @@ was given.
 
 _com_help()
 {
-       local a b
+       local a b ere tab='     '
+
+       _gsu_get_command_regex
+       ere="$result"
+
        if test -z "$1"; then
                _gsu_banner_msg 2>&1
                _gsu_usage 2>&1
@@ -203,21 +224,28 @@ _com_help()
                        printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
                        printf "com_prefs()\n$gsu_prefs_txt" | head -n 4; echo "--"
                        printf "com_complete()\n$gsu_complete_txt" | head -n 4; echo "--"
-                       grep -A 2 "$gsu_command_regex" $0
+                       grep -EA 2 "$ere" $0
                } | grep -v -- '--' \
-                       | sed -e "/$gsu_command_regex/bs" \
-                               -e 'H;$!d;x;s/\n//g;b' \
-                               -e :s \
-                               -e 'x;s/\n//g;${p;x;}' \
-                       | sed -e "s/${gsu_command_regex}#*/\1\t/" \
-                       | sort \
-                       | while read a b; do
-                               printf "$a\t"
-                               if test ${#a} -lt 8; then
-                                       printf "\t"
-                               fi
-                               echo "$b"
-                        done
+                       | sed -En "/$ere/"'!d
+                               # remove everything but the command name
+                               s/^com_(.*)\(\).*/\1/
+
+                               # append tab after short commands (less than 8 chars)
+                               s/^(.{1,7})$/\1'"$tab"'/g
+
+                               # remove next line (should contain only ## anyway)
+                               N
+                               s/#.*//
+
+                               # append next line, removing leading ##
+                               N
+                               s/#+ *//g
+
+                               # replace newline by tab
+                               y/\n/'"$tab"'/
+
+                               # and print the sucker
+                               p'
                echo
                echo "# Try $_gsu_self help <command> for info on <command>."
                ret=$GSU_SUCCESS
@@ -244,13 +272,32 @@ _com_help()
                return
        fi
        ret=$GSU_SUCCESS
-       if grep -q "^com_$1()" $0; then
-               sed -e "1,/^com_$1()$/d" -e '/^{/,$d' -e 's/^## *//' $0
+       _gsu_get_command_regex "$1"
+       ere="$result"
+       if ! grep -Eq "$ere" $0; then
+               _gsu_print_available_commands
+               result="$1"
+               ret=-$E_GSU_BAD_COMMAND
                return
        fi
-       _gsu_print_available_commands
-       result="$1"
-       ret=-$E_GSU_BAD_COMMAND
+       sed -nEe '
+               # only consider lines in the comment of the function
+               /'"$ere"'/,/^[^#]/ {
+
+                       # remove leading ##
+                       s/^## *//
+
+                       # if it did start with ##, jump to label p and print it
+                       tp
+
+                       # otherwise, move on to next line
+                       d
+
+                       # print it
+                       :p
+                       p
+               }
+       ' $0
 }
 
 complete_help()