Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: _user_expand completer



_user_expand is a new completer which allows you to define expansions of
your own.  Effectively they're a sort of abbreviation, but you have the
full power of the completion system in handling multiple expansions.
Most of the code is directly ripped off from _expand.

Simple example:

<add _user_expand to completers---after _expand is the obvious place>
typeset -gA my_ips
my_ips=(
  darth 192.168.135.2
  dean 10.104.10.123
  dash-lab-pc15 10.99.11.102
)
zstyle ':completion:*' user-expand '$my_ips'

Now "darth" expands to its IP address.  Not a great example, I might
just as well use a parameter for that (and the IP address is years out
of date anyway since I never use it and it's now in the DNS but you
don't know that).

There are all sorts of possible enhancements, for example delimiting
parts of a word to be expanded, but I'll see if it turns out to be
useful first.

The tt(bashcompinit) documentation looked a bit forlorn at the end of
the list of completers.  I've moved it up to where initialisaion
functions are documented.

Index: Completion/Base/Completer/.distfiles
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/Completer/.distfiles,v
retrieving revision 1.1
diff -u -r1.1 .distfiles
--- Completion/Base/Completer/.distfiles	2 Apr 2001 12:42:26 -0000	1.1
+++ Completion/Base/Completer/.distfiles	25 Mar 2009 13:06:19 -0000
@@ -1,6 +1,17 @@
 DISTFILES_SRC='
 .distfiles
-_all_matches   _correct       _history       _match         _prefix
-_approximate   _expand        _ignored       _menu
-_complete      _expand_alias  _list          _oldlist
+_all_matches
+_approximate
+_complete
+_correct
+_expand
+_expand_alias
+_history
+_ignored
+_list
+_match
+_menu
+_oldlist
+_prefix
+_user_expand
 '
Index: Completion/Base/Completer/_user_expand
===================================================================
RCS file: Completion/Base/Completer/_user_expand
diff -N Completion/Base/Completer/_user_expand
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Completion/Base/Completer/_user_expand	25 Mar 2009 13:06:20 -0000
@@ -0,0 +1,141 @@
+#autoload
+
+# This completer function is an addition to the _expand completer that
+# allows the user to define their own expansions.  It does not replace
+# the _expand completer.
+#
+# This function will allow other completer functions to be called if
+# the expansions done produce no result or do not change the original
+# word from the line.
+
+setopt localoptions nonomatch
+
+[[ _matcher_num -gt 1 ]] && return 1
+
+local exp word sort expr expl subd suf=" " asp tmp spec
+local -a specs reply
+
+if [[ "$funcstack[2]" = _prefix ]]; then
+  word="$IPREFIX$PREFIX$SUFFIX"
+else
+  word="$IPREFIX$PREFIX$SUFFIX$ISUFFIX"
+fi
+
+# In exp we will collect the expansions.
+
+exp=("$word")
+
+# Now look for user completions.
+
+zstyle -a ":completion:${curcontext}" user-expand specs || return 1
+
+for spec in $specs; do
+  case $spec in
+    ('$'[[:IDENT:]]##)
+    # Spec is an associative array with explicit keys.
+    # Surely there's a better way of doing an associative array
+    # lookup from its name?
+    eval tmp='${'$spec[2,-1]'[$word]}'
+    if [[ -n $tmp ]]; then
+      exp=("$tmp")
+      break
+    fi
+    ;;
+
+    ('_'*)
+    reply=()
+    $spec $word
+    if (( ${#reply} )); then
+      exp=("${reply[@]}")
+      break
+    fi
+    ;;
+  esac
+done
+
+[[ $#exp -eq 1 && "$exp[1]" = "$word" ]] && return 1
+
+# Now add as matches whatever the user requested.
+
+zstyle -s ":completion:${curcontext}:" sort sort
+
+[[ "$sort" = (yes|true|1|on) ]] && exp=( "${(@o)exp}" )
+
+if zstyle -s ":completion:${curcontext}:" add-space tmp; then
+  if [[ "$tmp" != *subst* || "$word" != *\$* || "$exp[1]" = *\$* ]]; then
+    [[ "$tmp" = *file* ]] && asp=file
+    [[ "$tmp" = *(yes|true|1|on|subst)* ]] && asp="yes$asp"
+  fi
+else
+  asp=file
+fi
+
+# If there is only one expansion, add a suitable suffix
+
+if (( $#exp == 1 )); then
+  if [[ -d ${exp[1]} && "$exp[1]" != */ ]]; then
+    suf=/
+  elif [[ "$asp" = yes* ||
+          ( "$asp" = *file && -f "${exp[1]}" ) ]]; then
+    suf=' '
+  else
+    suf=
+  fi
+fi
+
+if [[ -z "$compstate[insert]" ]] ;then
+  if [[ "$sort" = menu ]]; then
+    _description expansions expl expansions "o:$word"
+  else
+    _description -V expansions expl expansions "o:$word"
+  fi
+
+  compadd "$expl[@]" -UQ -qS "$suf" -a exp
+else
+  _tags all-expansions expansions original
+
+  if [[ $#exp -gt 1 ]] && _requested expansions; then
+    local i j normal space dir
+
+    if [[ "$sort" = menu ]]; then
+      _description expansions expl expansions "o:$word"
+    else
+      _description -V expansions expl expansions "o:$word"
+    fi
+    normal=()
+    space=()
+    dir=()
+
+    for i in "$exp[@]"; do
+      j="${i}"
+      if [[ -d "$j" && "$i" != */ ]]; then
+        dir=( "$dir[@]" "$i" )
+      elif [[ "$asp" = yes* || ( "$asp" = *file && -f "$j" ) ]]; then
+        space=( "$space[@]" "$i" )
+      else
+	normal=( "$normal[@]" "$i" )
+      fi
+    done
+    (( $#dir ))    && compadd "$expl[@]" -UQ -qS/ -a dir
+    (( $#space ))  && compadd "$expl[@]" -UQ -qS " " -a space
+    (( $#normal )) && compadd "$expl[@]" -UQ -qS "" -a normal
+  fi
+  if _requested all-expansions expl 'all expansions'; then
+    local disp dstr
+
+    if [[ "${#${exp}}" -ge COLUMNS ]]; then
+      disp=( -ld dstr )
+      dstr=( "${(r:COLUMNS-5:)exp} ..." )
+    else
+      disp=()
+    fi
+    [[ -o multios ]] && exp=($exp[1] $compstate[redirect]${^exp[2,-1]})
+    compadd "$disp[@]" "$expl[@]" -UQ -qS "$suf" - "$exp"
+  fi
+
+  _requested original expl original && compadd "$expl[@]" -UQ - "$word"
+
+  compstate[insert]=menu
+fi
+
+return 0
Index: Doc/Zsh/compsys.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
retrieving revision 1.219
diff -u -r1.219 compsys.yo
--- Doc/Zsh/compsys.yo	6 Feb 2009 09:59:38 -0000	1.219
+++ Doc/Zsh/compsys.yo	25 Mar 2009 13:06:20 -0000
@@ -202,6 +202,13 @@
 currently named in tt(fpath), set tt(_compdir) to an empty string before
 calling tt(compaudit) or tt(compinit).
 
+findex(bashcompinit)
+The function tt(bashcompinit) compatibility with bash's programmable
+completion system.  When run it will define the functions, tt(compgen) and
+tt(complete) which correspond to the bash builtins with the same names.
+It will then be possible to use completion specifications and functions
+written for bash.
+
 subsect(Autoloaded files)
 cindex(completion system, autoloaded functions)
 
@@ -3096,13 +3103,35 @@
 be moved to the end of the current word before the completion code is
 called and hence there will be no suffix.
 )
-findex(bashcompinit)
-item(tt(bashcompinit))(
-This function provides compatibility with bash's programmable completion
-system.  When run it will define the functions, tt(compgen) and
-tt(complete) which correspond to the bash builtins with the same names.
-It will then be possible to use completion specifications and functions
-written for bash.
+findex(_user_expand)
+item(tt(_user_expand))(
+This completer behaves similarly to the tt(_expand) completer but
+instead performs expansions defined by users.  The styles tt(add-space) and
+tt(sort) styles specific to the tt(_expand) completer are usable with
+tt(_user_expand) in addition to other styles handled more generally by
+the completion system.  The tag tt(all-expansions) is also available.
+
+The expansion depends on the array style tt(user-expand) being defined
+for the current context; remember that the context for completers is less
+specific than that for contextual completion as the full context has not
+yet been determined.  Elements of the array may have one of the following
+forms:
+startsitem()
+sitem(tt($)var(hash))(
+var(hash) is the name of an associative array.  Note this is not a full
+parameter expression, merely a tt($), suitably quoted to prevent immediate
+expansion, followed by the name of an associative array.  If the trial
+expansion word matches a key in var(hash), the resulting expansion is the
+corresponding value.
+)
+sitem(var(_func))(
+var(_func) is the name of a shell function whose name must begin with
+tt(_) but is not otherwise special to the completion system.  The function
+is called with the trial word as an argument.  If the word is to be
+expanded, the function should set the array tt(reply) to a list of
+expansions.  The return status of the function is irrelevant.
+)
+endsitem()
 )
 enditem()
 


-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070



Messages sorted by: Reverse Date, Date, Thread, Author