From 31c21031eafd2bf57aaadc92a74c7eb90b5fb0d4 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Wed, 21 Nov 2018 10:51:57 +0100
Subject: [PATCH] ENH: reduce intermediate text with generating completion
 options

- more filtering in the sed stage to remove non-essential text.
  Terminate parsing on first appearance of -help-full option.
---
 bin/tools/foamCreateCompletionCache | 20 ++++++++++++++++----
 etc/config.sh/bash_completion       | 22 ++++++++++++++++------
 2 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/bin/tools/foamCreateCompletionCache b/bin/tools/foamCreateCompletionCache
index 2bf5bac6254..4a8f56a144b 100755
--- a/bin/tools/foamCreateCompletionCache
+++ b/bin/tools/foamCreateCompletionCache
@@ -133,14 +133,26 @@ HEADER
 
 #-------------------------------------------------------------------------------
 
-# Scans the output of the application -help to detect options with/without
+# Scans the output of the application -help-full to detect options with/without
 # arguments.  Dispatch via _of_complete_
 #
+# Extract all options of the format
+#   -opt1         descrip
+#   -opt2 <arg>   descrip
+#   -help-full
+# Terminate parsing on first appearance of -help-full
+# - options with '=' (eg, -mode=ugo) are not handled very well at all.
+# - alternatives (eg, -a, -all) are not handled nicely either,
+#   for these treat ',' like a space to catch the worst of them.
 extractOptions()
 {
     local appName="$1"
     local helpText=$($appName -help-full 2>/dev/null | \
-        sed -n -e 's/,/ /g' -e 's/=.*$/=/' -e '/^  *-/p')
+        sed -ne 's/^ *//; /^$/d; /^[^-]/d; /^--/d;' \
+            -e 'y/,/ /; s/=.*$/=/;' \
+            -e '/^-[^ ]* </{ s/^\(-[^ ]* <\).*$/\1/; p; d }' \
+            -e 's/^\(-[^ ]*\).*$/\1/; p; /^-help-full/q;' \
+            )
 
     [ -n "$helpText" ] || {
         echo "Error calling $appName" 1>&2
@@ -148,11 +160,11 @@ extractOptions()
     }
 
     # Array of options with args
-    local argOpts=($(awk '/^ {0,4}-[a-z]/ && /</ {print $1}' <<< "$helpText"))
+    local argOpts=($(awk '/</ {print $1}' <<< "$helpText"))
 
     # Array of options without args, but skip the following:
     #     -help-compat -help-full
-    local boolOpts=($(awk '/^ {0,4}-[a-z]/ && !/</ && !/help-(compat|full)/ {print $1}' <<< "$helpText"))
+    local boolOpts=($(awk '!/</ && !/help-(compat|full)/ {print $1}' <<< "$helpText"))
 
     appName="${appName##*/}"
     echo "$appName" 1>&2
diff --git a/etc/config.sh/bash_completion b/etc/config.sh/bash_completion
index 98c3556b206..0a89e3f643b 100644
--- a/etc/config.sh/bash_completion
+++ b/etc/config.sh/bash_completion
@@ -98,7 +98,7 @@ foamAddCompletion()
 # The respective options are generated on-the-fly from the application's
 # -help-full output and cached to the _of_complete_cache_ global associative
 # array with entries formatted as "argOpts.. | boolOpts ..".
-# The '|' character separates options with and without arguments.
+# The '|' character separates options with/without arguments.
 #
 unset -f _of_complete_ 2>/dev/null
 _of_complete_()
@@ -134,12 +134,22 @@ _of_complete_()
         choices="${_of_complete_cache_[$appName]}"
 
         # Not in cache, obtain by parsing application -help-full
+        # Extract all options of the format
+        #   -opt1         descrip
+        #   -opt2 <arg>   descrip
+        #   -help-full
+        # Terminate parsing on first appearance of -help-full
+        # - options with '=' (eg, -mode=ugo) are not handled very well at all.
+        # - alternatives (eg, -a, -all) are not handled nicely either,
+        #   for these treat ',' like a space to catch the worst of them.
         if [ -z "$choices" ]
         then
-            # Treat ',' like space so '-a, -all' parses like '-a | -all'
-            # Options with '=' (Eg, -mode=ugo) are not handled very well.
             local helpText=$($appName -help-full 2>/dev/null | \
-                sed -ne 's/,/ /g' -e 's/=.*$/=/' -e '/^  *-/p')
+                sed -ne 's/^ *//; /^$/d; /^[^-]/d; /^--/d;' \
+                    -e 'y/,/ /; s/=.*$/=/;' \
+                    -e '/^-[^ ]* </{ s/^\(-[^ ]* <\).*$/\1/; p; d }' \
+                    -e 's/^\(-[^ ]*\).*$/\1/; p; /^-help-full/q;' \
+                    )
 
             if [ -z "$helpText" ]
             then
@@ -147,10 +157,10 @@ _of_complete_()
                 choices="false"  # Mark failure to prevent repeating again
             else
                 # Array of options with args
-                local argOpts=($(awk '/^ {0,4}-[a-z]/ && /</ {print $1}' <<< "$helpText"))
+                local argOpts=($(awk '/</ {print $1}' <<< "$helpText"))
 
                 # Array of options without args
-                local boolOpts=($(awk '/^ {0,4}-[a-z]/ && !/</ {print $1}' <<< "$helpText"))
+                local boolOpts=($(awk '!/</ {print $1}' <<< "$helpText"))
 
                 choices="${argOpts[@]} | ${boolOpts[@]}"
             fi
-- 
GitLab