about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Completion/Base/_brace_parameter2
-rw-r--r--Completion/Base/_long_options9
-rw-r--r--Completion/Base/_subscript13
-rw-r--r--Completion/Base/_vars2
-rw-r--r--Completion/Builtins/_cd2
-rw-r--r--Completion/Commands/_correct_filename47
-rw-r--r--Completion/Core/_multi_parts65
-rw-r--r--Completion/Core/_path_files3
-rw-r--r--Completion/Core/compinit5
-rw-r--r--Completion/README5
-rw-r--r--Completion/User/_pdf2
-rw-r--r--Config/version.mk4
-rw-r--r--Doc/Makefile.in32
-rw-r--r--Doc/Zsh/expn.yo114
-rw-r--r--Src/Zle/zle_hist.c7
-rw-r--r--Src/Zle/zle_misc.c3
-rw-r--r--Src/Zle/zle_tricky.c59
-rw-r--r--Src/Zle/zle_vi.c2
-rw-r--r--Src/init.c2
-rw-r--r--Src/params.c2
-rw-r--r--Src/parse.c10
-rw-r--r--Src/subst.c5
-rw-r--r--Src/utils.c7
-rwxr-xr-xconfig.guess9
-rw-r--r--configure.in6
-rw-r--r--patchlist.txt37
26 files changed, 373 insertions, 81 deletions
diff --git a/Completion/Base/_brace_parameter b/Completion/Base/_brace_parameter
index 092376e78..3fab8510a 100644
--- a/Completion/Base/_brace_parameter
+++ b/Completion/Base/_brace_parameter
@@ -2,4 +2,4 @@
 
 # Simple but without spiffy suffix handling: compgen -v -S '} '
 
-compadd -S '} ' -r '-:?#%+=[/'  - "${(@)${${${(f)$(typeset)}%%\=*}##* }:gs/'//}"
+compadd -S '} ' -r '-:?#%+=[/'  - "${(@)${(@)${(@f)$(set)}%%\=*}:gs/'//}"
diff --git a/Completion/Base/_long_options b/Completion/Base/_long_options
index a5d92632c..cc3175592 100644
--- a/Completion/Base/_long_options
+++ b/Completion/Base/_long_options
@@ -2,9 +2,12 @@
 
 # This function tries to automatically complete long option names. For 
 # this it invokes the command from the line with the `--help' option
-# and then parses the output to find possible option names. For
-# options that get an argument after a `=', the function also tries to 
-# automatically find out what should be complete as the argument.
+# and then parses the output to find possible option names, so you
+# should be careful to make sure that this function is not called for
+# a command that does not support this option.
+#
+# For options that get an argument after a `=', the function also tries
+# to automatically find out what should be complete as the argument.
 # The possible completions for option-arguments can be described with
 # the arguments to this function. This is done by giving pairs of
 # patterns and actions as consecutive arguments. The actions specify
diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript
index 670739a9a..e783d04e7 100644
--- a/Completion/Base/_subscript
+++ b/Completion/Base/_subscript
@@ -1,10 +1,7 @@
 #defcomp -subscript-
 
-local ret=1
-
-_compalso -math- && ret=0
-
-[[ ${(Pt)${compstate[parameter]}} = assoc* ]] &&
-  compgen -k "( ${(kP)${compstate[parameter]}} )" && ret=0
-
-return ret
+if [[ ${(Pt)${compstate[parameter]}} = assoc* ]]; then
+  compgen -S ']' -k "( ${(kP)${compstate[parameter]}} )"
+else
+  _compalso -math-
+fi
diff --git a/Completion/Base/_vars b/Completion/Base/_vars
index 92de51e1f..497a9316f 100644
--- a/Completion/Base/_vars
+++ b/Completion/Base/_vars
@@ -1,3 +1,3 @@
-#defcomp -math- getopts read unset vared
+#defcomp getopts read unset vared
 
 compgen -v
diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd
index 9a58effe0..44443c3d5 100644
--- a/Completion/Builtins/_cd
+++ b/Completion/Builtins/_cd
@@ -59,7 +59,7 @@ elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then
 
   return ret
 elif [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then
-  _path_files -W cdpath -/
+  _path_files -W "(. $cdpath)" -/
 else
   _path_files -/
 fi
diff --git a/Completion/Commands/_correct_filename b/Completion/Commands/_correct_filename
index 582555587..27295738c 100644
--- a/Completion/Commands/_correct_filename
+++ b/Completion/Commands/_correct_filename
@@ -6,18 +6,46 @@
 #
 # You can adapt max_approx to the maximum number of mistakes
 # which are allowed in total.
+#
+# If the numeric prefix is greater than 1, the maximum number of errors
+# will be set to that.
+
+# Doesn't get right special characters in the filename; should
+# strip them (e.g. "foo\ bar" -> "foo bar") and then re-insert them.
 
 emulate -LR zsh
 setopt extendedglob
 
-local file="$PREFIX$SUFFIX" trylist
+local file="$PREFIX$SUFFIX" trylist tilde etilde testcmd
 integer approx max_approx=6
 
-[[ -z $WIDGET ]] && file=$1 
+if [[ -z $WIDGET ]]; then
+  file=$1
+  local IPREFIX
+else
+  (( NUMERIC > 1 )) && max_approx=$NUMERIC
+fi
+
+if [[ $file = \~*/* ]]; then
+  tilde=${file%%/*}
+  etilde=${~tilde}
+  file=${file/#$tilde/$etilde}
+fi
+
+if [[ $CURRENT -eq 1 && $file != /* ]]; then
+  testcmd=1
+elif [[ $file = \=* ]]; then
+  [[ -n $WIDGET ]] && PREFIX="$PREFIX[2,-1]"
+  IPREFIX="${IPREFIX}="
+  file="$file[2,-1]"
+  testcmd=1
+fi
 
-if [[ -e "$file" ]]; then
+# We need the -Q's to avoid the tilde we've put back getting quoted.
+if [[ -z $testcmd && -e "$file" ]] ||
+  { [[ -n $testcmd ]] && whence "$file" >&/dev/null }; then
   if [[ -n $WIDGET ]]; then
-    compadd -U -i "$IPREFIX" "$file"
+    compadd -QUf -i "$IPREFIX" "${file/#$etilde/$tilde}"
     [[ -n "$compstate[insert]" ]] && compstate[insert]=menu
   else
     print "$file"
@@ -26,14 +54,19 @@ if [[ -e "$file" ]]; then
 fi
 
 for (( approx = 1; approx <= max_approx; approx++ )); do
-  trylist=( (#a$approx)"$file"(N) )
+  if [[ -z $testcmd ]]; then
+    trylist=( (#a$approx)"$file"(N) )
+  else
+    trylist=( "${(@)${(@f)$(whence -wm "(#a$approx)$file" 2>/dev/null)}%:*}" )
+    [[ $file = */* ]] || trylist=(${trylist##*/})
+  fi
   (( $#trylist )) && break
 done
 (( $#trylist )) || return 1
 
 if [[ -n $WIDGET ]]; then
-  compadd -U -i "$IPREFIX" -U "${trylist[@]}"
+  compadd -QUf -i "$IPREFIX" "${trylist[@]/#$etilde/$tilde}"
   [[ -n "$compstate[insert]" ]] && compstate[insert]=menu
 else
-  print "${trylist[@]}"
+  print "$IPREFIX${^trylist[@]}"
 fi
diff --git a/Completion/Core/_multi_parts b/Completion/Core/_multi_parts
index 1f51d2f6d..0c677aab7 100644
--- a/Completion/Core/_multi_parts
+++ b/Completion/Core/_multi_parts
@@ -8,7 +8,7 @@
 # separator character are then completed independently.
 
 local sep matches patstr orig matchflags pref i tmp1 tmp2 nm
-local group expl
+local group expl menu origflags mflags
 
 _match_test _multi_parts || return 1
 
@@ -42,22 +42,25 @@ else
 fi
 
 # Now build the pattern from what we have on the line. We also save
-# the original string in `orig'. The `eval' is used to replace our
-# separator character by `*<sep>'.
+# the original string in `orig'.
 
-if [[ -o globcomplete ]]; then
+if [[ $#compstate[pattern_match] -ne 0 ]]; then
   patstr="${PREFIX}*${SUFFIX}*"
 else
   patstr="${PREFIX:q}*${SUFFIX:q}*"
 fi
 orig="${PREFIX}${SUFFIX}"
 
+[[ $compstate[insert] = *menu || -n "$_comp_correct" ||
+   ( $#compstate[pattern_match] -ne 0 &&
+     "$orig" != "${orig:q}" ) ]] && menu=yes
+
 matchflags=""
 _match_pattern _path_files patstr matchflags
+origflags="$matchflags"
 [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
 
 patstr="${${patstr//$sep/*$sep}//\*##/*}"
-#eval patstr\="\$patstr:gs-${sep}-\*${sep}-:gs/\*\*/\*/"
 
 # First we will skip over those parts of the matches for which we have 
 # exact substrings on the line. In `pref' we will build the
@@ -70,19 +73,26 @@ while [[ "$orig" = *${sep}* ]] do
   # `matches' that match the prefix we have and the exact substring in 
   # the array `tmp1'.
 
-  pat="${${${patstr#*${sep}}%${sep}*}//\*/[^${sep}]#}${patstr##*${sep}}"
-  tmp1=( "${(@M)matches:#${~matchflags}${orig%%${sep}*}${sep}${~pat}}" )
+  if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then
+    mflags="$origflags"
+  else
+    mflags="$matchflags"
+  fi
+
+  pat="${${${patstr#*${sep}}%${sep}*}//\*/[^${sep}]#}"
+  tmp1=( "${(@M)matches:#${~mflags}${orig%%${sep}*}${sep}${~pat}}" )
 
   # If there are no words matching the exact substring, stop.
 
   (( $#tmp1 )) || break
 
   # Otherwise add the part to the prefix, remove it from the matches
-  # (which will also remove all words not matching the string at all), 
-  # and set `patstr' and `orig' to the next component.
+  # (and also remove all words not matching the string at all), and
+  # set `patstr' and `orig' to the next component.
 
-  pref="$pref${orig%%${sep}*}${sep}"
-  matches=( "${(@)${(@)matches#${orig%%${sep}*}${sep}}:#}" )
+  tmp1="${orig%%${sep}*}${sep}"
+  pref="$pref$tmp1"
+  matches=("${(@)${(@)${(@M)matches:#${tmp1}*}#$tmp1}:#}")
   orig="${orig#*${sep}}"
   patstr="${patstr#*${sep}}"
 done
@@ -95,11 +105,16 @@ if [[ "$patstr" = *${sep}* ]]; then
 else
   pat="$patstr"
 fi
-tmp1=( "${(@M)matches:#${~matchflags}${~pat}}" )
+if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then
+  mflags="$origflags"
+else
+  mflags="$matchflags"
+fi
+tmp1=( "${(@M)matches:#${~mflags}${~pat}}" )
 
 if (( $#tmp1 )); then
 
-  # There are words that are matched, put them int `matches' and then
+  # There are words that are matched, put them into `matches' and then
   # move all unambiguous components from the beginning into `pref'.
 
   matches=( "$tmp1[@]" )
@@ -113,7 +128,7 @@ if (( $#tmp1 )); then
     tmp2=( "${(@)matches:#${tmp1}*}" )
     (( $#tmp2 )) && break
 
-    # All matches have the same prefix, but it into `pref' and remove
+    # All matches have the same prefix, put it into `pref' and remove
     # it from the matches.
 
     pref="$pref$tmp1"
@@ -131,21 +146,26 @@ if (( $#tmp1 )); then
 
   if [[ -z "$orig" && "$PREFIX$SUFFIX" != "$pref$orig" ]]; then
     compadd -QU  "$group[@]" "$expl[@]" -i "$IPREFIX" -S '' - "${pref}${orig}"
-  elif [[ $compstate[insert] = *menu ]]; then
+  elif [[ -n "$menu" ]]; then
+    if [[ "$orig" = *${sep}* ]]; then
+      orig="${sep}${orig#*${sep}}"
+    else
+      orig=''
+    fi
     for i in "$matches[@]" ; do
       if [[ "$i" = *${sep}* ]]; then
         compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
-	        -p "$pref" -qS "$sep" - "${i%%${sep}*}"
+	        -p "$pref" -s "$orig" - "${i%%${sep}*}${sep}"
       else
         compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \
-	        -p "$pref" - "${i%%${sep}*}"
+	        -p "$pref" -s "$orig" - "${i%%${sep}*}"
       fi
     done
   else
     for i in "$matches[@]" ; do
       if [[ "$i" = *${sep}* ]]; then
-        compadd -U -i "$IPREFIX" -p "$pref" -s "${sep}${i#*${sep}}" \
-	        "$group[@]" "$expl[@]" -M "r:|${sep}=*" - "${i%%${sep}*}"
+        compadd -U -i "$IPREFIX" -p "$pref" -s "${i#*${sep}}" \
+	        "$group[@]" "$expl[@]" -M "r:|${sep:q}=*" - "${i%%${sep}*}${sep}"
       else
         compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -p "$pref" - "$i"
       fi
@@ -163,7 +183,12 @@ elif [[ "$patstr" = *${sep}* ]]; then
     # First we get all words matching at least this component in
     # `tmp1'. If there are none, we give up.
 
-    tmp1=( "${(@M)matches:#${~matchflags}${~patstr%%${sep}*}${sep}*}" )
+    if [[ -n "$_comp_correct" && "${#orig%%${sep}*}" -le _comp_correct ]]; then
+      mflags="$origflags"
+    else
+      mflags="$matchflags"
+    fi
+    tmp1=( "${(@M)matches:#${~mflags}${~patstr%%${sep}*}${sep}*}" )
     (( $#tmp1 )) || break
 
     # Then we check if there are words that have a different prefix.
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
index 535ba537c..4c61ac7ef 100644
--- a/Completion/Core/_path_files
+++ b/Completion/Core/_path_files
@@ -111,7 +111,7 @@ orig="${PREFIX}${SUFFIX}"
 
 [[ $compstate[insert] = *menu || -n "$_comp_correct" ||
    ( $#compstate[pattern_match] -ne 0 &&
-     "$orig" != "${orig:q}" ) ]] && menu=yes
+     "${orig#\~}" != "${${orig#\~}:q}" ) ]] && menu=yes
 
 
 # We will first try normal completion called with `compgen', but only if we
@@ -405,6 +405,7 @@ for prepath in "$prepaths[@]"; do
     # No match, insert the expanded path and add the original tail.
 
     [[ "$testpath[-1]" = / ]] && testpath="$testpath[1,-2]"
+    [[ -z "$testpath" && "$linepath[-1]" = / ]] && linepath="$linepath[1,-2]"
     [[ -n "$ostr" && -n "$linepath$testpath" ]] && ostr="/$ostr"
 
     # But only if something changed.
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index 31d011565..466c80d36 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -221,12 +221,11 @@ compdef() {
 # set key `baz' to the empty string.
 
 compconf() {
-  local i name
+  local i
 
   for i; do
     if [[ "$i" = *\=* ]]; then
-      name="${i%%\=*}"
-      compconfig[$name]="${i#*\=}"
+      compconfig[${i%%\=*}]="${i#*\=}"
     else
       compconfig[$i]=''
     fi
diff --git a/Completion/README b/Completion/README
index f95e67699..931d14355 100644
--- a/Completion/README
+++ b/Completion/README
@@ -74,7 +74,10 @@ Base:
     This handles options beginning with `--', as in many GNU commands.
     The command must accept the --help option to list the possible options.
     __long_options can also take arguments to help it decide what to
-    complete as the value of the option.
+    complete as the value of the option.  Note that this is potentially
+    dangerous because the command from the line will be called with the
+    --help option and hence could cause damage if used with a command
+    that does not support it.
   _match_pattern
   _match_test
     These are used by Base/_path_files (and hence also Base/_files)
diff --git a/Completion/User/_pdf b/Completion/User/_pdf
index 7d7756c3e..11abc216b 100644
--- a/Completion/User/_pdf
+++ b/Completion/User/_pdf
@@ -1,3 +1,3 @@
-function acroread
+#defcomp acroread
 
 _files -g '*.(pdf|PDF)'
diff --git a/Config/version.mk b/Config/version.mk
index e5fa2cbd6..005321c5d 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-12
-VERSION_DATE='March 11, 1999'
+VERSION=3.1.5-pws-13
+VERSION_DATE='March 20, 1999'
diff --git a/Doc/Makefile.in b/Doc/Makefile.in
index 7bc5d7ada..d1fcf162a 100644
--- a/Doc/Makefile.in
+++ b/Doc/Makefile.in
@@ -100,7 +100,37 @@ zshall.1: zsh.yo
 	$(YODL) -I$(sdir) META-FAQ.yo | sed -e '/NEXTLINE/N' -e '/DELLINE/d' -e '/^SECTHEAD$$/{N;s/^SECTHEAD.//;h;s/./-/g;H;g;}' -e 's/  *$$//' > $(sdir_top)/META-FAQ
 	test -f $(sdir_top)/META-FAQ
 
-$(YODLDOC): $(YODLSRC) version.yo
+$(YODLDOC): version.yo
+
+zsh.texi: $(YODLSRC)
+
+$(MAN): zmacros.yo zman.yo
+
+zsh.1 zshall.1: Zsh/intro.yo Zsh/metafaq.yo Zsh/invoke.yo Zsh/files.yo \
+                Zsh/filelist.yo Zsh/filelist.yo Zsh/seealso.yo
+
+zshbuiltins.1: Zsh/builtins.yo
+
+zshcompctl.1: Zsh/compctl.yo
+
+zshcompwid.1: Zsh/compwid.yo
+
+zshexpn.1: Zsh/expn.yo
+
+zshmisc.1: Zsh/grammar.yo Zsh/redirect.yo Zsh/exec.yo Zsh/func.yo \
+           Zsh/jobs.yo Zsh/arith.yo Zsh/cond.yo Zsh/compat.yo \
+           Zsh/prompt.yo Zsh/restricted.yo
+
+zshmodules.1: Zsh/modules.yo Zsh/mod_cap.yo Zsh/mod_clone.yo \
+              Zsh/mod_comp1.yo Zsh/mod_compctl.yo Zsh/mod_deltochar.yo \
+              Zsh/mod_example.yo Zsh/mod_files.yo Zsh/mod_sched.yo \
+              Zsh/mod_stat.yo Zsh/mod_zftp.yo Zsh/mod_zle.yo
+
+zshoptions.1: Zsh/options.yo
+
+zshparam.1: Zsh/params.yo
+
+zshzle.1: Zsh/zle.yo
 
 version.yo: $(sdir_top)/Config/version.mk
 	( \
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 4fd64981f..4f3a75199 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -464,10 +464,11 @@ item(tt(${=)var(spec)tt(}))(
 pindex(SH_WORD_SPLIT, use of)
 cindex(field splitting, sh style)
 cindex(sh, field splitting style)
-Turn on the tt(SH_WORD_SPLIT) option for the
-evaluation of var(spec); if the `tt(=)' is doubled, turn it off.
+Perform word splitting using the rules for tt(SH_WORD_SPLIT) during the
+evaluation of var(spec), but regardless of whether the parameter appears in
+double quotes; if the `tt(=)' is doubled, turn it off.
 vindex(IFS, use of)
-When this option is set, parameter expansions are split into
+This forces parameter expansions to be split into
 separate words before substitution, using tt(IFS) as a delimiter.
 This is done by default in most other shells.
 
@@ -494,6 +495,12 @@ possible to perform nested operations:  tt(${${foo#head}%tail})
 substitues the value of tt($foo) with both tt(head) and tt(tail)
 deleted.  The form with tt($LPAR())...tt(RPAR()) is often useful in
 combination with the flags described next; see the example below.
+
+Note that when nested parameter expansion takes place the flags are em(not)
+propagated back.  Each level of expansion uses three factors: whether it
+is in double quotes, what flags it has been provided with, and whether the
+value it has is a scalar or an array.  Some examples are given below.
+
 subsect(Parameter Expansion Flags)
 cindex(parameter expansion flags)
 cindex(flags, parameter expansion)
@@ -693,7 +700,64 @@ item(tt(N))(
 Include the length of the match in the result.
 )
 enditem()
-subsect(Example)
+
+subsect(Rules)
+
+Here is a summary of the rules for substitution.  Some particular examples
+are given below.  Note that the Zsh Development Group accepts em(no
+responsibility) for any brain damage which may occur during the reading of
+the following rules.
+
+startitem()
+item(tt(1.))(
+If multiple nested tt(${...}) forms are present, substitution is
+performed from the inside outwards.  At each level, the substitution takes
+account of whether the current value is a scalar or an array, whether the
+whole substitution is in double quotes, and what flags are supplied to the
+current level of substitution.  If the value is a raw parameter reference
+with a subscript, such as tt(${)var(var)tt([3]}), the effect of
+subscripting is applied directly to the parameter.  The value passed back
+to an enclosing substitution is always an array, which however will consist
+of one word if the value was not itself an array.
+)
+item(tt(2.))(
+If the value after this process is an array, and the substitution
+appears in double quotes, and no tt((@)) flag is present at the current
+level, the words of the value are joined with the first character of the
+parameter tt($IFS), by default a space, between each word (single word
+arrays are not modified).  If the tt((j)) flag is present, that is used for
+joining instead of tt($IFS). Any remaining subscript is evaluated at
+this point, based on whether the value is an array or a scalar.
+)
+item(tt(3.))(
+Any modifiers, as specified by a trailing tt(#), tt(%), tt(/)
+(possibly doubled) or by a set of modifiers of the form tt(:...) (see
+noderef(Modifiers) in noderef(History Expansion)), are applied to the words
+of the value at this level.
+)
+item(tt(4.))(
+If the tt((j)) flag is present, or no tt((j)) flag is present but
+the string is to be split as given by rules tt(5.) or tt(6.), and joining
+did not take place at step tt(2.), any words in the value are joined
+together using the given string or the first character of tt($IFS) if none.
+Note that the tt((F)) flag implicitly supplies a string for joining in this
+manner.
+)
+item(tt(5.))(
+If one of the tt((s)) or tt((f)) flags are present, or the tt(=)
+specifier was present (e.g. tt(${=)var(var)tt(})), the word is joined on
+occurrences of the specified string, or (for tt(=) with neither of the two
+flags present) any of the characters in tt($IFS).
+)
+item(tt(6.))(
+If no tt((s)), tt((f)) or tt(=) was given, but the word is not
+quoted and the option tt(SH_WORD_SPLIT) is set, the word is split on
+occurrences of any of the characters in tt($IFS).  Note that all steps,
+including this one, take place at all levels of a nested substitution.
+)
+enditem()
+
+subsect(Examples)
 The flag tt(f) is useful to split a double-quoted substitution line by
 line.  For example, `tt("${(f)$LPAR()<)var(file)tt(RPAR()}")'
 substitutes the contents of var(file) divided so that each line is
@@ -701,6 +765,48 @@ an element of the resulting array.  Compare this with the effect of
 `tt($)tt(LPAR()<)var(file)tt(RPAR())' alone, which divides the file
 up by words, or the same inside double quotes, which makes the entire
 content of the file a single string.
+
+The following illustrates the rules for nested parameter expansions.
+Suppose that tt($foo) contains the array tt(LPAR()bar baz)tt(RPAR()):
+
+startitem()
+item(tt("${(@)${foo}[1]}"))(
+This produces the result tt(bar baz).  First, the inner substitution
+tt("${foo}"), which has no array (tt(@)) flag, produces a single word
+result.  The outer substitution tt("${(@)...[1]}") acts on this result as
+if it were a one word array, because of the array flag, so the result is
+just that single word.
+)
+item(tt("${${(@)foo}[1]}"))(
+The produces the result tt(b).  In this case, the inner substitution
+tt("${(@)foo}") produces the array tt(LPAR()bar baz)tt(RPAR()).  The outer
+substitution tt("${...[1]}"), however, has no array flag, so that it joins
+the array it has to a single word and indexes as if it were a string.  Note
+that this is not identical to the case tt("${foo[1]}"), since here the
+expression tt(foo[1]) is recognised immediately as an index into an array,
+so that the result in that case is tt(bar).
+)
+enditem()
+
+As an example of the rules for word splitting and joining, suppose tt($foo)
+contains the array tt(LPAR()ax1 bx1)tt(RPAR()).  Then
+
+startitem()
+item(tt(${(s/x/)foo}))(
+produces the words `tt(a)', `tt(1 b)' and `tt(1)'.
+)
+item(tt(${(j/x/s/x/)foo}))(
+produces `tt(a)', `tt(1)', `tt(b)' and `tt(1)'.
+)
+item(tt(${(s/x/)foo%%1*}))(
+produces `tt(a)' and `tt( b)' (note the extra space).  As substitution
+occurs before either joining or splitting, the operation  first generates
+the modified array tt(LPAR()ax bx)tt(RPAR()), which is joined to give
+tt("ax bx"), and then split to give `tt(a)', `tt( b)' and `'.  The final
+empty string will then be elided, as it is not in double quotes.
+)
+enditem()
+
 texinode(Command Substitution)(Arithmetic Expansion)(Parameter Expansion)(Expansion)
 sect(Command Substitution)
 cindex(command substitution)
diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c
index 2def5f03a..0064d4ef0 100644
--- a/Src/Zle/zle_hist.c
+++ b/Src/Zle/zle_hist.c
@@ -498,6 +498,7 @@ zle_goto_hist(int ev)
     histline = ev;
     setline(t);
     setlastline();
+    clearlist = 1;
     return 1;
 }
 
@@ -515,6 +516,7 @@ pushline(void)
     stackcs = cs;
     *line = '\0';
     ll = cs = 0;
+    clearlist = 1;
 }
 
 /**/
@@ -537,9 +539,9 @@ pushlineoredit(void)
 	cs += ics;
     }
     pushline();
-    if (!isfirstln) {
+    if (!isfirstln)
 	errflag = done = 1;
-    }
+    clearlist = 1;
 }
 
 /**/
@@ -571,6 +573,7 @@ getline(void)
 	memcpy((char *)line + cs, s, cc);
 	cs += cc;
 	free(s);
+	clearlist = 1;
     }
 }
 
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index cf9aac435..e7f1744d5 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -135,6 +135,7 @@ killbuffer(void)
 {
     cs = 0;
     forekill(ll, 0);
+    clearlist = 1;
 }
 
 /**/
@@ -157,6 +158,7 @@ backwardkillline(void)
 		cs--, i++;
     }
     forekill(i, 1);
+    clearlist = 1;
 }
 
 /**/
@@ -288,6 +290,7 @@ killline(void)
 		cs++, i++;
     }
     backkill(i, 0);
+    clearlist = 1;
 }
 
 /**/
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index 62c39fdc9..c303fd97d 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -1322,18 +1322,17 @@ get_comp_string(void)
 	 * as being in math.                                              */
 	if (inwhat != IN_MATH) {
 	    int i = 0;
-	    char *nb = (iident(*s) ? s : s + 1), *ne = NULL;
+	    char *nnb = (iident(*s) ? s : s + 1), *nb = NULL, *ne = NULL;
 
 	    for (tt = s; ++tt < s + cs - wb;)
 		if (*tt == Inbrack) {
 		    i++;
+		    nb = nnb;
 		    ne = tt;
 		} else if (i && *tt == Outbrack)
 		    i--;
-		else if (!iident(*tt)) {
-		    nb = tt + 1;
-		    ne = NULL;
-		}
+		else if (!iident(*tt))
+		    nnb = tt + 1;
 	    if (i) {
 		inwhat = IN_MATH;
 		insubscr = 1;
@@ -1347,12 +1346,35 @@ get_comp_string(void)
 	    }
 	}
 	if (inwhat == IN_MATH) {
-	    /* In mathematical expression, we complete parameter names (even *
-	     * if they don't have a `$' in front of them).  So we have to    *
-	     * find that name.                                               */
-	    for (we = cs; iident(line[we]); we++);
-	    for (wb = cs; --wb >= 0 && iident(line[wb]););
-	    wb++;
+	    if (compfunc) {
+		int lev;
+		char *p;
+
+		for (wb = cs - 1, lev = 0; wb > 0; wb--)
+		    if (line[wb] == ']' || line[wb] == ')')
+			lev++;
+		    else if (line[wb] == '[') {
+			if (!lev--)
+			    break;
+		    } else if (line[wb] == '(') {
+			if (!lev && line[wb - 1] == '(')
+			    break;
+			if (lev)
+			    lev--;
+		    }
+		wb++;
+		p = (char *) line + wb;
+		if (wb && (*p == '[' || *p == '(') &&
+		    !skipparens(*p, (*p == '[' ? ']' : ')'), &p))
+			we = p - (char *) line;
+	    } else {
+		/* In mathematical expression, we complete parameter names  *
+		 * (even if they don't have a `$' in front of them).  So we *
+		 * have to find that name.                                  */
+		for (we = cs; iident(line[we]); we++);
+		for (wb = cs; --wb >= 0 && iident(line[wb]););
+		wb++;
+	    }
 	    zsfree(s);
 	    s = zalloc(we - wb + 1);
 	    strncpy(s, (char *) line + wb, we - wb);
@@ -5032,6 +5054,7 @@ static void
 docompletion(char *s, int lst, int incmd)
 {
     HEAPALLOC {
+	char *opm;
 	LinkNode n;
 
 	pushheap();
@@ -5045,7 +5068,7 @@ docompletion(char *s, int lst, int incmd)
 		   ((isset(AUTOLIST) && !isset(BASHAUTOLIST)) ? 
 		    (isset(LISTAMBIGUOUS) ? 3 : 2) : 0) : 1);
 	zsfree(comppatmatch);
-	comppatmatch = ztrdup(useglob ? "yes" : "");
+	opm = comppatmatch = ztrdup(useglob ? "yes" : "");
 	zsfree(compforcelist);
 	compforcelist = ztrdup("");
 	haspattern = 0;
@@ -5057,7 +5080,7 @@ docompletion(char *s, int lst, int incmd)
 	    clearlist = 1;
 	    goto compend;
 	}
-	if (comppatmatch && *comppatmatch)
+	if (comppatmatch && *comppatmatch && comppatmatch != opm)
 	    haspattern = 1;
 	if (!useline && uselist)
 	    /* All this and the guy only wants to see the list, sigh. */
@@ -5240,14 +5263,20 @@ callcompfunc(char *s, char *fn)
 	zsfree(compprefix);
 	zsfree(compsuffix);
 	if (unset(COMPLETEINWORD)) {
-	    tmp = quotename(s, NULL, NULL, NULL);
+	    if (inwhat == IN_MATH)
+		tmp = s;
+	    else
+		tmp = quotename(s, NULL, NULL, NULL);
 	    untokenize(tmp);
 	    compprefix = ztrdup(tmp);
 	    compsuffix = ztrdup("");
 	} else {
 	    char *ss = s + offs, sav;
 	    
-	    tmp = quotename(s, &ss, NULL, NULL);
+	    if (inwhat == IN_MATH)
+		tmp = s;
+	    else
+		tmp = quotename(s, &ss, NULL, NULL);
 	    sav = *ss;
 	    *ss = '\0';
 	    untokenize(tmp);
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index 2e4fb4a32..5b1548e25 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -535,6 +535,7 @@ viopenlinebelow(void)
     spaceinline(1);
     line[cs++] = '\n';
     startvitext(1);
+    clearlist = 1;
 }
 
 /**/
@@ -545,6 +546,7 @@ viopenlineabove(void)
     spaceinline(1);
     line[cs] = '\n';
     startvitext(1);
+    clearlist = 1;
 }
 
 /**/
diff --git a/Src/init.c b/Src/init.c
index ab955b26a..f3576aadd 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -743,7 +743,7 @@ run_init_scripts(void)
 	    char *s = getsparam("ENV");
 	    if (islogin)
 		sourcehome(".profile");
-	    noerrs = 1;
+	    noerrs = 2;
 	    if (s && !parsestr(s)) {
 		singsub(&s);
 		noerrs = 0;
diff --git a/Src/params.c b/Src/params.c
index eb50c0b7e..7ae6a75ec 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -413,7 +413,7 @@ createparamtable(void)
 
     argvparam = (Param) paramtab->getnode(paramtab, "*");
 
-    noerrs = 1;
+    noerrs = 2;
 
     HEAPALLOC {
 	/* Add the standard non-special parameters which have to    *
diff --git a/Src/parse.c b/Src/parse.c
index eb8398b1a..043aa0f0d 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -955,9 +955,17 @@ par_simple(Cmd c)
 	    nocorrect = 1;
 	else if (tok == ENVSTRING) {
 	    struct varasg *v = (struct varasg *)make_varnode();
+	    char *p;
 
 	    v->type = PM_SCALAR;
-	    equalsplit(v->name = tokstr, &v->str);
+	    v->name = tokstr;
+	    for (p = tokstr; *p && *p != Inbrack && *p != '='; p++);
+	    if (*p == Inbrack && !skipparens(Inbrack, Outbrack, &p) &&
+		*p == '=') {
+		*p = '\0';
+		v->str = p + 1;
+	    } else
+		equalsplit(tokstr, &v->str);
 	    addlinknode(c->vars, v);
 	    isnull = 0;
 	} else if (tok == ENVARRAY) {
diff --git a/Src/subst.c b/Src/subst.c
index 42e8e36d4..651179b72 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -941,6 +941,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	} else if ((*s == '#' || *s == Pound) &&
 		   (iident(s[1])
 		    || s[1] == '*' || s[1] == Star || s[1] == '@'
+		    || s[1] == '-' || (s[1] == ':' && s[2] == '-')
 		    || (isstring(s[1]) && (s[2] == Inbrace || s[2] == Inpar))))
 	    getlen = 1 + whichlen, s++;
 	else if (*s == '~' || *s == Tilde) {
@@ -976,7 +977,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s);
 	sav = *s;
 	*s = 0;
-	if (multsub(&val, (((quoted || aspar) && !nojoin) ? NULL : &aval),
+	if (multsub(&val, ((!aspar && (!quoted || nojoin)) ? &aval : NULL),
 		    &isarr, NULL) &&
 	    quoted) {
 	    isarr = -1;
@@ -1272,7 +1273,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	case '-':
 	    if (vunset) {
 		val = dupstring(s);
-		multsub(&val, &aval, &isarr, NULL);
+		multsub(&val, NULL, &isarr, NULL);
 		copied = 1;
 	    }
 	    break;
diff --git a/Src/utils.c b/Src/utils.c
index d010df4e0..3f8177271 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -52,8 +52,11 @@ char *scriptname;
 void
 zerr(const char *fmt, const char *str, int num)
 {
-    if (errflag || noerrs)
+    if (errflag || noerrs) {
+	if (noerrs < 2)
+	    errflag = 1;
 	return;
+    }
     errflag = 1;
     trashzle();
     /*
@@ -1306,7 +1309,7 @@ spckword(char **s, int hist, int cmd, int ask)
 		return;
 	    guess = dupstring(guess);
 	    ne = noerrs;
-	    noerrs = 1;
+	    noerrs = 2;
 	    singsub(&guess);
 	    noerrs = ne;
 	    if (!guess)
diff --git a/config.guess b/config.guess
index 2960d6e0d..9479759c3 100755
--- a/config.guess
+++ b/config.guess
@@ -767,6 +767,9 @@ EOF
     RM*:SINIX-*:*:*)
 	echo mips-sni-sysv4
 	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
     *:SINIX-*:*:*)
 	if uname -p 2>/dev/null >/dev/null ; then
 		UNAME_MACHINE=`(uname -p) 2>/dev/null`
@@ -801,6 +804,12 @@ EOF
 	        echo mips-unknown-sysv${UNAME_RELEASE}
 	fi
         exit 0 ;;
+    Power*:Rhapsody:*:*)
+        echo powerpc-apple-rhapsody${UNAME_RELEASE}
+        exit 0 ;;
+    *:Rhapsody:*:*)
+        echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+        exit 0 ;;
     BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
 	echo powerpc-be-beos
 	exit 0 ;;
diff --git a/configure.in b/configure.in
index 11aab932d..f022744f4 100644
--- a/configure.in
+++ b/configure.in
@@ -847,8 +847,8 @@ dnl CHECK FOR SYSTEMS REQUIRING GETCWD
 AC_CACHE_CHECK(whether we should use the native getcwd,
 zsh_cv_use_getcwd,
 [case "${host_cpu}-${host_vendor}-${host_os}" in
-    *QNX*) zsh_cv_use_getcwd=no ;;
-    *) zsh_cv_use_getcwd=yes ;;
+    *QNX*) zsh_cv_use_getcwd=yes ;;
+    *) zsh_cv_use_getcwd=no ;;
  esac])
 if test $zsh_cv_use_getcwd = yes; then
   AC_DEFINE(USE_GETCWD)
@@ -893,7 +893,7 @@ dnl system names directly.
 dnl The doubled square brackets are necessary because autoconf uses m4.
 AC_CACHE_CHECK(if typeahead needs FIONREAD, zsh_cv_sys_clobbers_typeahead,
 [case x-$host_vendor-$host_os in
-    x-*-ultrix* | x-*-dgux* | x-sni-sysv4*)
+    x-*-ultrix* | x-*-dgux* | x-sni-sysv4* | x-*-irix*)
 	zsh_cv_sys_clobbers_typeahead=yes;;
     *)
 	zsh_cv_sys_clobbers_typeahead=no;;
diff --git a/patchlist.txt b/patchlist.txt
index 7766e1e2e..131be8c10 100644
--- a/patchlist.txt
+++ b/patchlist.txt
@@ -766,3 +766,40 @@ _long_options into Base and mentioned it in Completion/README.
 
 Geoff: 5779: correct mistakes some bozo (guess who) made testing rlim_t for
 long long.
+
+  pws-13
+
+pws: 5780: Completion/Base/_brace_parameter change
+
+Sven (reposted by Bart): 5783: zerr() sets errflag even if noerrs is set
+
+Sven: 5795: parsing change for assignment and arrays in nested
+substitution.
+
+Sven: 5796: globcomplete shouldn't always turn on menucompletion
+
+pws: 5797: set CLOBBERS_TYPEAHEAD for Irix; old config.guess change for
+Reliant UNIX and Apple Rhapsody re-imported from old config.guess.
+
+Sven: 5800: _path_files; path altered when no possible match
+
+Sven: 5804: _pdf
+
+Sven: 5811: put back _multi_parts which got left out when it was moved into
+Core.
+
+Sven: 5818: parameter name in subscript which looks math-like; _subscript.
+
+Sven: 5829: clear the completion list in more zle functions
+
+Sven: 5830: in ${#:-stuff}, stuff is treated as a single word (unless split
+for some other reason).
+
+Sven: 5831: in subscripts and math environments, the whole string is always
+passed down to the function handler.
+
+Sven: 5852: warnings about _long_options
+
+pws: 5854: man page dependencies in Doc/Makefile.in
+
+Sven: 5862: _path_files (turning on menu) and _cd (include . in path)