about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-04-15 18:15:04 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-04-15 18:15:04 +0000
commitba4f5e80ec9d7e145718e79fed6e57a852c86c12 (patch)
treeae29f2dfb81bb4e20b015610d85ce5f5a2d96eda
parent850fb2e7f94b4e0e9fbf3538ad9e3c44c9fed74b (diff)
downloadzsh-3.1.5-pws-8.tar.gz
zsh-3.1.5-pws-8.tar.xz
zsh-3.1.5-pws-8.zip
zsh-3.1.5-pws-8 zsh-3.1.5-pws-8
-rw-r--r--Config/defs.mk1
-rw-r--r--Config/version.mk4
-rw-r--r--Doc/Zsh/builtins.yo10
-rw-r--r--Doc/Zsh/compctl.yo8
-rw-r--r--Doc/Zsh/guide.yo2
-rw-r--r--Doc/Zsh/params.yo81
-rw-r--r--Doc/Zsh/zle.yo15
-rw-r--r--Doc/zmacros.yo2
-rw-r--r--Functions/Completion/.distfiles11
-rw-r--r--Functions/Completion/__aliases2
-rw-r--r--Functions/Completion/__arrays2
-rw-r--r--Functions/Completion/__autoload2
-rw-r--r--Functions/Completion/__bg_jobs2
-rw-r--r--Functions/Completion/__bindkey7
-rw-r--r--Functions/Completion/__builtin7
-rw-r--r--Functions/Completion/__cd3
-rw-r--r--Functions/Completion/__command7
-rw-r--r--Functions/Completion/__command_names2
-rw-r--r--Functions/Completion/__compress3
-rw-r--r--Functions/Completion/__condition10
-rw-r--r--Functions/Completion/__configure11
-rw-r--r--Functions/Completion/__dd13
-rw-r--r--Functions/Completion/__default13
-rw-r--r--Functions/Completion/__dirs3
-rw-r--r--Functions/Completion/__disable6
-rw-r--r--Functions/Completion/__dvi3
-rw-r--r--Functions/Completion/__echotc2
-rw-r--r--Functions/Completion/__enable6
-rw-r--r--Functions/Completion/__fc7
-rw-r--r--Functions/Completion/__files10
-rw-r--r--Functions/Completion/__find24
-rw-r--r--Functions/Completion/__functions2
-rw-r--r--Functions/Completion/__gunzip3
-rw-r--r--Functions/Completion/__gzip3
-rw-r--r--Functions/Completion/__hash13
-rw-r--r--Functions/Completion/__hosts2
-rw-r--r--Functions/Completion/__jobs2
-rw-r--r--Functions/Completion/__kill8
-rw-r--r--Functions/Completion/__kill_helper3
-rw-r--r--Functions/Completion/__limits2
-rw-r--r--Functions/Completion/__main_complete48
-rw-r--r--Functions/Completion/__main_key_complete6
-rw-r--r--Functions/Completion/__make3
-rw-r--r--Functions/Completion/__man11
-rw-r--r--Functions/Completion/__mh70
-rw-r--r--Functions/Completion/__most_recent_file2
-rw-r--r--Functions/Completion/__normal54
-rw-r--r--Functions/Completion/__path_files272
-rw-r--r--Functions/Completion/__pdf3
-rw-r--r--Functions/Completion/__precommand15
-rw-r--r--Functions/Completion/__ps3
-rw-r--r--Functions/Completion/__rcs9
-rw-r--r--Functions/Completion/__rlogin9
-rw-r--r--Functions/Completion/__sched3
-rw-r--r--Functions/Completion/__set7
-rw-r--r--Functions/Completion/__setopt7
-rw-r--r--Functions/Completion/__source7
-rw-r--r--Functions/Completion/__strip2
-rw-r--r--Functions/Completion/__stty16
-rw-r--r--Functions/Completion/__subscript4
-rw-r--r--Functions/Completion/__tar14
-rw-r--r--Functions/Completion/__tex3
-rw-r--r--Functions/Completion/__trap7
-rw-r--r--Functions/Completion/__uncompress3
-rw-r--r--Functions/Completion/__unhash6
-rw-r--r--Functions/Completion/__unsetopt7
-rw-r--r--Functions/Completion/__vars2
-rw-r--r--Functions/Completion/__vars_eq2
-rw-r--r--Functions/Completion/__wait4
-rw-r--r--Functions/Completion/__which2
-rw-r--r--Functions/Completion/__x_options5
-rw-r--r--Functions/Completion/__xfig3
-rw-r--r--Functions/Completion/__zle7
-rw-r--r--Functions/Completion/__zmodload9
-rw-r--r--Functions/Completion/init253
-rw-r--r--Functions/allopt29
-rw-r--r--Src/Makefile.in8
-rw-r--r--Src/Zle/comp.h5
-rw-r--r--Src/Zle/comp1.c7
-rw-r--r--Src/Zle/compctl.c36
-rw-r--r--Src/Zle/zle_hist.c10
-rw-r--r--Src/Zle/zle_keymap.c4
-rw-r--r--Src/Zle/zle_main.c5
-rw-r--r--Src/Zle/zle_misc.c49
-rw-r--r--Src/Zle/zle_params.c28
-rw-r--r--Src/Zle/zle_refresh.c12
-rw-r--r--Src/Zle/zle_tricky.c115
-rw-r--r--Src/Zle/zle_vi.c5
-rw-r--r--Src/builtin.c6
-rw-r--r--Src/init.c30
-rw-r--r--Src/params.c8
-rw-r--r--Src/signames1.awk19
-rw-r--r--Src/signames2.awk100
-rw-r--r--Src/text.c3
-rw-r--r--Src/utils.c2
-rw-r--r--Src/zsh.mdd9
-rw-r--r--configure.in32
-rw-r--r--patchlist.txt56
98 files changed, 1624 insertions, 149 deletions
diff --git a/Config/defs.mk b/Config/defs.mk
index e0294f0de..65d19313e 100644
--- a/Config/defs.mk
+++ b/Config/defs.mk
@@ -44,6 +44,7 @@ mandir          = @mandir@
 
 # compilation
 CC              = @CC@
+CPP             = @CPP@
 CPPFLAGS        = @CPPFLAGS@
 DEFS            = @DEFS@
 CFLAGS          = @CFLAGS@
diff --git a/Config/version.mk b/Config/version.mk
index ccaf45fae..675dede6e 100644
--- a/Config/version.mk
+++ b/Config/version.mk
@@ -27,5 +27,5 @@
 # This must also serve as a shell script, so do not add spaces around the
 # `=' signs.
 
-VERSION=3.1.5-pws-7
-VERSION_DATE='February 5, 1999'
+VERSION=3.1.5-pws-8
+VERSION_DATE='February 13, 1999'
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 4a86b16de..0b2b9a4f8 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -215,13 +215,19 @@ cindex(compatibility, csh)
 cindex(sh, compatibility)
 cindex(ksh, compatibility)
 cindex(csh, compatibility)
-item(tt(emulate) [ tt(-R) ] {tt(zsh)|tt(sh)|tt(ksh)|tt(csh)})(
+item(tt(emulate) [ tt(-LR) ] {tt(zsh)|tt(sh)|tt(ksh)|tt(csh)})(
 Set up zsh options to emulate the specified shell as much as possible.
 bf(csh) will never be fully emulated.
 If the argument is not one of the shells listed above, tt(zsh)
 will be used as a default.  If the tt(-R) option is given, all options
 are reset to their default value corresponding to the specified emulation
-mode.
+mode, except for certain options describing the interactive
+environment; otherwise, only those options likely to cause portability
+problems in scripts and functions are altered.  If the tt(-L) option
+is given, the option tt(LOCAL_OPTIONS) will be set as well, causing
+the effect of the tt(emulate) command to be local to the immediately
+surrounding shell function, if any; normally this is turned off in all
+emulation modes except tt(ksh).
 )
 findex(enable)
 cindex(enabling commands)
diff --git a/Doc/Zsh/compctl.yo b/Doc/Zsh/compctl.yo
index f29be4731..6a7f19023 100644
--- a/Doc/Zsh/compctl.yo
+++ b/Doc/Zsh/compctl.yo
@@ -11,7 +11,7 @@ list(tt(compctl) [ tt(-CDT) ] var(options) \
   [ tt(PLUS()) var(options) [ tt(-x) ... tt(--) ] ... [tt(PLUS())] ] \
   [ var(command) ... ])
 list(tt(compctl) tt(-M) var(match-specs) ...)
-list(tt(compctl) tt(-L) [ tt(-CDT) ] [ var(command) ... ])
+list(tt(compctl) tt(-L) [ tt(-CDTM) ] [ var(command) ... ])
 list(tt(compctl) tt(PLUS()) var(command) ...)
 endlist()
 
@@ -99,9 +99,9 @@ not tried after the directory name is finished.
 item(tt(-L))(
 lists the existing completion behavior in a manner suitable for
 putting into a start-up script; the existing behavior is not changed.
-Any combination of the above forms may be specified, otherwise all
-defined completions are listed.  Any other flags supplied
-are ignored.
+Any combination of the above forms, or the tt(-M) flag (which must
+follow the tt(-L) flag), may be specified, otherwise all defined
+completions are listed.  Any other flags supplied are ignored.
 )
 item(em(no argument))(
 If no argument is given, tt(compctl) lists all defined completions
diff --git a/Doc/Zsh/guide.yo b/Doc/Zsh/guide.yo
index f54e6bfdb..0fb954e26 100644
--- a/Doc/Zsh/guide.yo
+++ b/Doc/Zsh/guide.yo
@@ -75,9 +75,9 @@ menu(Filename Generation)
 
 Parameters
 
-menu(Local Parameters)
 menu(Array Parameters)
 menu(Positional Parameters)
+menu(Local Parameters)
 menu(Parameters Set By The Shell)
 menu(Parameters Used By The Shell)
 
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index dc7f0b75d..41dd91510 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -28,31 +28,13 @@ Special parameters cannot have their type changed, and they stay special even
 if unset.  `<Z>' indicates that the parameter does not exist when the shell
 initialises in tt(sh) or tt(ksh) emulation mode.
 startmenu()
-menu(Local Parameters)
 menu(Array Parameters)
 menu(Positional Parameters)
+menu(Local Parameters)
 menu(Parameters Set By The Shell)
 menu(Parameters Used By The Shell)
 endmenu()
-texinode(Local Parameters)(Array Parameters)()(Parameters)
-sect(Local Parameters)
-Shell function executions delimit scopes for shell parameters.
-(Parameters are dynamically scoped.)  The tt(typeset) builtin, and its
-alternative forms tt(declare), tt(integer), tt(local) and tt(readonly)
-(but not tt(export)), can be used to declare a parameter as being local
-to the innermost scope.  Note that em(special) parameters cannot be made
-local.
-
-When a parameter is read or assigned to, the
-innermost existing parameter of that name is used.  (That is, the
-local parameter hides any less-local parameter.)  However, assigning
-to a non-existent parameter, or declaring a new parameter with tt(export),
-causes it to be created in the em(outer)most scope.
-
-Local parameters disappear when their scope ends.
-tt(unset) can be used to delete a parameter while it is still in scope;
-any outer parameter of the same name remains hidden.
-texinode(Array Parameters)(Positional Parameters)(Local Parameters)(Parameters)
+texinode(Array Parameters)(Positional Parameters)()(Parameters)
 sect(Array Parameters)
 The value of an array parameter may be assigned by writing:
 
@@ -65,7 +47,10 @@ interpreted as alternating keys and values:
 
 nofill(var(name)tt(=LPAR())var(key) var(value) ...tt(RPAR()))
 
-Every var(key) must have a var(value) in this case.
+Every var(key) must have a var(value) in this case.  To create an empty
+array or associative array, use:
+
+nofill(var(name)tt(=LPAR()RPAR()))
 
 Individual elements of an array may be selected using a
 subscript.  A subscript of the form `tt([)var(exp)tt(])'
@@ -108,7 +93,14 @@ work, the subscript otherwise not being treated specially.
 If a subscript is used on the left side of an assignment the selected
 element or range is replaced by the expression on the right side.  An
 array (but not an associative array) may be created by assignment to a
-range or element.
+range or element.  Arrays do not nest, so assigning a parenthesized list
+of values to an element or range changes the number of elements in the
+array, shifting the other elements to accomodate the new values.  (This
+is not supported for associative arrays.)
+
+To delete an element of an ordinary array, assign `tt(LPAR()RPAR())' to
+that element.
+To delete an element of an associative array, use the tt(unset) command.
 
 If the opening bracket or the comma is directly followed by an opening
 parentheses the string up to the matching closing one is considered to
@@ -164,17 +156,46 @@ the var(n)th or var(n)th last match (if var(expr) evaluates to
 var(n)).  This flag is ignored when the array is associative.
 )
 enditem()
-texinode(Positional Parameters)(Parameters Set By The Shell)(Array Parameters)(Parameters)
+texinode(Positional Parameters)(Local Parameters)(Array Parameters)(Parameters)
 sect(Positional Parameters)
-Positional parameters are set by the shell on invocation,
-by the tt(set) builtin, or by direct assignment.
+The positional parameters provide access to the command-line arguments
+of a shell function, shell script, or the shell itself; see
+noderef(Invocation), and also noderef(Functions).
 The parameter var(n), where var(n) is a number,
 is the var(n)th positional parameter.
 The parameters tt(*), tt(@) and tt(argv) are
 arrays containing all the positional parameters;
 thus `tt($argv[)var(n)tt(])', etc., is equivalent to simply `tt($)var(n)'.
 
-texinode(Parameters Set By The Shell)(Parameters Used By The Shell)(Positional Parameters)(Parameters)
+Positional parameters may be changed after the shell or function starts by
+using the tt(set) builtin, by assigning to the tt(argv) array, or by direct
+assignment of the form `var(n)tt(=)var(value)' where var(n) is the number of
+the positional parameter to be changed.  This also creates (with empty
+values) any of the positions from 1 to var(n) that do not already have
+values.  Note that, because the positional parameters form an array, an
+array assignment of the form `var(n)tt(=LPAR())var(value) ...tt(RPAR())' is
+allowed, and has the effect of shifting all the values at positions greater
+than var(n) by as many positions as necessary to accomodate the new values.
+
+texinode(Local Parameters)(Parameters Set By The Shell)(Positional Parameters)(Parameters)
+sect(Local Parameters)
+Shell function executions delimit scopes for shell parameters.
+(Parameters are dynamically scoped.)  The tt(typeset) builtin, and its
+alternative forms tt(declare), tt(integer), tt(local) and tt(readonly)
+(but not tt(export)), can be used to declare a parameter as being local
+to the innermost scope.  Note that em(special) parameters cannot be made
+local.
+
+When a parameter is read or assigned to, the
+innermost existing parameter of that name is used.  (That is, the
+local parameter hides any less-local parameter.)  However, assigning
+to a non-existent parameter, or declaring a new parameter with tt(export),
+causes it to be created in the em(outer)most scope.
+
+Local parameters disappear when their scope ends.
+tt(unset) can be used to delete a parameter while it is still in scope;
+any outer parameter of the same name remains hidden.
+texinode(Parameters Set By The Shell)(Parameters Used By The Shell)(Local Parameters)(Parameters)
 sect(Parameters Set By The Shell)
 The following parameters are automatically set by the shell:
 
@@ -206,11 +227,15 @@ An array containing the positional parameters.
 )
 vindex(argv)
 item(tt(argv) <S> <Z>)(
-Same as tt(*).
+Same as tt(*).  Assigning to tt(argv) changes the local positional
+parameters, but tt(argv) is em(not) itself a local parameter.
+Deleting tt(argv) with tt(unset) in any function deletes it everywhere,
+although only the innermost positional parameter array is deleted (so
+tt(*) and tt(@) in other scopes are not affected).
 )
 vindex(@)
 item(tt(@) <S>)(
-Same as tt(argv[@]).
+Same as tt(argv[@]), even when tt(argv) is not set.
 )
 vindex(?)
 item(tt(?) <S>)(
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index fccf538bd..c372c58eb 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -139,6 +139,21 @@ The part of the buffer that lies to the right of the cursor position.
 If it is assigned to, only that part of the buffer is replaced, and the
 cursor remains between the old tt($LBUFFER) and the new tt($RBUFFER).
 )
+vindex(WIDGET)
+item(tt(WIDGET) (scalar))(
+The name of the widget currently being executed.
+)
+vindex(LASTWIDGET)
+item(tt(LASTWIDGET) (scalar))(
+The name of the last widget that was executed.
+)
+vindex(keys)
+item(tt(keys) (array))(
+The keys typed to invoke this widget, one element per
+key. Control-keys are reported with a leading `tt(^)', as in `tt(^A)',
+and meta-keys are repoted with a leading `tt(M-)', as in `tt(M-a)' and 
+`tt(M-^A)'.
+)
 enditem()
 sect(Standard Widgets)
 cindex(widgets, standard)
diff --git a/Doc/zmacros.yo b/Doc/zmacros.yo
index c6df3d551..2bab2cb57 100644
--- a/Doc/zmacros.yo
+++ b/Doc/zmacros.yo
@@ -19,7 +19,7 @@ DEFINEMACRO(redef)(3)(\
 
 DEFINEMACRO(LPAR)(0)(CHAR(40))
 DEFINEMACRO(RPAR)(0)(CHAR(41))
-DEFINEMACRO(PLUS)(0)(CHAR(+))
+DEFINEMACRO(PLUS)(0)(CHAR(43))
 
 DEFINEMACRO(NL)(0)(
 )
diff --git a/Functions/Completion/.distfiles b/Functions/Completion/.distfiles
new file mode 100644
index 000000000..12621da29
--- /dev/null
+++ b/Functions/Completion/.distfiles
@@ -0,0 +1,11 @@
+DISTFILES_SRC='
+    .distfiles
+ __aliases __arrays __autoload __bg_jobs __bindkey __builtin __cd __command
+ __command_names __compress __condition __configure __dd __default __dirs
+ __disable __dvi __echotc __enable __fc __files __find __functions __gunzip
+ __gzip __hash __hosts __jobs __kill __kill_helper __limits __main_complete
+ __main_key_complete __make __man __mh __most_recent_file __normal __path_files
+ __pdf __precommand __ps __rcs __rlogin __sched __set __setopt __source __strip
+ __stty __subscript __tar __tex __trap __uncompress __unhash __unsetopt __vars
+ __vars_eq __wait __which __x_options __xfig __zle __zmodload init 
+'
diff --git a/Functions/Completion/__aliases b/Functions/Completion/__aliases
new file mode 100644
index 000000000..cbf204e51
--- /dev/null
+++ b/Functions/Completion/__aliases
@@ -0,0 +1,2 @@
+#array unalias
+__aliases=(-a)
diff --git a/Functions/Completion/__arrays b/Functions/Completion/__arrays
new file mode 100644
index 000000000..3f6ec8abe
--- /dev/null
+++ b/Functions/Completion/__arrays
@@ -0,0 +1,2 @@
+#array shift
+__arrays=(-A)
diff --git a/Functions/Completion/__autoload b/Functions/Completion/__autoload
new file mode 100644
index 000000000..9c3bb1f4f
--- /dev/null
+++ b/Functions/Completion/__autoload
@@ -0,0 +1,2 @@
+#array autoload
+__autoload=(-s '${^fpath}/*(N:t)')
diff --git a/Functions/Completion/__bg_jobs b/Functions/Completion/__bg_jobs
new file mode 100644
index 000000000..90e3b7ee0
--- /dev/null
+++ b/Functions/Completion/__bg_jobs
@@ -0,0 +1,2 @@
+#array bg
+__bg_jobs=(-z -P '%')
diff --git a/Functions/Completion/__bindkey b/Functions/Completion/__bindkey
new file mode 100644
index 000000000..c9005347a
--- /dev/null
+++ b/Functions/Completion/__bindkey
@@ -0,0 +1,7 @@
+#function bindkey
+
+if [[ -mword 1 -*[DAN]* || -mcurrent -1 -*M ]]; then
+  complist -s '$(bindkey -l)'
+else
+  complist -b
+fi
diff --git a/Functions/Completion/__builtin b/Functions/Completion/__builtin
new file mode 100644
index 000000000..5b4c777f5
--- /dev/null
+++ b/Functions/Completion/__builtin
@@ -0,0 +1,7 @@
+#function builtin
+
+if [[ -position 2 -1 ]]; then
+  compsub
+else
+  complist -eB
+fi
diff --git a/Functions/Completion/__cd b/Functions/Completion/__cd
new file mode 100644
index 000000000..ad5e36386
--- /dev/null
+++ b/Functions/Completion/__cd
@@ -0,0 +1,3 @@
+#function cd
+
+__files -W cdpath -g '*(-/)'
diff --git a/Functions/Completion/__command b/Functions/Completion/__command
new file mode 100644
index 000000000..deaabdb1f
--- /dev/null
+++ b/Functions/Completion/__command
@@ -0,0 +1,7 @@
+#function command
+
+if [[ -position 2 -1 ]]; then
+  compsub
+else
+  complist -em
+fi
diff --git a/Functions/Completion/__command_names b/Functions/Completion/__command_names
new file mode 100644
index 000000000..7a28fa527
--- /dev/null
+++ b/Functions/Completion/__command_names
@@ -0,0 +1,2 @@
+#array --command--
+__command_names=(-c)
diff --git a/Functions/Completion/__compress b/Functions/Completion/__compress
new file mode 100644
index 000000000..d4e71f531
--- /dev/null
+++ b/Functions/Completion/__compress
@@ -0,0 +1,3 @@
+#function compress
+
+__files -g '*~*.Z'
diff --git a/Functions/Completion/__condition b/Functions/Completion/__condition
new file mode 100644
index 000000000..8ceb969b8
--- /dev/null
+++ b/Functions/Completion/__condition
@@ -0,0 +1,10 @@
+#function --condition--
+
+if [[ -current -1 -o ]]; then
+  complist -o -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}'
+elif [[ -current -1 -nt || -current -1 -ot || -current -1 -ef ]]; then
+  files
+else
+  files
+  complist -v
+fi
diff --git a/Functions/Completion/__configure b/Functions/Completion/__configure
new file mode 100644
index 000000000..a4d00e0f2
--- /dev/null
+++ b/Functions/Completion/__configure
@@ -0,0 +1,11 @@
+#function configure
+if [[ $PREFIX = *=* ]]; then
+  # Complete filenames after e.g. --prefix=
+  IPREFIX=${PREFIX%%=*}=
+  PREFIX=${PREFIX#*=}
+  complist -f
+else
+  # Generate a list of options from configure --help
+  complist -s '$($COMMAND --help |
+  sed -n -e '\''s/^ *\(--[-a-z0-9]*\)[    =,].*$/\1/p'\'')'
+fi
diff --git a/Functions/Completion/__dd b/Functions/Completion/__dd
new file mode 100644
index 000000000..c0e04de75
--- /dev/null
+++ b/Functions/Completion/__dd
@@ -0,0 +1,13 @@
+#function dd
+
+if [[ -iprefix conv= ]]; then
+  # If there's a comma present, ignore up to the last one.  The
+  # test alone will have that effect.
+  [[ -string , ]]
+  complist -S, -q \
+  -k '(ascii ebcdic ibm block unblock lcase ucase swab noerror sync)'
+elif [[ -iprefix 'if=' || -iprefix 'of=' ]]; then
+  __files
+else
+  complist -S '=' -k '(if of ibs obs bs cbs skip files seek count conv)'
+fi
diff --git a/Functions/Completion/__default b/Functions/Completion/__default
new file mode 100644
index 000000000..cabe14a36
--- /dev/null
+++ b/Functions/Completion/__default
@@ -0,0 +1,13 @@
+#function --default--
+
+# We first try the `compctl's. This is without first (-T) and default (-D)
+# completion. If you want them add `-T' and/or `-D' to this command.
+# If there is a `compctl' for the command we are working on, we return
+# immediatly. If you want to use new style completion anyway, remove the
+# `|| return'. Also, you may want to use new style completion if the 
+# `compctl' didn't produce any matches. In that case remove the `|| return'
+# and at the line `[[ -nmatches 0 ]] || return' after `compcall'.
+
+compcall || return
+
+__files
diff --git a/Functions/Completion/__dirs b/Functions/Completion/__dirs
new file mode 100644
index 000000000..a838168bc
--- /dev/null
+++ b/Functions/Completion/__dirs
@@ -0,0 +1,3 @@
+#function rmdir df du dircmp
+
+__files -/ '*(-/)'
diff --git a/Functions/Completion/__disable b/Functions/Completion/__disable
new file mode 100644
index 000000000..c56ffb7f7
--- /dev/null
+++ b/Functions/Completion/__disable
@@ -0,0 +1,6 @@
+#function disable
+
+[[ -mcurrent -1 -*a* ]] && complist -ea
+[[ -mcurrent -1 -*f* ]] && complist -eF
+[[ -mcurrent -1 -*r* ]] && complist -ew
+[[ ! -mcurrent -1 -* ]] && complist -eB
diff --git a/Functions/Completion/__dvi b/Functions/Completion/__dvi
new file mode 100644
index 000000000..873d5812a
--- /dev/null
+++ b/Functions/Completion/__dvi
@@ -0,0 +1,3 @@
+#function xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
+
+__files -g '*.(dvi|DVI)'
diff --git a/Functions/Completion/__echotc b/Functions/Completion/__echotc
new file mode 100644
index 000000000..d9b7029c1
--- /dev/null
+++ b/Functions/Completion/__echotc
@@ -0,0 +1,2 @@
+#array echotc
+__echotc=(-k '(al dc dl do le up al bl cd ce cl cr dc dl do ho is le ma nd nl se so up)')
diff --git a/Functions/Completion/__enable b/Functions/Completion/__enable
new file mode 100644
index 000000000..b315611df
--- /dev/null
+++ b/Functions/Completion/__enable
@@ -0,0 +1,6 @@
+#function enable
+
+[[ -mcurrent -1 -*a* ]] && complist -da
+[[ -mcurrent -1 -*f* ]] && complist -dF
+[[ -mcurrent -1 -*r* ]] && complist -dw
+[[ ! -mcurrent -1 -* ]] && complist -dB
diff --git a/Functions/Completion/__fc b/Functions/Completion/__fc
new file mode 100644
index 000000000..9185312b0
--- /dev/null
+++ b/Functions/Completion/__fc
@@ -0,0 +1,7 @@
+#function fc
+
+if [[ -mcurrent -1 -*e ]]; then
+  complist -c
+elif [[ -mcurrent -1 -[ARWI]## ]]; then
+  __files
+fi
diff --git a/Functions/Completion/__files b/Functions/Completion/__files
new file mode 100644
index 000000000..dfade8c7f
--- /dev/null
+++ b/Functions/Completion/__files
@@ -0,0 +1,10 @@
+#helper
+
+# Utility function for completing files of a given type or any file.
+# In many cases you will want to call this one instead of __path_files().
+
+local nm=$NMATCHES
+
+__path_files "$@"
+
+[[ $# -ne 0 && -nmatches nm ]] && __path_files
diff --git a/Functions/Completion/__find b/Functions/Completion/__find
new file mode 100644
index 000000000..b16bb09c7
--- /dev/null
+++ b/Functions/Completion/__find
@@ -0,0 +1,24 @@
+#function find
+
+compsave
+
+if [[ -mbetween -(ok|exec) \\\; ]]; then
+  compsub
+elif [[ -iprefix - ]]; then
+  complist -s 'daystart {max,min,}depth follow noleaf version xdev \
+{a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \
+{i,}{l,}name {no,}{user,group} path perm regex size true uid used \
+exec {f,}print{f,0,} ok prune ls'
+  compreset
+elif [[ -position 1 ]]; then
+  complist -g '. ..'
+  __files -g '(-/)'
+elif [[ -mcurrent -1 -((a|c|)newer|fprint(|0|f)) ]]; then
+  __files
+elif [[ -current -1 -fstype ]]; then
+  complist -k '(ufs 4.2 4.3 nfs tmp mfs S51K S52K)'
+elif [[ -current -1 -group ]]; then
+  complist -k groups
+elif [[ -current -1 -user ]]; then
+  complist -u
+fi
diff --git a/Functions/Completion/__functions b/Functions/Completion/__functions
new file mode 100644
index 000000000..4fd24e379
--- /dev/null
+++ b/Functions/Completion/__functions
@@ -0,0 +1,2 @@
+#array unfunction
+__functions=(-F)
diff --git a/Functions/Completion/__gunzip b/Functions/Completion/__gunzip
new file mode 100644
index 000000000..f14803c62
--- /dev/null
+++ b/Functions/Completion/__gunzip
@@ -0,0 +1,3 @@
+#function gunzip zcat
+
+__files -g '*.[gG][z]'
diff --git a/Functions/Completion/__gzip b/Functions/Completion/__gzip
new file mode 100644
index 000000000..ce4e0787a
--- /dev/null
+++ b/Functions/Completion/__gzip
@@ -0,0 +1,3 @@
+#function gzip
+
+__files -g '*~*.[gG][zZ]'
diff --git a/Functions/Completion/__hash b/Functions/Completion/__hash
new file mode 100644
index 000000000..bd43eb967
--- /dev/null
+++ b/Functions/Completion/__hash
@@ -0,0 +1,13 @@
+#function hash
+
+if [[ -mword 1 -*d* ]]; then
+  if [[ -string 1 '=' ]]; then
+    pfiles -g '*(-/)'
+  else
+    complist -n -q -S '='
+  fi
+elif [[ -string 1 '=' ]]; then
+  files -g '*(*)' '*(-/)'
+else
+  complist -m -q -S '='
+fi
diff --git a/Functions/Completion/__hosts b/Functions/Completion/__hosts
new file mode 100644
index 000000000..a91251581
--- /dev/null
+++ b/Functions/Completion/__hosts
@@ -0,0 +1,2 @@
+#array ftp ncftp ping rwho rup xping traceroute nslookup
+__hosts=(-k hosts)
diff --git a/Functions/Completion/__jobs b/Functions/Completion/__jobs
new file mode 100644
index 000000000..d3e0d7776
--- /dev/null
+++ b/Functions/Completion/__jobs
@@ -0,0 +1,2 @@
+#array fg jobs
+__jobs=(-j -P '%')
diff --git a/Functions/Completion/__kill b/Functions/Completion/__kill
new file mode 100644
index 000000000..09ba248dc
--- /dev/null
+++ b/Functions/Completion/__kill
@@ -0,0 +1,8 @@
+#function kill
+
+if [[ -iprefix '-' ]]; then
+  complist -k "($signals[1,-3])"
+else
+  complist -P '%' -j
+  complist -y __kill_helper -s '`ps 2>/dev/null | tail +2 | cut -c1-5`'
+fi
diff --git a/Functions/Completion/__kill_helper b/Functions/Completion/__kill_helper
new file mode 100644
index 000000000..e1d286938
--- /dev/null
+++ b/Functions/Completion/__kill_helper
@@ -0,0 +1,3 @@
+#helper
+
+reply=( "$(ps 2>/dev/null)" )
diff --git a/Functions/Completion/__limits b/Functions/Completion/__limits
new file mode 100644
index 000000000..e3f97155d
--- /dev/null
+++ b/Functions/Completion/__limits
@@ -0,0 +1,2 @@
+#array limit unlimit
+__limits=(-k "(${(j: :)${(f)$(limit)}%% *})")
diff --git a/Functions/Completion/__main_complete b/Functions/Completion/__main_complete
new file mode 100644
index 000000000..48f2338de
--- /dev/null
+++ b/Functions/Completion/__main_complete
@@ -0,0 +1,48 @@
+#helper
+
+# The main loop of the completion code. This is what is called when 
+# completion is attempted from the command line.
+# The completion code gives us the special variables and the arguments
+# from the command line are given as positional parameters.
+
+local comp name
+
+setopt localoptions nullglob rcexpandparam globdots
+unsetopt markdirs globsubst shwordsplit nounset
+
+# An entry for `--first--' is the replacement for `compctl -T'
+# The `|| return 1' is used throughout: if a function producing matches
+# returns non-zero this is interpreted as `do not try to produce more matches'
+# (this is the replacement for `compctl -t').
+
+comp="$comps[--first--]"
+[[ -z "$comp" ]] || callcomplete comps --first-- "$@" || return 1
+
+# For arguments we use the `__normal' function called via the convenience
+# alias `compsub'.
+
+if [[ $CONTEXT == argument || $CONTEXT == command ]]; then
+  compsub
+else
+  # Let's see if we have a special completion definition for the other
+  # possible contexts.
+
+  comp=''
+
+  case $CONTEXT in
+  redirect)  name=--redirect--;;
+  math)      name=--math--;;
+  subscript) name=--subscript--;;
+  value)     name=--value--;;
+  condition) name=--condition--;;
+  esac
+
+  # If not, we use default completion, if any.
+
+  comp="$comps[$name]"
+  if [[ -z "$comp" ]]; then
+     name=--default--
+     comp="$comps[--default--]"
+  fi
+  [[ -z "$comp" ]] || callcomplete comps "$name" "$@" || return 1
+fi
diff --git a/Functions/Completion/__main_key_complete b/Functions/Completion/__main_key_complete
new file mode 100644
index 000000000..35fa1a0a3
--- /dev/null
+++ b/Functions/Completion/__main_key_complete
@@ -0,0 +1,6 @@
+#helper
+
+# The widget name looks like `__complete_key_<num>' where <num> can be
+# used as an index into the `keycomps' array to get at the definition.
+
+callcomplete keycomps "$WIDGET" "$@"
diff --git a/Functions/Completion/__make b/Functions/Completion/__make
new file mode 100644
index 000000000..4a2c5a7c8
--- /dev/null
+++ b/Functions/Completion/__make
@@ -0,0 +1,3 @@
+#function make gmake pmake
+
+complist -s "\$(awk '/^[a-zA-Z0-9][^/ 	]+:/ {print \$1}' FS=: [mM]akefile)"
diff --git a/Functions/Completion/__man b/Functions/Completion/__man
new file mode 100644
index 000000000..a0f00f58b
--- /dev/null
+++ b/Functions/Completion/__man
@@ -0,0 +1,11 @@
+#function man
+setopt localoptions rcexpandparam
+
+local rep
+if [[ $2 = (<->*|ln) ]]; then
+  rep=( $manpath/(man|cat)$2/$PREFIX*$SUFFIX.<->*(N:t:r) )
+else
+  rep=( $manpath/(man|cat)*/$PREFIX*$SUFFIX.<->*(N:t:r) )
+fi
+
+(( $#rep )) && compadd -m $rep
diff --git a/Functions/Completion/__mh b/Functions/Completion/__mh
new file mode 100644
index 000000000..2e4738e17
--- /dev/null
+++ b/Functions/Completion/__mh
@@ -0,0 +1,70 @@
+#function folder comp inc mark refile repl scan show next prev rmm pick whom mhn mhpath mhpatch
+
+# Completion for all possible MH commands.
+# Alter the following two to your own mh directory and the directory
+# where standard mh library files live.  (It works anyway, but this
+# will save a little time.)
+local mymhdir=~/Mail
+local mhlib=/usr/lib/mh
+
+# To be on the safe side, check this exists and if not, get it anyway.
+[[ -d $mymhdir ]] || mymhdir=$(mhpath +)
+
+if [[ -iprefix - ]]; then
+  # get list of options, which MH commands can generate themselves
+  # awk is just too icky to use for this, sorry.  send me one if
+  # you come up with it.
+  compadd -m $($COMMAND -help | perl -ne 'if (/^\s*-\(?(\S+)/) {
+    $n = $1;
+    $n =~ s/\)//g;
+    print $n =~ s/^\[([a-z]+)\]// ? "$n\n$1$n\n" : "$n\n";
+  }')
+  return
+elif [[ -iprefix '+' || -iprefix '@' || -current -1 -draftfolder ]]; then
+  # Complete folder names.
+  local mhpath
+  if [[ $IPREFIX != '@' ]]; then
+    [[ $IPREFIX = '+' ]] || IPREFIX=+
+    mhpath=$mymhdir
+  else
+    mhpath=$(mhpath)
+  fi
+
+  # painless, or what?
+  complist -W mhpath -/
+elif [[ -mcurrent -1 -(editor|(whatnow|rmm|show|more)proc) ]]; then
+  complist -c
+elif [[ -current -1 -file ]]; then
+  complist -f
+elif [[ -mcurrent -1 -(form|audit|filter) ]]; then
+  # Need some MH template file, which may be in our own MH directory
+  # or with the standard library.
+  local mhfpath
+  # This is the only place we need mhlib, so leave the test till here.
+  [[ -d $mhlib ]] || { mhlib=$(mhparam mhlproc); mhlib=$mhlib:h; }
+  mhfpath=($mymhdir $mhlib)
+
+  complist -W mhfpath -g '*(.)'
+elif [[ -mcurrent -1 -(no|)cc ]]; then
+  compadd -m all to cc me
+elif [[ -mcurrent -1 -[rw]cache ]]; then
+  compadd -m public private never ask
+else
+  # Generate sequences.
+  local foldnam folddir f
+  for f in $argv; do
+    [[ $f = [@+]* ]] && foldnam=$f
+  done
+  if [[ $foldnam = '+'* ]]; then
+    folddir=$mymhdir/${foldnam#+}
+  elif [[ $foldnam = '@'* ]]; then
+    folddir=$(mhpath)/${foldnam#@}
+  else
+    folddir=$(mhpath)
+    # leaving foldnam empty works here
+  fi
+
+  complist -s '$(mark $foldnam | awk -F: '\''{ print $1 }'\'')'
+  compadd -m reply next cur prev first last all unseen
+  complist -W folddir -g '<->'
+fi
diff --git a/Functions/Completion/__most_recent_file b/Functions/Completion/__most_recent_file
new file mode 100644
index 000000000..cf1f83282
--- /dev/null
+++ b/Functions/Completion/__most_recent_file
@@ -0,0 +1,2 @@
+#key-array expand-or-complete \C-xm
+__most_recent_file=(-g '*(om[1])')
diff --git a/Functions/Completion/__normal b/Functions/Completion/__normal
new file mode 100644
index 000000000..7750563d1
--- /dev/null
+++ b/Functions/Completion/__normal
@@ -0,0 +1,54 @@
+#helper
+
+local comp cmd1 cmd2 pat val name
+
+# Completing in command position? If not we set up `cmd1' and `cmd2' as
+# two strings we have search in the completion definition arrays (e.g.
+# a path and the last path name component).
+
+if [[ $CONTEXT == command ]]; then
+  comp="$comps[--command--]"
+  [[ -z "$comp" ]] || callcomplete comps --command-- "$@" || return 1
+  return 0
+elif [[ "$COMMAND[1]" == '=' ]]; then
+  eval cmd1\=$COMMAND
+  cmd2="$COMMAND[2,-1]"
+elif [[ "$COMMAND" == */* ]]; then
+  cmd1="$COMMAND"
+  cmd2="${COMMAND:t}"
+else
+  cmd1="$COMMAND"
+  eval cmd2=$(whence -p $COMMAND)
+fi
+
+# See if there are any matching pattern completions.
+
+if (( $#patcomps )); then
+  for i in "$patcomps[@]"; do
+    pat="${i% *}"
+    val="${i#* }"
+    if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]]; then
+      callcomplete patcomps "$pat" "$@" || return 1
+    fi
+  done
+fi
+
+# Now look up the two names in the normal completion array.
+
+name="$cmd1"
+comp="$comps[$cmd1]"
+
+if [[ -z "$comp" ]]; then
+  name="$cmd2"
+  comp="$comps[$cmd2]"
+fi
+
+# And generate the matches, probably using default completion.
+
+if [[ -z "$comp" ]]; then
+  name=--default--
+  comp="$comps[--default--]"
+fi
+[[ -z "$comp" ]] || callcomplete comps "$name" "$@" || return 1
+
+return 0
diff --git a/Functions/Completion/__path_files b/Functions/Completion/__path_files
new file mode 100644
index 000000000..f9e7c631a
--- /dev/null
+++ b/Functions/Completion/__path_files
@@ -0,0 +1,272 @@
+#helper
+
+# Utility function for in-path completion.
+# First argument should be an complist-option (e.g. -f, -/, -g). The other
+# arguments should be glob patterns, one per argument.
+#
+# E.g.: __path_files -g '*.tex' '*.texi'
+#
+# This is intended as a replacement for `complist -f', `complist -/', and
+# `complist -g ...' (but don't use it with other options).
+#
+# You may also give the `-W <spec>' option as with `compctl' and `complist',
+# but only as the first argument.
+#
+# This function also accepts an optional `-F <string>' option as its first
+# argument or just after the `-W <spec>'. This can be used to define file
+# name extension (a la `fignore'). Files with such an extension will not
+# be considered possible completions.
+#
+# This function behaves as if you have a matcher definition like:
+#   compctl -M 'r:|[-.,_/]=* r:|=* m:{a-z}={A-Z} m:-=_ m:.=,' \
+#              'm:{a-z}={A-Z} l:|=* r:|=*'
+# so you may want to modify this.
+
+local nm prepaths str linepath realpath donepath patstr prepath testpath rest
+local tmp1 collect tmp2 suffixes i ignore
+
+setopt localoptions nullglob rcexpandparam globdots extendedglob
+unsetopt markdirs globsubst shwordsplit nounset
+
+# Get the optional `-W' option and its argument.
+if [[ "$1" = -W ]]; then
+  tmp1="$2"
+  if [[ "$tmp1[1]" = '(' ]]; then
+    prepaths=( $tmp1[2,-2]/ )
+  else
+    prepaths=( ${(P)${tmp1}} )
+    [[ $#prepaths -eq 0 ]] && prepaths=( $tmp1/ )
+  fi
+  [[ $#prepaths -eq 0 ]] && prepaths=( '' )
+  shift 2
+else
+  prepaths=( '' )
+fi
+
+# Get the optional `-F' option and its argument.
+if [[ "$1" = -F ]]; then
+  ignore=(-F "$2")
+  shift 2
+else
+  ignore=''
+fi
+
+# str holds the whole string from the command line with a `*' between
+# the prefix and the suffix.
+
+str="${PREFIX:q}*${SUFFIX:q}"
+
+# We will first try normal completion called with `complist', but only if we
+# weren't given a `-F' option.
+
+if [[ -z "$ignore" ]]; then
+  # First build an array containing the `-W' option, if there is any and we
+  # want to use it. We don't want to use it if the string from the command line
+  # is a absolute path or relative to the current directory.
+
+  if [[ -z "$tmp1[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]]; then
+    tmp1=()
+  else
+    tmp1=(-W "( $ppres )")
+  fi
+
+  # Now call complist.
+
+  nm=$NMATCHES
+  if [[ $# -eq 0 ]]; then
+    complist "$tmp1[@]" -f
+  elif [[ "$1" = -g ]]; then
+    complist "$tmp1[@]" -g "$argv[2,-1]"
+    shift
+  else
+    complist "$tmp1[@]" $1
+    shift
+  fi
+
+  # If this generated any matches, we don't wnat to do in-path completion.
+
+  [[ -nmatches nm ]] || return
+
+  # No `-F' option, so we want to use `fignore'.
+
+  ignore=(-F fignore)
+fi
+
+# If we weren't given any file patterns as arguments, we trick ourselves
+# into believing that we were given the pattern `*'. This is just to simplify
+# the following code.
+
+[[ -z "$1" ]] && 1='*'
+
+# Now let's have a closer look at the string to complete.
+
+if [[ "$str[1]" = \~ ]]; then
+  # It begins with `~', so remember anything before the first slash to be able
+  # to report it to the completion code. Also get an expanded version of it
+  # (in `realpath'), so that we can generate the matches. Then remove that
+  # prefix from the string to complete, set `donepath' to build the correct
+  # paths and make sure that the loop below is run only once with an empty
+  # prefix path by setting `prepaths'.
+  
+  linepath="${str%%/*}/"
+  eval realpath\=path
+  str="${str#*/}"
+  donepath=''
+  prepaths=( '' )
+else
+  # If the string does not start with a `~' we don't remove a prefix from the
+  # string.
+
+  liniepath=''
+  realpath=''
+
+  if [[ "$str[1]" = / ]]; then
+    # If it is a absolut path name, we remove the first slash and put it in
+    # `donepath' meaning that we treat it as the path that was already handled.
+    # Also, we don't use the paths from `-W'.
+
+    str="$str[2,-1]"
+    donepath='/'
+    prepaths=( '' )
+  else
+    # The common case, we just use the string as it is, unless it begins with
+    # `./' or `../' in which case we don't use the paths from `-W'.
+    
+    [[ "$str" = (.|..)/* ]] && prepaths=( '' )
+    donepath=''
+  fi
+fi
+
+# First we skip over all pathname components in `str' which really exist in
+# the file-system, so that `/usr/lib/l<TAB>' doesn't offer you `lib' and
+# `lib5'. Pathname components skipped this way are taken from `str' and added
+# to `donepath'.
+
+while [[ "$str" = */* ]] do
+  [[ -e "$realpath$donepath${str%%/*}" ]] || break
+  donepath="$donepath${str%%/*}/"
+  str="${str#*/}"
+done
+
+# Now build the glob pattern. As noted above, this function behaves as if
+# a global matcher with two matching specifications are given.
+
+if [[ -matcher 1 ]]; then
+  patstr="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
+else
+  patstr="${str%/*}/*${str##*/}*"
+  patstr="$patstr:gs./.*/.:gs.**.*."
+fi
+
+# Finally, generate the matches. First we loop over all the paths from `-W'.
+# Note that in this loop `str' is used as a modifyable version of `patstr'
+# and `testpath' is a modifyable version of `donepath'.
+
+for prepath in "$prepaths[@]"; do
+  str="$patstr"
+  testpath="$donepath"
+
+  # The second loop tests the components of the path in `str' to get the
+  # possible matches.
+
+  while [[ "$str" = */* ]] do
+    # `rest' is the pathname after the first slash that is left. In `tmp1'
+    # we get the globbing matches for the pathname component currently
+    # handled.
+
+    rest="${str#*/}"
+    tmp1="${prepath}${realpath}${testpath}(#l)${str%%/*}(-/)"
+    tmp1=( $~tmp1 )
+
+    if [[ $#tmp1 -eq 0 ]]; then
+      # If this didn't produce any matches, we don't need to test this path
+      # any further, so continue with the next `-W' path, if any.
+
+      continue 2
+    elif [[ $#tmp1 -gt 1 ]]; then
+      # If it produced more than one match, we want to remove those which
+      # don't have possible following pathname components matching the 
+      # rest of the string we are completing. (The case with only one
+      # match is handled below.)
+      # In `collect' we will collect those of the produced pathnames that
+      # have a matching possible path-suffix. In `suffixes' we build an
+      # array containing strings build from the rest of the string to 
+      # complete and the glob patterns we were given as arguments.
+
+      collect=()
+      suffixes=( $rest$@ )
+      suffixes=( "${(@)suffixes:gs.**.*.}" )
+
+      # In the loop the prefixes from the `tmp1' array produced above and
+      # the suffixes we just built are used to produce possible matches
+      # via globbing.
+
+      for i in $tmp1; do
+        tmp2=( $~i/(#l)$~suffixes )
+        [[ $#tmp2 -ne 0 ]] && collect=( $collect $i )
+      done
+
+      # If this test showed that none of the matches from the glob in `tmp1'
+      # has a possible sub-path matching what's on the line, we give up and
+      # continue with the next `-W' path.
+
+      if [[ $#collect -eq 0 ]]; then
+        continue 2
+      elif [[ $#collect -ne 1 ]]; then
+        # If we have more than one possible match, this means that the
+	# pathname component currently handled is ambiguous, so we give
+	# it to the completion code.
+	# First we build the full path prefix in `tmp1'.
+
+        tmp1="$prepath$realpath$testpath"
+
+	# Now produce all matching pathnames in `collect'.
+
+        collect=( $~collect/(#l)$~suffixes )
+
+	# And then remove the common path prefix from all these matches.
+
+        collect=( ${collect#$tmp1} )
+
+	# Finally, we add all these matches with the common (unexpanded)
+	# pathprefix (the `-p' option), the path-prefix (the `-W' option)
+	# to allow the completion code to test file type, and the path-
+	# suffix (the `-s' option). We also tell the completion code that
+	# these are file names and that `fignore' should be used as usual
+	# (the `-f' and `-F' options).
+
+        for i in $collect; do
+          compadd -p "$linepath$testpath" -W "$tmp1" -s "/${i#*/}" -f "$ignore[@]" -- "${i%%/*}"
+        done
+
+	# We have just finished handling all the matches from above, so we
+	# can continue with the next `-W' path.
+
+	continue 2
+      fi
+      # We reach this point if only one of the path prefixes in `tmp1'
+      # has a existing path-suffix matching the string from the line.
+      # In this case we accept this match and continue with the next
+      # path-name component.
+
+      tmp1=( "$collect[1]" )
+    fi
+    # This is also reached if the first globbing produced only one match
+    # in this case we just continue with the next pathname component, too.
+
+    tmp1="$tmp1[1]"
+    testpath="$testpath${tmp1##*/}/"
+    str="$rest"
+  done
+
+  # We are here if all pathname components except the last one (which is still
+  # not tested) are unambiguous. So we add matches with the full path prefix, 
+  # no path suffix, the `-W' we are currently handling, all the matches we
+  # can produce in this directory, if any.
+
+  tmp1="$prepath$realpath$testpath"
+  suffixes=( $str$@ )
+  suffixes=( "${(@)suffixes:gs.**.*.}" )
+  tmp2=( $~tmp1(#l)$~suffixes )
+  compadd -p "$linepath$testpath" -W "$prepath$realpath$testpath" -f "$ignore[@]" -- ${tmp2#$tmp1}
+done
diff --git a/Functions/Completion/__pdf b/Functions/Completion/__pdf
new file mode 100644
index 000000000..97f656f40
--- /dev/null
+++ b/Functions/Completion/__pdf
@@ -0,0 +1,3 @@
+function acroread
+
+__files -g '*.(pdf|PDF)'
diff --git a/Functions/Completion/__precommand b/Functions/Completion/__precommand
new file mode 100644
index 000000000..a07cae96a
--- /dev/null
+++ b/Functions/Completion/__precommand
@@ -0,0 +1,15 @@
+#function - nohup nice eval time rusage noglob nocorrect exec
+
+# We just change the special completion parameters, to make the first
+# argument be treated as the command name and removing it from the 
+# positional parameters.
+
+COMMAND="$1"
+shift
+(( CURRENT-- ))
+if [[ CURRENT -eq 0 ]]; then
+  CONTEXT=command
+else
+  CONTEXT=argument
+fi
+compsub
diff --git a/Functions/Completion/__ps b/Functions/Completion/__ps
new file mode 100644
index 000000000..fa7395113
--- /dev/null
+++ b/Functions/Completion/__ps
@@ -0,0 +1,3 @@
+#function  gs ghostview gview psnup psselect pswrap pstops pstruct lpr
+
+__files -g '*([pP][sS]|eps)'
diff --git a/Functions/Completion/__rcs b/Functions/Completion/__rcs
new file mode 100644
index 000000000..8d55cc470
--- /dev/null
+++ b/Functions/Completion/__rcs
@@ -0,0 +1,9 @@
+#function co ci rcs
+
+[[ $COMMAND = ci || $COMMAND = rcs ]] && __files
+
+if [[ $NMATCHES -eq 0 && -d RCS && $COMMAND != ci ]]; then
+  local rep
+  rep=(RCS/$PREFIX*$SUFFIX,v(:t:s/\,v//))
+  (( $#rep )) && compadd -m $rep
+fi
diff --git a/Functions/Completion/__rlogin b/Functions/Completion/__rlogin
new file mode 100644
index 000000000..69fdebe13
--- /dev/null
+++ b/Functions/Completion/__rlogin
@@ -0,0 +1,9 @@
+#function rlogin rsh ssh
+
+if [[ -position 1 ]]; then
+  complist -k hosts
+elif [[ -position 2 ]]; then
+  complist -k '(-l)'
+else
+  complist -u
+fi
diff --git a/Functions/Completion/__sched b/Functions/Completion/__sched
new file mode 100644
index 000000000..dcd7385e1
--- /dev/null
+++ b/Functions/Completion/__sched
@@ -0,0 +1,3 @@
+#function sched
+
+[[ -position 2 -1 ]] && compsub
diff --git a/Functions/Completion/__set b/Functions/Completion/__set
new file mode 100644
index 000000000..e9db6c43a
--- /dev/null
+++ b/Functions/Completion/__set
@@ -0,0 +1,7 @@
+#function  set
+
+if [[ -mcurrent -1 [-+]o ]]; then
+  complist -o
+elif [[ -current -1 -A ]]; then
+  complist -A
+fi
diff --git a/Functions/Completion/__setopt b/Functions/Completion/__setopt
new file mode 100644
index 000000000..8a97befc7
--- /dev/null
+++ b/Functions/Completion/__setopt
@@ -0,0 +1,7 @@
+#function setopt
+
+local nm=$NMATCHES
+
+complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
+         -s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)'
+[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
diff --git a/Functions/Completion/__source b/Functions/Completion/__source
new file mode 100644
index 000000000..3478c9f38
--- /dev/null
+++ b/Functions/Completion/__source
@@ -0,0 +1,7 @@
+#function source
+
+if [[ -position 2 -1 ]]; then
+  compsub
+else
+  __files
+fi
diff --git a/Functions/Completion/__strip b/Functions/Completion/__strip
new file mode 100644
index 000000000..9abd38b63
--- /dev/null
+++ b/Functions/Completion/__strip
@@ -0,0 +1,2 @@
+#function strip
+__files -g '*(*)'
diff --git a/Functions/Completion/__stty b/Functions/Completion/__stty
new file mode 100644
index 000000000..ebf0de68f
--- /dev/null
+++ b/Functions/Completion/__stty
@@ -0,0 +1,16 @@
+#function stty
+
+if [[ -mcurrent -1 \
+  (*erase|discard|status|dsusp|intr|kill|lnext|quit|reprint|start|s*p) ]]
+then
+     compadd -m -Q '^-' '^h' '^?' '^c' '^u'
+else
+  [[ -string '-' || -string '+' ]]
+  compadd -m rows columns intr quit erase kill eof eol \
+    eol2 start stop susp dsusp reprint discard werase lnext \
+    parenb parodd cs8 cstopb hupcl cread clocal parext \
+    ignbrk brkint ignpar parmrk inpck istrip inlcr igncr icrnl iuclc \
+    ixon ixany ixoff imaxbel isig icanon xcase echo echoe echok \
+    echonl noflsh tostop echoctl echoprt echoke flusho pending iexten \
+    opost olcuc onlcr ocrnl onocr onlret ofill ofdel 
+fi
diff --git a/Functions/Completion/__subscript b/Functions/Completion/__subscript
new file mode 100644
index 000000000..a10b1202b
--- /dev/null
+++ b/Functions/Completion/__subscript
@@ -0,0 +1,4 @@
+#function --subscript--
+
+compalso --math-- "$@"
+[[ ${(Pt)${COMMAND}} = assoc* ]] && complist -k "( ${(kP)${COMMAND}} )"
diff --git a/Functions/Completion/__tar b/Functions/Completion/__tar
new file mode 100644
index 000000000..4f8b51a00
--- /dev/null
+++ b/Functions/Completion/__tar
@@ -0,0 +1,14 @@
+#function tar
+
+local nm=$NMATCHES tf="$2"
+compsave
+
+if [[ ( -mword 1 *t*f* || -mword 1 *x*f* ) && -position 3 100000 ]]; then
+  complist -k "( $(tar tf $tf) )"
+  compreset
+elif [[ -mword 1 *c*f* && -position 3 100000 ]]; then
+  __files
+  compreset
+elif [[ -mcurrent -1 *f* && -position 2 ]]; then
+  __files -g '*.(tar|TAR)'
+fi
diff --git a/Functions/Completion/__tex b/Functions/Completion/__tex
new file mode 100644
index 000000000..7331bb794
--- /dev/null
+++ b/Functions/Completion/__tex
@@ -0,0 +1,3 @@
+#function tex latex slitex
+
+__files -g '*.(tex|TEX|texinfo|texi)'
diff --git a/Functions/Completion/__trap b/Functions/Completion/__trap
new file mode 100644
index 000000000..0171bdc2b
--- /dev/null
+++ b/Functions/Completion/__trap
@@ -0,0 +1,7 @@
+#function trap
+
+if [[ -position 1 ]]; then
+  complist -c
+else
+  complist -k signals
+fi
diff --git a/Functions/Completion/__uncompress b/Functions/Completion/__uncompress
new file mode 100644
index 000000000..91343521e
--- /dev/null
+++ b/Functions/Completion/__uncompress
@@ -0,0 +1,3 @@
+#function uncompress zmore
+
+__files -g '*.Z'
diff --git a/Functions/Completion/__unhash b/Functions/Completion/__unhash
new file mode 100644
index 000000000..73196ca1b
--- /dev/null
+++ b/Functions/Completion/__unhash
@@ -0,0 +1,6 @@
+#function unhash
+
+[[ -mword 1 -*d* ]] && complist -n
+[[ -mword 1 -*a* ]] && complist -a
+[[ -mword 1 -*f* ]] && complist -F
+[[ ! -mword 1 -* ]] && complist -m
diff --git a/Functions/Completion/__unsetopt b/Functions/Completion/__unsetopt
new file mode 100644
index 000000000..c9a074d9b
--- /dev/null
+++ b/Functions/Completion/__unsetopt
@@ -0,0 +1,7 @@
+#function unsetopt
+
+local nm=$NMATCHES
+
+complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
+         -s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)'
+[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
diff --git a/Functions/Completion/__vars b/Functions/Completion/__vars
new file mode 100644
index 000000000..649e347fa
--- /dev/null
+++ b/Functions/Completion/__vars
@@ -0,0 +1,2 @@
+#array --math-- getopts read unset vared
+__vars=(-v)
diff --git a/Functions/Completion/__vars_eq b/Functions/Completion/__vars_eq
new file mode 100644
index 000000000..e0b5d9ae5
--- /dev/null
+++ b/Functions/Completion/__vars_eq
@@ -0,0 +1,2 @@
+#array declare export integer local readonly typeset
+__varseq=(-v -q -S '=')
diff --git a/Functions/Completion/__wait b/Functions/Completion/__wait
new file mode 100644
index 000000000..1c04108f6
--- /dev/null
+++ b/Functions/Completion/__wait
@@ -0,0 +1,4 @@
+#function wait
+
+complist -P '%' -j
+complist -y __kill_helper -s '`ps 2>/dev/null | tail +2 | cut -c1-5`'
diff --git a/Functions/Completion/__which b/Functions/Completion/__which
new file mode 100644
index 000000000..32b95b9c5
--- /dev/null
+++ b/Functions/Completion/__which
@@ -0,0 +1,2 @@
+#array which whence where type
+__which=(-caF)
diff --git a/Functions/Completion/__x_options b/Functions/Completion/__x_options
new file mode 100644
index 000000000..d5f85ea36
--- /dev/null
+++ b/Functions/Completion/__x_options
@@ -0,0 +1,5 @@
+#pattern-function '*/X11/*'
+
+# A simple pattern completion, just as an example.
+
+complist -J options -k '(-display -name -xrm)'
diff --git a/Functions/Completion/__xfig b/Functions/Completion/__xfig
new file mode 100644
index 000000000..7f17c2e42
--- /dev/null
+++ b/Functions/Completion/__xfig
@@ -0,0 +1,3 @@
+#function xfig
+
+__files -g '*.fig'
diff --git a/Functions/Completion/__zle b/Functions/Completion/__zle
new file mode 100644
index 000000000..f677374c8
--- /dev/null
+++ b/Functions/Completion/__zle
@@ -0,0 +1,7 @@
+#function zle
+
+if [[ -word 1 -N && -position 3 ]]; then
+  complist -F
+else
+  complist -b
+fi
diff --git a/Functions/Completion/__zmodload b/Functions/Completion/__zmodload
new file mode 100644
index 000000000..78c7393a3
--- /dev/null
+++ b/Functions/Completion/__zmodload
@@ -0,0 +1,9 @@
+#function zmodload
+
+if [[ -mword 1 -*(a*u|u*a)* || -mword 1 -*a* && -position 3 -1 ]]; then
+  complist -B
+elif [[ -mword 1 -*u* ]]; then
+  complist -s '$(zmodload)'
+else
+  complist -s '${^module_path}/*(N:t:r)'
+fi
diff --git a/Functions/Completion/init b/Functions/Completion/init
new file mode 100644
index 000000000..a40c5f61b
--- /dev/null
+++ b/Functions/Completion/init
@@ -0,0 +1,253 @@
+# 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).
+# The names of the files that will be considered for autoloading have to
+# start with two underscores (like `__setopt).
+# The first line of these files will be read and has to say what should be
+# done with its contents:
+#
+#   `#function <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
+#
+#   `#array <names ...>'
+#     with a first line like this, the filename is taken as
+#     the name of an array; when trying to generate matches
+#     for the command <name>, the file will be sourced and
+#     should define this array, the builtin `complist' will
+#     then be called with the elements of this array as its
+#     arguments; this is intended for simple definitions
+#     for which you don't need a shell function
+#
+#   `#pattern-function <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
+#
+#   `#pattern-array <pattern>'
+#     like `#pattern-function' but defining an array
+#
+#   `#key-function <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,
+#     menu-complete, menu-expand-or-complete, or reverse-menu-complete).
+#     This creates a widget behaving like <style> so that the
+#     completions are chosen as given in the the rest of the file,
+#     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.
+#
+#   `#key-array <style> [ <key-sequence> ... ]
+#     like `#key-function', but defining an array instead
+#
+#   `#helper'
+#     this is for helper functions that are not used to
+#     generate matches, but should automatically be loaded
+#     when they are called
+#
+# Note that no white space is allowed between the `#' and the rest of
+# the string.
+
+
+# An associative array for completions definitions. The keys of the entries
+# are the names of the command, the values are names of functions or variables
+# that are to be used to generate the matches.
+# Pattern completions will be stored in an normal array named `patcomps'.
+# Completion definitions bound directly to keys are stored in an assoc array
+# named `keycomps'.
+
+typeset -A comps
+typeset -A keycomps
+
+
+# This may be used to define completion handlers. The first argument is the
+# name of the function or variable containing the definition, the other
+# arguments are the command names for which this definition should be used.
+# With only one argument the function/variable-name __$1 is used.
+# If given the `-a' option, the function is defined as being autoloaded.
+
+defcomp() {
+  local name autol=''
+
+  if [[ "$1" = -a ]]; then
+    shift
+    autol=yes
+  fi
+  if [[ $# -eq 1 ]]; then
+    comps[$1]="__$1"
+    [[ -z "$autol" ]] || autoload "__$1"
+  else
+    name="$1"
+    shift
+    for i; do
+      comps[$i]="$name"
+    done
+    [[ -z "$autol" ]] || autoload "$name"
+  fi
+}
+
+
+# Almost like `defcomp', but this always gets two arguments: the name of a
+# variable or function describing what should be completed and the pattern
+# that will be compared to the command names for which completion is attempted.
+
+defpatcomp() {
+  if [[ "$1" = -a ]]; then
+    shift
+    autoload "$1"
+  fi
+  if (( $+patcomps )) then
+    patcomps=("$patcomps[@]" "$2 $1" )
+  else
+    patcomps=( "$2 $1" )
+  fi
+}
+
+
+# This is used to define completion handlers directly bound to keys. The
+# first argument is as for `defcomp', giving the handler. The second
+# argument is the name of one of the built-in completion widgets. Any
+# remaining arguments are used as key sequences to bind the widget.
+# Typing that key sequence will complete the word the cursor is on
+# according to the completion definition given and will behave as if the
+# built-in completion widget was used.
+
+defkeycomp() {
+  local name
+
+  if [[ "$1" = -a ]]; then
+    shift
+    autoload "$1"
+    name="$1"
+  elif [[ "${1[1]}" = ' ' ]]; then
+    name="${1:t}"
+  else
+    name="$1"
+  fi
+  keycomps[$name]="$1"
+  shift
+  zle -C "$name" "$1" __main_key_complete
+  shift
+  while (( $# )); do
+    bindkey "$1" "$name"
+    shift
+  done
+}
+
+# These can be used to easily save and restore the state of the special
+# variables used by the completion code.
+
+alias compsave='local _oprefix _oiprefix _oargv _ocurrent; \
+                _oprefix="$PREFIX"; \
+                _oiprefix="$IPREFIX"; \
+                _oargv=( "$@" ); \
+                _ocurrent="$CURRENT"'
+alias compreset='PREFIX="$_oprefix"; \
+                 IPREFIX="$_oiprefix"; \
+                 argv=( "$_oargv[@]" ); \
+		 CURRENT="$_ocur"'
+
+
+# This is an easy way to get completion for sub-commands.
+
+alias compsub='__normal "$@" || return 1'
+
+
+# This searches $1 in the array for normal completions and calls the result.
+
+compalso() {
+  local tmp
+
+  tmp="$comps[$1]"
+  [[ -z "$tmp" ]] || callcomplete comps "$1" "$@"
+}
+
+
+# This generates matches. The first argument is the name of one of the
+# arrays containing completion definitions. The second argument is the index
+# into this array. The other arguments are the positional parameters to give
+# to the completion function (containing the arguments from the command line).
+
+callcomplete() {
+  local file def
+
+  # Get the definition from the array.
+
+  eval "def=\$${1}[${2}]"
+
+  # If the definition starts with a space then this means that we should
+  # source a file to get the definition for an array.
+
+  if [[ "$def[1]" = ' ' ]]; then
+    # The definition starts with a space, so source the file and change
+    # the definition.
+
+    file="$def[2,-1]"
+    builtin . "$file"
+    def="${file:t}"
+    eval "${1}[${2}]=$def"
+  fi
+
+  # Get rid of the array-name and -index.
+
+  shift 2
+  if [[ ${(P)+def} -eq 1 ]]; then
+    # It is a parameter name, call complist directly.
+
+    complist "${(@P)def}"
+  else
+    # Otherwise it's a function name, call this function.
+
+    "$def" "$@"
+  fi
+}
+
+
+# Now we make the files automatically autoloaded.
+
+local dir file line func
+
+for dir in $fpath; do
+  [[ $dir = . ]] && continue
+  for file in $dir/__*~*~(N); do
+    read -rA line < $file
+    func=$line[1]
+    shift line
+    if [[ $func = '#function' ]]; then
+      defcomp -a ${file:t} "${line[@]}"
+    elif [[ $func = '#array' ]]; then
+      defcomp " $file" "${line[@]}"
+    elif [[ $func = '#pattern-function' ]]; then
+      defpatcomp -a ${file:t} "${line[@]}"
+    elif [[ $func = '#pattern-array' ]]; then
+      defcomp " $file" "${line[@]}"
+    elif [[ $func = '#key-function' ]]; then
+      defkeycomp -a "${file:t}" "${line[@]}"
+    elif [[ $func = '#key-array' ]]; then
+      defkeycomp " $file" "${line[@]}"
+    elif [[ $func = '#helper' ]]; then
+      autoload ${file:t}
+    fi
+  done
+done
+
+
+# Finally we make all this be called by changing the key bindings.
+
+bindkey | while read -A line; do
+            if [[ "$line[2]" = complete-word ||
+	    	  "$line[2]" = delete-char-or-list ||
+	    	  "$line[2]" = expand-or-complete ||
+	    	  "$line[2]" = expand-or-complete-prefix ||
+	    	  "$line[2]" = list-choices ||
+	    	  "$line[2]" = menu-complete ||
+	    	  "$line[2]" = menu-expand-or-complete ||
+	    	  "$line[2]" = reverse-menu-complete ]]; then
+              zle -C __complete_$line[2] $line[2] __main_complete
+              bindkey "${line[1][2,-2]}" __complete_$line[2]
+            fi
+          done
diff --git a/Functions/allopt b/Functions/allopt
new file mode 100644
index 000000000..604e76198
--- /dev/null
+++ b/Functions/allopt
@@ -0,0 +1,29 @@
+# This function lists options with the no's in front removed for
+# improved comprehension, i.e. `norcs off' becomes `rcs on'.
+# The format is otherwise like that with `kshoptionprint' set,
+# i.e. you can see all options whether on or off.
+# It can take a list of option names or parts thereof to search for
+# via egrep.
+#
+# Written by Sweth Chandramouli with hacks by Bart Schaefer.
+
+listalloptions () {
+   emulate -R zsh
+   builtin setopt localoptions kshoptionprint
+   local OPT_NAME OPT_PAIR OPT_VALUE
+   for OPT_PAIR in "${(f)$(builtin setopt)}" ; do
+      OPT_VALUE=${OPT_PAIR##* }
+      OPT_NAME=${OPT_PAIR%% *}
+      if [[ ${OPT_NAME#no} != ${OPT_NAME} ]] ; then
+         OPT_VALUE=${(L)${${OPT_VALUE:s/on/OFF}:s/off/on}} &&
+            OPT_NAME=${OPT_NAME#no};
+      fi;
+      echo ${(r:21:)OPT_NAME} ${OPT_VALUE}
+   done
+}
+
+if [[ -n $@ ]]; then
+    listalloptions | egrep "${(j.|.)@}"
+else
+    listalloptions
+fi
diff --git a/Src/Makefile.in b/Src/Makefile.in
index 27891e92a..1b5256e16 100644
--- a/Src/Makefile.in
+++ b/Src/Makefile.in
@@ -85,7 +85,9 @@ modobjs: headers rm-modobjs-tmp
 rm-modobjs-tmp:
 	rm -f stamp-modobjs.tmp
 
-Makemod modules.index prep: modules-bltin
+@@config.mk@@
+
+Makemod modules.index prep: modules-bltin $(CONFIG_INCS)
 	( cd $(sdir_top) && $(SHELL) $(subdir)/mkmodindex.sh $(subdir) ) \
 	    > modules.index.tmp
 	@if cmp -s modules.index.tmp modules.index; then \
@@ -200,6 +202,4 @@ install.modules uninstall.modules \
 modobjs modules headers proto $(MAIN_OBJS): Makemod
 	@$(MAKE) -f Makemod $(MAKEDEFS) $@
 
-# ========== DEPENDENCIES FOR MAINTENANCE ==========
-
-@@config.mk@@
+$(MAIN_OBJS): $(sdir)/zsh.h
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h
index 5f263557a..124ae454a 100644
--- a/Src/Zle/comp.h
+++ b/Src/Zle/comp.h
@@ -211,6 +211,7 @@ struct cmatch {
     int brpl;			/* the place where to put the brace prefix */
     int brsl;			/* ...and the suffix */
     char *rems;			/* when to remove the suffix */
+    char *remf;			/* shell function to call for suffix-removal */
 };
 
 #define CMF_FILE     1		/* this is a file */
@@ -228,6 +229,7 @@ struct cmlist {
 };
 
 struct cmatcher {
+    int refc;			/* reference counter */
     Cmatcher next;		/* next matcher */
     int flags;			/* see CMF_* below */
     Cpattern line;		/* what matches on the line */
@@ -280,5 +282,4 @@ struct cline {
 #define CAF_MENU     2
 #define CAF_NOSORT   4
 #define CAF_ALT      8
-#define CAF_FIGNORE 16
-#define CAF_MATCH   32
+#define CAF_MATCH   16
diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c
index a5e35bc3c..77fe0a1fe 100644
--- a/Src/Zle/comp1.c
+++ b/Src/Zle/comp1.c
@@ -49,7 +49,7 @@ void (*makecompparamsptr) _((void));
 /* pointers to functions required by compctl and defined by zle */
 
 /**/
-void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char **));
+void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char **));
 
 /**/
 char *(*comp_strptr) _((int*,int*));
@@ -61,7 +61,7 @@ int (*getcpatptr) _((char *, int, char *, int));
 void (*makecomplistcallptr) _((Compctl));
 
 /**/
-void (*makecomplistctlptr) _((int));
+int (*makecomplistctlptr) _((int));
 
 /* Hash table for completion info for commands */
  
@@ -249,6 +249,9 @@ freecmatcher(Cmatcher m)
 {
     Cmatcher n;
 
+    if (!m || --(m->refc))
+	return;
+
     while (m) {
 	n = m->next;
 	freecpattern(m->line);
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index dcc206c96..cec71fc5b 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -38,6 +38,7 @@
 #define COMP_DEFAULT	(1<<2)	/* -D */
 #define COMP_FIRST	(1<<3)	/* -T */
 #define COMP_REMOVE	(1<<4)
+#define COMP_LISTMATCH	(1<<5)	/* -L and -M */
 
 #define COMP_SPECIAL (COMP_COMMAND|COMP_DEFAULT|COMP_FIRST)
 
@@ -82,6 +83,7 @@ cpcmatcher(Cmatcher m)
     while (m) {
 	*p = n = (Cmatcher) zalloc(sizeof(struct cmatcher));
 
+	n->refc = 1;
 	n->next = NULL;
 	n->flags = m->flags;
 	n->line = cpcpattern(m->line);
@@ -712,7 +714,9 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl)
 		cct.mask2 |= CC_NOSORT;
 		break;
 	    case 'M':
-		if ((*argv)[1]) {
+		if (cclist & COMP_LIST) {
+		    cclist |= COMP_LISTMATCH;
+		} else if ((*argv)[1]) {
 		    if ((cct.matcher =
 			 parse_cmatcher(name, (cct.mstr = (*argv) + 1))) ==
 			pcm_err) {
@@ -1572,7 +1576,7 @@ bin_compctl(char *name, char **argv, char *ops, int func)
     /* If no commands and no -C, -T, or -D, print all the compctl's *
      * If some flags (other than -C, -T, or -D) were given, then    *
      * only print compctl containing those flags.                   */
-    if (!*argv && !(cclist & COMP_SPECIAL)) {
+    if (!*argv && !(cclist & (COMP_SPECIAL|COMP_LISTMATCH))) {
 	Patcomp pc;
 
 	for (pc = patcomps; pc; pc = pc->next)
@@ -1619,6 +1623,8 @@ bin_compctl(char *name, char **argv, char *ops, int func)
 	    printcompctl("", &cc_default, 0, 0);
 	if (cclist & COMP_FIRST)
 	    printcompctl("", &cc_first, 0, 0);
+	if (cclist & COMP_LISTMATCH)
+	    print_gmatcher(COMP_LIST);
 	return ret;
     }
 
@@ -1670,6 +1676,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
     char *p, **sp, *e;
     char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
     char *pre = NULL, *suf = NULL, *group = NULL, *m = NULL, *rs = NULL;
+    char *ign = NULL, *rf = NULL;
     int f = 0, a = 0, dm;
     Cmatcher match = NULL;
 
@@ -1692,7 +1699,8 @@ bin_compadd(char *name, char **argv, char *ops, int func)
 		f |= CMF_FILE;
 		break;
 	    case 'F':
-		a |= CAF_FIGNORE;
+		sp = &ign;
+		e = "string expected after -%c";
 		break;
 	    case 'n':
 		f |= CMF_NOLIST;
@@ -1746,9 +1754,15 @@ bin_compadd(char *name, char **argv, char *ops, int func)
 		dm = 1;
 		break;
 	    case 'r':
+		f |= CMF_REMOVE;
 		sp = &rs;
 		e = "string expected after -%c";
 		break;
+	    case 'R':
+		f |= CMF_REMOVE;
+		sp = &rf;
+		e = "function name expected after -%c";
+		break;
 	    case '-':
 		argv++;
 		goto ca_args;
@@ -1782,8 +1796,11 @@ bin_compadd(char *name, char **argv, char *ops, int func)
     if (!*argv)
 	return 1;
 
+    match = cpcmatcher(match);
     addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group,
-		  rs, f, a, match, argv);
+		  rs, rf, ign, f, a, match, argv);
+    freecmatcher(match);
+
     return 0;
 }
 
@@ -1795,9 +1812,8 @@ bin_compcall(char *name, char **argv, char *ops, int func)
 	zerrnam(name, "can only be called from completion function", NULL, 0);
 	return 1;
     }
-    makecomplistctlptr((ops['T'] ? 0 : CFN_FIRST) |
-		       (ops['D'] ? 0 : CFN_DEFAULT));
-    return 0;
+    return makecomplistctlptr((ops['T'] ? 0 : CFN_FIRST) |
+			      (ops['D'] ? 0 : CFN_DEFAULT));
 }
 
 #define VAR(X) ((void *) (&(X)))
@@ -2016,7 +2032,7 @@ cond_strcl(char **a, int id)
 {
     if (comp_check()) {
 	char *s;
-	int i;
+	int i, ipl;
 
 	if (a[1]) {
 	    s = cond_str(a, 1);
@@ -2029,9 +2045,9 @@ cond_strcl(char **a, int id)
 	    zerr("zle not loaded, zle condition not available", NULL, 0);
 	    return 1;
 	}
-	i = getcpatptr(comp_strptr(NULL, NULL), i, s, id);
+	i = getcpatptr(comp_strptr(&ipl, NULL), i, s, id);
 	if (i != -1) {
-	    ignore_prefix(i);
+	    ignore_prefix(i - ipl);
 	    return 1;
 	}
     }
diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c
index e6b385652..a4b3866e5 100644
--- a/Src/Zle/zle_hist.c
+++ b/Src/Zle/zle_hist.c
@@ -663,10 +663,7 @@ doisearch(int dir)
     static char *previous_search = NULL;
     static int previous_search_len = 0;
 
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
 
     strcpy(ibuf, ISEARCH_PROMPT);
     memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
@@ -948,10 +945,7 @@ getvisrchstr(void)
 	zsfree(visrchstr);
 	visrchstr = NULL;
     }
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
     statusline = sbuf;
     sbuf[0] = (visrchsense == -1) ? '?' : '/';
     selectkeymap("main", 1);
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index 1ffe6f156..1baa3a845 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -108,7 +108,9 @@ static HashTable keymapnamtab;
 
 /* key sequence reading data */
 
-static char *keybuf;
+/**/
+char *keybuf;
+
 static int keybuflen, keybufsz = 20;
 
 /* last command executed with execute-named-command */
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index ca7a7fe19..277d154a6 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -792,10 +792,7 @@ describekeybriefly(void)
 
     if (statusline)
 	return;
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
     statusline = "Describe key briefly: _";
     statusll = strlen(statusline);
     zrefresh();
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 4b5df9cde..ea8874010 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -612,10 +612,7 @@ executenamedcommand(char *prmt)
     char *ptr;
     char *okeymap = curkeymapname;
 
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
     cmdbuf = halloc(l + NAMLEN + 2);
     strcpy(cmdbuf, prmt);
     statusline = cmdbuf;
@@ -767,6 +764,11 @@ executenamedcommand(char *prmt)
 /**/
 int suffixlen[257];
 
+/* Shell function to call to remove the suffix. */
+
+/**/
+static char *suffixfunc;
+
 /* Set up suffix: the last n characters are a suffix that should be *
  * removed in the usual word end conditions.                        */
 
@@ -801,9 +803,13 @@ makeparamsuffix(int br, int n)
 
 /**/
 void
-makesuffixstr(char *s, int n)
+makesuffixstr(char *f, char *s, int n)
 {
-    if (s) {
+    if (f) {
+	zsfree(suffixfunc);
+	suffixfunc = ztrdup(f);
+	suffixlen[0] = n;
+    } else if (s) {
 	int inv, i, v, z = 0;
 
 	if (*s == '^' || *s == '!') {
@@ -845,10 +851,33 @@ makesuffixstr(char *s, int n)
 void
 iremovesuffix(int c)
 {
-    int sl = suffixlen[c];
-    if(sl) {
-	backdel(sl);
-	invalidatelist();
+    if (suffixfunc) {
+	List l = getshfunc(suffixfunc);
+
+	if (l != &dummy_list) {
+	    LinkList args = newlinklist();
+	    char buf[20];
+	    int osc = sfcontext;
+
+	    sprintf(buf, "%d", suffixlen[0]);
+	    addlinknode(args, suffixfunc);
+	    addlinknode(args, buf);
+
+	    startparamscope();
+	    makezleparams(0);
+	    sfcontext = SFC_COMPLETE;
+	    doshfunc(suffixfunc, l, args, 0, 1);
+	    sfcontext = osc;
+	    endparamscope();
+	}
+	zsfree(suffixfunc);
+	suffixfunc = NULL;
+    } else {
+	int sl = suffixlen[c];
+	if(sl) {
+	    backdel(sl);
+	    invalidatelist();
+	}
     }
     fixsuffix();
 }
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index 74f905ef4..7e15d3d8b 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -65,6 +65,8 @@ static struct zleparam {
         zleunsetfn, NULL },
     { "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget),
         zleunsetfn, NULL },
+    { "keys", PM_ARRAY | PM_READONLY, NULL, FN(get_keys),
+        zleunsetfn, NULL },
     { NULL, 0, NULL, NULL, NULL, NULL }
 };
 
@@ -216,3 +218,29 @@ get_lwidget(Param pm)
 {
     return (lbindk ? lbindk->nam : "");
 }
+
+/**/
+static char **
+get_keys(Param pm)
+{
+    char **r, **q, *p, *k, c;
+
+    r = (char **) halloc((strlen(keybuf) + 1) * sizeof(char *));
+    for (q = r, p = keybuf; (c = *p); q++, p++) {
+	k = *q = (char *) halloc(5);
+	if (c & 0x80) {
+	    *k++ = 'M';
+	    *k++ = '-';
+	    c &= 0x7f;
+	}
+	if (c < 32 || c == 0x7f) {
+	    *k++ = '^';
+	    c ^= 64;
+	}
+	*k++ = c;
+	*k = '\0';
+    }
+    *q = NULL;
+
+    return r;
+}
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index c8d6c70a7..9e07676e8 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -60,6 +60,11 @@ int showinglist;
 /**/
 int clearflag;
 
+/* Non-zero if zrefresh() should clear the list below the prompt. */
+
+/**/
+int clearlist;
+
 #ifdef HAVE_SELECT
 /* cost of last update */
 /**/
@@ -248,6 +253,13 @@ zrefresh(void)
     if (inlist)
 	return;
 
+    if (clearlist) {
+	invalidatelist();
+	moveto(0, 0);
+	clearflag = 0;
+	resetneeded = 1;
+	clearlist = 0;
+    }
 #ifdef HAVE_SELECT
     cost = 0;			/* reset */
 #endif
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index f1285da8c..f1078ef11 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -212,6 +212,10 @@ static LinkList ccstack;
 
 static Cmlist mstack;
 
+/* A list with references to all matcher we used. */
+
+static LinkList matchers;
+
 /* A heap of free Cline structures. */
 
 static Cline freecl;
@@ -2454,10 +2458,10 @@ instmatch(Cmatch m)
 /**/
 void
 addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
-	   char *suf, char *group, char *rems, 
+	   char *suf, char *group, char *rems, char *remf, char *ign,
 	   int flags, int aflags, Cmatcher match, char **argv)
 {
-    char *s, *t, *e, *te, *ms, *lipre = NULL, *lpre, *lsuf;
+    char *s, *t, *e, *te, *ms, *lipre = NULL, *lpre, *lsuf, **aign = NULL;
     int lpl, lsl, i, pl, sl, test, bpl, bsl, lsm, llpl;
     Aminfo ai;
     Cline lc = NULL;
@@ -2477,22 +2481,26 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 	mst.next = mstack;
 	mst.matcher = match;
 	mstack = &mst;
+	addlinknode(matchers, match);
+	match->refc++;
     }
     if ((aflags & CAF_MENU) && isset(AUTOMENU))
 	usemenu = 1;
+    if (ign)
+	aign = get_user_var(ign);
+
     SWITCHHEAPS(compheap) {
 	HEAPALLOC {
 	    if (aflags & CAF_MATCH) {
-		ctokenize(lipre = dupstring(compiprefix));
-		remnulargs(lipre);
-		ctokenize(lpre = dupstring(compprefix));
-		remnulargs(lpre);
+		lipre = dupstring(compiprefix);
+		lpre = dupstring(compprefix);
 		llpl = strlen(lpre);
-		ctokenize(lsuf = dupstring(compsuffix));
-		remnulargs(lsuf);
+		lsuf = dupstring(compsuffix);
 	    }
 	    if (ipre)
 		ipre = (lipre ? dyncat(lipre, ipre) : dupstring(ipre));
+	    else if (lipre)
+		ipre = lipre;
 	    if (ppre) {
 		ppre = dupstring(ppre);
 		lpl = strlen(ppre);
@@ -2520,7 +2528,10 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 		if (aflags & CAF_NOSORT)
 		    mgroup->flags |= CGF_NOSORT;
 	    }
-	    if (rems)
+	    if (remf) {
+		remf = dupstring(remf);
+		rems = NULL;
+	    } else if (rems)
 		rems = dupstring(rems);
     	    if (ai->pprefix) {
 		if (pre)
@@ -2535,8 +2546,8 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 		ms = NULL;
 		bpl = brpl;
 		bsl = brsl;
-		if ((!psuf || !*psuf) && (aflags & CAF_FIGNORE)) {
-		    char **pt = fignore;
+		if ((!psuf || !*psuf) && aign) {
+		    char **pt = aign;
 		    int filell;
 
 		    for (test = 1; test && *pt; pt++)
@@ -2635,6 +2646,7 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 		cm->flags = flags;
 		cm->brpl = bpl;
 		cm->brsl = bsl;
+		cm->remf = remf;
 		cm->rems = rems;
 		addlinknode(l, cm);
 
@@ -2936,7 +2948,7 @@ addmatch(char *s, char *t)
     cm->flags = mflags | isf;
     cm->brpl = bpl;
     cm->brsl = bsl;
-    cm->rems = NULL;
+    cm->rems = cm->remf = NULL;
     addlinknode(l, cm);
 
     /* One more match for this explanation. */
@@ -3259,17 +3271,20 @@ static void
 docompletion(char *s, int lst, int incmd)
 {
     HEAPALLOC {
+	LinkNode n;
+
 	pushheap();
 
 	ainfo = fainfo = NULL;
+	matchers = newlinklist();
 
 	/* Make sure we have the completion list and compctl. */
 	if (makecomplist(s, incmd, lst)) {
 	    /* Error condition: feeeeeeeeeeeeep(). */
 	    feep();
+	    clearlist = 1;
 	    goto compend;
 	}
-
 	if (lst == COMP_LIST_COMPLETE)
 	    /* All this and the guy only wants to see the list, sigh. */
 	    showinglist = -2;
@@ -3324,6 +3339,9 @@ docompletion(char *s, int lst, int incmd)
 	    }
 	}
       compend:
+	for (n = firstnode(matchers); n; incnode(n))
+	    freecmatcher((Cmatcher) getdata(n));
+
 	ll = strlen((char *)line);
 	if (cs > ll)
 	    cs = ll;
@@ -3460,13 +3478,26 @@ static int
 makecomplist(char *s, int incmd, int lst)
 {
     struct cmlist ms;
-    Cmlist m = cmatcher;
+    Cmlist m;
 
     /* If we already have a list from a previous execution of this *
      * function, skip the list building code.                      */
     if (validlist)
 	return !nmatches;
 
+    if ((m = cmatcher)) {
+	Cmlist mm, *mp = &mm;
+
+	for (; m; m = m->next) {
+	    *mp = (Cmlist) halloc(sizeof(struct cmlist));
+	    (*mp)->matcher = m->matcher;
+	    (*mp)->next = NULL;
+	    mp = &((*mp)->next);
+	    addlinknode(matchers, m->matcher);
+	    m->matcher->refc++;
+	}
+	m = mm;
+    }
     compmatcher = 1;
     for (;;) {
 	if (m) {
@@ -3613,11 +3644,13 @@ static int cdepth = 0;
 #define MAX_CDEPTH 16
 
 /**/
-void
+int
 makecomplistctl(int flags)
 {
+    int ret;
+
     if (cdepth == MAX_CDEPTH)
-	return;
+	return 0;
 
     cdepth++;
     SWITCHHEAPS(compheap) {
@@ -3641,9 +3674,10 @@ makecomplistctl(int flags)
 	    *q = NULL;
 	    offs = lip + lp;
 	    incompfunc = 2;
-	    makecomplistglobal(str,
-			       (!clwpos && !strcmp(compcontext, "command")),
-			       COMP_COMPLETE, flags);
+	    ret = makecomplistglobal(str,
+				     (!clwpos &&
+				      !strcmp(compcontext, "command")),
+				     COMP_COMPLETE, flags);
 	    incompfunc = 1;
 	    offs = ooffs;
 	    compnmatches = mnum;
@@ -3656,13 +3690,15 @@ makecomplistctl(int flags)
 	} LASTALLOC;
     } SWITCHBACKHEAPS;
     cdepth--;
+
+    return ret;
 }
 
 /* This function gets the compctls for the given command line and *
  * adds all completions for them. */
 
 /**/
-static void
+static int
 makecomplistglobal(char *os, int incmd, int lst, int flags)
 {
     Compctl cc;
@@ -3694,46 +3730,48 @@ makecomplistglobal(char *os, int incmd, int lst, int flags)
     } else if (linredir)
 	/* In redirections use default completion. */
 	cc = &cc_default;
-    else {
+    else
 	/* Otherwise get the matches for the command. */
-	makecomplistcmd(os, incmd, flags);
-	cc = NULL;
-    }
+	return makecomplistcmd(os, incmd, flags);
+
     if (cc) {
 	/* First, use the -T compctl. */
 	if (!(flags & CFN_FIRST)) {
 	    makecomplistcc(&cc_first, os, incmd);
 
 	    if (!(ccont & CC_CCCONT))
-		return;
+		return 0;
 	}
 	makecomplistcc(cc, os, incmd);
+	return 1;
     }
+    return 0;
 }
 
 /* This produces the matches for a command. */
 
 /**/
-static void
+static int
 makecomplistcmd(char *os, int incmd, int flags)
 {
     Compctl cc;
     Compctlp ccp;
     char *s;
+    int ret = 0;
 
     /* First, use the -T compctl. */
     if (!(flags & CFN_FIRST)) {
 	makecomplistcc(&cc_first, os, incmd);
 
 	if (!(ccont & CC_CCCONT))
-	    return;
+	    return 0;
     }
     /* Then search the pattern compctls, with the command name and the *
      * full pathname of the command. */
     if (cmdstr) {
-	makecomplistpc(os, incmd);
+	ret |= makecomplistpc(os, incmd);
 	if (!(ccont & CC_CCCONT))
-	    return;
+	    return ret;
     }
     /* If the command string starts with `=', try the path name of the *
      * command. */
@@ -3758,31 +3796,36 @@ makecomplistcmd(char *os, int incmd, int flags)
 	    (ccp = (Compctlp) compctltab->getnode(compctltab, s)) &&
 	    (cc = ccp->cc))))) {
 	if (flags & CFN_DEFAULT)
-	    return;
+	    return ret;
 	cc = &cc_default;
-    }
+    } else
+	ret|= 1;
     makecomplistcc(cc, os, incmd);
+    return ret;
 }
 
 /* This add the matches for the pattern compctls. */
 
 /**/
-static void
+static int
 makecomplistpc(char *os, int incmd)
 {
     Patcomp pc;
     Comp pat;
     char *s = findcmd(cmdstr, 1);
+    int ret = 0;
 
     for (pc = patcomps; pc; pc = pc->next) {
 	if ((pat = parsereg(pc->pat)) &&
 	    (domatch(cmdstr, pat, 0) ||
 	     (s && domatch(s, pat, 0)))) {
 	    makecomplistcc(pc->cc, os, incmd);
+	    ret |= 2;
 	    if (!(ccont & CC_CCCONT))
-		return;
+		return ret;
 	}
     }
+    return ret;
 }
 
 /* This produces the matches for one compctl. */
@@ -4111,6 +4154,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	ms.next = mstack;
 	ms.matcher = cc->matcher;
 	mstack = &ms;
+	addlinknode(matchers, cc->matcher);
+	cc->matcher->refc++;
     }
     /* Insert the prefix (compctl -P), if any. */
     if (cc->prefix) {
@@ -5225,6 +5270,7 @@ dupmatch(Cmatch m)
     r->brpl = m->brpl;
     r->brsl = m->brsl;
     r->rems = ztrdup(m->rems);
+    r->remf = ztrdup(m->remf);
 
     return r;
 }
@@ -5337,6 +5383,7 @@ freematch(Cmatch m)
     zsfree(m->psuf);
     zsfree(m->prpre);
     zsfree(m->rems);
+    zsfree(m->remf);
 
     zfree(m, sizeof(m));
 }
@@ -5591,7 +5638,7 @@ do_single(Cmatch m)
 	if (menuwe) {
 	    menuend += menuinsc;
 	    if (m->flags & CMF_REMOVE) {
-		makesuffixstr(m->rems, menuinsc);
+		makesuffixstr(m->remf, m->rems, menuinsc);
 		if (menuinsc == 1)
 		    suffixlen[STOUC(m->suf[0])] = 1;
 	    }
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index a116921b4..2e4fb4a32 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -816,10 +816,7 @@ viswapcase(void)
 void
 vicapslockpanic(void)
 {
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
     zbeep();
     statusline = "press a lowercase key to continue";
     statusll = strlen(statusline);
diff --git a/Src/builtin.c b/Src/builtin.c
index 2b77c57bc..fc9b113ca 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -56,7 +56,7 @@ static struct builtin builtins[] =
     BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
     BUILTIN("echo", BINF_PRINTOPTS | BINF_ECHOPTS, bin_print, 0, -1, BIN_ECHO, "neE", "-"),
     BUILTIN("echotc", 0, bin_echotc, 1, -1, 0, NULL, NULL),
-    BUILTIN("emulate", 0, bin_emulate, 1, 1, 0, "R", NULL),
+    BUILTIN("emulate", 0, bin_emulate, 1, 1, 0, "LR", NULL),
     BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmr", NULL),
     BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
     BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
@@ -643,7 +643,7 @@ set_pwd_env(void)
     pm = (Param) paramtab->getnode(paramtab, "OLDPWD");
     if (!(pm->flags & PM_EXPORTED)) {
 	pm->flags |= PM_EXPORTED;
-	pm->env = addenv("PWD", pwd);
+	pm->env = addenv("OLDPWD", oldpwd);
     }
 }
 
@@ -3051,6 +3051,8 @@ int
 bin_emulate(char *nam, char **argv, char *ops, int func)
 {
     emulate(*argv, ops['R']);
+    if (ops['L'])
+	dosetopt(LOCALOPTIONS, 1, 0);
     return 0;
 }
 
diff --git a/Src/init.c b/Src/init.c
index 10013c52b..d66d157c9 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -890,6 +890,20 @@ init_bltinmods(void)
     mod.nam = NULL;
 }
 
+/**/
+void
+noop_function(void)
+{
+    /* do nothing */
+}
+
+/**/
+void
+noop_function_int(int nothing)
+{
+    /* do nothing */
+}
+
 /* ZLE entry point pointers.  They are defined here because the initial *
  * values depend on whether ZLE is linked in or not -- if it is, we     *
  * avoid wasting space with the fallback functions.  No other source    *
@@ -898,7 +912,7 @@ init_bltinmods(void)
 #ifdef LINKED_XMOD_zle
 
 /**/
-ZleVoidFn trashzleptr;
+ZleVoidFn trashzleptr = noop_function;
 /**/
 ZleVoidFn gotwordptr;
 /**/
@@ -921,20 +935,6 @@ ZleReadFn zlereadptr = fallback_zleread;
 # endif /* !UNLINKED_XMOD_zle */
 
 /**/
-void
-noop_function(void)
-{
-    /* do nothing */
-}
-
-/**/
-void
-noop_function_int(int nothing)
-{
-    /* do nothing */
-}
-
-/**/
 # ifdef UNLINKED_XMOD_zle
 
 /**/
diff --git a/Src/params.c b/Src/params.c
index f91a448a1..88b5fdf73 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -246,6 +246,10 @@ IPDEF9F("path", &path, "PATH", PM_RESTRICTED),
 };
 #undef BR
 
+#define IS_UNSET_VALUE(V) \
+	((V) && (!(V)->pm || ((V)->pm->flags & PM_UNSET) || \
+		 !(V)->pm->nam || !*(V)->pm->nam))
+
 static Param argvparam;
 
 /* hash table containing the parameters */
@@ -966,7 +970,7 @@ getindex(char **pptr, Value v)
     if (*tbrack == Outbrack)
 	*tbrack = ']';
     if ((s[0] == '*' || s[0] == '@') && s[1] == ']') {
-	if (v->isarr && s[0] == '@')
+	if ((v->isarr || IS_UNSET_VALUE(v)) && s[0] == '@')
 	    v->isarr |= SCANPM_ISVAR_AT;
 	v->a = 0;
 	v->b = -1;
@@ -1205,6 +1209,8 @@ getarrvalue(Value v)
 
     if (!v)
 	return arrdup(nular);
+    else if (IS_UNSET_VALUE(v))
+	return arrdup(&nular[1]);
     if (v->inv) {
 	char buf[DIGBUFSIZE];
 
diff --git a/Src/signames1.awk b/Src/signames1.awk
new file mode 100644
index 000000000..27d21ac7b
--- /dev/null
+++ b/Src/signames1.awk
@@ -0,0 +1,19 @@
+# This is an awk script which finds out what the possibilities for
+# the signal names are, and dumps them out so that cpp can turn them
+# into numbers.  Since we don't need to decide here what the
+# real signals are, we can afford to be generous about definitions,
+# in case the definitions are in terms of other definitions.
+# However, we need to avoid definitions with parentheses, which will
+# mess up the syntax.
+BEGIN { printf "#include <signal.h>\n\n" }
+
+/^[\t ]*#[\t ]*define[\t _]*SIG[A-Z][A-Z0-9]*[\t ][\t ]*[^(\t ]/ { 
+    sigindex = index($0, "SIG")
+    sigtail = substr($0, sigindex, 80)
+    split(sigtail, tmp)
+    signam = substr(tmp[1], 4, 20)
+    if (substr($0, sigindex-1, 1) == "_")
+        printf("XXNAMES XXSIG%s _SIG%s\n", signam, signam)
+    else
+        printf("XXNAMES XXSIG%s SIG%s\n", signam, signam)
+}
diff --git a/Src/signames2.awk b/Src/signames2.awk
new file mode 100644
index 000000000..3aea76ee3
--- /dev/null
+++ b/Src/signames2.awk
@@ -0,0 +1,100 @@
+#
+# {g,n}awk script to generate signames.c
+# This version relies on the previous output of the preprocessor
+# on sigtmp.c, sigtmp.out, which is in turn generated by signames1.awk.
+#
+# NB: On SunOS 4.1.3 - user-functions don't work properly, also \" problems
+# Without 0 + hacks some nawks compare numbers as strings
+#
+/^XXNAMES XXSIG[A-Z][A-Z0-9]* [1-9][0-9]*/ {
+    sigindex = index($0, "SIG")
+    sigtail = substr($0, sigindex, 80)
+    split(sigtail, tmp)
+    signam = substr(tmp[1], 4, 20)
+    signum = tmp[2]
+    if (sig[signum] == "") {
+	sig[signum] = signam
+	if (0 + max < 0 + signum && signum < 60)
+	    max = signum
+	if (signam == "ABRT")   { msg[signum] = "abort" }
+	if (signam == "ALRM")   { msg[signum] = "alarm" }
+	if (signam == "BUS")    { msg[signum] = "bus error" }
+	if (signam == "CHLD")   { msg[signum] = "death of child" }
+	if (signam == "CLD")    { msg[signum] = "death of child" }
+	if (signam == "CONT")   { msg[signum] = "continued" }
+	if (signam == "EMT")    { msg[signum] = "EMT instruction" }
+	if (signam == "FPE")    { msg[signum] = "floating point exception" }
+	if (signam == "HUP")    { msg[signum] = "hangup" }
+	if (signam == "ILL")    { msg[signum] = "illegal hardware instruction" }
+	if (signam == "INFO")   { msg[signum] = "status request from keyboard" }
+	if (signam == "INT")    { msg[signum] = "interrupt" }
+	if (signam == "IO")     { msg[signum] = "i/o ready" }
+	if (signam == "IOT")    { msg[signum] = "IOT instruction" }
+	if (signam == "KILL")   { msg[signum] = "killed" }
+	if (signam == "LOST")	{ msg[signum] = "resource lost" }
+	if (signam == "PIPE")   { msg[signum] = "broken pipe" }
+	if (signam == "POLL")	{ msg[signum] = "pollable event occurred" }
+	if (signam == "PROF")   { msg[signum] = "profile signal" }
+	if (signam == "PWR")    { msg[signum] = "power fail" }
+	if (signam == "QUIT")   { msg[signum] = "quit" }
+	if (signam == "SEGV")   { msg[signum] = "segmentation fault" }
+	if (signam == "SYS")    { msg[signum] = "invalid system call" }
+	if (signam == "TERM")   { msg[signum] = "terminated" }
+	if (signam == "TRAP")   { msg[signum] = "trace trap" }
+	if (signam == "URG")	{ msg[signum] = "urgent condition" }
+	if (signam == "USR1")   { msg[signum] = "user-defined signal 1" }
+	if (signam == "USR2")   { msg[signum] = "user-defined signal 2" }
+	if (signam == "VTALRM") { msg[signum] = "virtual time alarm" }
+	if (signam == "WINCH")  { msg[signum] = "window size changed" }
+	if (signam == "XCPU")   { msg[signum] = "cpu limit exceeded" }
+	if (signam == "XFSZ")   { msg[signum] = "file size limit exceeded" }
+    }
+}
+
+END {
+    ps = "%s"
+    ifdstr = sprintf("# ifdef USE_SUSPENDED\n\t%csuspended%s%c,\n%s else\n\t%cstopped%s%c,\n# endif\n", 34, ps, 34, "#", 34, ps, 34)
+
+    printf "/** signames.c                                 **/\n"
+    printf "/** architecture-customized signames.c for zsh **/\n"
+    printf "\n"
+    printf "#define SIGCOUNT\t%d\n", max
+    printf "\n"
+    printf "#include %czsh.mdh%c\n", 34, 34
+    printf "\n"
+    printf "/**/\n"
+    printf "char *sigmsg[SIGCOUNT+2] = {\n"
+    printf "\t%c%s%c,\n", 34, "done", 34
+
+    for (i = 1; i <= 0 + max; i++)
+	if (msg[i] == "") {
+	    if (sig[i] == "")
+		printf("\t%c%c,\n", 34, 34)
+	    else if (sig[i] == "STOP")
+		printf ifdstr, " (signal)", " (signal)"
+	    else if (sig[i] == "TSTP")
+		printf ifdstr, "", ""
+	    else if (sig[i] == "TTIN")
+		printf ifdstr, " (tty input)", " (tty input)"
+	    else if (sig[i] == "TTOU")
+		printf ifdstr, " (tty output)", " (tty output)"
+	    else
+		printf("\t%cSIG%s%c,\n", 34, sig[i], 34)
+	} else
+	    printf("\t%c%s%c,\n", 34, msg[i], 34)
+    print "\tNULL"
+    print "};"
+    print ""
+    print "/**/"
+    printf "char *sigs[SIGCOUNT+4] = {\n"
+    printf("\t%cEXIT%c,\n", 34, 34)
+    for (i = 1; i <= 0 + max; i++)
+	if (sig[i] == "")
+	    printf("\t%c%d%c,\n", 34, i, 34)
+	else
+	    printf("\t%c%s%c,\n", 34, sig[i], 34)
+    printf("\t%cZERR%c,\n", 34, 34)
+    printf("\t%cDEBUG%c,\n", 34, 34)
+    print "\tNULL"
+    print "};"
+}
diff --git a/Src/text.c b/Src/text.c
index ec724f27d..88a27495d 100644
--- a/Src/text.c
+++ b/Src/text.c
@@ -415,7 +415,6 @@ getcond(Cond nm, int addpar)
 	    /* Module defined prefix condition. */
 	    char **p = (char **) nm->right;
 
-	    taddstr("-");
 	    taddstr(nm->left);
 	    for (; *p; p++) {
 		taddstr(" ");
@@ -426,7 +425,7 @@ getcond(Cond nm, int addpar)
     case COND_MODI:
 	/* Module defined infix condition. */
 	taddstr(((char **) nm->right)[0]);
-	taddstr(" -");
+	taddstr(" ");
 	taddstr(nm->left);
 	taddstr(" ");
 	taddstr(((char **) nm->right)[1]);
diff --git a/Src/utils.c b/Src/utils.c
index 18a797948..ee06cfeca 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1160,7 +1160,7 @@ read1char(void)
     char c;
 
     while (read(SHTTY, &c, 1) != 1) {
-	if (errno != EINTR)
+	if (errno != EINTR || errflag)
 	    return -1;
     }
     return STOUC(c);
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index f4a1e4015..214f26681 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -12,8 +12,11 @@ headers="../config.h system.h zsh.h sigcount.h signals.h \
 prototypes.h hashtable.h ztype.h"
 
 :<<\Make
-signames.c: signames.awk ../config.h @SIGNAL_H@
-	$(AWK) -f $(sdir)/signames.awk @SIGNAL_H@ > $@
+signames.c: signames1.awk signames2.awk ../config.h @SIGNAL_H@
+	$(AWK) -f $(sdir)/signames1.awk @SIGNAL_H@ >sigtmp.c
+	$(CPP) sigtmp.c >sigtmp.out
+	$(AWK) -f $(sdir)/signames2.awk sigtmp.out > $@
+	rm -f sigtmp.c sigtmp.out
 
 sigcount.h: signames.c
 	grep 'define.*SIGCOUNT' signames.c > $@
@@ -25,7 +28,7 @@ params.o: version.h
 version.h: $(sdir_top)/Config/version.mk
 	echo '#define ZSH_VERSION "'$(VERSION)'"' > $@
 
-zshpaths.h: FORCE
+zshpaths.h: FORCE Makemod
 	@echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp
 	@if cmp -s zshpaths.h zshpaths.h.tmp; then \
 	    rm -f zshpaths.h.tmp; \
diff --git a/configure.in b/configure.in
index 975e02e49..dd6ce1e69 100644
--- a/configure.in
+++ b/configure.in
@@ -214,7 +214,7 @@ if test -n "$auto_cflags"; then
 fi
 if test -n "$auto_ldflags"; then
   case "${enable_zsh_debug}$host_os" in
-    yesaix*|yeshpux*) ;;  # AIX ld does not accept -g
+    yesaix*|yeshpux*|yesnetbsd*) ;;  # "ld -g" is not valid on these systems
     yes*)    LDFLAGS=-g ;;
     *)       LDFLAGS=-s ;;
   esac
@@ -664,12 +664,30 @@ AC_MSG_RESULT($signals_style)
 
 dnl Where is <signal.h> located?  Needed as input for signals.awk
 AC_CACHE_CHECK(where signal.h is located, zsh_cv_path_signal_h,
-[for SIGNAL_H in /usr/include/bsd/sys/signal.h  dnl Next
-                 /usr/include/asm/signum.h      dnl alpha-Linux
-                 /usr/include/asm/signal.h      dnl Linux 1.3.0 and above
-                 /usr/include/linux/signal.h    dnl Linux up to 1.2.11
-                 /usr/include/sys/signal.h      dnl Almost everybody else
-                 /dev/null;                     dnl Just in case we fall through
+[dnl Look at the output from the preprocessor.
+dnl We should get lines of the form `# 1 "/usr/include/signal.h"'
+dnl The following assumes the real definitions are in a file which
+dnl contains the name `sig'; we could relax this if necessary,
+dnl but then you can get a rather long list of files to test.
+dnl The backslash substitution is to persuade cygwin to cough up
+dnl slashes rather than doubled backslashes in the path.
+echo "#include <signal.h>" > nametmp.c
+sigfile_list="`$CPP nametmp.c |
+sed -n -e 's/^#[ 	].*\"\(.*\)\"/\1/p' -e 's/\\\\\\\\/\//g' |
+$AWK '{ if (\$1 ~ \"sig\") files[[\$1]] = \$1 }
+  END { for (var in files) print var }'`"
+rm -f nametmp.c
+if test -z "$sigfile_list"; then
+  dnl In case we don't get the stuff from the preprocesor, use the old
+  dnl list of standard places.
+  sigfile_list="/usr/include/bsd/sys/signal.h
+/usr/include/asm/signum.h
+/usr/include/asm/signal.h
+/usr/include/linux/signal.h
+/usr/include/sys/signal.h
+/dev/null"
+fi
+for SIGNAL_H in $sigfile_list
 do
   test -f $SIGNAL_H && \
   grep '#[ 	]*define[ 	][ 	]*SIG[0-9A-Z]*[ 	]*[0-9][0-9]*' $SIGNAL_H > /dev/null && \
diff --git a/patchlist.txt b/patchlist.txt
index 1cfea6fe8..05fc91e98 100644
--- a/patchlist.txt
+++ b/patchlist.txt
@@ -386,8 +386,62 @@ Sven: GLOB_COMPLETE docs, 5261, 5268
 
 Sven: compctl -M and REC_EXACT fixes, 5262
 
-Sven: rewrite of $foo:q, 5265
+Sven: rewrite of $foo:q, 5265, +doc, 5284
 
 Sven: get matcher number in new completion function, 5266
 
 Me: interrupts in getquery() weren't gracefully handled, 5281
+
+  pws-8
+
+Geoff: no ld -g for NetBSD, 5295
+
+Bart: alter local variables and $argv documentation, 5297
+
+Bart: PWD and OLDPWD export confusion (fixing, not creating), 5299
+
+Bart: trashzle() crashed shell with dynamical loading and zle builtin,
+5305
+
+Matt: CHAR(+) -> CHAR(43) in zmacros, 5311
+
+Sven: compctl matcher to use reference counts, 5316
+
+Sven: keys available in zle widget functions, 5320
+
+Me: compctl -LM, 5321
+
+Me: revamped signames.c generation, 5326, 5329, plus Matt fix, 5330
+
+Sweth, Bart, Me: Functions/allopt, basically as in 2121 with the odd
+emulate and local.
+
+Me: emulate -L, 5332
+
+Sven: printing of zle condition codes, 5335
+
+Sven: Modularisation of new completion shell code, 5341
+
+Sven: ignoring ignored prefix in new conditions, 5342; related fixes,
+5343
+
+Me: patch for completion init and __normal, 5344; Sven fix, 5351
+
+Me: "$foo[@]" didn't remove the argument if $foo wasn't set, 5349;
+Bart's fix so this works on OSes other than AIX, 5361
+
+Sven: change fignore handling, 5352
+
+Sven: redisplay of completion lists; remove display when completion
+failed, 5354
+
+Sven: compadd -R function for suffix removal, 5355
+
+Me: #key-* completions now allow 0 or more key bindings, 5362
+
+Me: Moved Misc/Completion to Functions/Completion; added some of my own
+new-style completions: not posted
+
+Me: 5281 now works, 5364
+
+Me: make dependencies for main.o, Makemod, zshpaths.h, 5365