about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@zsh.org>2013-10-13 10:59:52 -0700
committerBart Schaefer <schaefer@zsh.org>2013-10-13 10:59:52 -0700
commit332924513bade9bae205bd8ffd5d0e3f8e8e1d62 (patch)
treeda57173ab6013d0f85e9760447c18a34c3633f93
parent5faab39a7e87d180e52bb6ebb9bf101f176cc40b (diff)
parentd5ba3ed24579bb12df958c09224367e16e70bad2 (diff)
downloadzsh-332924513bade9bae205bd8ffd5d0e3f8e8e1d62.tar.gz
zsh-332924513bade9bae205bd8ffd5d0e3f8e8e1d62.tar.xz
zsh-332924513bade9bae205bd8ffd5d0e3f8e8e1d62.zip
Merge branch 'master' of git://git.code.sf.net/p/zsh/code
-rw-r--r--ChangeLog39
-rw-r--r--Completion/Unix/Command/_sh11
-rw-r--r--Completion/Zsh/Command/_disable15
-rw-r--r--Completion/Zsh/Command/_enable14
-rw-r--r--Doc/Zsh/builtins.yo2
-rw-r--r--Doc/Zsh/compsys.yo167
-rw-r--r--Doc/Zsh/mod_parameter.yo8
-rw-r--r--Src/Modules/parameter.c40
-rw-r--r--Src/Modules/parameter.mdd2
-rw-r--r--Src/hist.c17
-rw-r--r--Src/pattern.c3
-rw-r--r--Test/V01zmodload.ztst2
12 files changed, 232 insertions, 88 deletions
diff --git a/ChangeLog b/ChangeLog
index 524f54242..4a88f25aa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2013-10-12  Barton E. Schaefer  <schaefer@zsh.org>
+
+	* 31818: Completion/Unix/Command/_sh, Doc/Zsh/compsys.yo: to avoid
+	side effects, reposition the _arguments call in _sh for the zsh
+	special case.  Document the side effects so avoided, and clean up
+	the _arguments documentation a bit along the way.
+
+2013-10-11  Mikael Magnusson  <mikachu@gmail.com>
+
+	* 31805: Doc/Zsh/mod_parameter.yo, Src/Modules/parameter.c,
+	Src/Modules/parameter.mdd, Src/pattern.c, Test/V01zmodload.ztst:
+	Add $patchars and $dis_patchars to zsh/parameter module
+
+	* 31805: Completion/Zsh/Command/_disable,
+	Completion/Zsh/Command/_enable, Doc/Zsh/builtins.yo: Update
+	_enable and _disable for -p, fix related typo in docs
+
+	* 31806: Completion/Zsh/Command/_disable,
+	Completion/Zsh/Command/_enable, Workaround special characters
+	in alias and function names breaking _arguments syntax
+
+2013-10-11  Peter Stephenson  <p.stephenson@samsung.com>
+
+	* 31815: Src/hist.c: more fallout from 31789: we need to save
+	using pushed history file before we pop.
+
 2013-10-10  Peter Stephenson  <p.stephenson@samsung.com>
 
 	* 31810: Test/E02xtrace.ztst: tests for simple cases of XTRACE
@@ -13,12 +39,13 @@
 
 2013-10-08  Barton E. Schaefer  <schaefer@zsh.org>
 
-	* 31797: partly fix long-standing history expansion bug in which
-	in some circumstances a default history expansion would occur even
-	when there is neither an event nor a word designator, which is
-	contradictory to the documentation.  There are still some cases in
-	which expansion is attempted when it should not be, but in most of
-	those cases the expansion simply fails.
+	* 31797: Src/hist.c: partly fix long-standing history expansion
+	bug in which in some circumstances a default history expansion
+	would occur even when there is neither an event nor a word
+	designator, which is contradictory to the documentation.
+	There are still some cases in which expansion is attempted
+	when it should not be, but in most of those cases the expansion
+	simply fails.
 
 2013-10-07  Peter Stephenson  <p.stephenson@samsung.com>
 
diff --git a/Completion/Unix/Command/_sh b/Completion/Unix/Command/_sh
index 7258e4260..104c7576c 100644
--- a/Completion/Unix/Command/_sh
+++ b/Completion/Unix/Command/_sh
@@ -5,10 +5,7 @@ if [[ $service == zsh ]]; then
   if [[ ${words[CURRENT-1]} == -o ]]; then
     _options
     # no other possibilities
-    return 0
-  fi
-  if _arguments -S -s -- '*:'; then
-    return 0
+    return
   fi
 fi
 
@@ -25,3 +22,9 @@ else
   fi
   _default
 fi
+
+local ret=$?
+
+[[ $service == zsh ]] && _arguments -S -s -- '*:' && ret=0
+
+return ret
diff --git a/Completion/Zsh/Command/_disable b/Completion/Zsh/Command/_disable
index 3b627fb5f..52b82a6e9 100644
--- a/Completion/Zsh/Command/_disable
+++ b/Completion/Zsh/Command/_disable
@@ -1,9 +1,16 @@
 #compdef disable
 
+local -a ali_arr sali_arr func_arr
+
+ali_arr=(${(k)aliases} ${(k)galiases})
+sali_arr=(${(k)saliases})
+func_arr=(${(k)functions})
+
 _arguments -C -s -A "-*" -S \
-  "(-f -r -s)-a[act on regular or global aliases]:*:regular or global aliases:(${(k)aliases} ${(k)galiases})" \
-  "(-a -r -s)-f[act on functions]:*:functions:(${(k)functions})" \
-  "(-a -f -s)-r[act on reserved words]:*:reserved-words:compadd -k reswords" \
-  "(-a -f -r)-s[act on suffix aliases]:*:suffix aliases:(${(k)saliases})" \
+  "(-f -r -s -p)-a[act on regular or global aliases]:*:regular or global aliases:compadd -k ali_arr" \
+  "(-a -r -s -p)-f[act on functions]:*:functions:compadd -k func_arr" \
+  "(-a -f -s -p)-r[act on reserved words]:*:reserved-words:compadd -k reswords" \
+  "(-a -f -r -p)-s[act on suffix aliases]:*:suffix aliases:compadd -k sali_arr" \
+  "(-a -f -r -s)-p[act on pattern characters]:*:pattern characters:compadd -k patchars" \
   '-m[treat arguments as patterns]' \
   "*:builtin command:(${(k)builtins})"
diff --git a/Completion/Zsh/Command/_enable b/Completion/Zsh/Command/_enable
index c5f8b2c43..9410651b7 100644
--- a/Completion/Zsh/Command/_enable
+++ b/Completion/Zsh/Command/_enable
@@ -1,8 +1,16 @@
 #compdef enable
 
+local -a ali_arr sali_arr func_arr
+
+ali_arr=(${(k)dis_aliases} ${(k)dis_galiases})
+sali_arr=(${(k)dis_saliases})
+func_arr=(${(k)dis_functions})
+
 _arguments -C -s -A "-*" -S \
-  "(-f -r)-a[act on aliases]:*:aliases:(${(k)dis_aliases})" \
-  "(-a -r)-f[act on functions]:*:functions:(${(k)dis_functions})" \
-  "(-a -f)-r[act on reserved words]:*:reserved-words:compadd -k dis_reswords" \
+  "(-f -r -s -p)-a[act on regular or global aliases]:*:aliases:compadd -k ali_arr" \
+  "(-a -r -s -p)-f[act on functions]:*:functions:compadd -k func_arr" \
+  "(-a -f -s -p)-r[act on reserved words]:*:reserved-words:compadd -k dis_reswords" \
+  "(-a -f -r -p)-s[act on suffix aliases]:*:suffix aliases:compadd -k sali_arr" \
+  "(-a -f -r -s)-p[act on pattern characters]:*:pattern characters:compadd -k dis_patchars" \
   '-m[treat arguments as patterns]' \
   "*:builtin command:(${(k)dis_builtins})"
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 8e46a88ee..2cc33d241 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -471,7 +471,7 @@ problems in scripts and functions are altered.  If the tt(-L) switch is given,
 the options tt(LOCAL_OPTIONS), tt(LOCAL_PATTERNS) and tt(LOCAL_TRAPS)
 will be set as
 well, causing the effects of the tt(emulate) command and any tt(setopt),
-tt(disable -p) or tt(enable -b), and tt(trap) commands to be local to
+tt(disable -p) or tt(enable -p), and tt(trap) commands to be local to
 the immediately surrounding shell
 function, if any; normally these options are turned off in all emulation
 modes except tt(ksh). The tt(-L) switch is mutually exclusive with the
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 4a436dae5..d42ad9779 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -3470,14 +3470,26 @@ Like tt(_tags) this function supports the tt(-C) option to give a
 different name for the argument context field.
 )
 findex(_arguments)
-item(tt(_arguments) [ tt(-nswWACRS) ] [ tt(-O) var(name) ] [ tt(-M) var(matchspec) ] [ tt(:) ] var(spec) ...)(
-This function can be used to give a complete specification for
-completion for a command whose arguments follow standard UNIX option and
-argument conventions.  The following forms specify individual sets of
-options and arguments; to avoid ambiguity, these may be separated from the
-options to tt(_arguments) itself by a single colon.  Options to
-tt(_arguments) itself must be in separate words, i.e. tt(-s -w), not
-tt(-sw).
+xitem(tt(_arguments) [ tt(-nswWCRS) ] [ tt(-A) var(pat) ] [ tt(-O) var(name) ] [ tt(-M) var(matchspec) ] [ tt(:) ] var(spec)...)
+item(tt(_arguments) [ var(opts)... ] tt(-)tt(-) [ -i var(pats) ] [ tt(-s) var(pair) ] [ var(helpspec)... ])(
+This function can be used to give a complete specification for completion
+for a command whose arguments follow standard UNIX option and argument
+conventions.  Options to tt(_arguments) itself must be in separate words,
+i.e. tt(-s -w), not tt(-sw).
+
+When calling tt(_arguments), all var(spec)s that describe options of the
+analyzed command line must precede all var(spec)s that describe non-option
+(aka "normal") arguments of the analyzed line.  To avoid ambiguity, all
+options to tt(_arguments) itself may be separated from the var(spec) forms
+by a single colon.
+
+The tt(-s -w -W -A) and tt(-S) options describe how parsing of the command
+line should proceed, and are discussed in context below.  The `tt(-)tt(-)'
+form is used to intuit var(spec) forms from the help output of the command
+being analyzed, and is described in detail below.  The var(opts) for the
+`tt(-)tt(-)' form are otherwise the same options as the first form.  Note
+that `tt(-s)' following `tt(-)tt(-)' has a distinct meaning from `tt(-s)'
+preceding `tt(-)tt(-)', and both may appear.
 
 With the option tt(-n), tt(_arguments) sets the parameter tt(NORMARG)
 to the position of the first normal argument in the tt($words) array,
@@ -3486,6 +3498,17 @@ has not been reached, tt(NORMARG) is set to tt(-1).  The caller
 should declare `tt(integer NORMARG)' if the tt(-n) option is passed;
 otherwise the parameter is not used.
 
+The option `tt(-M) var(matchspec)' sets a match specification to use to
+completion option names and values.  The default var(matchspec) is:
+
+example(tt(r:|[_-]=* r:|=*))
+
+This allows partial word completion after `tt(_)' and `tt(-)', for example
+`-f-b' can be completed to `tt(-foo-bar)'.
+
+Each of the following forms is a var(spec) describing individual sets of
+options or arguments on the command line being analyzed.
+
 startitem()
 xitem(var(n)tt(:)var(message)tt(:)var(action))
 item(var(n)tt(::)var(message)tt(:)var(action))(
@@ -3530,10 +3553,10 @@ suitable for standard GNU options.
 
 The combination of tt(-s) with tt(-w) allows single-letter options to be
 combined in a single word even if one or more of the options take
-arguments.  For example, if tt(-a) takes an argument, with no
-tt(-s) `tt(-ab)' is considered as a single (unhandled) option; with
-tt(-s) tt(-ab) is an option with the argument `tt(b)'; with both tt(-s)
-and tt(-w), tt(-ab) may be the option tt(-a) and the option tt(-b) with
+arguments.  For example, if tt(-x) takes an argument, with no
+tt(-s) `tt(-xy)' is considered as a single (unhandled) option; with
+tt(-s) tt(-xy) is an option with the argument `tt(y)'; with both tt(-s)
+and tt(-w), tt(-xy) may be the option tt(-x) and the option tt(-y) with
 arguments still to come.
 
 The option tt(-W) takes this a stage further:  it is possible to
@@ -3603,6 +3626,23 @@ enditem()
 It is possible for options with a literal `PLUS()' or `tt(=)' to
 appear, but that character must be quoted, for example `tt(-\+)'.
 
+The options tt(-S) and tt(-A) are available to simplify the specifications
+for commands with standard option parsing.  With tt(-S), no option will be
+completed after a `tt(-)tt(-)' appearing on its own on the line; this
+argument will otherwise be ignored; hence in the line
+
+example(foobar -x -- -y)
+
+the `tt(-x)' is considered an option but the `tt(-y)' is considered an
+argument, while the `tt(-)tt(-)' is considered to be neither.
+
+With tt(-A), no options will be completed after the first non-option
+argument on the line.  The tt(-A) must be followed by a pattern matching
+all strings which are not to be taken as arguments.  For example, to make
+tt(_arguments) stop completing options after the first normal argument, but
+ignoring all strings starting with a hyphen even if they are not described
+by one of the var(optspec)s, the form is `tt(-A "-*")'.
+
 Each var(optarg) following an var(optspec) must take one of the
 following forms:
 
@@ -3676,6 +3716,11 @@ form below, the var(action) will be executed by calling the
 tt(_all_labels) function to process all tag labels.  No special handling
 of tags is needed unless a function call introduces a new one.
 
+The option `tt(-O) var(name)' specifies the name of an array whose elements
+will be passed as arguments to functions called to execute var(action)s.
+For example, this can be used to pass the same set of options for the
+tt(compadd) builtin to all var(action)s.
+
 The forms for var(action) are as follows.
 
 startitem()
@@ -3804,6 +3849,18 @@ Furthermore, during the evaluation of the var(action) the context name in
 the tt(curcontext) parameter is altered to append the same string that is
 stored in the tt(context) parameter.
 
+The option tt(-C) tells tt(_arguments) to modify the tt(curcontext)
+parameter for an action of the form `tt(->)var(state)'.  This is the
+standard parameter used to keep track of the current context.  Here it
+(and not the tt(context) array) should be made local to the calling
+function to avoid passing back the modified value and should be
+initialised to the current value at the start of the function:
+
+example(local curcontext="$curcontext")
+
+This is useful where it is not possible for multiple states to be valid
+together.
+
 It is possible to specify multiple sets of options and
 arguments with the sets separated by single hyphens.  The specifications
 before the first hyphen (if any) are shared by all the remaining sets.
@@ -3850,47 +3907,6 @@ A useful alternative is often an option specification with rest-arguments
 (as in `tt(-foo:*:...)'); here the option tt(-foo) swallows up all
 remaining arguments as described by the var(optarg) definitions.
 
-The options tt(-S) and tt(-A) are available to simplify the specifications
-for commands with standard option parsing.  With tt(-S), no option will be
-completed after a `tt(-)tt(-)' appearing on its own on the line; this
-argument will otherwise be ignored; hence in the line
-
-example(foobar -a -- -b)
-
-the `tt(-a)' is considered an option but the `tt(-b)' is considered an
-argument, while the `tt(-)tt(-)' is considered to be neither.
-
-With tt(-A), no options will be completed after the first non-option
-argument on the line.  The tt(-A) must be followed by a pattern matching
-all strings which are not to be taken as arguments.  For example, to make
-tt(_arguments) stop completing options after the first normal argument, but
-ignoring all strings starting with a hyphen even if they are not described
-by one of the var(optspec)s, the form is `tt(-A "-*")'.
-
-The option `tt(-O) var(name)' specifies the name of an array whose elements
-will be passed as arguments to functions called to execute var(actions).
-For example, this can be used to pass the same set of options for the
-tt(compadd) builtin to all var(action)s.
-
-The option `tt(-M) var(spec)' sets a match specification to use to
-completion option names and values.  It must appear before the first
-argument specification.  The default is `tt(r:|[_-]=* r:|=*)': this allows
-partial word completion after `tt(_)' and `tt(-)', for example `-f-b'
-can be completed to `tt(-foo-bar)'.
-
-The option tt(-C) tells tt(_arguments) to modify
-the tt(curcontext) parameter for an action of the form
-`tt(->)var(state)'.  This is the standard parameter used to keep track of
-the current context.  Here it (and not the tt(context) array) should be
-made local to the calling function
-to avoid passing back the modified value and should be initialised to the
-current value at the start of the function:
-
-example(local curcontext="$curcontext")
-
-This is useful where it is not possible for multiple states to be valid
-together.
-
 The option `tt(-)tt(-)' allows tt(_arguments) to work out the names of long
 options that support the `tt(-)tt(-help)' option which is standard in many
 GNU commands.  The command word is called with the argument
@@ -3901,11 +3917,16 @@ the behaviour of the command is unspecified.
 In addition to options, `tt(_arguments -)tt(-)' will try to deduce the
 types of arguments available for options when the form
 `tt(-)tt(-)var(opt)=var(val)' is valid.  It is also possible to provide
-hints by examining the help text of the command and adding specifiers of
-the form `var(pattern)tt(:)var(message)tt(:)var(action)'; note that normal
-tt(_arguments) specifiers are not used.  The var(pattern) is matched
+hints by examining the help text of the command and adding var(helpspec) of
+the form `var(pattern)tt(:)var(message)tt(:)var(action)'; note that other
+tt(_arguments) var(spec) forms are not used.  The var(pattern) is matched
 against the help text for an option, and if it matches the var(message) and
-var(action) are used as for other argument specifiers.  For example:
+var(action) are used as for other argument specifiers.  The special case
+of `tt(*:)' means both var(message) and var(action) are empty, which has
+the effect of causing options having no description in the help output to
+be ordered in listings ahead of options that have a description.
+
+For example:
 
 example(_arguments -- '*\*:toggle:(yes no)' \ 
               '*=FILE*:file:_files' \ 
@@ -3947,12 +3968,23 @@ will cause completion to ignore the options
 useful with GNU tt(configure)).
 
 The `tt(_arguments -)tt(-)' form can also be followed by the option `tt(-s)
-var(pair)' to describe option aliases.  Each var(pair) consists of a
-pattern and a replacement.  For example, some tt(configure)-scripts
-describe options only as `tt(-)tt(-enable-foo)', but also accept
+var(pair)' to describe option aliases.  The var(pair) consists of a list
+of alternating patterns and corresponding replacements, enclosed in parens
+and quoted so that it forms a single argument word in the tt(_arguments)
+call.
+
+For example, some tt(configure)-script help output describes options only
+as `tt(-)tt(-enable-foo)', but the script also accepts the negated form
 `tt(-)tt(-disable-foo)'.  To allow completion of the second form:
 
-example(_arguments -- -s "LPAR()#-tt(-enable- -)tt(-disable-RPAR()"))
+example(tt(_arguments -- -s "LPAR()#-)tt(-enable- -)tt(-disable-RPAR()"))
+
+Finally, note that tt(_arguments) generally expects to be the primary
+function handling any completion for which it is used.  It may have side
+effects which change the treatment of any matches added by other functions
+called after it.  To combine tt(_arguments) with other functions, those
+functions should be called either before tt(_arguments), as an var(action)
+within a var(spec), or in handlers for `tt(->)var(state)' actions.
 
 Here is a more general example of the use of tt(_arguments):
 
@@ -4251,11 +4283,14 @@ which already contains an expanded description.
 The tt(-12VJ) options and the var(group) are passed to tt(compadd) and
 hence determine the group the message string is added to.
 
-The second form gives a description for completions with the tag
-var(tag) to be shown even if there are no matches for that tag.  The tag
-can be omitted and if so the tag is taken from the parameter
-tt($curtag); this is maintained by the completion system and so is
-usually correct.
+The second tt(-e) form gives a description for completions with the tag
+var(tag) to be shown even if there are no matches for that tag.  This form
+is called by tt(_arguments) in the event that there is no action for an
+option specification.  The tag can be omitted and if so the tag is taken
+from the parameter tt($curtag); this is maintained by the completion
+system and so is usually correct.  Note that if there are no matches at
+the time this function is called, tt(compstate[insert]) is cleared, so
+additional matches generated later are not inserted on the command line.
 )
 findex(_multi_parts)
 item(tt(_multi_parts) var(sep) var(array))(
diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo
index 5948d74f2..32d4796f7 100644
--- a/Doc/Zsh/mod_parameter.yo
+++ b/Doc/Zsh/mod_parameter.yo
@@ -57,6 +57,14 @@ vindex(dis_reswords)
 item(tt(dis_reswords))(
 Like tt(reswords) but for disabled reserved words.
 )
+vindex(patchars)
+item(tt(patchars))(
+This array contains the enabled pattern characters.
+)
+vindex(dis_patchars)
+item(tt(dis_patchars))(
+Like tt(patchars) but for disabled pattern characters.
+)
 vindex(aliases)
 item(tt(aliases))(
 This maps the names of the regular aliases currently enabled to their
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index a029c9cb4..22148f991 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -759,6 +759,38 @@ disreswordsgetfn(UNUSED(Param pm))
     return getreswords(DISABLED);
 }
 
+/* Functions for the patchars special parameter. */
+
+/**/
+static char **
+getpatchars(int dis)
+{
+    int i;
+    char **ret, **p;
+
+    p = ret = (char **) zhalloc(ZPC_COUNT * sizeof(char *));
+
+    for (i = 0; i < ZPC_COUNT; i++)
+	if (zpc_strings[i] && !dis == !zpc_disables[i])
+	    *p++ = dupstring(zpc_strings[i]);
+
+    *p = NULL;
+
+    return ret;
+}
+
+static char **
+patcharsgetfn(UNUSED(Param pm))
+{
+    return getpatchars(0);
+}
+
+static char **
+dispatcharsgetfn(UNUSED(Param pm))
+{
+    return getpatchars(1);
+}
+
 /* Functions for the options special parameter. */
 
 /**/
@@ -2018,6 +2050,10 @@ static const struct gsu_array reswords_gsu =
 { reswordsgetfn, arrsetfn, stdunsetfn };
 static const struct gsu_array disreswords_gsu =
 { disreswordsgetfn, arrsetfn, stdunsetfn };
+static const struct gsu_array patchars_gsu =
+{ patcharsgetfn, arrsetfn, stdunsetfn };
+static const struct gsu_array dispatchars_gsu =
+{ dispatcharsgetfn, arrsetfn, stdunsetfn };
 static const struct gsu_array dirs_gsu =
 { dirsgetfn, dirssetfn, stdunsetfn };
 static const struct gsu_array historywords_gsu =
@@ -2038,6 +2074,8 @@ static struct paramdef partab[] = {
 	    &pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions),
     SPECIALPMDEF("dis_galiases", 0,
 	    &pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases),
+    SPECIALPMDEF("dis_patchars", PM_ARRAY|PM_READONLY,
+	    &dispatchars_gsu, NULL, NULL),
     SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY,
 	    &disreswords_gsu, NULL, NULL),
     SPECIALPMDEF("dis_saliases", 0,
@@ -2072,6 +2110,8 @@ static struct paramdef partab[] = {
 	    &pmoptions_gsu, getpmoption, scanpmoptions),
     SPECIALPMDEF("parameters", PM_READONLY,
 	    NULL, getpmparameter, scanpmparameters),
+    SPECIALPMDEF("patchars", PM_ARRAY|PM_READONLY,
+	    &patchars_gsu, NULL, NULL),
     SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY,
 	    &reswords_gsu, NULL, NULL),
     SPECIALPMDEF("saliases", 0,
diff --git a/Src/Modules/parameter.mdd b/Src/Modules/parameter.mdd
index eb48d5f2a..a91a5dc09 100644
--- a/Src/Modules/parameter.mdd
+++ b/Src/Modules/parameter.mdd
@@ -2,6 +2,6 @@ name=zsh/parameter
 link=either
 load=yes
 
-autofeatures="p:parameters p:commands p:functions p:dis_functions p:funcfiletrace p:funcsourcetrace p:funcstack p:functrace p:builtins p:dis_builtins p:reswords p:dis_reswords p:options p:modules p:dirstack p:history p:historywords p:jobtexts p:jobdirs p:jobstates p:nameddirs p:userdirs p:aliases p:dis_aliases p:galiases p:dis_galiases p:saliases p:dis_saliases"
+autofeatures="p:parameters p:commands p:functions p:dis_functions p:funcfiletrace p:funcsourcetrace p:funcstack p:functrace p:builtins p:dis_builtins p:reswords p:dis_reswords p:patchars p:dis_patchars p:options p:modules p:dirstack p:history p:historywords p:jobtexts p:jobdirs p:jobstates p:nameddirs p:userdirs p:aliases p:dis_aliases p:galiases p:dis_galiases p:saliases p:dis_saliases"
 
 objects="parameter.o"
diff --git a/Src/hist.c b/Src/hist.c
index bd650e81e..ed9560952 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -937,12 +937,21 @@ hbegin(int dohist)
     /*
      * For INCAPPENDHISTORY, when interactive, save the history here
      * as it gives a better estimate of the times of commands.
+     *
      * If SHAREHISTORY is also set continue to do so in the
      * standard place, because that's safer about reading and
      * rewriting history atomically.
+     *
+     * The histsave_stack_pos test won't usually fail here.
+     * We need to test the opposite for the hend() case because we
+     * need to save in the history file we've switched to, but then
+     * we pop immediately after that so the variable becomes zero.
+     * We will already have saved the line and restored the history
+     * so that (correctly) nothing happens here.  But it shows
+     * I thought about it.
      */
     if (isset(INCAPPENDHISTORY) && !isset(SHAREHISTORY) &&
-	!(histactive & HA_NOINC) && !strin)
+	!(histactive & HA_NOINC) && !strin && histsave_stack_pos == 0)
 	savehistfile(hf, 0, HFILE_USE_OPTIONS | HFILE_FAST);
 }
 
@@ -1348,7 +1357,11 @@ hend(Eprog prog)
     chline = hptr = NULL;
     chwords = NULL;
     histactive = 0;
-    if (isset(SHAREHISTORY) && histfileIsLocked())
+    /*
+     * For normal INCAPPENDHISTORY case and reasoning, see hbegin().
+     */
+    if (isset(SHAREHISTORY) ? histfileIsLocked() :
+	(isset(INCAPPENDHISTORY) && histsave_stack_pos != 0))
 	savehistfile(hf, 0, HFILE_USE_OPTIONS | HFILE_FAST);
     unlockhistfile(hf); /* It's OK to call this even if we aren't locked */
     /*
diff --git a/Src/pattern.c b/Src/pattern.c
index 4f0166bfa..609a9e372 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -236,7 +236,8 @@ static const char zpc_chars[ZPC_COUNT] = {
  * Corresponding strings used in enable/disable -p.
  * NULL means no way of turning this on or off.
  */
-static const char *zpc_strings[ZPC_COUNT] = {
+/**/
+const char *zpc_strings[ZPC_COUNT] = {
    NULL, NULL, "|", NULL, "~", "(", "?", "*", "[", "<",
    "^", "#", NULL, "?(", "*(", "+(", "!(", "@("
 };
diff --git a/Test/V01zmodload.ztst b/Test/V01zmodload.ztst
index ea908e952..3580bacea 100644
--- a/Test/V01zmodload.ztst
+++ b/Test/V01zmodload.ztst
@@ -183,6 +183,7 @@
 >p:dis_builtins
 >p:dis_functions
 >p:dis_galiases
+>p:dis_patchars
 >p:dis_reswords
 >p:dis_saliases
 >p:funcfiletrace
@@ -200,6 +201,7 @@
 >p:nameddirs
 >p:options
 >p:parameters
+>p:patchars
 >p:reswords
 >p:saliases
 >p:userdirs