zsh-workers
 help / color / mirror / code / Atom feed
From: "Bart Schaefer" <schaefer@candle.brasslantern.com>
To: zsh-workers@sunsite.auc.dk
Subject: Chatty little precompiler for _arguments
Date: Sun, 19 Sep 1999 22:57:45 +0000	[thread overview]
Message-ID: <990919225746.ZM8479@candle.brasslantern.com> (raw)

For your consideration ... if _arguments gets converted into C code, I'd like
to see an interface something like this available for it (in addtion to the
more compact/cryptic one).  Before that happens, it's probably not efficient
to use this kind of thing for anything but testing.

An extremely useful dual of this would be an _arg_explain that takes exactly
the same arguments as _arguments, but outputs this little language; so one
could check that what one wrote is really what one meant.  I'm probably not
going to get around to writing that anytime soon, but maybe someone else ...
though it would be really useful if $param:q could emit quoting instead of
backslashes.

If anyone feels inspired to tackle the TODOs, go ahead.

Also below is a fix for a rather amusing typo in a comment in _describe.

Index: Completion/Base/_arg_compile
===================================================================
@@ -0,0 +1,199 @@
+#autoload
+
+# A simple compiler for _arguments descriptions.  The first argument of
+# _arg_compile is the name of an array parameter in which the parse is
+# returned.  The remaining arguments form a series of `phrases'.  Each
+# `phrase' begins with one of the keywords "argument", "option", or "help"
+# and consists of a series of keywords and/or values.  The syntax is as
+# free-form as possible, but "argument" phrases generally must appear in
+# the same relative position as the corresponding argument on the command
+# line to be completed, and there are some restrictions on ordering of
+# keywords and values within each phrase.
+#
+# Anything appearing before the first phrase or after the last is passed
+# through verbatim.  (See TODO.)  If more detailed mixing of compiled and
+# uncompiled fragments is necessary, use two or more calls, either with
+# different array names or by passing the output of each previous call
+# through the next.
+#
+# In the documentation below, brackets [ ] indicate optional elements and
+# braces { } indicate elements that may be repeated zero or more times.
+# Except as noted, bracketed or braced elements may appear in any order
+# relative to each other, but tokens within each element are ordered.
+#
+#   argument [POS] [means MSG] [action ACT]
+#
+#     POS may be an integer N for the Nth argument or "*" for all, and
+#      must appear first if it appears at all.
+#     MSG is a string to be displayed above the matches in a listing.
+#     ACT is (currently) as described in the compsys manual.
+#
+#   option OPT [follow HOW] [explain STR] {unless XOR} \
+#    {[means MSG] [action ACT]} [through PAT [means MSG] [action ACT]]
+#
+#     OPT is the option, prefixed with "*" if it may appear more than once.
+#     HOW refers to a following argument, and may be one of:
+#       "close"   must appear in the same word (synonyms "join" or "-")
+#       "next"    the argument must appear in the next word (aka "split")
+#       "loose"   the argument may appear in the same or the next word ("+")
+#       "assign"  as loose, but must follow an "=" in the same word ("=")
+#     HOW should be suffixed with a colon if the following argument is
+#      _not_ required to appear.
+#     STR is to be displayed based on compconfig[describe_options].
+#     XOR is another option in combination with which OPT may not appear.
+#      It may be ":" to disable non-option completions when OPT is present.
+#     MSG is a string to be displayed above the matches in a listing.
+#     ACT is (currently) as described in the compsys manual.
+#     PAT is either "*" for "all remaining words on the line" or a pattern
+#      that, if matched, marks the end of the arguments of this option.
+#      The "through PAT ..." description must be the last.
+#     PAT may be suffixed with one colon to narrow the $words array to
+#      the remainder of the command line, or with two colons to narrow
+#      to the words before (not including) the next that matches PAT.
+#
+#   help PAT [means MSG] action ACT
+#
+#     ACT is applied to any option output by --help that matches PAT.
+#      Do not use "help" with commands that do not support --help.
+#     PAT may be suffixed with a colon if the following argument is
+#      _not_ required to appear (this is usually inferred from --help).
+#     MSG is a string to be displayed above the matches in a listing.
+
+# EXAMPLE:
+# This is from _gprof in the standard distribution.  Note that because of
+# the brace expansion trick used in the "function name" case, no attempt
+# is made to use `phrase' form; that part gets passed through unchanged.
+# It could simply be moved to the _arguments call ahead of "$args[@]".
+#
+# _arg_compile args -s -{a,b,c,D,h,i,l,L,s,T,v,w,x,y,z} \
+#              -{A,C,e,E,f,F,J,n,N,O,p,P,q,Q,Z}:'function name:->funcs' \
+#              option -I means directory action _dir_list \
+#              option -d follow close means "debug level" \
+#              option -k means "function names" action '->pair' \
+#              option -m means "minimum execution count" \
+#              argument means executable action '_files -g \*\(\*\)' \
+#              argument means "profile file" action '_files -g gmon.\*' \
+#              help '*=name*' means "function name" action '->funcs' \
+#              help '*=dirs*' means "directory" action _dir_list
+# _arguments "$args[@]"
+
+# TODO:
+# Verbose forms of various actions, e.g. (but not exactly)
+#   "state foo"                  becomes "->foo"
+#   "completion X explain Y ..." becomes "((X\:Y ...))"
+#   etc.
+# Represent leading "*" in OPT some other way.
+# Represent trailing colons in HOW and PAT some other way.
+# Stricter syntax checking on HOW, sanity checks on XOR.
+# Something less obscure than "unless :" would be nice.
+# Warning or other syntax check for stuff after the last phrase.
+
+emulate -L zsh
+local -h argspec dspec helpspec prelude xor
+local -h -A amap dmap safe
+
+[[ -n "$1" ]] || return 1
+[[ ${(tP)${1}} = *-local ]] && { print -R NAME CONFLICT: $1 1>&2; return 1 }
+safe[reply]="$1"; shift
+
+# First consume and save anything before the argument phrases
+
+helpspec=()
+prelude=()
+
+while (($#))
+do
+  case $1 in
+  (argument|help|option) break;;
+  (*) prelude=("$prelude[@]" "$1"); shift;;
+  esac
+done
+
+# Consume all the argument phrases and build the argspec array
+
+while (($#))
+do
+  amap=()
+  dspec=()
+  case $1 in
+
+  # argument [POS] [means MSG] [action ACT]
+  (argument)
+    shift
+    while (($#))
+    do
+      case $1 in
+      (<1->|\*) amap[position]="$1"; shift;;
+      (means|action) amap[$1]="$2"; shift 2;;
+      (argument|option|help) break;;
+      (*) print -R SYNTAX ERROR at "$@" 1>&2; return 1;;
+      esac
+    done
+    if (( $#amap ))
+    then
+      argspec=("$argspec[@]" "${amap[position]}:${amap[means]}:${amap[action]}")
+    fi;;
+
+  # option OPT [follow HOW] [explain STR] {unless XOR} \
+  #  {[through PAT] [means MSG] [action ACT]}
+  (option)
+    amap[option]="$2"; shift 2
+    dmap=()
+    xor=()
+    while (( $# ))
+    do
+      (( ${+amap[$1]} || ${+dmap[through]} )) && break;
+      case $1 in
+      (follow)
+	amap[follow]="${2:s/join/-/:s/close/-/:s/next//:s/split//:s/loose/+/:s/assign/=/:s/none//}"
+	shift 2;;
+      (explain) amap[explain]="[$2]" ; shift 2;;
+      (unless) xor=("$xor[@]" "${(@)=2}"); shift 2;;
+      (through|means|action)
+	while (( $# ))
+	do
+	  (( ${+dmap[$1]} )) && break 2
+	  case $1 in
+	  (through|means|action) dmap[$1]=":${2}"; shift 2;;
+	  (argument|option|help|follow|explain|unless) break;;
+	  (*) print -R SYNTAX ERROR at "$@" 1>&2; return 1;;
+	  esac
+	done;;
+      (argument|option|help) break;;
+      (*) print -R SYNTAX ERROR at "$@" 1>&2; return 1;;
+      esac
+      if (( $#dmap ))
+      then
+	dspec=("$dspec[@]" "${dmap[through]}${dmap[means]:-:}${dmap[action]:-:}")
+      fi
+    done
+    if (( $#amap ))
+    then
+      argspec=("$argspec[@]" "${xor:+($xor)}${amap[option]}${amap[follow]}${amap[explain]}${dspec}")
+    fi;;
+
+  # help PAT [means MSG] action ACT
+  (help)
+    amap[pattern]="$2"; shift 2
+    while (($#))
+    do
+      (( ${+amap[$1]} )) && break;
+      case $1 in
+      (means|action) amap[$1]="$2"; shift 2;;
+      (argument|option|help) break;;
+      (*) print -R SYNTAX ERROR at "$@" 1>&2; return 1;;
+      esac
+    done
+    if (( $#amap ))
+    then
+      helpspec=("$helpspec[@]" "${amap[pattern]}:${amap[means]}:${amap[action]}")
+    fi;;
+  (*) break;;
+  esac
+done
+
+eval $safe[reply]'=( "${prelude[@]}" "${argspec[@]}" ${helpspec:+"-- ${helpspec[@]}"} "$@" )'
+
+# print -R _arguments "${prelude[@]:q}" "${argspec[@]:q}" ${helpspec:+"-- ${helpspec[@]:q}"} "$@:q"
+
+return 0
Index: Completion/Base/_describe
===================================================================
@@ -24,7 +24,7 @@
 
 if [[ -n "$isopt" ]]; then
 
-  # We take the value to test the number of patches from a non-local
+  # We take the value to test the number of matches from a non-local
   # parameter `nm' if that exists and contains only digits. It's a hack.
 
   if [[ "$nm" = [0-9]## ]]; then

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


             reply	other threads:[~1999-09-19 22:58 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-09-19 22:57 Bart Schaefer [this message]
1999-09-20  8:43 Sven Wischnowsky
1999-09-20 12:15 ` PATCH: was: " Sven Wischnowsky
1999-09-20 16:36   ` Bart Schaefer
1999-09-23  1:39 ` Tanaka Akira
1999-09-20 12:57 Sven Wischnowsky
1999-09-21  7:15 Sven Wischnowsky
1999-09-23  9:13 Sven Wischnowsky
1999-09-23 13:57 ` Tanaka Akira
1999-09-23 10:28 Sven Wischnowsky
1999-09-23 14:12 ` Tanaka Akira
1999-09-23 15:12   ` Bart Schaefer
1999-09-25  2:53     ` Tanaka Akira
1999-09-23 14:07 Sven Wischnowsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=990919225746.ZM8479@candle.brasslantern.com \
    --to=schaefer@candle.brasslantern.com \
    --cc=zsh-workers@sunsite.auc.dk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).