about summary refs log tree commit diff
path: root/Completion/Core/compinit
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Core/compinit')
-rw-r--r--Completion/Core/compinit427
1 files changed, 331 insertions, 96 deletions
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index ec5867838..6a35d17a7 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -1,25 +1,23 @@
 # Initialisation for new style completion. This mainly contains some helper
-# function and aliases. Everything else is split into different files in this
-# directory that will automatically be made autoloaded (see the end of this
-# file).
+# functions and aliases. Everything else is split into different files that
+# will automatically be made autoloaded (see the end of this file).
 # The names of the files that will be considered for autoloading have to
-# start with a underscores (like `_setopt).
+# start with an underscores (like `_setopt').
 # The first line of these files will be read and has to say what should be
 # done with its contents:
 #
-#   `#defcomp <names ...>'
-#     if the first line looks like this, the file is
-#     autoloaded as a function and that function will
-#     be called to generate the matches when completing
-#     for one of the commands whose <name> is given
+#   `#compdef <names ...>'
+#     If the first line looks like this, the file is autoloaded as a
+#     function and that function will be called to generate the matches
+#     when completing for one of the commands whose <names> are given.
 #
-#   `#defpatcomp <pattern>'
-#     this defines a function that should be called to generate
-#     matches for commands whose name matches <pattern>; note
-#     that only one pattern may be given
+#   `#compdef -p <pattern>'
+#     This defines a function that should be called to generate matches
+#     for commands whose name matches <pattern>. Note that only one pattern
+#     may be given.
 #
-#   `#defkeycomp <style> [ <key-sequence> ... ]
-#     this is used to bind special completions to all the given
+#   `#compdef -k <style> [ <key-sequence> ... ]'
+#     This is used to bind special completions to all the given
 #     <key-sequence>(s). The <style> is the name of one of the built-in
 #     completion widgets (complete-word, delete-char-or-list,
 #     expand-or-complete, expand-or-complete-prefix, list-choices,
@@ -29,35 +27,89 @@
 #     rather than by the context.  The widget has the same name as
 #     the autoload file and can be bound using bindkey in the normal way.
 #
-#   `#autoload'
-#     this is for helper functions that are not used to
+#   `#compdef -K <widget-name> <style> <key-sequence> [ ... ]'
+#     This is similar to -k, except it takes any number of sets of
+#     three arguments.  In each set, the widget <widget-name> will
+#     be defined, which will behave as <style>, as with -k, and will
+#     be bound to <key-sequence>, exactly one of which must be defined.
+#     <widget-name> must be different for each:  this must begin with an
+#     underscore, else one will be added, and should not clash with other
+#     completion widgets (names based on the name of the function are the
+#     clearest), but is otherwise arbitrary.  It can be tested in the
+#     function by the parameter $WIDGET.
+#
+#   `#autoload [ <options> ]'
+#     This is for helper functions that are not used to
 #     generate matches, but should automatically be loaded
-#     when they are called
+#     when they are called. The <options> will be given to the
+#     autoload builtin when making the function autoloaded. Note
+#     that this need not include `-U'.
 #
 # Note that no white space is allowed between the `#' and the rest of
 # the string.
 #
-# See the file `compdump' for how to speed up initialiation.
-#
-# If you are using global matching specifications with `compctl -M ...'
-# have a look at the files `_match_test' and `_match_pattern'. To make
-# all the example functions use matching as specified with `-M' these
-# need some editing.
+# Functions that are used to generate matches should return zero if they
+# were able to add matches and non-zero otherwise.
 #
+# See the file `compdump' for how to speed up initialisation.
+
 # If we got the `-d'-flag, we will automatically dump the new state (at
-# the end).
+# the end).  This takes the dumpfile as an argument.  -d (with the
+# default dumpfile) is now the default; to turn off dumping use -D.
+
+emulate -L zsh
+setopt extendedglob
+
+typeset _i_dumpfile _i_files _i_line _i_done _i_dir _i_autodump=1
+typeset _i_tag _i_file _i_addfiles
+
+while [[ $# -gt 0 && $1 = -[dDf] ]]; do
+  if [[ "$1" = -d ]]; then
+    _i_autodump=1
+    shift
+    if [[ $# -gt 0 && "$1" != -[df] ]]; then
+      _i_dumpfile="$1"
+      shift
+    fi
+  elif [[ "$1" = -D ]]; then
+    _i_autodump=0
+    shift
+  elif [[ "$1" = -f ]]; then
+    # Not used any more; use _compdir
+    shift
+    shift
+  fi
+done
 
-if [[ "$1" = -d ]]; then
-  _i_autodump=1
+# The associative array containing the definitions for the commands.
+# Definitions for patterns will be stored in the associations `_patcomps'
+# and `_postpatcomps'. `_compautos' contains the names and options
+# for autoloaded functions that get options.
+
+typeset -gA _comps _patcomps _postpatcomps _compautos
+
+# The associative array use to report information about the last
+# cmpletion to the outside.
+
+typeset -gA _lastcomp
+
+# Remember dumpfile.
+if [[ -n $_i_dumpfile ]]; then
+  # Explicitly supplied dumpfile.
+  _comp_dumpfile="$_i_dumpfile"
 else
-  _i_autodump=0
+  _comp_dumpfile="${ZDOTDIR:-$HOME}/.zcompdump"
 fi
 
-# The associative array containing the definitions for the commands.
-# Definitions for patterns will be stored in the normal array `_patcomps'.
+# These can hold names of functions that are to be called before/after all
+# matches have been generated.
 
-typeset -A _comps
-_patcomps=()
+compprefuncs=()
+comppostfuncs=()
+
+# Loading it now ensures that the `funcstack' parameter is always correct.
+
+: $funcstack
 
 # This function is used to register or delete completion functions. For
 # registering completion functions, it is invoked with the name of the
@@ -70,6 +122,9 @@ _patcomps=()
 # function will be invoked when completing for a command whose name 
 # matches the pattern given as argument after the function name (in this
 # case only one argument is accepted).
+# The option `-P' is like `-p', but the function will be called after
+# trying to find a function defined for the command on the line if no
+# such function could be found.
 # With the `-k' option a function for a special completion keys is 
 # defined and immediatly bound to those keys. Here, the extra arguments
 # are the name of one of the builtin completion widgets and any number
@@ -78,7 +133,8 @@ _patcomps=()
 # whose name is given as the first argument be autoloaded. When defining
 # a function for command names the `-n' option may be given and keeps
 # the definitions from overriding any previous definitions for the
-# commands.
+# commands; with `-k', the `-n' option prevents compdef from rebinding
+# a key sequence which is already bound.
 # For deleting definitions, the `-d' option must be given. Without the
 # `-p' option, this deletes definitions for functions for the commands
 # whose names are given as arguments. If combined with the `-p' option
@@ -110,11 +166,16 @@ compdef() {
 
   # Get the options.
 
-  while getopts "anpkd" opt; do
+  if [[ $#* -eq 0 ]]; then
+    echo "compdef needs parameters"
+    return 1
+  fi
+  
+  while getopts "anpPkKd" opt; do
     case "$opt" in
     a)    autol=yes;;
     n)    new=yes;;
-    [pk]) if [[ -n "$type" ]]; then
+    [pPkK]) if [[ -n "$type" ]]; then
             # Error if both `-p' and `-k' are given (or one of them
 	    # twice).
             echo "$0: type already set to $type"
@@ -122,6 +183,10 @@ compdef() {
 	  fi
 	  if [[ "$opt" = p ]]; then
 	    type=pattern
+	  elif [[ "$opt" = P ]]; then
+	    type=postpattern
+	  elif [[ "$opt" = K ]]; then
+	    type=widgetkey
 	  else
 	    type=key
 	  fi
@@ -131,12 +196,17 @@ compdef() {
   done
   shift OPTIND-1
 
+  if [[ $#* -eq 0 ]]; then
+    echo "compdef needs parameters"
+    return 1
+  fi
+  
   if [[ -z "$delete" ]]; then
     # Adding definitions, first get the name of the function name
     # and probably do autoloading.
 
     func="$1"
-    [[ -n "$autol" ]] && autoload "$func"
+    [[ -n "$autol" ]] && autoload -U "$func"
     shift
 
     case "$type" in
@@ -145,11 +215,33 @@ compdef() {
         echo "$0: only one pattern allowed"
 	return 1
       fi
-      # Patterns are stored in strings like `c* foo', with a space
-      # between the pattern and the function name.
-
-      _patcomps=("$_patcomps[@]" "$1 $func")
+      _patcomps[$1]="$func"
       ;;
+    postpattern)
+      if [[ $# -gt 1 ]]; then
+        echo "$0: only one pattern allowed"
+	return 1
+      fi
+      _postpatcomps[$1]="$func"
+      ;;
+    widgetkey)
+      while [[ -n $1 ]]; do
+	if [[ $# -lt 3 ]]; then
+	  echo "$0: compdef -K requires <widget> <comp-widget> <key>"
+	  return 1
+	fi
+	[[ $1 = _* ]] || 1="_$1"
+	[[ $2 = .* ]] || 2=".$2"
+	zle -C "$1" "$2" "$func"
+	if [[ -n $new ]]; then
+	  bindkey "$3" | read -A opt
+	  [[ $opt[-1] = undefined-key ]] && bindkey "$3" "$1"
+	else
+	  bindkey "$3" "$1"
+	fi
+	shift 3
+      done
+      ;;	 
     key)
       if [[ $# -lt 2 ]]; then
         echo "$0: missing keys"
@@ -157,30 +249,44 @@ compdef() {
       fi
 
       # Define the widget.
-      zle -C "$func" "$1" "$func"
+      if [[ $1 = .* ]]; then
+	zle -C "$func" "$1" "$func"
+      else
+	zle -C "$func" ".$1" "$func"
+      fi
       shift
 
       # And bind the keys...
       for i; do
+        if [[ -n $new ]]; then
+	   bindkey "$i" | read -A opt
+	   [[ $opt[-1] = undefined-key ]] || continue
+	fi
         bindkey "$i" "$func"
       done
       ;;
     *)
       # For commands store the function name in the `_comps'
       # associative array, command names as keys.
-      for i; do
-        [[ -z "$new" || "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
-      done
+      if [[ -z "$new" ]]; then
+	for i; do
+	  _comps[$i]="$func"
+	done
+      else
+        for i; do
+          [[ "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
+        done
+      fi
       ;;
     esac
   else
     # Handle the `-d' option, deleting.
     case "$type" in
     pattern)
-      # Note the space.
-      for i; do
-        _patcomps=("${(@)patcomps:#$i *}")
-      done
+      unset "_patcomps[$^@]"
+      ;;
+    postpattern)
+      unset "_postpatcomps[$^@]"
       ;;
     key)
       # Oops, cannot do that yet.
@@ -189,81 +295,210 @@ compdef() {
       return 1
       ;;
     *)
-      # Deleting definitons for command is even simpler.
-      for i; do
-        unset "_comps[$i]"
-      done
+      unset "_comps[$^@]"
     esac
   fi
 }
 
-# Now we automatically make the definition files autoloaded.
+# Do *not* use this...
 
-# First we get the name of a dump file if this will be used.
+compconf() {
 
-: ${COMPDUMP:=$0.dump}
+  local style name val i tmp cmt
 
-if [[ ! -o extendedglob ]]; then
-  _i_noextglob=yes
-  setopt extendedglob
-fi
+  if [[ -z "$_compconf_warn" ]]; then
+    _compconf_warn=yep
+
+    print "
+
+Hello
+
+\`compconf' will be removed in the near future, we now use a more
+general (and powerful) mechanism using the \`zstyle' builtin. An
+approximation to your old setup using \`zstyle' should be available
+in the file:
+
+    \`${HOME}/.zsh-styles'
+
+Note that the values for the styles may be partly incorrect. Please
+read the manual to find out how to configure the completion system
+with styles.
+
+Have fun
+
+   Sven
+" 1>&2
+    command rm -f ${HOME}/.zsh-styles
+  fi
+
+  for i; do
+    name="${i%%\=*}"
+    val="${i#*\=}"
+
+    tmp=''
+    cmt=''
+
+    case "$name" in
+    urls_path)
+      tmp="'*:urls' path ${(qq)val}"
+      ;;
+    urls_localhttp)
+      tmp="'*:urls' local ${${(qqs.:.)val}}"
+      ;;
+    describe_options)
+      tmp="'*:options' verbose 'yes'"
+      ;;
+    describe_values)
+      tmp="'*:values' verbose 'yes'"
+      ;;
+    autodescribe_options)
+      tmp="'*:options' auto-description ${(qq)val}"
+      ;;
+    description_format)
+      tmp="'*:descriptions' format ${(qq)val}"
+      ;;
+    message_format)
+      tmp="'*:messages' format ${(qq)val}"
+      ;;
+    warning_format)
+      tmp="'*:warnings' format ${(qq)val}"
+      ;;
+    option_prefix)
+      tmp="'*:options' prefix-needed yes"
+      [[ "$val" = hide* ]] &&
+          tmp="$tmp
+zstyle ':completion:*:options' prefix-hidden yes"
+      ;;    
+    group_matches)
+      tmp="'*' group-name ''"
+      ;;
+    colors_path)
+      tmp="'*:colors' path ${(qq)val}"
+      ;;
+    path_expand)
+      tmp="'*:paths' expand ${(qq)val}"
+      ;;
+    path_cursor)
+      tmp="'*:paths' cursor ${(qq)val}"
+      ;;
+    (approximate|incremental|predict|list|oldlist|match)_*)
+      tmp="'*${name%%_*}:*' ${${name#*_}//_/-} ${(qq)val}"
+      ;;
+    correct_*)
+      cmt="# This one is a bit ugly. You may want to use only \`*:correct'
+# if you also have the \`correctword_*' or \`approximate_*' keys.
+"
+      tmp="'*(correct(|-word)|approximate):*' ${name#*_} ${(qq)val}"
+      ;;
+    correctword_*)
+      tmp="'*:correct-word' ${name#correctword_} ${(qq)val}"
+      ;;
+    expand_*)
+      cmt="# This one is a bit ugly. You may want to use only \`*:expand'
+# if you also have the \`expandword_*' keys.
+"
+      tmp="'*expand(|expand-word):*' ${name#*_} ${(qq)val}"
+      ;;
+    expandword_*)
+      tmp="'expand-word:*' ${name#expandword_} ${(qq)val}"
+      ;;
+    history_*)
+      tmp="'history-words:*' ${name#history_} ${(qq)val}"
+      ;;
+    completer)
+      tmp="'*' completer ${${(qqs.:.)val}}"
+      ;;
+    last_prompt)
+      tmp="'*' last-prompt 'yes'"
+      ;;
+    esac
+    [[ -n "$tmp" ]] && style="${style}${cmt}zstyle :completion:${tmp}
+"
+  done
+
+  eval "${style}"
+
+  print "$style" >>! ${HOME}/.zsh-styles
+}
+
+# Now we automatically make the definition files autoloaded.
 
 typeset -U _i_files
-_i_files=( ${^~fpath}/_*~*~(N:t) )
-_i_initname=$0
+_i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
+if [[ $#_i_files -lt 20 || $_compdir = */Core || -d $_compdir/Core ]]; then
+  # Too few files:  we need some more directories,
+  # or we need to check that all directories (not just Core) are present.
+  if [[ -n $_compdir ]]; then
+    _i_addfiles=()
+    if [[ $_compdir = */Core ]]; then
+      # Add all the Completion subdirectories
+      _i_addfiles=(${_compdir:h}/*(/))
+    elif [[ -d $_compdir/Core ]]; then
+      # Likewise
+      _i_addfiles=(${_compdir}/*(/))
+    fi
+    for _i_line in {1..$#i_addfiles}; do
+      _i_file=${_i_addfiles[$_i_line]}
+      [[ -d $_i_file && -z ${fpath[(r)$_i_file]} ]] ||
+        _i_addfiles[$_i_line]=
+    done
+    fpath=($fpath $_i_addfiles)
+    _i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N:t) )
+  fi
+fi
+
+
+# Rebind the standard widgets
+for _i_line in complete-word delete-char-or-list expand-or-complete \
+  expand-or-complete-prefix list-choices menu-complete \
+  menu-expand-or-complete reverse-menu-complete; do
+  zle -C $_i_line .$_i_line _main_complete
+done
+zle -la menu-select && zle -C menu-select .menu-select _main_complete
+
 _i_done=''
 
+# Make sure compdump is available, even if we aren't going to use it.
+autoload -U compdump compinstall
+
 # If we have a dump file, load it.
 
-if [[ -f "$COMPDUMP" ]]; then
-  read -rA _i_line < "$COMPDUMP"
+if [[ -f "$_comp_dumpfile" ]]; then
+  read -rA _i_line < "$_comp_dumpfile"
   if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files ]]; then
-    builtin . "$COMPDUMP"
+    builtin . "$_comp_dumpfile"
     _i_done=yes
   fi
-  unset _i_line
 fi
 if [[ -z "$_i_done" ]]; then
   for _i_dir in $fpath; do
     [[ $_i_dir = . ]] && continue
-    for _i_file in $_i_dir/_*~*~(N); do
+    for _i_file in $_i_dir/^([^_]*|*~|*.zwc)(N); do
       read -rA _i_line < $_i_file
       _i_tag=$_i_line[1]
       shift _i_line
-      if [[ $_i_tag = '#defcomp' ]]; then
-        compdef -na "${_i_file:t}" "${_i_line[@]}"
-      elif [[ $_i_tag = '#defpatcomp' ]]; then
-        compdef -pa "${_i_file:t}" "${_i_line[@]}"
-      elif [[ $_i_tag = '#defkeycomp' ]]; then
-        compdef -ka "${_i_file:t}" "${_i_line[@]}"
-      elif [[ $_i_tag = '#autoload' ]]; then
-	autoload ${_i_file:t}
-      fi
+      case $_i_tag in
+      (\#compdef)
+	if [[ $_i_line[1] = -[pPkK](n|) ]]; then
+	  compdef ${_i_line[1]}na "${_i_file:t}" "${(@)_i_line[2,-1]}"
+	else
+	  compdef -na "${_i_file:t}" "${_i_line[@]}"
+	fi
+	;;
+      (\#autoload)
+	autoload -U "$_i_line[@]" ${_i_file:t}
+	[[ "$_i_line" != \ # ]] && _compautos[${_i_file:t}]="$_i_line"
+	;;
+      esac
     done
   done
 
-  bindkey |
-    while read -rA _i_line; do
-      if [[ "$_i_line[2]" = complete-word ||
-	"$_i_line[2]" = delete-char-or-list ||
-	"$_i_line[2]" = expand-or-complete ||
-	"$_i_line[2]" = expand-or-complete-prefix ||
-	"$_i_line[2]" = list-choices ||
-	"$_i_line[2]" = menu-complete ||
-	"$_i_line[2]" = menu-expand-or-complete ||
-	"$_i_line[2]" = reverse-menu-complete ]]; then
-	zle -C _complete_$_i_line[2] $_i_line[2] _main_complete
-	bindkey "${_i_line[1][2,-2]}" _complete_$_i_line[2]
-      fi
-    done
-
-  unset _i_dir _i_line _i_file _i_tag
-
   # If autodumping was requested, do it now.
 
-  (( _i_autodump )) && builtin . ${_i_initname:h}/compdump
+  if [[ $_i_autodump = 1 ]]; then
+    compdump
+  fi
 fi
 
-[[ -z "$_i_noextglob" ]] || unsetopt extendedglob
-
-unset _i_files _i_initname _i_done _i_autodump _i_noextglob
+unfunction compinit
+autoload -U compinit