Subject: [PATCH] Refactor baud rate completion
From: Frank Terbeck <[email-masked]>
To: [email-masked]
Cc: Ryan Wilson <[email-masked]>
Date: Sun, 1 May 2016 14:47:55 +0200
List-Id: Zsh Workers List <zsh-workers.zsh.org>

This adds a new helper function _baudrate and uses it in place of
private solutions in various existing completions.
---
  So I'm embracing my mistake and expose the filtering options
  to the user via styles. That way the user always has the final
  say in which baud rates are available. Now callers of _baudrate
  can define default filters if they want to and the user can
  override those if he/she so desires.

 Completion/BSD/Command/_cu       |  2 +-
 Completion/Unix/Command/_gdb     |  4 +-
 Completion/Unix/Command/_joe     |  2 +-
 Completion/Unix/Command/_picocom | 27 +------------
 Completion/Unix/Command/_screen  |  2 +-
 Completion/Unix/Type/_baudrate   | 84 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 89 insertions(+), 32 deletions(-)
 create mode 100644 Completion/Unix/Type/_baudrate

diff --git a/Completion/BSD/Command/_cu b/Completion/BSD/Command/_cu
index bdd5795..4b9f25d 100644
--- a/Completion/BSD/Command/_cu
+++ b/Completion/BSD/Command/_cu
@@ -3,5 +3,5 @@
 _arguments -s -A '-*' \
   '-d[do not block waiting for a carrier to be detected]' \
   '-l[line to use]:line:(/dev/(cuaU#<->|ttyS<->)(N%c))' \
-  '-s[line speed]:line speed:(75 110 300 1200 2400 4800 9600 19200 38400 57600 115200)' \
+  '-s[line speed]:line speed:_baudrate -d "line speed"' \
   '(-*)1:host:'
diff --git a/Completion/Unix/Command/_gdb b/Completion/Unix/Command/_gdb
index e9c3339..d5eed5a 100644
--- a/Completion/Unix/Command/_gdb
+++ b/Completion/Unix/Command/_gdb
@@ -37,9 +37,7 @@ else
   (-[csx]) _files && return 0 ;;
   (-e)     _description files expl executable
            _files "$expl[@]" -g '*(-*)' && return 0 ;;
-  (-b)     _wanted -V values expl 'baud rate' \
-               compadd 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \
-		       9600 19200 38400 57600 115200 230400 && return 0 ;;
+  (-b)     _baudrate && return 0 ;;
   esac
 
   w=( "${(@)words[2,-1]}" )
diff --git a/Completion/Unix/Command/_joe b/Completion/Unix/Command/_joe
index 96ad0a4..4e5b43b 100644
--- a/Completion/Unix/Command/_joe
+++ b/Completion/Unix/Command/_joe
@@ -3,7 +3,7 @@
 _arguments \
   '-asis[characters with codes >127 will be displayed non-inverted]' \
   '-backpath[backup file directory]:backup file directory:_files -/' \
-  '-baud[inserts delays for baud rates below 19200]:baud rate:(57600 38400 19200 9600 4800 2400 1200 300)' \
+  '-baud[inserts delays for baud rates below 19200]:baud rate:_baudrate -u 19199' \
   '-beep[beep on command errors or when cursor goes past extremes]' \
   '-columns[sets the number of screen columns]:num of columns' \
   '-csmode[continued search mode]' \
diff --git a/Completion/Unix/Command/_picocom b/Completion/Unix/Command/_picocom
index 6653bc2..c9d3be0 100644
--- a/Completion/Unix/Command/_picocom
+++ b/Completion/Unix/Command/_picocom
@@ -1,30 +1,5 @@
 #compdef picocom
 
-# The following function uses a generated list; first find out where the B*
-# macros are defined:
-#
-#   grep -r B115200 /usr/include
-#
-# Then generate the actual list:
-#
-#   sed -ne '/^[ \t]*#define[ \t]*B[0-9][0-9]*/s,^.*B\([0-9][0-9]*\).*,\1,p' \
-#           < /usr/include/asm-generic/termbits.h
-#
-# This one was generated on a Debian Stretch system, leaving out the "0" rate,
-# which is synonymous to "hang-up".
-function _picocom_baudrate () {
-    local expl
-    local -a rates
-    rates=( 50 75 110 134 150 200 300 600
-            1200 1800 2400 4800 9600
-            19200 38400 57600
-            115200 230400 460800 500000 576000 921600
-            1000000 1152000 1500000 2000000 2500000 3000000 3500000 4000000 )
-    # -1V removes dupes (which there shouldn't be) and otherwise leaves the
-    # order in the $rates array intact.
-    _wanted -1V baud-rate expl 'baud rate' compadd -a $expl -- rates
-}
-
 function _picocom_flowcontrol () {
     local expl
     local -a modes
@@ -57,7 +32,7 @@ function _picocom_escape () {
 function _picocom () {
     local -a args
 
-    args=( '(--baud -b)'{--baud,-b}'[define baud-rate to set the terminal to]:baud rate:_picocom_baudrate'
+    args=( '(--baud -b)'{--baud,-b}'[define baud-rate to set the terminal to]:baud rate:_baudrate'
            '(--flow -f)'{--flow,-f}'[define type of flow control to use]:flow control:_picocom_flowcontrol'
            '(--parity -p)'{--parity,-p}'[define type of parity to use]:parity mode:_picocom_paritymode'
            '(--databits -d)'{--databits,-d}'[define the number of databits per word]:data bits:_picocom_databits'
diff --git a/Completion/Unix/Command/_screen b/Completion/Unix/Command/_screen
index 510fd71..f4d2ef9 100644
--- a/Completion/Unix/Command/_screen
+++ b/Completion/Unix/Command/_screen
@@ -99,7 +99,7 @@ if [[ -n $state ]]; then
       if (( CURRENT == 1 )) && [[ $PREFIX == /dev/* ]]; then
 	  _path_files -g '*(%)'
       elif (( CURRENT == 2 )) && [[ ${words[1]} == /dev/* ]]; then
-	  _message "baud rate"
+	  _baudrate
       elif (( CURRENT > 2 )) && [[ ${words[1]} == /dev/* ]]; then
 	  _message "no more parameters"
       else
diff --git a/Completion/Unix/Type/_baudrate b/Completion/Unix/Type/_baudrate
new file mode 100644
index 0000000..3d141dc
--- /dev/null
+++ b/Completion/Unix/Type/_baudrate
@@ -0,0 +1,84 @@
+#autoload
+
+# Offer a list of baud-rates. Usage:
+#
+#   _baudrate [OPTION(s)...]
+#
+# Available options:
+#
+#     -u LIMIT     Upper limit. LIMIT is the maximum value the offered list
+#                  will contain, if the complete list includes LIMIT exactly.
+#
+#     -l LIMIT     Lower limit. Like -u but for the lower boundary.
+#
+#     -f FUNCTION  If given FUNCION is used as a predicate to filter the
+#                  value in the complete list to generate an arbitrary
+#                  sub-set.
+#
+#     -t TAG       Use TAG as the tag value in _wanted call.
+#
+#     -d DESC      Use DESC as the description value in _wanted call.
+#
+# The default complete list of available baud rates is also configurable via
+# the 'baud-rates' style:
+#
+#   zstyle ':completion:*' baud-rates 23 42 666
+#
+# It is also possible to override the arguments to -f, -u and -l via styles in
+# a similar fashion:
+#
+#   zstyle ':completion:*:*:screen:*' max-baud-rate 9600
+#   zstyle ':completion:*:*:screen:*' min-baud-rate 1200
+#   zstyle ':completion:*:*:screen:*' baud-filter some_function_name
+
+local -A opts
+local expl tag desc tmp
+local -a rates
+
+zparseopts -E -A opts u: l: f:
+
+# The following uses a generated list; first find out where the B* macros are
+# defined:
+#
+#   grep -r B115200 /usr/include
+#
+# Then generate the actual list:
+#
+#   sed -ne '/^[ \t]*#define[ \t]*B[0-9][0-9]*/s,^.*B\([0-9][0-9]*\).*,\1,p' \
+#           < /usr/include/asm-generic/termbits.h
+#
+# This one was generated on a Debian Stretch system, leaving out the "0" rate,
+# which is synonymous to "hang-up".
+
+zstyle -a ":completion:${curcontext}:" baud-rates rates ||
+    rates=( 50 75 110 134 150 200 300 600
+            1200 1800 2400 4800 9600
+            19200 38400 57600
+            115200 230400 460800 500000 576000 921600
+            1000000 1152000 1500000 2000000 2500000 3000000 3500000 4000000 )
+
+zstyle -s ":completion:${curcontext}:" max-baud-rate tmp && opts[-u]=$tmp
+zstyle -s ":completion:${curcontext}:" min-baud-rate tmp && opts[-l]=$tmp
+zstyle -s ":completion:${curcontext}:" baud-rate-filter tmp && opts[-f]=$tmp
+
+if (( ${+opts[-u]} )) || (( ${+opts[-l]} )); then
+    local -i min max
+    min=${opts[-l]:-0}
+    max=${opts[-u]:-${${(On)rates}[1]}}
+    rates=( ${(M)rates:#${~:-<$min-$max>}} )
+fi
+
+if (( ${+opts[-f]} )); then
+    set -- $rates
+    rates=( )
+    for item; do
+        ${opts[-f]} $item && rates+=( $item )
+    done
+fi
+
+tag=${opts[-t]:-baud-rate}
+desc=${opts[-d]:-baud rate}
+
+# -1V removes dupes (which there shouldn't be) and otherwise leaves the
+# order in the $rates array intact.
+_wanted -1V $tag expl $desc compadd -a $expl -- rates
-- 
2.8.1