From e1946bacf82653b4795793abe5ae095e3e65fea7 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 12 Mar 2020 18:06:21 +0000 Subject: 45540: vcs_info git: In non-interactive rebases, compute patch names for unapplied patches. --- Doc/Zsh/contrib.yo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index c6bf745b7..0909cd4f5 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1177,7 +1177,7 @@ If there are two different ways of gathering information, you can select the simpler one by setting this style to true; the default is to use the not-that-simple code, which is potentially a lot slower but might be more accurate in all possible cases. This style is -used by the tt(bzr) and tt(hg) backends. In the case of tt(hg) it will invoke +used by the tt(bzr), tt(hg), and tt(git) backends. In the case of tt(hg) it will invoke the external hexdump program to parse the binary dirstate cache file; this method will not return the local revision number. ) @@ -1236,7 +1236,7 @@ item(tt(get-unapplied))( This boolean style controls whether a backend should attempt to gather a list of unapplied patches (for example with Mercurial Queue patches). -Used by the tt(quilt) and tt(hg) backends. +Used by the tt(quilt), tt(hg), and tt(git) backends. ) enditem() -- cgit v1.2.3 From 68d2a1bc2235a8b88399252e801025b663d6e9be Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 01:54:38 +0000 Subject: unposted: ${(Z)}: Convert documentation to a description block. --- ChangeLog | 3 +++ Doc/Zsh/expn.yo | 21 +++++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 26b60e7e5..6a7bbfdc2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-03-20 Daniel Shahaf + * unposted: Doc/Zsh/expn.yo: ${(Z)}: Convert documentation to + a description block. + * unposted: Util/ztst-syntax.vim: internal: ztst.vim: Make sure syntax elements are only hidden if they're followed by something visible diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index c129b4228..2a66ab997 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1377,16 +1377,29 @@ i.e. tt("${(@s.:.)line}"). item(tt(Z:)var(opts)tt(:))( As tt(z) but takes a combination of option letters between a following pair of delimiter characters. With no options the effect is identical -to tt(z). tt(LPAR()Z+PLUS()c+PLUS()RPAR()) +to tt(z). The following options are available: + +startitem() +item(tt(LPAR()Z+PLUS()c+PLUS()RPAR()))( causes comments to be parsed as a string and retained; any field in the resulting array beginning with an unquoted comment character is a -comment. tt(LPAR()Z+PLUS()C+PLUS()RPAR()) causes comments to be parsed +comment. +) +item(tt(LPAR()Z+PLUS()C+PLUS()RPAR()))( +causes comments to be parsed and removed. The rule for comments is standard: anything between a word starting with the third character of tt($HISTCHARS), default tt(#), up to -the next newline is a comment. tt(LPAR()Z+PLUS()n+PLUS()RPAR()) causes +the next newline is a comment. +) +item(tt(LPAR()Z+PLUS()n+PLUS()RPAR()))( +causes unquoted newlines to be treated as ordinary whitespace, else they are treated as if they are shell code delimiters and converted to -semicolons. Options are combined within the same set of delimiters, +semicolons. +) +enditem() + +Options are combined within the same set of delimiters, e.g. tt(LPAR()Z+PLUS()Cn+PLUS()RPAR()). ) item(tt(_:)var(flags)tt(:))( -- cgit v1.2.3 From 386d9ac8ff961b8f0333d09511e927ab31011658 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 18:00:16 +0000 Subject: 45583/0008: Add the 'function -T' syntax. Config/version.mk was bumped in the previous commit. --- ChangeLog | 3 +++ Doc/Zsh/grammar.yo | 13 ++++++++++++- README | 7 +++++++ Src/exec.c | 8 +++++--- Src/parse.c | 11 +++++++++-- Test/E02xtrace.ztst | 25 +++++++++++++++++++++++++ 6 files changed, 61 insertions(+), 6 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index fe4102045..8f39d7263 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-03-22 Daniel Shahaf + * 45583/0008: Doc/Zsh/grammar.yo, README, Src/exec.c, + Src/parse.c, Test/E02xtrace.ztst: Add the 'function -T' syntax. + * 45583/0007: Config/version.mk, Src/exec.c, Src/parse.c, Src/text.c: WC_FUNCDEF: Add a placeholder element. diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index e028c8512..fa0d72ff5 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -357,7 +357,7 @@ deliberately left unspecified, because historically there was a mismatch between the documented and implemented behaviours. Cf. 20076, 21734/21735, 45075.) ) findex(function) -xitem(tt(function) var(word) ... [ tt(()) ] [ var(term) ] tt({) var(list) tt(})) +xitem(tt(function) [ tt(-T) ] var(word) ... [ tt(()) ] [ var(term) ] tt({) var(list) tt(})) xitem(var(word) ... tt(()) [ var(term) ] tt({) var(list) tt(})) item(var(word) ... tt(()) [ var(term) ] var(command))( where var(term) is one or more newline or tt(;). @@ -367,6 +367,17 @@ are usually only useful for setting traps. The body of the function is the var(list) between the tt({) and tt(}). See noderef(Functions). +The options of tt(function) have the following meanings: + +startitem() +item(-T)( +Enable tracing for this function, as though with tt(functions -T). See the +documentation of the tt(-f) option to the tt(typeset) builtin, in +ifzman(zmanref(zshbuiltins))\ +ifnzman(noderef(Shell Builtin Commands)). +) +enditem() + If the option tt(SH_GLOB) is set for compatibility with other shells, then whitespace may appear between the left and right parentheses when there is a single var(word); otherwise, the parentheses will be treated as diff --git a/README b/README index 2bd5c2179..ae4f788bc 100644 --- a/README +++ b/README @@ -43,6 +43,13 @@ name of an external command. Now it may also be a shell function. Normal command word precedece rules apply, so if you have a function and a command with the same name, the function will be used. +The syntax "function -T { ... }" used to define a function named "-T". +It now defines an anonymous function with single-level tracing enabled --- +same as "function f { ... }; functions -T f; f", but without naming the +function. The syntax "function -T foo { ... }" is similarly affected: it +now defines a function "foo" with tracing enabled; previously it defined +two functions, named "-T" and "foo" (see the MULTI_FUNC_DEF option). + Incompatibilities since 5.7.1 ----------------------------- diff --git a/Src/exec.c b/Src/exec.c index 3c3fcfa3e..2b8e2167f 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -5157,23 +5157,25 @@ execfuncdef(Estate state, Eprog redir_prog) { Shfunc shf; char *s = NULL; - int signum, nprg, sbeg, nstrs, npats, len, plen, i, htok = 0, ret = 0; + int signum, nprg, sbeg, nstrs, npats, do_tracing, len, plen, i, htok = 0, ret = 0; int anon_func = 0; Wordcode beg = state->pc, end; Eprog prog; Patprog *pp; LinkList names; + int tracing_flags; end = beg + WC_FUNCDEF_SKIP(state->pc[-1]); names = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok); sbeg = *state->pc++; nstrs = *state->pc++; npats = *state->pc++; - (void) *state->pc++; + do_tracing = *state->pc++; nprg = (end - state->pc); plen = nprg * sizeof(wordcode); len = plen + (npats * sizeof(Patprog)) + nstrs; + tracing_flags = do_tracing ? PM_TAGGED_LOCAL : 0; if (htok && names) { execsubst(names); @@ -5223,7 +5225,7 @@ execfuncdef(Estate state, Eprog redir_prog) shf = (Shfunc) zalloc(sizeof(*shf)); shf->funcdef = prog; - shf->node.flags = 0; + shf->node.flags = tracing_flags; /* No dircache here, not a directory */ shf->filename = ztrdup(scriptfilename); shf->lineno = diff --git a/Src/parse.c b/Src/parse.c index 0111c25b6..0342ee1f8 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -173,7 +173,7 @@ struct heredocs *hdocs; * - followed by offset to first string * - followed by length of string table * - followed by number of patterns for body - * - followed by a placeholder + * - followed by an integer indicating tracing status * - followed by codes for body * - followed by strings for body * - if number of names is 0, followed by: @@ -1670,6 +1670,7 @@ par_funcdef(int *cmplx) int oecused = ecused, num = 0, onp, p, c = 0; int so, oecssub = ecssub; zlong oldlineno = lineno; + int do_tracing = 0; lineno = 0; nocorrect = 1; @@ -1679,6 +1680,12 @@ par_funcdef(int *cmplx) p = ecadd(0); ecadd(0); /* p + 1 */ + if (tok == STRING && tokstr[0] == Dash && + tokstr[1] == 'T' && !tokstr[2]) { + ++do_tracing; + zshlex(); + } + while (tok == STRING) { if ((*tokstr == Inbrace || *tokstr == '{') && !tokstr[1]) { @@ -1732,7 +1739,7 @@ par_funcdef(int *cmplx) ecbuf[p + num + 2] = so - oecssub; ecbuf[p + num + 3] = ecsoffs - so; /* "length of string table" */ ecbuf[p + num + 4] = ecnpats; /* "number of patterns for body" */ - ecbuf[p + num + 5] = 0; + ecbuf[p + num + 5] = do_tracing; ecbuf[p + 1] = num; /* "number of names" */ ecnpats = onp; diff --git a/Test/E02xtrace.ztst b/Test/E02xtrace.ztst index 795f7e616..d72b2d000 100644 --- a/Test/E02xtrace.ztst +++ b/Test/E02xtrace.ztst @@ -180,3 +180,28 @@ > # traced > echo inner >} + + function -T { echo traced anonymous function } + functions -- -T # no output +1:define traced function: anonymous function +?+(anon):0> echo traced anonymous function +>traced anonymous function + + function -T f { echo traced named function } + functions -- -T # no output + functions f + f +0:define traced function: named function +>f () { +> # traced +> echo traced named function +>} +?+f:0> echo traced named function +>traced named function + + function -T -T { echo trace function literally named "-T" } + -T +0:define traced function: parse test +?+-T:0> echo trace function literally named -T +>trace function literally named -T + -- cgit v1.2.3 From 8923d2a61824b0856839d52f3bf52aedb86fd827 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Thu, 26 Dec 2019 03:54:17 +0100 Subject: Add SHORT_REPEAT option --- ChangeLog | 6 ++++++ Doc/Zsh/grammar.yo | 2 ++ Doc/Zsh/options.yo | 8 ++++++++ Src/lex.c | 2 +- Src/options.c | 1 + Src/parse.c | 2 +- Src/zsh.h | 1 + Test/E01options.ztst | 19 ++++++++++++++----- 8 files changed, 34 insertions(+), 7 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 0d43e8bae..09e89ceaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2020-04-02 Mikael Magnusson + + * 45142: Doc/Zsh/grammar.yo, Doc/Zsh/options.yo, Src/lex.c, + Src/options.c, Src/parse.c, Src/zsh.h, Test/E01options.ztst: + Add SHORT_REPEAT option + 2020-04-02 Daniel Shahaf * unposted: Test/D02glob.ztst: Make test platform-independent. diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index fa0d72ff5..a4e0c1121 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -428,6 +428,8 @@ else the end of the test will not be recognized. For the tt(for), tt(repeat), tt(case) and tt(select) commands no such special form for the arguments is necessary, but the other condition (the special form of var(sublist) or use of the tt(SHORT_LOOPS) option) still applies. +The tt(SHORT_REPEAT) option is available to enable the short version only +for the tt(repeat) command. startitem() item(tt(if) var(list) tt({) var(list) tt(}) [ tt(elif) var(list) tt({) var(list) tt(}) ] ... [ tt(else {) var(list) tt(}) ])( diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index fdea51412..2b7637ff4 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1377,6 +1377,14 @@ item(tt(SHORT_LOOPS) )( Allow the short forms of tt(for), tt(repeat), tt(select), tt(if), and tt(function) constructs. ) +pindex(SHORT_REPEAT) +pindex(NO_SHORT_REPEAT) +pindex(SHORTREPEAT) +pindex(NOSHORTREPEAT) +item(tt(SHORT_REPEAT))( +Allow the short form tt(repeat) as tt(SHORT_LOOPS) but without enabling +it for the other constructs. +) pindex(SUN_KEYBOARD_HACK) pindex(NO_SUN_KEYBOARD_HACK) pindex(SUNKEYBOARDHACK) diff --git a/Src/lex.c b/Src/lex.c index 1d86da94e..a541defe6 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -270,7 +270,7 @@ zshlex(void) do { if (inrepeat_) ++inrepeat_; - if (inrepeat_ == 3 && isset(SHORTLOOPS)) + if (inrepeat_ == 3 && (isset(SHORTLOOPS) || isset(SHORTREPEAT))) incmdpos = 1; tok = gettok(); } while (tok != ENDINPUT && exalias()); diff --git a/Src/options.c b/Src/options.c index 08ba71917..7586d21d2 100644 --- a/Src/options.c +++ b/Src/options.c @@ -248,6 +248,7 @@ static struct optname optns[] = { {{NULL, "shnullcmd", OPT_EMULATE|OPT_BOURNE}, SHNULLCMD}, {{NULL, "shoptionletters", OPT_EMULATE|OPT_BOURNE}, SHOPTIONLETTERS}, {{NULL, "shortloops", OPT_EMULATE|OPT_NONBOURNE},SHORTLOOPS}, +{{NULL, "shortrepeat", OPT_EMULATE}, SHORTREPEAT}, {{NULL, "shwordsplit", OPT_EMULATE|OPT_BOURNE}, SHWORDSPLIT}, {{NULL, "singlecommand", OPT_SPECIAL}, SINGLECOMMAND}, {{NULL, "singlelinezle", OPT_KSH}, SINGLELINEZLE}, diff --git a/Src/parse.c b/Src/parse.c index 08919b2da..10c9b4c29 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1593,7 +1593,7 @@ par_repeat(int *cmplx) if (tok != ZEND) YYERRORV(oecused); zshlex(); - } else if (unset(SHORTLOOPS)) { + } else if (unset(SHORTLOOPS) && unset(SHORTREPEAT)) { YYERRORV(oecused); } else par_save_list1(cmplx); diff --git a/Src/zsh.h b/Src/zsh.h index d72c338da..1f2d774a1 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2508,6 +2508,7 @@ enum { SHNULLCMD, SHOPTIONLETTERS, SHORTLOOPS, + SHORTREPEAT, SHWORDSPLIT, SINGLECOMMAND, SINGLELINEZLE, diff --git a/Test/E01options.ztst b/Test/E01options.ztst index cfe2c75cc..70736f444 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -1109,15 +1109,22 @@ F:Regression test for workers/41811 eval 'for f (word1 word2) print $f' eval 'repeat 3 print nonsense' } - unsetopt shortloops - print option unset + unsetopt shortloops shortrepeat + print shortloops and shortrepeat unset + fn + setopt shortrepeat + print shortrepeat set fn setopt shortloops - print option set + print shortloops set fn 0:SHORT_LOOPS option ->option unset ->option set +>shortloops and shortrepeat unset +>shortrepeat set +>nonsense +>nonsense +>nonsense +>shortloops set >foo >bar >word1 @@ -1127,6 +1134,8 @@ F:Regression test for workers/41811 >nonsense ?(eval):1: parse error near `print' ?(eval):1: parse error near `print' +?(eval):1: parse error near `print' +?(eval):1: parse error near `print' ?(eval):1: parse error near `print' fn() { print -l $*; } -- cgit v1.2.3 From 6ec97e1d48d74371252c6c67a2076bc6b01a4084 Mon Sep 17 00:00:00 2001 From: dg1727 Date: Sun, 12 Apr 2020 01:26:25 +0000 Subject: 45661: docs: Clarify the effect of KSH_ARRAYS on the (I) subscript. --- ChangeLog | 5 +++++ Doc/Zsh/params.yo | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 2d003e8a5..610e7a7e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-04-12 dg1727 + + * 45661: Doc/Zsh/params.yo: docs: Clarify the effect of + KSH_ARRAYS on the (I) subscript. + 2020-04-09 Peter Stephenson * 45660: Src/builtin,c, Src/init.c: Delay initial setting of diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 8daf33d5e..8a6eb2446 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -399,6 +399,10 @@ Like `tt(i)', but gives the index of the last match, or all possible matching keys in an associative array. On failure substitutes 0, or the empty string for an associative array. This flag is best when testing for values or keys that do not exist. + +Note: If the option tt(KSH_ARRAYS) is in effect and no match is found, the +result is indistinguishable from the case when the first element of the array +matches. ) item(tt(k))( If used in a subscript on an associative array, this flag causes the keys -- cgit v1.2.3 From 28277a84ddf0609d0ec4b02f47e43afed3884c2a Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 15 Apr 2020 21:33:48 +0100 Subject: 45684: Document - glob qualifier in error cases --- ChangeLog | 5 +++++ Doc/Zsh/expn.yo | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 610e7a7e7..3a7072ba1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-04-15 Peter Stephenson + + * 45684: Doc/Zsh/expn.yo: - glob qualifier behaviour in error + cases. + 2020-04-12 dg1727 * 45661: Doc/Zsh/params.yo: docs: Clarify the effect of diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 2a66ab997..69cb0b08a 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -2837,7 +2837,9 @@ negates all qualifiers following it ) item(tt(-))( toggles between making the qualifiers work on symbolic links (the -default) and the files they point to +default) and the files they point to, if any; any symbolic link for +whose target the `tt(stat)' system call fails (whatever the cause of the +failure) is treated as a file in its own right ) item(tt(M))( sets the tt(MARK_DIRS) option for the current pattern -- cgit v1.2.3 From f179dbf72a4f482c1ad513b7c58cd7f96c7cf7f3 Mon Sep 17 00:00:00 2001 From: dana Date: Mon, 20 Apr 2020 00:06:55 -0500 Subject: 45702: compsys: Improve documentation of {insert,separate}-sections --- ChangeLog | 5 +++++ Doc/Zsh/compsys.yo | 25 ++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 3a7072ba1..50c05fa59 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-04-20 dana + + * 45702: Doc/Zsh/compsys.yo: Improve documentation of + {insert,separate}-sections + 2020-04-15 Peter Stephenson * 45684: Doc/Zsh/expn.yo: - glob qualifier behaviour in error diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index c2d20ca40..a1a1da935 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -1826,6 +1826,24 @@ be unsuccessful until that point. If the value is any other string, menu completion will be started when the string typed by the user is longer than the common prefix to the corresponding IDs. ) +kindex(insert-sections, completion style) +item(tt(insert-sections))( +This style is used with tags of the form `tt(manuals.)var(X)' when +completing names of manual pages. If set to `true' and the var(X) in the +tag name matches the section number of the page being completed, the +section number is inserted along with the page name. For example, given + +example(zstyle ':completion:*:manuals.*' insert-sections true) + +tt(man ssh_) may be completed to tt(man 5 ssh_config). + +This is especially useful in conjunction with tt(separate-sections), as +it ensures that the page requested of tt(man) corresponds to the one +displayed in the completion listing when there are multiple pages with the +same name (e.g., tt(printf+LPAR()1+RPAR()) and tt(printf+LPAR()3+RPAR())). + +The default for this style is `false'. +) kindex(insert-tab, completion style) item(tt(insert-tab))( If this is set to `true', the completion system will @@ -2445,7 +2463,7 @@ For example, example(zstyle ':completion:*' recursive-files '*/zsh/*') If the current directory is tt(/home/pws/zsh/Src), then -tt(zle_tr)em(TAB) can be completed to tt(Zle/zle_tricky.c). +tt(zle_tr) can be completed to tt(Zle/zle_tricky.c). ) kindex(regular, completion style) item(tt(regular))( @@ -2502,12 +2520,13 @@ kindex(separate-sections, completion style) item(tt(separate-sections))( This style is used with the tt(manuals) tag when completing names of manual pages. If it is `true', entries for different sections are -added separately using tag names of the form `tt(manual.)var(X)', +added separately using tag names of the form `tt(manuals.)var(X)', where var(X) is the section number. When the tt(group-name) style is also in effect, pages from different sections will appear separately. This style is also used similarly with the tt(words) style when completing words for the dict command. It allows words from different -dictionary databases to be added separately. +dictionary databases to be added separately. See also tt(insert-sections). + The default for this style is `false'. ) kindex(show-ambiguity, completion style) -- cgit v1.2.3 From 25c9b61a6663f90bfb22fa73c1a7aa4fb9dee4ae Mon Sep 17 00:00:00 2001 From: Cedric Ware Date: Mon, 20 Apr 2020 12:10:01 -0500 Subject: 45708: zsh/system: Enable sub-second timeout in zsystem flock --- ChangeLog | 4 ++ Doc/Zsh/mod_system.yo | 16 ++++-- Src/Modules/system.c | 79 ++++++++++++++++++++++++-- Src/compat.c | 26 +++++++++ Src/utils.c | 36 ++++++++++++ Test/V14system.ztst | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 302 insertions(+), 9 deletions(-) create mode 100644 Test/V14system.ztst (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 50c05fa59..b73a7ed80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2020-04-20 dana + * Cedric Ware: 45708: Doc/Zsh/mod_system.yo, + Src/Modules/system.c, Src/compat.c, Src/utils.c, + Test/V14system.ztst: Enable sub-second timeout in zsystem flock + * 45702: Doc/Zsh/compsys.yo: Improve documentation of {insert,separate}-sections diff --git a/Doc/Zsh/mod_system.yo b/Doc/Zsh/mod_system.yo index 6292af071..06ea87918 100644 --- a/Doc/Zsh/mod_system.yo +++ b/Doc/Zsh/mod_system.yo @@ -166,7 +166,7 @@ to the command, or 2 for an error on the write; no error message is printed in the last case, but the parameter tt(ERRNO) will reflect the error that occurred. ) -xitem(tt(zsystem flock) [ tt(-t) var(timeout) ] [ tt(-f) var(var) ] [tt(-er)] var(file)) +xitem(tt(zsystem flock) [ tt(-t) var(timeout) ] [ tt(-i) var(interval) ] [ tt(-f) var(var) ] [tt(-er)] var(file)) item(tt(zsystem flock -u) var(fd_expr))( The builtin tt(zsystem)'s subcommand tt(flock) performs advisory file locking (via the manref(fcntl)(2) system call) over the entire contents @@ -196,9 +196,17 @@ a safety check that the file descriptor is in use for file locking. By default the shell waits indefinitely for the lock to succeed. The option tt(-t) var(timeout) specifies a timeout for the lock in -seconds; currently this must be an integer. The shell will attempt -to lock the file once a second during this period. If the attempt -times out, status 2 is returned. +seconds; fractional seconds are allowed. During this period, the +shell will attempt to lock the file every var(interval) seconds +if the tt(-i) var(interval) option is given, otherwise once a second. +(This var(interval) is shortened before the last attempt if needed, +so that the shell waits only until the var(timeout) and not longer.) +If the attempt times out, status 2 is returned. + +(Note: var(timeout) must be less than +ifzman(2^30-1)ifnzman(2NOTRANS(@sup{30})-1) seconds (about 34 years), +and var(interval) must be less than 0.999 * LONG_MAX microseconds +(only about 35 minutes on 32-bit systems).) If the option tt(-e) is given, the file descriptor for the lock is preserved when the shell uses tt(exec) to start a new process; diff --git a/Src/Modules/system.c b/Src/Modules/system.c index fb3d80773..972aa0767 100644 --- a/Src/Modules/system.c +++ b/Src/Modules/system.c @@ -29,6 +29,7 @@ #include "system.mdh" #include "system.pro" +#include #ifdef HAVE_POLL_H # include @@ -531,7 +532,9 @@ static int bin_zsystem_flock(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { int cloexec = 1, unlock = 0, readlock = 0; - zlong timeout = -1; + double timeout = -1; + long timeout_interval = 1e6; + mnumber timeout_param; char *fdvar = NULL; #ifdef HAVE_FCNTL_H struct flock lck; @@ -583,7 +586,51 @@ bin_zsystem_flock(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } else { optarg = *args++; } - timeout = mathevali(optarg); + timeout_param = matheval(optarg); + timeout = (timeout_param.type & MN_FLOAT) ? + timeout_param.u.d : (double)timeout_param.u.l; + + /* + * timeout must not overflow time_t, but little is known + * about this type's limits. Conservatively limit to 2^30-1 + * (34 years). Then it can only overflow if time_t is only + * a 32-bit int and CLOCK_MONOTONIC is not supported, in which + * case there is a Y2038 problem anyway. + */ + if (timeout < 1e-6 || timeout > 1073741823.) { + zwarnnam(nam, "flock: invalid timeout value: '%s'", + optarg); + return 1; + } + break; + + case 'i': + /* retry interval in seconds */ + if (optptr[1]) { + optarg = optptr + 1; + optptr += strlen(optarg) - 1; + } else if (!*args) { + zwarnnam(nam, + "flock: option %c requires " + "a numeric retry interval", + opt); + return 1; + } else { + optarg = *args++; + } + timeout_param = matheval(optarg); + if (!(timeout_param.type & MN_FLOAT)) { + timeout_param.type = MN_FLOAT; + timeout_param.u.d = (double)timeout_param.u.l; + } + timeout_param.u.d *= 1e6; + if (timeout_param.u.d < 1 + || timeout_param.u.d > 0.999 * LONG_MAX) { + zwarnnam(nam, "flock: invalid interval value: '%s'", + optarg); + return 1; + } + timeout_interval = (long)timeout_param.u.d; break; case 'u': @@ -647,7 +694,24 @@ bin_zsystem_flock(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) lck.l_len = 0; /* lock the whole file */ if (timeout > 0) { - time_t end = time(NULL) + (time_t)timeout; + /* + * Get current time, calculate timeout time. + * No need to check for overflow, already checked above. + */ + struct timespec now, end; + double timeout_s; + long remaining_us; + zgettime_monotonic_if_available(&now); + end.tv_sec = now.tv_sec; + end.tv_nsec = now.tv_nsec; + end.tv_nsec += modf(timeout, &timeout_s) * 1000000000L; + end.tv_sec += timeout_s; + if (end.tv_nsec >= 1000000000L) { + end.tv_nsec -= 1000000000L; + end.tv_sec += 1; + } + + /* Try acquiring lock, loop until timeout. */ while (fcntl(flock_fd, F_SETLK, &lck) < 0) { if (errflag) { zclose(flock_fd); @@ -658,11 +722,16 @@ bin_zsystem_flock(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) zwarnnam(nam, "failed to lock file %s: %e", args[0], errno); return 1; } - if (time(NULL) >= end) { + zgettime_monotonic_if_available(&now); + remaining_us = timespec_diff_us(&now, &end); + if (remaining_us <= 0) { zclose(flock_fd); return 2; } - sleep(1); + if (remaining_us <= timeout_interval) { + timeout_interval = remaining_us; + } + zsleep(timeout_interval); } } else { while (fcntl(flock_fd, timeout == 0 ? F_SETLK : F_SETLKW, &lck) < 0) { diff --git a/Src/compat.c b/Src/compat.c index 74e426fba..817bb4aaf 100644 --- a/Src/compat.c +++ b/Src/compat.c @@ -126,6 +126,32 @@ zgettime(struct timespec *ts) return ret; } +/* Likewise with CLOCK_MONOTONIC if available. */ + +/**/ +mod_export int +zgettime_monotonic_if_available(struct timespec *ts) +{ + int ret = -1; + +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + struct timespec dts; + if (clock_gettime(CLOCK_MONOTONIC, &dts) < 0) { + zwarn("unable to retrieve CLOCK_MONOTONIC time: %e", errno); + ret--; + } else { + ret++; + ts->tv_sec = (time_t) dts.tv_sec; + ts->tv_nsec = (long) dts.tv_nsec; + } +#endif + + if (ret) { + ret = zgettime(ts); + } + return ret; +} + /* compute the difference between two calendar times */ diff --git a/Src/utils.c b/Src/utils.c index 69885fed3..e258ef836 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -2748,6 +2748,42 @@ read_poll(int fd, int *readchar, int polltty, zlong microseconds) return (ret > 0); } +/* + * Return the difference between 2 times, given as struct timespec*, + * expressed in microseconds, as a long. If the difference doesn't fit + * into a long, return LONG_MIN or LONG_MAX so that the times can still + * be compared. + * + * Note: returns a long rather than a zlong because zsleep() below + * takes a long. + */ + +/**/ +long +timespec_diff_us(const struct timespec *t1, const struct timespec *t2) +{ + int reverse = (t1->tv_sec > t2->tv_sec); + time_t diff_sec; + long diff_usec, max_margin, res; + + /* Don't just subtract t2-t1 because time_t might be unsigned. */ + diff_sec = (reverse ? t1->tv_sec - t2->tv_sec : t2->tv_sec - t1->tv_sec); + if (diff_sec > LONG_MAX / 1000000L) { + goto overflow; + } + res = diff_sec * 1000000L; + max_margin = LONG_MAX - res; + diff_usec = (reverse ? + t1->tv_nsec - t2->tv_nsec : t2->tv_nsec - t1->tv_nsec + ) / 1000; + if (diff_usec <= max_margin) { + res += diff_usec; + return (reverse ? -res : res); + } + overflow: + return (reverse ? LONG_MIN : LONG_MAX); +} + /* * Sleep for the given number of microseconds --- must be within * range of a long at the moment, but this is only used for diff --git a/Test/V14system.ztst b/Test/V14system.ztst new file mode 100644 index 000000000..b8af96cda --- /dev/null +++ b/Test/V14system.ztst @@ -0,0 +1,150 @@ +# Test zsh/system module + +%prep + + if zmodload -s zsh/system && zmodload -s zsh/zselect; then + tst_dir=V14.tmp + mkdir -p -- $tst_dir + else + ZTST_unimplemented='the zsh/system and zsh/zselect modules are not available' + fi + : > $tst_dir/file # File on which to acquire flock. + +%test + + ( + zsystem flock -t 0.1 -i 0.000001 $tst_dir/file + ) +0:zsystem flock valid time arguments + + ( + zsystem flock -t -1 $tst_dir/file || + zsystem flock -t 0.49e-6 $tst_dir/file || + zsystem flock -t 1073741824 $tst_dir/file || + zsystem flock -t 1e100 $tst_dir/file || + zsystem flock -i -1 $tst_dir/file || + zsystem flock -i 0.49e-6 $tst_dir/file || + zsystem flock -i 1e100 $tst_dir/file + ) +1:zsystem flock invalid time arguments +?(eval):zsystem:2: flock: invalid timeout value: '-1' +?(eval):zsystem:3: flock: invalid timeout value: '0.49e-6' +?(eval):zsystem:4: flock: invalid timeout value: '1073741824' +?(eval):zsystem:5: flock: invalid timeout value: '1e100' +?(eval):zsystem:6: flock: invalid interval value: '-1' +?(eval):zsystem:7: flock: invalid interval value: '0.49e-6' +?(eval):zsystem:8: flock: invalid interval value: '1e100' + + ( + # Lock file for 1 second in the background. + lock_flag=$tst_dir/locked1 + (zsystem flock $tst_dir/file \ + && touch $lock_flag \ + && zselect -t 100 + mv $lock_flag $lock_flag.done) & + # Wait until sub-shell above has started. + while ! [[ -f $lock_flag || -f $lock_flag.done ]]; do + zselect -t 1 + done + if [[ -f $lock_flag.done ]]; then + echo "Background shell should not have completed already." 1>&2 + else + # Attempt to lock file with 0.5 second timeout: must fail. + zsystem flock -t 0.5 $tst_dir/file + fi + ) +2:zsystem flock unsuccessful wait test +F:This timing test might fail due to process scheduling issues unrelated to zsh. + + ( + # Lock file for 0.5 second in the background. + lock_flag=$tst_dir/locked2 + (zsystem flock $tst_dir/file \ + && touch $lock_flag \ + && zselect -t 50 + mv $lock_flag $lock_flag.done) & + # Wait until sub-shell above has started. + while ! [[ -f $lock_flag || -f $lock_flag.done ]]; do + zselect -t 1 + done + if [[ -f $lock_flag.done ]]; then + echo "Background shell should not have completed already." 1>&2 + fi + typeset -F SECONDS + start=$SECONDS + # Attempt to lock file without a timeout: + # must succeed after sub-shell above releases it (0.5 second). + if zsystem flock $tst_dir/file; then + elapsed=$[ $SECONDS - $start ] + if [[ $elapsed -ge 0.3 && $elapsed -le 0.7 ]]; then + echo "elapsed time seems OK" 1>&2 + else + echo "elapsed time $elapsed should be ~ 0.5 second" 1>&2 + fi + fi + ) +0:zsystem flock successful wait test, no timeout +?elapsed time seems OK +F:This timing test might fail due to process scheduling issues unrelated to zsh. + + ( + # Lock file for 0.5 second in the background. + lock_flag=$tst_dir/locked3 + (zsystem flock $tst_dir/file \ + && touch $lock_flag \ + && zselect -t 50 + mv $lock_flag $lock_flag.done) & + # Wait until sub-shell above has started. + while ! [[ -f $lock_flag || -f $lock_flag.done ]]; do + zselect -t 1 + done + if [[ -f $lock_flag.done ]]; then + echo "Background shell should not have completed already." 1>&2 + fi + typeset -F SECONDS + start=$SECONDS + # Attempt to lock file with 1-second timeout: + # must succeed 1 second after start because we retry every 1 second. + if zsystem flock -t 1 $tst_dir/file; then + elapsed=$[ $SECONDS - $start ] + if [[ $elapsed -ge 0.8 && $elapsed -le 1.2 ]]; then + echo "elapsed time seems OK" 1>&2 + else + echo "elapsed time $elapsed should be ~ 1 second" 1>&2 + fi + fi + ) +0:zsystem flock successful wait test, integral seconds +?elapsed time seems OK +F:This timing test might fail due to process scheduling issues unrelated to zsh. + + ( + # Lock file for 0.25 second in the background. + lock_flag=$tst_dir/locked4 + (zsystem flock $tst_dir/file \ + && touch $lock_flag \ + && zselect -t 25 + mv $lock_flag $lock_flag.done) & + # Wait until sub-shell above has started. + while ! [[ -f $lock_flag || -f $lock_flag.done ]]; do + zselect -t 1 + done + if [[ -f $lock_flag.done ]]; then + echo "Background shell should not have completed already." 1>&2 + fi + typeset -F SECONDS + start=$SECONDS + # Attempt to lock file with 0.4-second timeout, retrying every 0.1 second: + # must succeed 0.3 second after start. + if zsystem flock -t 0.4 -i 0.1 $tst_dir/file; then + elapsed=$[ $SECONDS - $start ] + if [[ $elapsed -ge 0.2 && $elapsed -le 0.5 ]]; then + echo "elapsed time seems OK" 1>&2 + else + echo "elapsed time $elapsed should be ~ 0.3 second" 1>&2 + fi + fi + ) +0:zsystem flock successful wait test, fractional seconds +?elapsed time seems OK +F:This timing test might fail due to process scheduling issues unrelated to zsh. -- cgit v1.2.3 From 1cac862b0f621f9567d15a116a86d0e3117d77f8 Mon Sep 17 00:00:00 2001 From: dana Date: Mon, 20 Apr 2020 12:12:12 -0500 Subject: unposted: zsh/system: Adjust documentation from workers/45708 --- ChangeLog | 3 +++ Doc/Zsh/mod_system.yo | 7 +++---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index b73a7ed80..4df20c334 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-04-20 dana + * unposted: Doc/Zsh/mod_system.yo: Adjust documentation from + workers/45708 + * Cedric Ware: 45708: Doc/Zsh/mod_system.yo, Src/Modules/system.c, Src/compat.c, Src/utils.c, Test/V14system.ztst: Enable sub-second timeout in zsystem flock diff --git a/Doc/Zsh/mod_system.yo b/Doc/Zsh/mod_system.yo index 06ea87918..8f525c576 100644 --- a/Doc/Zsh/mod_system.yo +++ b/Doc/Zsh/mod_system.yo @@ -203,10 +203,9 @@ if the tt(-i) var(interval) option is given, otherwise once a second. so that the shell waits only until the var(timeout) and not longer.) If the attempt times out, status 2 is returned. -(Note: var(timeout) must be less than -ifzman(2^30-1)ifnzman(2NOTRANS(@sup{30})-1) seconds (about 34 years), -and var(interval) must be less than 0.999 * LONG_MAX microseconds -(only about 35 minutes on 32-bit systems).) +(Note: var(timeout) is limited to 2^30-1 seconds (about 34 years), and +var(interval) to 0.999 * LONG_MAX microseconds (only about 35 minutes +on 32-bit systems).) If the option tt(-e) is given, the file descriptor for the lock is preserved when the shell uses tt(exec) to start a new process; -- cgit v1.2.3 From ff50d96b19373baaceeb49ccce5d9db218f2c4db Mon Sep 17 00:00:00 2001 From: Benjamin Esham Date: Sun, 26 Apr 2020 19:36:34 -0700 Subject: github #56: typo: Add a single quote that had been missing --- ChangeLog | 5 +++++ Doc/Zsh/mod_zutil.yo | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 545f7a5b2..66ea195d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-04-27 Benjamin Esham + + * github #56: Doc/Zsh/mod_zutil.yo: typo: Add a single quote + that had been missing + 2020-04-21 Daniel Shahaf * unposted: README: Give the 'zsystem flock' limit in diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 24aebdfaf..812a1fd38 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -37,7 +37,7 @@ For example, to define your preferred form of precipitation depending on which city you're in, you might set the following in your tt(zshrc): example(zstyle ':weather:europe:*' preferred-precipitation rain -zstyle ':weather:europe:germany:* preferred-precipitation none +zstyle ':weather:europe:germany:*' preferred-precipitation none zstyle ':weather:europe:germany:*:munich' preferred-precipitation snow) Then, the fictional `tt(weather)' plugin might run under the hood a command -- cgit v1.2.3 From 5d9f7975a97a368ab16e1cd96a361a7594acdbbf Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 27 Apr 2020 10:06:57 +0000 Subject: 45722: docs: Change zstyle example to a non-hierarchical one --- ChangeLog | 3 + Doc/Zsh/mod_zutil.yo | 23 ++++--- Test/V05styles.ztst | 153 ----------------------------------------------- V05styles.ztst | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+), 161 deletions(-) delete mode 100644 Test/V05styles.ztst create mode 100644 V05styles.ztst (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index aba434c8c..e980c9187 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-05-02 Daniel Shahaf + * 45722: Doc/Zsh/mod_zutil.yo, V05styles.ztst: docs: Change + zstyle example to a non-hierarchical one + * 45752/0002: Completion/Unix/Command/_gcc: Complete --output like -o. diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 812a1fd38..c69233f9d 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -32,20 +32,27 @@ If two patterns are equally specific, the tie is broken in favour of the pattern that was defined first. em(Example) +kindex(preferred-precipitation, example style) +findex(weather, example function) -For example, to define your preferred form of precipitation depending on which -city you're in, you might set the following in your tt(zshrc): +For example, a fictional `tt(weather)' plugin might state in its documentation +that it looks up the tt(preferred-precipitation) style under the +`tt(:weather:)var(continent)tt(:)var(day-of-the-week)tt(:)var(phase-of-the-moon))' context. +According to this, you might set the following in your tt(zshrc): -example(zstyle ':weather:europe:*' preferred-precipitation rain -zstyle ':weather:europe:germany:*' preferred-precipitation none -zstyle ':weather:europe:germany:*:munich' preferred-precipitation snow) +example(zstyle ':weather:*:Sunday:*' preferred-precipitation snow +zstyle ':weather:europe:*' preferred-precipitation rain) -Then, the fictional `tt(weather)' plugin might run under the hood a command -such as +Then the plugin would run under the hood a command such as -example(zstyle -s ":weather:${continent}:${country}:${county}:${city}" preferred-precipitation REPLY) +example(zstyle -s ":weather:${continent}:${day_of_week}:${moon_phase}" preferred-precipitation REPLY) in order to retrieve your preference into the scalar variable tt($REPLY). +On Sundays tt($REPLY) would be set to `tt(snow)'; in Europe it would be set +to `tt(rain)'; and on Sundays in Europe it would be set to `tt(snow)' again, +because the patterns `tt(:weather:europe:*)' and `tt(:weather:*:Sunday:*)' both +match the var(context) argument to tt(zstyle -s), are equally specific, and the +latter was defined first. em(Usage) diff --git a/Test/V05styles.ztst b/Test/V05styles.ztst deleted file mode 100644 index c221d9db8..000000000 --- a/Test/V05styles.ztst +++ /dev/null @@ -1,153 +0,0 @@ -%prep - -# Test the use of styles, if the zsh/zutil module is available. - - if ! zmodload zsh/zutil 2>/dev/null; then - ZTST_unimplemented="can't load the zsh/zutil module for testing" - fi - -%test - zstyle :random:stuff any-old-style with any old value - zstyle :randomly:chosen some-other-style I can go on and on - zstyle -d - zstyle -0:zstyle -d restores a pristine state - -# patterns should be ordered by weight, so add in reverse order to check - zstyle ':ztst:context*' scalar-style other-scalar-value - zstyle ':ztst:context:*' scalar-style second-scalar-value - zstyle ':ztst:context:sub1' scalar-style scalar-value - zstyle ':ztst:context:sub1' array-style array value elements 'with spaces' - zstyle ':ztst:context*' boolean-style false - zstyle ':ztst:context:sub1' boolean-style true -0:defining styles - -# styles are now sorted, but patterns are in order of definition - zstyle -0:listing styles in default format ->array-style -> :ztst:context:sub1 array value elements 'with spaces' ->boolean-style -> :ztst:context:sub1 true -> :ztst:context* false ->scalar-style -> :ztst:context:sub1 scalar-value -> :ztst:context:* second-scalar-value -> :ztst:context* other-scalar-value - - zstyle -L -0:listing styles in zstyle format ->zstyle :ztst:context:sub1 array-style array value elements 'with spaces' ->zstyle :ztst:context:sub1 boolean-style true ->zstyle ':ztst:context*' boolean-style false ->zstyle :ztst:context:sub1 scalar-style scalar-value ->zstyle ':ztst:context:*' scalar-style second-scalar-value ->zstyle ':ztst:context*' scalar-style other-scalar-value - - zstyle -b :ztst:context:sub1 boolean-style bool; print $bool - zstyle -t :ztst:context:sub1 boolean-style -0:boolean test -b/-t + true ->yes - - zstyle -b :ztst:context:sub2 boolean-style bool; print $bool - zstyle -t :ztst:context:sub2 boolean-style -1:boolean test -b/-t + false ->no - - zstyle -b :ztst:context:sub1 boolean-unset-style bool; print $bool - zstyle -t :ztst:context:sub1 boolean-unset-style -2:boolean test -b/-t + unset ->no - - zstyle -T :ztst:context:sub1 boolean-style -0:boolean test -T + true - - zstyle -T :ztst:context:sub2 boolean-style -1:boolean test -T + false - - zstyle -T :ztst:context:sub1 boolean-unset-style -0:boolean test -T + unset - - zstyle -s :ztst:context:sub1 scalar-style scalar && print $scalar - zstyle -s :ztst:context:sub2 scalar-style scalar && print $scalar - zstyle -s :ztst:contextual-psychedelia scalar-style scalar && print $scalar - zstyle -s :ztst:contemplative scalar-style scalar || print no match -0:pattern matching rules ->scalar-value ->second-scalar-value ->other-scalar-value ->no match - - zstyle -s :ztst:context:sub1 array-style scalar + && print $scalar -0:scalar with separator ->array+value+elements+with spaces - - zstyle -e :ztst:\* eval-style 'reply=($something)' - something=(one two three) - zstyle -a :ztst:eval eval-style array && print -l $array -0:zstyle -e evaluations ->one ->two ->three - -# pattern ordering on output is not specified, so although in the -# current implementation it's deterministic we shouldn't -# assume it's always the same. Thus we sort the array. -# (It might be a nice touch to order patterns by weight, which is -# the way they are stored for each separate style.) - zstyle -g array && print -l ${(o)array} -0:retrieving patterns ->:ztst:* ->:ztst:context* ->:ztst:context:* ->:ztst:context:sub1 - - zstyle -m :ztst:context:sub1 array-style 'w* *s' -0:positive pattern match - - zstyle -m :ztst:context:sub1 array-style 'v' -1:negative pattern match - - zstyle -g array ':ztst:context*' && print -l $array -0:retrieving styles by pattern ->boolean-style ->scalar-style - - zstyle -g array ':ztst:context:sub1' array-style && print -l $array -0:retrieving values by pattern and name ->array ->value ->elements ->with spaces - - zstyle -d :ztst:context:sub1 - zstyle -0:deleting styles by pattern only ->boolean-style -> :ztst:context* false ->eval-style ->(eval) :ztst:* 'reply=($something)' ->scalar-style -> :ztst:context:* second-scalar-value -> :ztst:context* other-scalar-value - - zstyle -d :ztst:context\* scalar-style - zstyle -0:deleting styles by pattern and style name ->boolean-style -> :ztst:context* false ->eval-style ->(eval) :ztst:* 'reply=($something)' ->scalar-style -> :ztst:context:* second-scalar-value - - (zstyle 'ctx?' foo one - zstyle 'ctx*' foo two - zstyle -s 'ctx1' foo bar && print $bar) - (zstyle 'ctx*' foo two - zstyle 'ctx?' foo one - zstyle -s 'ctx1' foo bar && print $bar) -0:patterns of equal weight are used in order of definition ->one ->two - diff --git a/V05styles.ztst b/V05styles.ztst new file mode 100644 index 000000000..9b5fc4517 --- /dev/null +++ b/V05styles.ztst @@ -0,0 +1,166 @@ +%prep + +# Test the use of styles, if the zsh/zutil module is available. + + if ! zmodload zsh/zutil 2>/dev/null; then + ZTST_unimplemented="can't load the zsh/zutil module for testing" + fi + +%test + zstyle :random:stuff any-old-style with any old value + zstyle :randomly:chosen some-other-style I can go on and on + zstyle -d + zstyle +0:zstyle -d restores a pristine state + +# patterns should be ordered by weight, so add in reverse order to check + zstyle ':ztst:context*' scalar-style other-scalar-value + zstyle ':ztst:context:*' scalar-style second-scalar-value + zstyle ':ztst:context:sub1' scalar-style scalar-value + zstyle ':ztst:context:sub1' array-style array value elements 'with spaces' + zstyle ':ztst:context*' boolean-style false + zstyle ':ztst:context:sub1' boolean-style true +0:defining styles + +# styles are now sorted, but patterns are in order of definition + zstyle +0:listing styles in default format +>array-style +> :ztst:context:sub1 array value elements 'with spaces' +>boolean-style +> :ztst:context:sub1 true +> :ztst:context* false +>scalar-style +> :ztst:context:sub1 scalar-value +> :ztst:context:* second-scalar-value +> :ztst:context* other-scalar-value + + zstyle -L +0:listing styles in zstyle format +>zstyle :ztst:context:sub1 array-style array value elements 'with spaces' +>zstyle :ztst:context:sub1 boolean-style true +>zstyle ':ztst:context*' boolean-style false +>zstyle :ztst:context:sub1 scalar-style scalar-value +>zstyle ':ztst:context:*' scalar-style second-scalar-value +>zstyle ':ztst:context*' scalar-style other-scalar-value + + zstyle -b :ztst:context:sub1 boolean-style bool; print $bool + zstyle -t :ztst:context:sub1 boolean-style +0:boolean test -b/-t + true +>yes + + zstyle -b :ztst:context:sub2 boolean-style bool; print $bool + zstyle -t :ztst:context:sub2 boolean-style +1:boolean test -b/-t + false +>no + + zstyle -b :ztst:context:sub1 boolean-unset-style bool; print $bool + zstyle -t :ztst:context:sub1 boolean-unset-style +2:boolean test -b/-t + unset +>no + + zstyle -T :ztst:context:sub1 boolean-style +0:boolean test -T + true + + zstyle -T :ztst:context:sub2 boolean-style +1:boolean test -T + false + + zstyle -T :ztst:context:sub1 boolean-unset-style +0:boolean test -T + unset + + zstyle -s :ztst:context:sub1 scalar-style scalar && print $scalar + zstyle -s :ztst:context:sub2 scalar-style scalar && print $scalar + zstyle -s :ztst:contextual-psychedelia scalar-style scalar && print $scalar + zstyle -s :ztst:contemplative scalar-style scalar || print no match +0:pattern matching rules +>scalar-value +>second-scalar-value +>other-scalar-value +>no match + + zstyle -s :ztst:context:sub1 array-style scalar + && print $scalar +0:scalar with separator +>array+value+elements+with spaces + + zstyle -e :ztst:\* eval-style 'reply=($something)' + something=(one two three) + zstyle -a :ztst:eval eval-style array && print -l $array +0:zstyle -e evaluations +>one +>two +>three + +# pattern ordering on output is not specified, so although in the +# current implementation it's deterministic we shouldn't +# assume it's always the same. Thus we sort the array. +# (It might be a nice touch to order patterns by weight, which is +# the way they are stored for each separate style.) + zstyle -g array && print -l ${(o)array} +0:retrieving patterns +>:ztst:* +>:ztst:context* +>:ztst:context:* +>:ztst:context:sub1 + + zstyle -m :ztst:context:sub1 array-style 'w* *s' +0:positive pattern match + + zstyle -m :ztst:context:sub1 array-style 'v' +1:negative pattern match + + zstyle -g array ':ztst:context*' && print -l $array +0:retrieving styles by pattern +>boolean-style +>scalar-style + + zstyle -g array ':ztst:context:sub1' array-style && print -l $array +0:retrieving values by pattern and name +>array +>value +>elements +>with spaces + + zstyle -d :ztst:context:sub1 + zstyle +0:deleting styles by pattern only +>boolean-style +> :ztst:context* false +>eval-style +>(eval) :ztst:* 'reply=($something)' +>scalar-style +> :ztst:context:* second-scalar-value +> :ztst:context* other-scalar-value + + zstyle -d :ztst:context\* scalar-style + zstyle +0:deleting styles by pattern and style name +>boolean-style +> :ztst:context* false +>eval-style +>(eval) :ztst:* 'reply=($something)' +>scalar-style +> :ztst:context:* second-scalar-value + + (zstyle 'ctx?' foo one + zstyle 'ctx*' foo two + zstyle -s 'ctx1' foo bar && print $bar) + (zstyle 'ctx*' foo two + zstyle 'ctx?' foo one + zstyle -s 'ctx1' foo bar && print $bar) +0:patterns of equal weight are used in order of definition +>one +>two + + ( + zstyle ':weather:*:Sunday:*' preferred-precipitation snow + zstyle ':weather:europe:*' preferred-precipitation rain + zstyle -s ':weather:europe:Sunday:foo' preferred-precipitation REPLY && print $REPLY + ) + ( + zstyle ':weather:europe:*' preferred-precipitation rain + zstyle ':weather:*:Sunday:*' preferred-precipitation snow + zstyle -s ':weather:europe:Sunday:foo' preferred-precipitation REPLY && print $REPLY + ) +0:the example in the documentation remains correct +>snow +>rain -- cgit v1.2.3 From 7f73edad7a7547d357e540ca26264768c1eddbfb Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Tue, 28 Apr 2020 19:59:10 +0000 Subject: 45739: docs: Clarifications about zstyle patterns. - Consistently use the term "pattern" rather than "context" or "style pattern" - Correct statements about order of precedence of patterns - Give the rationale for the "rule of thumb" --- ChangeLog | 3 +++ Doc/Zsh/compsys.yo | 28 +++++++++++++++++----------- Doc/Zsh/zftpsys.yo | 8 +++----- 3 files changed, 23 insertions(+), 16 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index e980c9187..3969dd76b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-05-02 Daniel Shahaf + * 45739: Doc/Zsh/compsys.yo, Doc/Zsh/zftpsys.yo: docs: + Clarifications about zstyle patterns. + * 45722: Doc/Zsh/mod_zutil.yo, V05styles.ztst: docs: Change zstyle example to a non-hierarchical one diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index a1a1da935..1ce17dccc 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -49,7 +49,7 @@ Styles modify various operations of the completion system, such as output formatting, but also what kinds of completers are used (and in what order), or which tags are examined. Styles may accept arguments and are manipulated using the tt(zstyle) command described in -ifzman(see zmanref(zshmodules))\ +ifzman(zmanref(zshmodules))\ ifnzman(noderef(The zsh/zutil Module)). In summary, tags describe em(what) the completion objects are, and style @@ -658,8 +658,8 @@ ifnzman(noderef(Bindable Commands)). When looking up styles the completion system uses full context names, including the tag. Looking up the value of a style therefore consists of two things: the context, which is matched to the most specific (best -fitting) style pattern, and the name of the style itself, which must be -matched exactly. The following examples demonstrate that style patterns +fitting) pattern, and the name of the style itself, which must be +matched exactly. The following examples demonstrate that patterns may be loosely defined for styles that apply broadly, or as tightly defined as desired for styles that apply in narrower circumstances. @@ -673,7 +673,7 @@ example(zstyle ':completion:*' verbose yes) in a startup file (probably tt(.zshrc)). This gives the tt(verbose) style the value tt(yes) in every context inside the completion system, unless that context has a more -specific definition. It is best to avoid giving the context as `tt(*)' +specific definition. It is best to avoid giving the pattern as `tt(*)' in case the style has some meaning outside the completion system. Many such general purpose styles can be configured simply by using the @@ -710,15 +710,21 @@ as tt(menu) and tt(list-rows-first). Note that the order in which styles are em(defined) does not matter; the style mechanism uses the most specific possible match for a particular -style to determine the set of values. More precisely, strings are +style to determine the set of values. Strings are preferred over patterns (for example, `tt(:completion::complete:::foo)' is more specific than `tt(:completion::complete:::*')), and longer patterns are -preferred over shorter patterns. - -A good rule of thumb is that any completion style pattern that needs to -include more than one wildcard (tt(*)) and that does not end in a tag -name, should include all six colons (tt(:)), possibly surrounding -additional wildcards. +preferred over the pattern `tt(*)'. See +ifzman(zmanref(zmodules))ifnzman(noderef(The zsh/zutil Module)) +for details. + +Context patterns that use something other than a wildcard (tt(*)) to match the +middle parts of the context DASH()- the var(completer), var(command), and +var(argument) in +tt(:completion:)var(function)tt(:)var(completer)tt(:)var(command)tt(:)var(argument)tt(:)var(tag) +DASH()- should include all six colons (tt(:)) explicitly. Without this, +a pattern such as tt(:completion:*:foo:*) could match tt(foo) against a +component other than the intended one (for example, against var(completer) when +a match against var(command) was intended). Style names like those of tags are arbitrary and depend on the completion function. However, the following two sections list some of the most diff --git a/Doc/Zsh/zftpsys.yo b/Doc/Zsh/zftpsys.yo index 349039edc..c2fbdd23f 100644 --- a/Doc/Zsh/zftpsys.yo +++ b/Doc/Zsh/zftpsys.yo @@ -518,13 +518,11 @@ command `tt(zstyle ':zftp:*') var(style) var(value) ...'. defines the var(style) to have value var(value); more than one value may be given, although that is not useful in the cases described here. These values will then be used throughout the zftp function system. For more -precise control, the first argument, which gives a context in which the +precise control, the first argument, which gives a pattern that matches em(contexts) in which the style applies, can be modified to include a particular function, as for example `tt(:zftp:zfget)': the style will then have the given value only -in the tt(zfget) function. Values for the same style in different contexts -may be set; the most specific function will be used, where -strings are held to be more specific than patterns, and longer patterns and -shorter patterns. Note that only the top level function name, as called by +in the tt(zfget) function, and will override styles set under `tt(:zftp:*)'. +Note that only the top level function name, as called by the user, is used; calling of lower level functions is transparent to the user. Hence modifications to the title bar in tt(zftp_chpwd) use the contexts tt(:zftp:zfopen), tt(:zftp:zfcd), etc., depending where it was -- cgit v1.2.3 From 34d69acbef44f654ea51d762ffdb02f5b1e8b9e1 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 29 Apr 2020 00:30:17 +0000 Subject: 45737 (+ docs, and update the test from 45722): zstyle: When determining the weight (specificity) of a pattern, consider the number of components before anything else, as documented. --- ChangeLog | 6 ++++++ Doc/Zsh/mod_zutil.yo | 6 +++--- README | 19 +++++++++++++++++++ Src/Modules/zutil.c | 13 +++++++++++-- Test/V05styles.ztst | 2 +- 5 files changed, 40 insertions(+), 6 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index ec1e413c7..1fd8b9944 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2020-05-02 Daniel Shahaf + * 45737 (+ docs, and update the test from 45722): + Doc/Zsh/mod_zutil.yo, README, Src/Modules/zutil.c, + Test/V05styles.ztst: zstyle: When determining the weight + (specificity) of a pattern, consider the number of components + before anything else, as documented. + * unposted: Test/V05styles.ztst: Revert unintentional move from 45722. diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index c69233f9d..9c50e6122 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -40,8 +40,8 @@ that it looks up the tt(preferred-precipitation) style under the `tt(:weather:)var(continent)tt(:)var(day-of-the-week)tt(:)var(phase-of-the-moon))' context. According to this, you might set the following in your tt(zshrc): -example(zstyle ':weather:*:Sunday:*' preferred-precipitation snow -zstyle ':weather:europe:*' preferred-precipitation rain) +example(zstyle ':weather:europe:*' preferred-precipitation rain +zstyle ':weather:*:Sunday:*' preferred-precipitation snow) Then the plugin would run under the hood a command such as @@ -52,7 +52,7 @@ On Sundays tt($REPLY) would be set to `tt(snow)'; in Europe it would be set to `tt(rain)'; and on Sundays in Europe it would be set to `tt(snow)' again, because the patterns `tt(:weather:europe:*)' and `tt(:weather:*:Sunday:*)' both match the var(context) argument to tt(zstyle -s), are equally specific, and the -latter was defined first. +latter is more specific (because it has more colon-separated components). em(Usage) diff --git a/README b/README index b87f660bf..8ae615153 100644 --- a/README +++ b/README @@ -64,6 +64,25 @@ The sh-compatible function definition syntax, "f() { ... }", is unchanged. The time-out (-t) value given to zsh/system's `zsystem flock` command is now limited to 2^30-1 seconds (= a little over 34 years). +zstyle: For background, recall that the zstyle builtin associates styles with +values for particular contexts, and when a context (such as ':foo:bar:baz') is +matched by multiple patterns (such as ':foo:*' and ':foo:bar:*'), the style's +value for the more specific of the patterns is used. In zsh 5.8 and earlier +the determination of which pattern is "more specific" used semantics slightly +different to those the documentation promised. The implementation was changed +to match the documentation. The upshot of this is that if you set a single +style in multiple contexts, zsh 5.9 may use the values set for a pattern other +than the one zsh 5.8 used. For example, if you do + zstyle ':foo:bar:*' style value1 + zstyle ':foo:*:baz:*' style value2 +and the style is looked up under a context that both patterns match (e.g., +:foo:bar:baz:qux), zsh 5.9 will use value2 -- which is consistent with the +documentation of both 5.8 and 5.9 -- but zsh 5.8 will use value1. If this +affects you, make the implied colons in the first pattern explicit, as in: + zstyle ':foo:bar:*:*' style value1 + zstyle ':foo:*:baz:*' style value2 +This will use value1 in both 5.8 and 5.9. + Incompatibilities between 5.7.1 and 5.8 --------------------------------------- diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 7d9bf05d6..5c96d06c1 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -96,7 +96,7 @@ struct stypat { Stypat next; char *pat; /* pattern string */ Patprog prog; /* compiled pattern */ - int weight; /* how specific is the pattern? */ + zulong weight; /* how specific is the pattern? */ Eprog eval; /* eval-on-retrieve? */ char **vals; }; @@ -293,7 +293,9 @@ newzstyletable(int size, char const *name) static int setstypat(Style s, char *pat, Patprog prog, char **vals, int eval) { - int weight, tmp, first; + zulong weight; + int tmp; + int first; char *str; Stypat p, q, qq; Eprog eprog = NULL; @@ -348,6 +350,12 @@ setstypat(Style s, char *pat, Patprog prog, char **vals, int eval) * - A component that's a literal string scores 2 points. * - The score of a pattern is the sum of the score of its components. * + * The result of this calculation is stored in the low bits of 'weight'. + * The high bits of 'weight' are used to store the number of ':'-separated + * components. This provides a lexicographic comparison: first compare + * the number of components, and if that's equal, compare the specificity + * of the components. + * * This corresponds to the notion of 'more specific' in the zshmodules(1) * documentation of zstyle. */ @@ -367,6 +375,7 @@ setstypat(Style s, char *pat, Patprog prog, char **vals, int eval) if (*str == ':') { /* Yet another component. */ + weight += ZLONG_CONST(1) << (CHAR_BIT * sizeof(weight) / 2); first = 1; weight += tmp; diff --git a/Test/V05styles.ztst b/Test/V05styles.ztst index 9b5fc4517..048751941 100644 --- a/Test/V05styles.ztst +++ b/Test/V05styles.ztst @@ -163,4 +163,4 @@ ) 0:the example in the documentation remains correct >snow ->rain +>snow -- cgit v1.2.3 From deca7c928520fba5a73383f1cac0b3ace8e0e45d Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 27 Apr 2020 19:30:40 +0000 Subject: 45730: _arguments: Add the -0 flag, which makes $opt_args be populated sanely. Also, write/extend docstrings for sepjoin() and zjoin(). --- ChangeLog | 5 +++++ Completion/Base/Utility/_arguments | 8 +++++--- Doc/Zsh/compsys.yo | 25 +++++++++++++++++++++--- Src/Zle/computil.c | 40 +++++++++++++++++++++++++++++++++----- Src/utils.c | 15 +++++++++++++- Test/Y03arguments.ztst | 8 +++++++- 6 files changed, 88 insertions(+), 13 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 1942d9aab..1afa30114 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2020-05-03 Daniel Shahaf + * 45730: Completion/Base/Utility/_arguments, Doc/Zsh/compsys.yo, + Src/Zle/computil.c, Src/utils.c, Test/Y03arguments.ztst: + _arguments: Add the -0 flag, which makes $opt_args be populated + sanely. + * 45729: Src/Modules/curses.c, Src/Zle/compcore.c, Src/Zle/computil.c, Src/builtin.c, Src/linklist.c: internal: Add a second parameter to zlinklist2array(), analogously to diff --git a/Completion/Base/Utility/_arguments b/Completion/Base/Utility/_arguments index 136dd5826..3f1b39304 100644 --- a/Completion/Base/Utility/_arguments +++ b/Completion/Base/Utility/_arguments @@ -7,11 +7,13 @@ local long cmd="$words[1]" descr odescr mesg subopts opt opt2 usecc autod local oldcontext="$curcontext" hasopts rawret optarg singopt alwopt local setnormarg start rest local -a match mbegin mend +integer opt_args_use_NUL_separators=0 subopts=() singopt=() -while [[ "$1" = -([AMO]*|[CRSWnsw]) ]]; do +while [[ "$1" = -([AMO]*|[0CRSWnsw]) ]]; do case "$1" in + -0) opt_args_use_NUL_separators=1; shift ;; -C) usecc=yes; shift ;; -O) subopts=( "${(@P)2}" ); shift 2 ;; -O*) subopts=( "${(@P)${1[3,-1]}}" ); shift ;; @@ -388,7 +390,7 @@ if (( $# )) && comparguments -i "$autod" "$singopt[@]" "$@"; then if [[ "$action" = -\>* ]]; then action="${${action[3,-1]##[ ]#}%%[ ]#}" if (( ! $state[(I)$action] )); then - comparguments -W line opt_args + comparguments -W line opt_args $opt_args_use_NUL_separators state+=( "$action" ) state_descr+=( "$descr" ) if [[ -n "$usecc" ]]; then @@ -406,7 +408,7 @@ if (( $# )) && comparguments -i "$autod" "$singopt[@]" "$@"; then local=yes fi - comparguments -W line opt_args + comparguments -W line opt_args $opt_args_use_NUL_separators if [[ "$action" = \ # ]]; then diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 1ce17dccc..98ab46d8a 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -3740,6 +3740,12 @@ The default var(matchspec) allows partial word completion after `tt(_)' and var(matchspec) is: example(tt(r:|[_-]=* r:|=*)) ) +item(tt(-0))( +When populating values of the `tt(opt_args)' associative array, don't +backslash-escape colons and backslashes and use NUL rather than colon for +joining multiple values. This option is described in more detail below, under +the heading em(var(spec)s: actions). +) enditem() em(var(spec)s: overview) @@ -3912,6 +3918,7 @@ specific contexts: on the first call `tt(_arguments $global_options)' is used, and on subsequent calls `tt(_arguments !$^global_options)'. em(var(spec)s: actions) +COMMENT(If you change this section title, change the references to it in running text.) In each of the forms above the var(action) determines how completions should be generated. Except for the `tt(->)var(string)' @@ -4033,9 +4040,21 @@ the normal arguments from the command line, i.e. the words from the command line after the command name excluding all options and their arguments. Options are stored in the associative array `tt(opt_args)' with option names as keys and their arguments as -the values. For options that have more than one argument these are -given as one string, separated by colons. All colons and backslashes -in the original arguments are preceded with backslashes. +the values. By default, all colons and backslashes in the value are escaped +with backslashes, and if an option has multiple arguments (for example, when +using an var(optspec) of the form `tt(*)var(optspec)'), they are joined with +(unescaped) colons. However, if the tt(-0) option was passed, no backslash +escaping is performed, and multiple values are joined with NUL bytes. For +example, after `tt(zsh -o foo:foo -o bar:bar -o )', the contents of +`tt(opt_args)' would be + +example(typeset -A opt_args=( [-o]='foo\:foo:bar\:bar:' )) + +by default, and + +example(typeset -A opt_args=( [-o]=$'foo:foo\x00bar:bar\x00' )) + +if tt(_arguments) had been called with the tt(-0) option. The parameter `tt(context)' is set when returning to the calling function to perform an action of the form `tt(->)var(string)'. It is set to an diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index ddfa70077..e08788e89 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -2375,6 +2375,23 @@ ca_parse_line(Cadef d, Cadef all, int multi, int first) return 0; } +/* Build a NUL-separated from a list. + * + * This is only used to populate values of $opt_args. + */ + +static char * +ca_nullist(LinkList l) +{ + if (l) { + char **array = zlinklist2array(l, 0 /* don't dup elements */); + char *ret = zjoin(array, '\0', 0 /* permanent allocation */); + free(array); /* the elements are owned by the list */ + return ret; + } else + return ztrdup(""); +} + /* Build a colon-list from a list. * * This is only used to populate values of $opt_args. @@ -2563,7 +2580,7 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) case 's': min = 1; max = 1; break; case 'M': min = 1; max = 1; break; case 'a': min = 0; max = 0; break; - case 'W': min = 2; max = 2; break; + case 'W': min = 3; max = 3; break; case 'n': min = 1; max = 1; break; default: zwarnnam(nam, "invalid option: %s", args[0]); @@ -2795,11 +2812,20 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) return 0; return 1; case 'W': - /* This gets two parameter names as arguments. The first is set to - * the current word sans any option prefixes handled by comparguments. + /* This gets two parameter names and one integer as arguments. + * + * The first parameter is set to the current word sans any option + * prefixes handled by comparguments. + * * The second parameter is set to an array containing the options on * the line and their arguments. I.e. the stuff _arguments returns - * to its caller in the `line' and `opt_args' parameters. */ + * to its caller in the `line' and `opt_args' parameters. + * + * The integer is one if the second parameter (which is just $opt_args, + * you know) should encode multiple values by joining them with NULs + * and zero if it should encode multiple values by joining them with + * colons after backslash-escaping colons and backslashes. + */ { Castate s; char **ret, **p; @@ -2807,6 +2833,7 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) LinkList *a; Caopt o; int num; + int opt_args_use_NUL_separators = (args[3][0] != '0'); for (num = 0, s = lstate; s; s = s->snext) num += countlinknodes(s->args); @@ -2832,7 +2859,10 @@ bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) if (*a) { *p++ = (o->gsname ? tricat(o->gsname, o->name, "") : ztrdup(o->name)); - *p++ = ca_colonlist(*a); + if (opt_args_use_NUL_separators) + *p++ = ca_nullist(*a); + else + *p++ = ca_colonlist(*a); } *p = NULL; diff --git a/Src/utils.c b/Src/utils.c index e258ef836..5158a70b1 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -3596,6 +3596,17 @@ strftimehandling: return buf - origbuf; } +/* + * Return a string consisting of the elements of 'arr' joined by the character + * 'delim', which will be metafied if necessary. The string will be allocated + * on the heap iff 'heap'. + * + * Comparable to: + * + * char metafied_delim[] = { Meta, delim ^ 32, '\0' }; + * sepjoin(arr, metafied_delim, heap) + */ + /**/ mod_export char * zjoin(char **arr, int delim, int heap) @@ -3894,10 +3905,12 @@ wordcount(char *s, char *sep, int mul) /* * 's' is a NULL-terminated array of strings. - * 'sep' is a string. + * 'sep' is a string, or NULL to split on ${IFS[1]}. * * Return a string consisting of the elements of 's' joined by 'sep', * allocated on the heap iff 'heap'. + * + * See also zjoin(). */ /**/ diff --git a/Test/Y03arguments.ztst b/Test/Y03arguments.ztst index fa4589374..a815799b3 100644 --- a/Test/Y03arguments.ztst +++ b/Test/Y03arguments.ztst @@ -231,9 +231,15 @@ tst_arguments '-a:one: :two' ':descr:{compadd -Q - $opt_args[-a]}' comptest $'tst -a 1:x \\2 \t' -0:opt_args with multiple arguments and quoting of colons and backslashes +0:opt_args with multiple arguments and quoting of colons and backslashes, part #1: default behaviour >line: {tst -a 1:x \2 1\:x:\\2 }{} + # Same as previous test, except with -0 and (qqqq) added + tst_arguments -0 : '-a:one: :two' ':descr:{compadd -Q - ${(qqqq)opt_args[-a]}}' + comptest $'tst -a 1:x \\2 \t' +0:opt_args with multiple arguments and quoting of colons and backslashes, part #2: NUL escaping +>line: {tst -a 1:x \2 $'1:x\0\\2' }{} + tst_arguments -a -b comptest $'tst rest -\t\C-w\eb\C-b-\t' 0:option completion with rest arguments on the line but not in the specs -- cgit v1.2.3 From 7c2a740d0f20fee3b953f6738f27b8339dd97d91 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 16 May 2020 20:48:40 +0000 Subject: users/24843: zshcompsys(1): Point to the 'format' style from the 'tag-order' style. --- ChangeLog | 5 +++++ Doc/Zsh/compsys.yo | 3 +++ 2 files changed, 8 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 923913cc9..992b7b205 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-05-16 Daniel Shahaf + + * users/24843: Doc/Zsh/compsys.yo: zshcompsys(1): Point to the + 'format' style from the 'tag-order' style. + 2020-05-12 Mikael Magnusson * 45796: Src/subst.c, Test/D04parameter.ztst: Support diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 98ab46d8a..8d2813c5a 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -1685,6 +1685,9 @@ example(zstyle ':completion:*' group-name '') All matches for which no group name is defined will be put in a group named tt(-default-). + +To display the group name in the output, see the tt(format) style (q.v.) +under the tt(descriptions) tag. ) kindex(group-order, completion style) item(tt(group-order))( -- cgit v1.2.3 From 086acd095d02158e4f67d4a4f39174feb2fbe19a Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sun, 17 May 2020 13:26:04 -0700 Subject: unposted: remove blank line that messed up "man" formatting --- Doc/Zsh/compsys.yo | 1 - 1 file changed, 1 deletion(-) (limited to 'Doc') diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 8d2813c5a..9cfb4fd04 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -5331,7 +5331,6 @@ in the tt(_comp_caller_options) associative array. Option names, spelled in lowercase without underscores, are mapped to one or other of the strings `tt(on)' and `tt(off)'. ) - item(tt(_comp_priv_prefix))( Completion functions such as tt(_sudo) can set the tt(_comp_priv_prefix) array to a command prefix that may then be used by tt(_call_program) to -- cgit v1.2.3 From 3df604a4be76db6ccf285eda6b4b3f5f6ec7497d Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 9 Jun 2020 18:04:46 +0100 Subject: 46026: Add CLOBBER_EMPTY option. --- ChangeLog | 5 +++++ Doc/Zsh/options.yo | 16 ++++++++++++++++ Src/exec.c | 27 ++++++++++++++++++++++----- Src/options.c | 1 + Src/zsh.h | 1 + Test/A04redirect.ztst | 14 ++++++++++++++ 6 files changed, 59 insertions(+), 5 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 979fa729b..3addf253f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-06-09 Peter Stephenson + + * 46026: Doc/Zsh/options.yo, Src/exec.c, Src/options.c, + Src/zsh.h, Test/A04redirect.ztst: Add CLOBBER_EMPTY option. + 2020-06-08 Peter Stephenson * uwers/24909: Src/exec.c: Don't clean up files used for diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 2b7637ff4..6da68308f 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1168,6 +1168,22 @@ If the option is not set, and the option tt(APPEND_CREATE) is also not set, `tt(>>!)' or `tt(>>|)' must be used to create a file. If either option is set, `tt(>>)' may be used. ) +pindex(CLOBBER_EMPTY) +pindex(NO_CLOBBER_EMPTY) +pindex(CLOBBEREMPTY) +pindex(NOCLOBBEREMPTY) +cindex(clobbering, of empty files) +cindex(file clobbering, of empty files) +item(tt(CLOBBER_EMPTY))( +This option is only used if the option tt(CLOBBER) is not set: note that +it is set by default. + +If this option is set, then regular files of zero length may be +ovewritten (`clobbered'). Note that it is possible another process +has written to the file between this test and use of the file by +the current process. This option should therefore not be used in +cases where files to be clobbered may be written to asynchronously. +) pindex(CORRECT) pindex(NO_CORRECT) pindex(NOCORRECT) diff --git a/Src/exec.c b/Src/exec.c index c72d485b2..045b5d2b9 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -2143,14 +2143,15 @@ clobber_open(struct redir *f) { struct stat buf; int fd, oerrno; + char *ufname = unmeta(f->name); /* If clobbering, just open. */ if (isset(CLOBBER) || IS_CLOBBER_REDIR(f->type)) - return open(unmeta(f->name), + return open(ufname, O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY, 0666); /* If not clobbering, attempt to create file exclusively. */ - if ((fd = open(unmeta(f->name), + if ((fd = open(ufname, O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, 0666)) >= 0) return fd; @@ -2158,11 +2159,27 @@ clobber_open(struct redir *f) * Try opening, and if it's a regular file then close it again * * because we weren't supposed to open it. */ oerrno = errno; - if ((fd = open(unmeta(f->name), O_WRONLY | O_NOCTTY)) != -1) { - if(!fstat(fd, &buf) && !S_ISREG(buf.st_mode)) - return fd; + if ((fd = open(ufname, O_WRONLY | O_NOCTTY)) != -1) { + if(!fstat(fd, &buf)) { + if (!S_ISREG(buf.st_mode)) + return fd; + /* + * If CLOBBER_EMPTY is in effect and the file is empty, + * we are allowed to re-use it. + * + * Note: there is an intrinsic race here because another + * process can write to this file at any time. The only fix + * would be file locking, which we wish to avoid in basic + * file operations at this level. This would not be + * fixed. just additionally complicated, by re-opening the + * file and truncating. + */ + if (isset(CLOBBEREMPTY) && buf.st_size == 0) + return fd; + } close(fd); } + errno = oerrno; return -1; } diff --git a/Src/options.c b/Src/options.c index 7586d21d2..fba021e7d 100644 --- a/Src/options.c +++ b/Src/options.c @@ -114,6 +114,7 @@ static struct optname optns[] = { {{NULL, "checkjobs", OPT_EMULATE|OPT_ZSH}, CHECKJOBS}, {{NULL, "checkrunningjobs", OPT_EMULATE|OPT_ZSH}, CHECKRUNNINGJOBS}, {{NULL, "clobber", OPT_EMULATE|OPT_ALL}, CLOBBER}, +{{NULL, "clobberempty", 0}, CLOBBEREMPTY}, {{NULL, "combiningchars", 0}, COMBININGCHARS}, {{NULL, "completealiases", 0}, COMPLETEALIASES}, {{NULL, "completeinword", 0}, COMPLETEINWORD}, diff --git a/Src/zsh.h b/Src/zsh.h index 1f2d774a1..ed123f2b9 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2378,6 +2378,7 @@ enum { CHECKJOBS, CHECKRUNNINGJOBS, CLOBBER, + CLOBBEREMPTY, APPENDCREATE, COMBININGCHARS, COMPLETEALIASES, diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst index d60519064..993138e7d 100644 --- a/Test/A04redirect.ztst +++ b/Test/A04redirect.ztst @@ -708,3 +708,17 @@ cat <&$testfd 0:Regression test for here document with fd declarator > This is, in some sense, a here document. + + (setopt noclobber clobberempty + rm -f foo + touch foo + print Works >foo + cat foo + print Works not >foo + # Make sure the file was not harmed + cat foo + ) +0:CLOBBER_EMPTY +>Works +>Works +?(eval):6: file exists: foo -- cgit v1.2.3 From c5f12fb732cc9ee9f151dd3357cf5f3f4bb55a48 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 10 Jun 2020 13:07:52 +0000 Subject: unposted: zstyle docs: Fix typo. This manifested as a trailing non-underlined ".RE" in the rendered man page. (I guess that was a man page directive, but I'm not sure how the extraneous closing parenthesis caused it to be rendered in the output.) --- ChangeLog | 4 ++++ Doc/Zsh/mod_zutil.yo | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 3addf253f..2e02cb123 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2020-06-10 Daniel Shahaf + + * unposted: Doc/Zsh/mod_zutil.yo: zstyle docs: Fix typo. + 2020-06-09 Peter Stephenson * 46026: Doc/Zsh/options.yo, Src/exec.c, Src/options.c, diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 9c50e6122..41d3dfdb0 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -37,7 +37,7 @@ findex(weather, example function) For example, a fictional `tt(weather)' plugin might state in its documentation that it looks up the tt(preferred-precipitation) style under the -`tt(:weather:)var(continent)tt(:)var(day-of-the-week)tt(:)var(phase-of-the-moon))' context. +`tt(:weather:)var(continent)tt(:)var(day-of-the-week)tt(:)var(phase-of-the-moon)' context. According to this, you might set the following in your tt(zshrc): example(zstyle ':weather:europe:*' preferred-precipitation rain -- cgit v1.2.3 From 33361e81bc60fa3d6cb78442136d105abd565d56 Mon Sep 17 00:00:00 2001 From: Miroslav Koškár Date: Wed, 17 Jun 2020 08:02:05 +0200 Subject: 46049: docs: Correct the sense of the single-letter abstract of the GLOBAL_RCS option (-d) --- ChangeLog | 5 +++++ Doc/Zsh/options.yo | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 3103d1877..1da64ca26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-06-17 Miroslav Koškár + + * 46049: Doc/Zsh/options.yo: docs: Correct the sense of the + single-letter abstract of the GLOBAL_RCS option (-d) + 2020-06-11 Oliver Kiddle * gitlab !12: Jan Máslo: Completion/Linux/Command/_mat, diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 6da68308f..b3bf11f5c 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1124,7 +1124,7 @@ pindex(GLOBALRCS) pindex(NOGLOBALRCS) cindex(startup files, global, inhibiting) cindex(files, global startup, inhibiting) -item(tt(GLOBAL_RCS) (tt(-d)) )( +item(tt(GLOBAL_RCS) (tt(+d)) )( If this option is unset, the startup files tt(zprofile()), tt(zshrc()), tt(zlogin()) and tt(zlogout()) will not be run. It can be disabled and re-enabled at any time, including inside local startup -- cgit v1.2.3 From ae0129b49f9f1b624fb4b067f6f1ef6757a24fd2 Mon Sep 17 00:00:00 2001 From: Manuel Jacob Date: Mon, 22 Jun 2020 00:22:30 +0200 Subject: 46091: Add code to Mercurial VCS backend to show topic if there is any. "Topics" is an experimental concept in Mercurial that augments the current branching concept (called "named branches"). For more information, see the not always up-to-date Mercurial Wiki page https://www.mercurial-scm.org/wiki/TopicPlan. --- ChangeLog | 6 ++++++ Doc/Zsh/contrib.yo | 3 ++- Functions/VCS_Info/Backends/VCS_INFO_get_data_hg | 11 ++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 79fa9c085..bf139ed0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2020-06-22 Manuel Jacob + + * 46091: Doc/Zsh/contrib.yo, + Functions/VCS_Info/Backends/VCS_INFO_get_data_hg: Add code to + Mercurial VCS backend to show topic if there is any. + 2020-06-19 Daniel Shahaf * 46044 (tweaked per Matthew): Completion/Unix/Command/_units: diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 0909cd4f5..b9f48e8af 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1328,7 +1328,8 @@ enditem() In tt(branchformat) these replacements are done: startsitem() -sitem(tt(%b))(The branch name.) +sitem(tt(%b))(The branch name. For tt(hg), the branch name can include a +topic name.) sitem(tt(%r))(The current revision number or the tt(hgrevformat) style for tt(hg).) endsitem() diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg index cd5ef321d..9f61aeaf4 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg @@ -5,7 +5,7 @@ setopt localoptions extendedglob NO_shwordsplit -local hgbase bmfile branchfile rebasefile dirstatefile mqseriesfile \ +local hgbase bmfile branchfile topicfile rebasefile dirstatefile mqseriesfile \ curbmfile curbm \ mqstatusfile mqguardsfile patchdir mergedir \ r_csetid r_lrev r_branch i_bmhash i_bmname \ @@ -27,6 +27,7 @@ mergedir="${hgbase}/.hg/merge/" bmfile="${hgbase}/.hg/bookmarks" curbmfile="${hgbase}/.hg/bookmarks.current" branchfile="${hgbase}/.hg/branch" +topicfile="${hgbase}/.hg/topic" rebasefile="${hgbase}/.hg/rebasestate" dirstatefile="${hgbase}/.hg/dirstate" mqstatusfile="${patchdir}/status" # currently applied patches @@ -69,6 +70,14 @@ fi # If we still don't know the branch it's safe to assume default [[ -n ${r_branch} ]] || r_branch="default" +# Show topic if there is any (the UI for this experimental concept is not yet +# final, but for a long time the convention has been to join the branch name +# and the topic name by a colon) +if [[ -f ${topicfile} && -r ${topicfile} && -s ${topicfile} ]] ; then + IFS= read -r REPLY < ${topicfile} + r_branch=${r_branch}:${REPLY} +fi + # The working dir has uncommitted-changes if the revision ends with a + if [[ $r_lrev[-1] == + ]] ; then hgchanges=1 -- cgit v1.2.3 From dd6e702ee49c7292c39037843b1b1b2b080f9fda Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 25 Jun 2020 11:41:21 +0000 Subject: 46068 (tweaked) (was: github #57): region_highlight: Add memo= support. This is useful when multiple plugins add region_highlight entries and subsequently want to remove only their own entries. Without this functionality, recognizing one's region_highlight entries is not trivial because the 'start' and 'end' offsets are modified by editing of $BUFFER and the highlight specification may not be unique or distinctive. The tweaks are as follows: - Change zfree() to zsfree() per workers/46070. - Remove the mem.c hunk, as it changed the signature of only one out of two alternative definitions of zsfree(). (The definition that hunk touched is the one that's not used by default.) --- ChangeLog | 5 ++++ Doc/Zsh/zle.yo | 36 +++++++++++++++++++++------ README | 9 +++++++ Src/Zle/zle.h | 4 +++ Src/Zle/zle_refresh.c | 62 ++++++++++++++++++++++++++++++++++++++++++----- Src/Zle/zle_utils.c | 21 ++++++++++++++++ Src/prompt.c | 9 ++++--- Test/X04zlehighlight.ztst | 44 +++++++++++++++++++++++++++++++++ 8 files changed, 173 insertions(+), 17 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index f55891b47..f530ab1eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2020-06-25 Daniel Shahaf + * 46068 (tweaked) (was: github #57): Doc/Zsh/zle.yo, README, + Src/Zle/zle.h, Src/Zle/zle_refresh.c, Src/Zle/zle_utils.c, + Src/prompt.c, Test/X04zlehighlight.ztst: region_highlight: + Add memo= support. + * 46102: Test/ztst.zsh: test harness: Make the XPass message distinct from the Fail message. diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index c928b8ca2..909abeb49 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -974,27 +974,39 @@ of the non-editable parts of the command line in tt(PREDISPLAY) and tt(POSTDISPLAY) are possible, but note that the tt(P) flag is needed for character indexing to include tt(PREDISPLAY). -Each string consists of the following parts: +Each string consists of the following whitespace-separated parts: startitemize() itemiz(Optionally, a `tt(P)' to signify that the start and end offset that follow include any string set by the tt(PREDISPLAY) special parameter; this is needed if the predisplay string itself is to be highlighted. -Whitespace may follow the `tt(P)'.) -itemiz(A start offset in the same units as tt(CURSOR), terminated by -whitespace.) -itemiz(An end offset in the same units as tt(CURSOR), terminated by -whitespace.) +Whitespace between the `tt(P)' and the start offset is optional.) +itemiz(A start offset in the same units as tt(CURSOR).) +itemiz(An end offset in the same units as tt(CURSOR).) itemiz(A highlight specification in the same format as used for contexts in the parameter tt(zle_highlight), see ifnzman(noderef(Character Highlighting))\ ifzman(the section `Character Highlighting' below); -for example, tt(standout) or tt(fg=red,bold)). +for example, tt(standout) or tt(fg=red,bold).) +itemiz(Optionally, a string of the form `tt(memo=)var(token)'. +The var(token) consists of everything between the `tt(=)' and the next +whitespace, comma, NUL, or the end of the string. +The var(token) is preserved verbatim but not parsed in any way. + +Plugins may use this to identify array elements they have added: for example, +a plugin might set var(token) to its (the plugin's) name and then use +`tt(region_highlight=+LPAR() ${region_highlight:#*memo=)var(token)tt(} +RPAR())' +in order to remove array elements it have added. + +(This example uses the `tt(${)var(name)tt(:#)var(pattern)tt(})' array-grepping +syntax described in +ifzman(the section `Parameter Expansion' in zmanref(zshexpn))\ +ifnzman(noderef(Parameter Expansion)).)) enditemize() For example, -example(region_highlight=("P0 20 bold")) +example(region_highlight=("P0 20 bold memo=foobar")) specifies that the first twenty characters of the text including any predisplay string should be highlighted in bold. @@ -1002,6 +1014,14 @@ any predisplay string should be highlighted in bold. Note that the effect of tt(region_highlight) is not saved and disappears as soon as the line is accepted. +Note that zsh 5.8 and older do not support the `tt(memo=)var(token)' field +and may misparse the third (highlight specification) field when a memo +is given. +COMMENT(The syntax `tt(0 20 bold, memo=foobar)' (with an auxiliary comma) +happens to work on both zsh <=5.8 and zsh 5.9-to-be, but that seems to be more of +an accident of implementation than something we should make a first-class-citizen +API promise. It's mentioned in the "Incompatibilities" section of README.) + The final highlighting on the command line depends on both tt(region_highlight) and tt(zle_highlight); see ifzman(the section CHARACTER HIGHLIGHTING below)\ diff --git a/README b/README index 8ae615153..9b1b1605f 100644 --- a/README +++ b/README @@ -83,6 +83,15 @@ affects you, make the implied colons in the first pattern explicit, as in: zstyle ':foo:*:baz:*' style value2 This will use value1 in both 5.8 and 5.9. +Elements of the region_highlight array have gained a fourth space-separated +field. Code written against 5.9 that sets the new field may break under 5.8: +for example, the element "0 20 bold memo=foo", which is valid under 5.9, would +not work under 5.8. (Under the hood, 5.8 does not recognize the space as +terminating the highlighting specification.) On the other hand, code that does +not set the new, fourth field will continue to work under both 5.8 and 5.9. +(As it happens, adding a comma after "bold" will make both 5.8 and 5.9 do the +right thing, but this should be viewed as an unsupported hack.) + Incompatibilities between 5.7.1 and 5.8 --------------------------------------- diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index 609493f8c..391586c4a 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -447,6 +447,10 @@ struct region_highlight { * Any of the flags defined above. */ int flags; + /* + * User-settable "memo" key. Metafied. + */ + const char *memo; }; /* diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index 7b8593dec..d9d9503e2 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -212,9 +212,9 @@ static zattr default_atr_on, special_atr_on; /* * Array of region highlights, no special termination. - * The first element (0) always describes the region between - * point and mark. Any other elements are set by the user - * via the parameter region_highlight. + * The first N_SPECIAL_HIGHLIGHTS elements describe special uses of + * highlighting, documented under N_SPECIAL_HIGHLIGHTS. + * Any other elements are set by the user via the parameter region_highlight. */ /**/ @@ -414,16 +414,19 @@ get_region_highlight(UNUSED(Param pm)) arrsize--; rhp++, arrp++) { char digbuf1[DIGBUFSIZE], digbuf2[DIGBUFSIZE]; - int atrlen = 0, alloclen; + int atrlen, alloclen; + const char memo_equals[] = "memo="; sprintf(digbuf1, "%d", rhp->start); sprintf(digbuf2, "%d", rhp->end); atrlen = output_highlight(rhp->atr, NULL); alloclen = atrlen + strlen(digbuf1) + strlen(digbuf2) + - 3; /* 2 spaces, 1 0 */ + 3; /* 2 spaces, 1 terminating NUL */ if (rhp->flags & ZRH_PREDISPLAY) alloclen += 2; /* "P " */ + if (rhp->memo) + alloclen += 1 /* space */ + strlen(memo_equals) + strlen(rhp->memo); *arrp = (char *)zhalloc(alloclen * sizeof(char)); /* * On input we allow a space after the flags. @@ -436,6 +439,12 @@ get_region_highlight(UNUSED(Param pm)) (rhp->flags & ZRH_PREDISPLAY) ? "P" : "", digbuf1, digbuf2); (void)output_highlight(rhp->atr, *arrp + strlen(*arrp)); + + if (rhp->memo) { + strcat(*arrp, " "); + strcat(*arrp, memo_equals); + strcat(*arrp, rhp->memo); + } } *arrp = NULL; return retarr; @@ -460,6 +469,8 @@ set_region_highlight(UNUSED(Param pm), char **aval) /* no null termination, but include special highlighting at start */ int newsize = len + N_SPECIAL_HIGHLIGHTS; int diffsize = newsize - n_region_highlights; + + free_region_highlights_memos(); region_highlights = (struct region_highlight *) zrealloc(region_highlights, sizeof(struct region_highlight) * newsize); @@ -476,6 +487,7 @@ set_region_highlight(UNUSED(Param pm), char **aval) *aval; rhp++, aval++) { char *strp, *oldstrp; + const char memo_equals[] = "memo="; oldstrp = *aval; if (*oldstrp == 'P') { @@ -502,7 +514,44 @@ set_region_highlight(UNUSED(Param pm), char **aval) while (inblank(*strp)) strp++; - match_highlight(strp, &rhp->atr); + strp = (char*) match_highlight(strp, &rhp->atr); + + while (inblank(*strp)) + strp++; + + if (strpfx(memo_equals, strp)) { + const char *memo_start = strp + strlen(memo_equals); + const char *i, *memo_end; + + /* + * Forward compatibility: end parsing at a comma or whitespace to + * allow the following extensions: + * + * - A fifth field: "0 20 bold memo=foo bar". + * + * - Additional attributes in the fourth field: "0 20 bold memo=foo,bar" + * and "0 20 bold memo=foo\0bar". + * + * For similar reasons, we don't flag an error if the fourth field + * doesn't start with "memo=" as we expect. + */ + i = memo_start; + + /* ### TODO: Consider optimizing the common case that memo_start to + * end-of-string is entirely ASCII */ + while (1) { + int nbytes; + convchar_t c = unmeta_one(i, &nbytes); + + if (c == '\0' || c == ',' || inblank(c)) { + memo_end = i; + break; + } else + i += nbytes; + } + rhp->memo = ztrduppfx(memo_start, memo_end - memo_start); + } else + rhp->memo = NULL; } freearray(av); @@ -2797,6 +2846,7 @@ zle_refresh_finish(void) if (region_highlights) { + free_region_highlights_memos(); zfree(region_highlights, sizeof(struct region_highlight) * n_region_highlights); region_highlights = NULL; diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 2b306fdcd..927b88bba 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -557,6 +557,22 @@ zlegetline(int *ll, int *cs) } +/* + * free() the 'memo' elements of region_highlights. + */ + +/**/ +void +free_region_highlights_memos(void) +{ + struct region_highlight *rhp; + for (rhp = region_highlights; + rhp < region_highlights + n_region_highlights; + rhp++) { + zfree(rhp->memo, 0); + } +} + /* Forward reference */ struct zle_region; @@ -568,6 +584,7 @@ struct zle_region { int start; int end; int flags; + const char *memo; }; /* Forward reference */ @@ -632,6 +649,7 @@ zle_save_positions(void) newrhp->next = NULL; newrhp->atr = rhp->atr; newrhp->flags = rhp->flags; + newrhp->memo = ztrdup(rhp->memo); if (zlemetaline) { newrhp->start = rhp->start_meta; newrhp->end = rhp->end_meta; @@ -682,6 +700,7 @@ zle_restore_positions(void) nreg++, oldrhp = oldrhp->next) ; if (nreg + N_SPECIAL_HIGHLIGHTS != n_region_highlights) { + free_region_highlights_memos(); n_region_highlights = nreg + N_SPECIAL_HIGHLIGHTS; region_highlights = (struct region_highlight *) zrealloc(region_highlights, @@ -694,6 +713,7 @@ zle_restore_positions(void) rhp->atr = oldrhp->atr; rhp->flags = oldrhp->flags; + rhp->memo = oldrhp->memo; /* transferring ownership of the permanently-allocated memory */ if (zlemetaline) { rhp->start_meta = oldrhp->start; rhp->end_meta = oldrhp->end; @@ -707,6 +727,7 @@ zle_restore_positions(void) rhp++; } } else if (region_highlights) { + free_region_highlights_memos(); zfree(region_highlights, sizeof(struct region_highlight) * n_region_highlights); region_highlights = NULL; diff --git a/Src/prompt.c b/Src/prompt.c index b65bfb86b..bc9734720 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -1724,10 +1724,11 @@ match_colour(const char **teststrp, int is_fg, int colour) /* * Match a set of highlights in the given teststr. * Set *on_var to reflect the values found. + * Return a pointer to the first character not consumed. */ /**/ -mod_export void +mod_export const char * match_highlight(const char *teststr, zattr *on_var) { int found = 1; @@ -1745,7 +1746,7 @@ match_highlight(const char *teststr, zattr *on_var) atr = match_colour(&teststr, is_fg, 0); if (*teststr == ',') teststr++; - else if (*teststr) + else if (*teststr && *teststr != ' ') break; found = 1; /* skip out of range colours but keep scanning attributes */ @@ -1758,7 +1759,7 @@ match_highlight(const char *teststr, zattr *on_var) if (*val == ',') val++; - else if (*val) + else if (*val && *val != ' ') break; *on_var |= hl->mask_on; @@ -1769,6 +1770,8 @@ match_highlight(const char *teststr, zattr *on_var) } } } + + return teststr; } /* diff --git a/Test/X04zlehighlight.ztst b/Test/X04zlehighlight.ztst index 475a2e309..7ab050bee 100644 --- a/Test/X04zlehighlight.ztst +++ b/Test/X04zlehighlight.ztst @@ -94,6 +94,50 @@ 0:basic region_highlight with 8 colors >0m27m24mCDE|32|trueCDE|39| + zpty_start + zpty_input 'rh_widget() { region_highlight+=( "0 4 fg=green memo=someplugin" ); typeset -p region_highlight }' + zpty_input 'zle -N rh_widget' + zpty_input 'bindkey "\C-a" rh_widget' + zpty_enable_zle + zpty_input $'\C-a' + zpty_line + zpty_stop +0:region_highlight memo information round trips +>typeset -a region_highlight=( '0 4 fg=green memo=someplugin' ) + + zpty_start + zpty_input 'rh_widget() { region_highlight+=( "0 4 fg=green memo=someplugin,futureattribute=futurevalue" ); typeset -p region_highlight }' + zpty_input 'zle -N rh_widget' + zpty_input 'bindkey "\C-a" rh_widget' + zpty_enable_zle + zpty_input $'\C-a' + zpty_line + zpty_stop +0:region_highlight memo information forward compatibility, #1 +>typeset -a region_highlight=( '0 4 fg=green memo=someplugin' ) + + zpty_start + zpty_input 'rh_widget() { region_highlight+=( "0 4 fg=green memo=someplugin futurefifthfield" ); typeset -p region_highlight }' + zpty_input 'zle -N rh_widget' + zpty_input 'bindkey "\C-a" rh_widget' + zpty_enable_zle + zpty_input $'\C-a' + zpty_line + zpty_stop +0:region_highlight memo information forward compatibility, #2 +>typeset -a region_highlight=( '0 4 fg=green memo=someplugin' ) + + zpty_start + zpty_input 'rh_widget() { region_highlight+=( "0 4 fg=green memo=some'$'\0''plugin" ); typeset -p region_highlight }' + zpty_input 'zle -N rh_widget' + zpty_input 'bindkey "\C-a" rh_widget' + zpty_enable_zle + zpty_input $'\C-a' + zpty_line + zpty_stop +0:region_highlight memo information forward compatibility, #3: NULs +>typeset -a region_highlight=( '0 4 fg=green memo=some' ) + zpty_start zpty_input 'rh_widget() { BUFFER="true"; region_highlight+=( "0 4 fg=#040810" ); }' zpty_input 'zle -N rh_widget' -- cgit v1.2.3 From 4e3d08fea8b82a638211b02fbaa7772cf1b2863d Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 2 May 2020 02:41:26 +0000 Subject: unposted: docs: Fix some markup and typos. --- ChangeLog | 6 ++++++ Doc/Zsh/contrib.yo | 4 ++-- Doc/Zsh/expn.yo | 4 ++-- Doc/Zsh/mod_mapfile.yo | 2 +- Etc/FAQ.yo | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index b48d6a40c..9b58db95c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2020-06-26 Daniel Shahaf + + * unposted: Doc/Zsh/contrib.yo, Doc/Zsh/expn.yo, + Doc/Zsh/mod_mapfile.yo, Etc/FAQ.yo: docs: Fix some markup + and typos. + 2020-06-26 Peter Stephenson * 46110: Src/subst.c, Test/D03procsubst.ztst: If =subst occurs diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index b9f48e8af..c611ff43b 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -598,7 +598,7 @@ changes to descendant directories; earlier directories on the list are not pruned. For example, changing from ~pws/yet/another to ~pws/some/other/dir does not cause ~pws to be pruned. ) -item(tt(pattern:var(pattern)))( +item(tt(pattern:)var(pattern))( Gives a zsh pattern for directories that should not be added to the recent list (if not already there). This element can be repeated to add different patterns. For example, @@ -660,7 +660,7 @@ sect(Abbreviated dynamic references to directories) The dynamic directory naming system is described in the subsection em(Dynamic named directories) of -ifzman(the section em(Filename Expansion) in zmanref(expn))\ +ifzman(the section em(Filename Expansion) in zmanref(zshexpn))\ ifnzman(noderef(Filename Expansion)). In this, a reference to tt(~[)var(...)tt(]) is expanded by a function found by the hooks mechanism. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 69cb0b08a..3800f2fb0 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -2900,8 +2900,8 @@ repeated, but note that the maximum number of sort operators of any kind that may appear in any glob expression is 12. ) item(tt(O)var(c))( -like `tt(o)', but sorts in descending order; i.e. `tt(*(^oc))' is the -same as `tt(*(Oc))' and `tt(*(^Oc))' is the same as `tt(*(oc))'; `tt(Od)' +like `tt(o)', but sorts in descending order; i.e. `tt(*+LPAR()^o)var(c)tt(+RPAR())' is the +same as `tt(*+LPAR()O)var(c)tt(+RPAR())' and `tt(*+LPAR()^O)var(c)tt(+RPAR())' is the same as `tt(*+LPAR()o)var(c)tt(+RPAR())'; `tt(Od)' puts files in the current directory before those in subdirectories at each level of the search. ) diff --git a/Doc/Zsh/mod_mapfile.yo b/Doc/Zsh/mod_mapfile.yo index 640beeb12..9d8f07214 100644 --- a/Doc/Zsh/mod_mapfile.yo +++ b/Doc/Zsh/mod_mapfile.yo @@ -13,7 +13,7 @@ value is the content of the file. The value is treated identically to any other text coming from a parameter. The value may also be assigned to, in which case the file in question is written (whether or not it originally existed); or an element may be unset, which will delete the file in -question. For example, `tt(vared mapfile[myfile])' works as expected, +question. For example, `tt(vared 'mapfile[myfile]')' works as expected, editing the file `tt(myfile)'. When the array is accessed as a whole, the keys are the names of files in diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo index e4197a069..45502bede 100644 --- a/Etc/FAQ.yo +++ b/Etc/FAQ.yo @@ -2548,7 +2548,7 @@ label(62) zsh-workers-subscribe@zsh.org ) (the actual content is unimportant). Replace tt(subscribe) with - tt(unsubscribe) to unsubscribe. The mailing software (tt(ezlm)) has + tt(unsubscribe) to unsubscribe. The mailing software (tt(ezmlm)) has various bells and whistles: you can retrieve archived messages. Mail email(zsh-workers-help@zsh.org) for detailed information. Administrative matters are best sent to -- cgit v1.2.3 From 7f58463dd33cfd75af894ba30fcbda576c112e46 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 24 Jun 2020 10:40:23 +0000 Subject: users/24959/0001: Extend documentation of global aliases. --- ChangeLog | 5 +++++ Doc/Zsh/builtins.yo | 8 +++++++- Doc/Zsh/grammar.yo | 9 +++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 9b58db95c..1f86a4884 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-06-27 Daniel Shahaf + + * users/24959/0001: Doc/Zsh/builtins.yo, Doc/Zsh/grammar.yo: + Extend documentation of global aliases. + 2020-06-26 Daniel Shahaf * unposted: Doc/Zsh/contrib.yo, Doc/Zsh/expn.yo, diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index ada69c99a..d35cad182 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -105,7 +105,13 @@ For each var(name) with a corresponding var(value), define an alias with that value. A trailing space in var(value) causes the next word to be checked for alias expansion. If the tt(-g) flag is present, define a global alias; global aliases are expanded even if they do not -occur in command position. +occur in command position: + +example(% perldoc --help 2>&1 | grep 'built-in functions' + -f Search Perl built-in functions +% alias -g HG='--help 2>&1 | grep' +% perldoc HG 'built-in functions' + -f Search Perl built-in functions) If the tt(-s) flag is present, define a suffix alias: if the command word on a command line is in the form `var(text)tt(.)var(name)', where diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index a4e0c1121..7eabd75ce 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -597,6 +597,15 @@ word, e.g. tt(\foo). Any form of quoting works, although there is nothing to prevent an alias being defined for the quoted form such as tt(\foo) as well. +In particular, note that quoting must be used when using tt(unalias) to remove +global aliases: + +example(% alias -g foo=bar +% unalias foo +unalias: no such hash table element: bar +% unalias \foo +% ) + When tt(POSIX_ALIASES) is set, only plain unquoted strings are eligible for aliasing. The tt(alias) builtin does not reject ineligible aliases, but they are not expanded. -- cgit v1.2.3 From 9575f2f1bf404b90002a5a55e13558288152a105 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 24 Jun 2020 10:40:45 +0000 Subject: users/24959/0002: Update aliases documentation for the addition of the ALIAS_FUNC_DEF option. --- ChangeLog | 3 +++ Doc/Zsh/grammar.yo | 25 +++++-------------------- 2 files changed, 8 insertions(+), 20 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 1f86a4884..cc1963af2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-06-27 Daniel Shahaf + * users/24959/0002: Doc/Zsh/grammar.yo: Update aliases + documentation for the addition of the ALIAS_FUNC_DEF option. + * users/24959/0001: Doc/Zsh/builtins.yo, Doc/Zsh/grammar.yo: Extend documentation of global aliases. diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index 7eabd75ce..2eb2018d2 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -571,6 +571,11 @@ position (if it could be the first word of a simple command), or if the alias is global. If the replacement text ends with a space, the next word in the shell input is always eligible for purposes of alias expansion. + +It is an error for the function name, var(word), in the sh-compatible function +definition syntax `var(word) tt(+LPAR()+RPAR()) ...' to be a word that resulted +from alias expansion, unless the tt(ALIAS_FUNC_DEF) option is set. + findex(alias, use of) cindex(aliases, global) An alias is defined using the tt(alias) builtin; global aliases @@ -656,26 +661,6 @@ a problem in shell scripts, functions, and code executed with `tt(source)' or `tt(.)'. Consequently, use of functions rather than aliases is recommended in non-interactive code. -Note also the unhelpful interaction of aliases and function definitions: - -example(alias func='noglob func' -func+LPAR()RPAR() { - echo Do something with $* -}) - -Because aliases are expanded in function definitions, this causes the -following command to be executed: - -example(noglob func+LPAR()RPAR() { - echo Do something with $* -}) - -which defines tt(noglob) as well as tt(func) as functions with the -body given. To avoid this, either quote the name tt(func) or use the -alternative function definition form `tt(function func)'. Ensuring the -alias is defined after the function works but is problematic if the -code fragment might be re-executed. - texinode(Quoting)()(Aliasing)(Shell Grammar) sect(Quoting) cindex(quoting) -- cgit v1.2.3 From 0cffb0a6b3602a00cebe2bbb7537d76727892959 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 18 Jun 2020 11:42:19 +0000 Subject: 46072 + 46136: Add the 'zle $widget -f nolast' syntax, to improve add-zle-hook-widget support for multiple hook functions. See workers/46004 for the use-case. --- ChangeLog | 6 ++++++ Doc/Zsh/contrib.yo | 2 +- Doc/Zsh/zle.yo | 7 +++++-- Functions/Misc/add-zle-hook-widget | 4 ++-- Src/Zle/zle_thingy.c | 19 +++++++++++++++++-- Test/X04zlehighlight.ztst | 11 +++++++++++ 6 files changed, 42 insertions(+), 7 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index cc1963af2..0d3a50cd5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2020-06-27 Daniel Shahaf + * 46072 + 46136: Doc/Zsh/contrib.yo, Doc/Zsh/zle.yo, + Functions/Misc/add-zle-hook-widget, Src/Zle/zle_thingy.c, + Test/X04zlehighlight.ztst: Add the 'zle $widget -f nolast' + syntax, to improve add-zle-hook-widget support for multiple + hook functions. + * users/24959/0002: Doc/Zsh/grammar.yo: Update aliases documentation for the addition of the ALIAS_FUNC_DEF option. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index c611ff43b..7cde0033f 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -347,7 +347,7 @@ as the var(hook) argument. var(widgetname) is the name of a ZLE widget. If no options are given this is added to the array of widgets to be invoked in the given hook context. Widgets are invoked in the order they were added, with -example(tt(zle )var(widgetname)tt( -Nw -- "$@")) +example(tt(zle )var(widgetname)tt( -Nw -f "nolast" -- "$@")) vindex(WIDGET, in hooks) Note that this means that the `tt(WIDGET)' special parameter tracks the diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 909abeb49..84be010e1 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -415,7 +415,7 @@ xitem(tt(zle) tt(-K) var(keymap)) xitem(tt(zle) tt(-F) [ tt(-L) | tt(-w) ] [ var(fd) [ var(handler) ] ]) xitem(tt(zle) tt(-I)) xitem(tt(zle) tt(-T) [ tt(tc) var(function) | tt(-r) tt(tc) | tt(-L) ] ) -item(tt(zle) var(widget) [ tt(-n) var(num) ] [ tt(-Nw) ] [ tt(-K) var(keymap) ] var(args) ...)( +item(tt(zle) var(widget) [ tt(-n) var(num) ] [ tt(-f) var(flag) ] [ tt(-Nw) ] [ tt(-K) var(keymap) ] var(args) ...)( The tt(zle) builtin performs a number of different actions concerning ZLE. @@ -683,7 +683,7 @@ optional argument for debugging or testing. Note that this transformation is not applied to other non-printing characters such as carriage returns and newlines. ) -item(var(widget) [ tt(-n) var(num) ] [ tt(-Nw) ] [ tt(-K) var(keymap) ] var(args) ...)( +item(var(widget) [ tt(-n) var(num) ] [ tt(-f) var(flag) ] [ tt(-Nw) ] [ tt(-K) var(keymap) ] var(args) ...)( Invoke the specified var(widget). This can only be done when ZLE is active; normally this will be within a user-defined widget. @@ -702,6 +702,9 @@ appears as if the top-level widget called by the user were still active. With the option tt(-w), tt(WIDGET) and related parameters are set to reflect the widget being executed by the tt(zle) call. +Normally, when var(widget) returns the special parameter tt(LASTWIDGET) will +point to it. This can be inhibited by passing the option tt(-f nolast). + Any further arguments will be passed to the widget; note that as standard argument handling is performed, any general argument list should be preceded by tt(-)tt(-). If it is a shell diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index 9cc35496f..4d8049083 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -47,9 +47,9 @@ function azhw:${^hooktypes} { for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do if [[ "$hook" = user:* ]]; then # Preserve $WIDGET within the renamed widget - zle "$hook" -N -- "$@" + zle "$hook" -f "nolast" -N -- "$@" else - zle "$hook" -Nw -- "$@" + zle "$hook" -f "nolast" -Nw -- "$@" fi || return done return 0 diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index ce61db27b..cd3f2c356 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -678,6 +678,7 @@ bin_zle_flags(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) else if (!strcmp(*flag, "keepsuffix")) w->flags |= ZLE_KEEPSUFFIX; */ + /* If you add magic strings here, be consistent with bin_zle_call() */ else if (!strcmp(*flag, "vichange")) { if (invicmdmode()) { startvichange(-1); @@ -703,7 +704,7 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) { Thingy t; struct modifier modsave = zmod; - int ret, saveflag = 0, setbindk = 0, setlbindk, remetafy; + int ret, saveflag = 0, setbindk = 0, setlbindk = 0, remetafy; char *wname = *args++, *keymap_restore = NULL, *keymap_tmp; if (!wname) @@ -727,12 +728,26 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) while (*args && **args == '-') { char skip_this_arg[2] = "x"; char *num; + char *flag; if (!args[0][1] || args[0][1] == '-') { args++; break; } while (*++(*args)) { switch (**args) { + case 'f': + flag = args[0][1] ? args[0]+1 : args[1]; + if (flag == NULL || strcmp(flag, "nolast")) { + zwarnnam(name, "%s", "'nolast' expected after -f"); + if (remetafy) + metafy_line(); + return 1; + } + if (!args[0][1]) + *++args = skip_this_arg; + /* If you add magic strings here, be consistent with bin_zle_flags() */ + setlbindk = 1; + break; case 'n': num = args[0][1] ? args[0]+1 : args[1]; if (!num) { @@ -787,7 +802,7 @@ bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) * a vi range to detect a repeated key */ setbindk = setbindk || (t->widget && (t->widget->flags & (WIDGET_INT | ZLE_VIOPER)) == WIDGET_INT); - setlbindk = t->widget && (t->widget->flags & ZLE_NOLAST) == ZLE_NOLAST; + setlbindk |= t->widget && (t->widget->flags & ZLE_NOLAST) == ZLE_NOLAST; ret = execzlefunc(t, args, setbindk, setlbindk); unrefthingy(t); if (saveflag) diff --git a/Test/X04zlehighlight.ztst b/Test/X04zlehighlight.ztst index 7ab050bee..ea1d64fe1 100644 --- a/Test/X04zlehighlight.ztst +++ b/Test/X04zlehighlight.ztst @@ -198,6 +198,17 @@ 0:overlapping region_highlight with near-color (hex-triplets at input) >0m27m24mCDE|340|tCDE|3160|rCDE|39|CDE|340|ueCDE|39| + zpty_start + zpty_input 'f () { zle clear-screen; zle g -f nolast; BUFFER=": ${(q)LASTWIDGET}" }; zle -N f' + zpty_input 'g () { }; zle -N g' + zpty_input 'bindkey "\C-a" f' + zpty_enable_zle + zpty_input $'\C-a' + zpty_line 1 p + zpty_stop +0:zle $widgetname -f nolast +>0m27m24m0m27m24m: clear-screen + %clean zmodload -ui zsh/zpty -- cgit v1.2.3 From f636cde7b501180c6ec07db8b60355c7af518c78 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 26 Jun 2020 18:52:21 +0000 Subject: 46132: docs: Use an itemized list in the documentation of the *(o) glob qualifier. This should be easier to read, both as a tutorial and as a reference. --- ChangeLog | 3 +++ Doc/Zsh/expn.yo | 28 ++++++++++++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 1da0d92bf..ec66ace61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-06-28 Daniel Shahaf + * 46132: Doc/Zsh/expn.yo: docs: Use an itemized list in the + documentation of the *(o) glob qualifier. + * 46131: Completion/Unix/Command/_git: _git-config: Partly fix a bug whereby a 'foo.ba' wouldn't be completed to 'foo.bar.baz'. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 3800f2fb0..a637b78a1 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -2869,18 +2869,26 @@ matches in directory traversal order will be considered. Implies tt(oN) when no tt(o)var(c) qualifier is used. ) item(tt(o)var(c))( -specifies how the names of the files should be sorted. If var(c) is -tt(n) they are sorted by name; if it is tt(L) they -are sorted depending on the size (length) of the files; if tt(l) -they are sorted by the number of links; if tt(a), tt(m), or tt(c) -they are sorted by the time of the last access, modification, or -inode change respectively; if tt(d), files in subdirectories appear before +specifies how the names of the files should be sorted. The following values +of var(c) sort in the following ways: + +startsitem() +sitem(tt(n))(By name.) +sitem(tt(L))(By the size (length) of the files.) +sitem(tt(l))(By number of links.) +sitem(tt(a))(By time of last access, youngest first.) +sitem(tt(m))(By time of last modification, youngest first.) +sitem(tt(c))(By time of last inode change, youngest first.) +sitem(tt(d))(By directories: files in subdirectories appear before those in the current directory at each level of the search DASH()- this is best combined with other criteria, for example `tt(odon)' to sort on names for -files within the same directory; if tt(N), no sorting is performed. -Note that tt(a), tt(m), and tt(c) compare -the age against the current time, hence the first name in the list is the -youngest file. Also note that the modifiers tt(^) and tt(-) are used, +files within the same directory.) +sitem(tt(N))(No sorting is performed.) +xitem(tt(e)var(string)) +sitem(tt(+)var(cmd))(Sort by shell code (see below).) +endsitem() + +Note that the modifiers tt(^) and tt(-) are used, so `tt(*(^-oL))' gives a list of all files sorted by file size in descending order, following any symbolic links. Unless tt(oN) is used, multiple order specifiers may occur to resolve ties. -- cgit v1.2.3 From 4e0058afc5ea040a788d70edbfa43593295816d1 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 3 Jul 2020 21:05:46 +0100 Subject: users/24971: ${(-)var} sorts on signed integers --- ChangeLog | 6 ++++++ Doc/Zsh/expn.yo | 12 +++++++++--- Src/sort.c | 25 +++++++++++++++++++------ Src/subst.c | 4 ++++ Src/zsh.h | 7 ++++--- Test/D04parameter.ztst | 7 +++++++ 6 files changed, 49 insertions(+), 12 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index b2d94f38c..5161ef6d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2020-07-03 Peter Stephenson + + * users/24971: Doc/Zsh/expn.yo, Src/sort.c, Src/subst.c, + Src/zsh.h, Test/D04parameter.ztst: Add parameter flag (-) + to allow signed numeric sorting. + 2020-06-28 zsugabubus * 46097: Completion/Unix/Command/_rm: Fix "assignment to invalid diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index a637b78a1..79b6037df 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1097,17 +1097,23 @@ are sorted before those with fewer or none. Hence the array `tt(foo1 foo02 foo2 foo3 foo20 foo23)' is sorted into the order shown. May be combined with `tt(i)' or `tt(O)'. ) +item(tt(-))( +As tt(n), but a leading minus sign indicates a negative decimal +integer. A `tt(-)' not followed by an integer does not trigger +numeric sorting. +) item(tt(o))( Sort the resulting words in ascending order; if this appears on its own the sorting is lexical and case-sensitive (unless the locale renders it case-insensitive). Sorting in ascending order is the default for other forms of sorting, so this is ignored if combined -with `tt(a)', `tt(i)' or `tt(n)'. +with `tt(a)', `tt(i)', `tt(n)' or `tt(DASH())'. ) item(tt(O))( Sort the resulting words in descending order; `tt(O)' without `tt(a)', -`tt(i)' or `tt(n)' sorts in reverse lexical order. May be combined -with `tt(a)', `tt(i)' or `tt(n)' to reverse the order of sorting. +`tt(i)', `tt(n)' or `tt(DASH())' sorts in reverse lexical order. May be +combined with `tt(a)', `tt(i)', `tt(n)' or tt(DASH()) to reverse the +order of sorting. ) item(tt(P))( This forces the value of the parameter var(name) to be interpreted as a diff --git a/Src/sort.c b/Src/sort.c index 8faf9349c..26949ad9c 100644 --- a/Src/sort.c +++ b/Src/sort.c @@ -135,12 +135,23 @@ eltpcmp(const void *a, const void *b) #endif if (sortnumeric) { + int mul = 0; for (; *as == *bs && *as; as++, bs++); #ifndef HAVE_STRCOLL cmp = (int)STOUC(*as) - (int)STOUC(*bs); #endif - if (idigit(*as) || idigit(*bs)) { + if (sortnumeric < 0) { + if (*as == '-' && idigit(as[1]) && idigit(*bs)) { + cmp = -1; + mul = 1; + } else if (*bs == '-' && idigit(bs[1]) && idigit(*as)) { + cmp = 1; + mul = 1; + } + } + if (!mul && (idigit(*as) || idigit(*bs))) { for (; as > ao && idigit(as[-1]); as--, bs--); + mul = (sortnumeric < 0 && as > ao && as[-1] == '-') ? -1 : 1; if (idigit(*as) && idigit(*bs)) { while (*as == '0') as++; @@ -148,13 +159,13 @@ eltpcmp(const void *a, const void *b) bs++; for (; idigit(*as) && *as == *bs; as++, bs++); if (idigit(*as) || idigit(*bs)) { - cmp = (int)STOUC(*as) - (int)STOUC(*bs); + cmp = mul * ((int)STOUC(*as) - (int)STOUC(*bs)); while (idigit(*as) && idigit(*bs)) as++, bs++; if (idigit(*as) && !idigit(*bs)) - return sortdir; + return mul * sortdir; if (idigit(*bs) && !idigit(*as)) - return -sortdir; + return -mul * sortdir; } } } @@ -195,7 +206,8 @@ zstrcmp(const char *as, const char *bs, int sortflags) sortdir = 1; sortnobslash = (sortflags & SORTIT_IGNORING_BACKSLASHES) ? 1 : 0; - sortnumeric = (sortflags & SORTIT_NUMERICALLY) ? 1 : 0; + sortnumeric = (sortflags & SORTIT_NUMERICALLY_SIGNED) ? -1 : + (sortflags & SORTIT_NUMERICALLY) ? 1 : 0; ret = eltpcmp(&aeptr, &beptr); @@ -389,7 +401,8 @@ strmetasort(char **array, int sortwhat, int *unmetalenp) oldsortnumeric = sortnumeric; sortdir = (sortwhat & SORTIT_BACKWARDS) ? -1 : 1; - sortnumeric = (sortwhat & SORTIT_NUMERICALLY) ? 1 : 0; + sortnumeric = (sortwhat & SORTIT_NUMERICALLY_SIGNED) ? -1 : + (sortwhat & SORTIT_NUMERICALLY) ? 1 : 0; qsort(sortptrarr, nsort, sizeof(SortElt), eltpcmp); diff --git a/Src/subst.c b/Src/subst.c index ed3f4a82b..b98ddaf02 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1979,6 +1979,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, case 'n': sortit |= SORTIT_NUMERICALLY; break; + case '-': + case Dash: + sortit |= SORTIT_NUMERICALLY_SIGNED; + break; case 'a': sortit |= SORTIT_SOMEHOW; indord = 1; diff --git a/Src/zsh.h b/Src/zsh.h index ed123f2b9..c48be4ffd 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2997,17 +2997,18 @@ enum { SORTIT_ANYOLDHOW = 0, /* Defaults */ SORTIT_IGNORING_CASE = 1, SORTIT_NUMERICALLY = 2, - SORTIT_BACKWARDS = 4, + SORTIT_NUMERICALLY_SIGNED = 4, + SORTIT_BACKWARDS = 8, /* * Ignore backslashes that quote another character---which may * be another backslash; the second backslash is active. */ - SORTIT_IGNORING_BACKSLASHES = 8, + SORTIT_IGNORING_BACKSLASHES = 16, /* * Ignored by strmetasort(); used by paramsubst() to indicate * there is some sorting to do. */ - SORTIT_SOMEHOW = 16, + SORTIT_SOMEHOW = 32, }; /* diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index e51c955ee..ac99ff0e3 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1398,6 +1398,13 @@ >a6 a17 a117 b6 b17 b117 >b117 b17 b6 a117 a17 a6 + foo=(a-6 a117 a-17 a-34 b6 b-117 b17 b-2) + print ${(-)foo} + print ${(O-)foo} +0:Numeric sorting of signed integers +>a-34 a-17 a-6 a117 b-117 b-2 b6 b17 +>b17 b6 b-2 b-117 a117 a-6 a-17 a-34 + x=sprodj x[-10]=scrumf print $x -- cgit v1.2.3 From b53f465481920171159d8d471f97be81d2e14fc4 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 3 Jul 2020 22:16:33 +0000 Subject: unposted (cf. users/24972, users/24978): Use an ASCII hyphen/minus rather than a dash. --- ChangeLog | 5 +++++ Doc/Zsh/expn.yo | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 5161ef6d7..b76d1988e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-07-03 Daniel Shahaf + + * unposted (cf. users/24972, users/24978): Doc/Zsh/expn.yo: + Use an ASCII hyphen/minus rather than a dash. + 2020-07-03 Peter Stephenson * users/24971: Doc/Zsh/expn.yo, Src/sort.c, Src/subst.c, diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 79b6037df..41ad967b2 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1107,12 +1107,12 @@ Sort the resulting words in ascending order; if this appears on its own the sorting is lexical and case-sensitive (unless the locale renders it case-insensitive). Sorting in ascending order is the default for other forms of sorting, so this is ignored if combined -with `tt(a)', `tt(i)', `tt(n)' or `tt(DASH())'. +with `tt(a)', `tt(i)', `tt(n)' or `tt(-)'. ) item(tt(O))( Sort the resulting words in descending order; `tt(O)' without `tt(a)', -`tt(i)', `tt(n)' or `tt(DASH())' sorts in reverse lexical order. May be -combined with `tt(a)', `tt(i)', `tt(n)' or tt(DASH()) to reverse the +`tt(i)', `tt(n)' or `tt(-)' sorts in reverse lexical order. May be +combined with `tt(a)', `tt(i)', `tt(n)' or `tt(-)' to reverse the order of sorting. ) item(tt(P))( -- cgit v1.2.3 From 4ab0d047c7539f306d32edbcefa791870a783e75 Mon Sep 17 00:00:00 2001 From: Pete Moore Date: Mon, 6 Jul 2020 12:50:54 +0200 Subject: 46194: docs: metafaq: Remove spurious closing bracket --- ChangeLog | 5 +++++ Doc/Zsh/metafaq.yo | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index f0c4a9f5f..0cf55eff6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-07-06 Pete Moore + + * 46194: Doc/Zsh/metafaq.yo: docs: metafaq: Remove spurious + closing bracket + 2020-07-05 Daniel Shahaf * 46175/0003: Src/exec.c, Test/E01options.ztst: Fix the diff --git a/Doc/Zsh/metafaq.yo b/Doc/Zsh/metafaq.yo index c123a7cea..e41b88dc5 100644 --- a/Doc/Zsh/metafaq.yo +++ b/Doc/Zsh/metafaq.yo @@ -25,7 +25,6 @@ cindex(acquiring zsh by FTP) cindex(availability of zsh) nofill(uref(ftp://ftp.zsh.org/pub/) uref(https://www.zsh.org/pub/)) -) The up-to-date source code is available via Git from Sourceforge. See uref(https://sourceforge.net/projects/zsh/) for details. A summary of -- cgit v1.2.3 From 89618fe37d0c6568b1b42e237057278e686005d6 Mon Sep 17 00:00:00 2001 From: Nuri Jung Date: Tue, 7 Jul 2020 13:26:53 +0000 Subject: github #58: docs: Note that the zsh/regex syntax is platform-dependent. --- ChangeLog | 5 +++++ Doc/Zsh/mod_regex.yo | 12 ++++++++++++ 2 files changed, 17 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 0cf55eff6..ae583fd05 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-07-07 Nuri Jung + + * github #58: Doc/Zsh/mod_regex.yo: docs: Note that the zsh/regex + syntax is platform-dependent. + 2020-07-06 Pete Moore * 46194: Doc/Zsh/metafaq.yo: docs: metafaq: Remove spurious diff --git a/Doc/Zsh/mod_regex.yo b/Doc/Zsh/mod_regex.yo index f20451664..40ee92785 100644 --- a/Doc/Zsh/mod_regex.yo +++ b/Doc/Zsh/mod_regex.yo @@ -26,5 +26,17 @@ tt(-regex-match) operator. If tt(BASH_REMATCH) is set, then the array tt(BASH_REMATCH) will be set instead of tt(MATCH) and tt(match). + +Note that the tt(zsh/regex) module logic relies on the host system. The +same var(expr) and var(regex) pair could produce different results on different +platforms if a var(regex) with non-standard syntax is given. + +For example, no syntax for matching a word boundary is defined in the POSIX +extended regular expression standard. GNU tt(libc) and BSD tt(libc) both provide +such syntaxes as extensions (tt(\b) and tt([[:<:]])/tt([[:>:]]) respectively), +but neither of these syntaxes is supported by both of these implementations. + +Refer to the manref(regcomp)(3) and manref(re_format)(7) manual pages on your +system for locally-supported syntax. ) enditem() -- cgit v1.2.3 From 7dfc4f754e8c5033e43ddfdd7b6141cdbe11341e Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 12 Jul 2020 11:39:29 +0000 Subject: users/24985: Clarify documentation of the ${(n)} and ${(-)} parameter expansion flags, and add a forward compatibility hatch to the latter. --- ChangeLog | 4 ++++ Doc/Zsh/expn.yo | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 4aa15f6f6..93894f290 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2020-07-12 Daniel Shahaf + * users/24985: Doc/Zsh/expn.yo: Clarify documentation of the + ${(n)} and ${(-)} parameter expansion flags, and add a forward + compatibility hatch to the latter. + * 46204: Test/E01options.ztst: Fix new test case for the theoretical case of having more than 100 files in the root directory. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 41ad967b2..21ecf9d6e 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1092,15 +1092,18 @@ Convert all letters in the result to lower case. item(tt(n))( Sort decimal integers numerically; if the first differing characters of two test strings are not digits, sorting -is lexical. Integers with more initial zeroes -are sorted before those with fewer or none. Hence the array `tt(foo1 foo02 +is lexical. `tt(+)' and `tt(-)' are not treated specially; they are treated as +any other non-digit. Integers with more initial zeroes +are sorted before those with fewer or none. Hence the array `tt(foo+24 foo1 foo02 foo2 foo3 foo20 foo23)' is sorted into the order shown. May be combined with `tt(i)' or `tt(O)'. ) item(tt(-))( As tt(n), but a leading minus sign indicates a negative decimal -integer. A `tt(-)' not followed by an integer does not trigger +integer. A leading minus sign not followed by an integer does not trigger numeric sorting. +Note that `tt(+)' signs are not handled specially (this may change in the +future). ) item(tt(o))( Sort the resulting words in ascending order; if this appears on its -- cgit v1.2.3 From fa51a38955d7d2cf4d38c0a74f35f271e338d7c0 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 12 Jul 2020 18:06:50 +0000 Subject: 46240: Make the expansion of manref()() in ztexi.yo match its expansion in zman.yo. The difference was mostly harmless in the common case "(see manref(foo)(42))", which expanded to "(see man page foo(42))" under ztexi.yo, but in other contexts the ztexi.yo expansion was was nonsensical; for example: "the BSD manref(echo)(1) command" "the string returned by the manref(getlogin)(3) system call" "advisory file locking (via the manref(fcntl)(2) system call)" "this is the exact opposite from manref(ls)(1)," While there, copyedit some uses of manref()(). --- ChangeLog | 7 +++++++ Doc/Zsh/builtins.yo | 2 +- Doc/Zsh/contrib.yo | 5 +++-- Doc/Zsh/jobs.yo | 2 +- Doc/Zsh/params.yo | 2 +- Doc/ztexi.yo | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 74a47dece..a5c11292d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2020-07-13 Daniel Shahaf + + * 46240: Doc/Zsh/builtins.yo, Doc/Zsh/contrib.yo, + Doc/Zsh/jobs.yo, Doc/Zsh/params.yo, Doc/ztexi.yo: Make the + expansion of manref()() in ztexi.yo match its expansion in + zman.yo. + 2020-07-12 Daniel Shahaf * 46183: Test/D03procsubst.ztst: New XFail test: external diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index d35cad182..4b91db1fe 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -2300,7 +2300,7 @@ findex(umask) cindex(umask) item(tt(umask) [ tt(-S) ] [ var(mask) ])( The umask is set to var(mask). var(mask) can be either -an octal number or a symbolic value as described in manref(chmod)(1). +an octal number or a symbolic value as described in the manref(chmod)(1) man page. If var(mask) is omitted, the current value is printed. The tt(-S) option causes the mask to be printed as a symbolic value. Otherwise, the mask is printed as an octal number. Note that in diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 7cde0033f..66e6bdc1e 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -3560,7 +3560,8 @@ Calling tt(zsh-mime-setup) with the option tt(-v) causes verbose output to be shown during the setup operation. The system respects the tt(mailcap) flags tt(needsterminal) and -tt(copiousoutput), see manref(mailcap)(4). +tt(copiousoutput); see manref(mailcap)(4) or manref(mailcap)(5) +(the man page's name varies across platforms). The functions use the following styles, which are defined with the tt(zstyle) builtin command (\ @@ -4465,7 +4466,7 @@ counts the number of arguments passed to each execution of var(command), em(including) any var(arg) list. Also, any time tt(-i) or tt(-I) is used, each var(input) is processed separately as if by `tt(-L) tt(1)'. -For details of the other tt(zargs) options, see zmanref(xargs) (but note +For details of the other tt(zargs) options, see the manref(xargs)(1) man page (but note the difference in function between tt(zargs) and tt(xargs)) or run tt(zargs) with the tt(-)tt(-help) option. ) diff --git a/Doc/Zsh/jobs.yo b/Doc/Zsh/jobs.yo index 70559f2d8..331b91d8d 100644 --- a/Doc/Zsh/jobs.yo +++ b/Doc/Zsh/jobs.yo @@ -111,7 +111,7 @@ cindex(jobs, disowning) cindex(disowning jobs) findex(disown, use of) To avoid having the shell terminate the running jobs, either -use the bf(nohup) command (see manref(nohup)(1)) +use the manref(nohup)(1) command or the tt(disown) builtin. sect(Signals) The tt(INT) and tt(QUIT) signals for an invoked diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 8a6eb2446..36c1ae4c2 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -731,7 +731,7 @@ explicitly set locally. ) vindex(ERRNO) item(tt(ERRNO) )( -The value of errno (see manref(errno)(3)) +The value of tt(errno) (see manref(errno)(3)) as set by the most recently failed system call. This value is system dependent and is intended for debugging purposes. It is also useful with the tt(zsh/system) module which diff --git a/Doc/ztexi.yo b/Doc/ztexi.yo index 7d52e6e91..50bae6d48 100644 --- a/Doc/ztexi.yo +++ b/Doc/ztexi.yo @@ -150,7 +150,7 @@ def(comment)(1)(\ COMMENT(--- cross-references ---) -def(manref)(2)(man page ARG1+LPAR()ARG2+RPAR()) +def(manref)(2)(ARG1+LPAR()ARG2+RPAR()) def(zmanref)(1)(manref(ARG1)(1)) def(noderef)(1)(\ NOTRANS(@ref{)ARG1+NOTRANS(})\ -- cgit v1.2.3 From e2be2d061a2ea1c941a3316349d6aa81c48fc378 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 7 Aug 2020 11:42:15 +0000 Subject: unposted: Update documentation for the move to new hosting. --- ChangeLog | 3 +++ Doc/Zsh/metafaq.yo | 2 +- Etc/FAQ.yo | 17 +++++++---------- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 54cc37f67..35de0e236 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-08-08 Daniel Shahaf + * unposted: Doc/Zsh/metafaq.yo, Etc/FAQ.yo: Update documentation + for the move to new hosting. + * 47296 (+ unposted additional tests and comments): Src/loop.c, Test/A05execution.ztst: 'repeat' loops: Let the repeat count use $?. diff --git a/Doc/Zsh/metafaq.yo b/Doc/Zsh/metafaq.yo index e41b88dc5..0eeda4a13 100644 --- a/Doc/Zsh/metafaq.yo +++ b/Doc/Zsh/metafaq.yo @@ -73,7 +73,7 @@ maintained by Karsten Thygesen tt(). The mailing lists are archived; the archives can be accessed via the administrative addresses listed above. There is also a hypertext -archive, maintained by Geoff Wing tt(), available at +archive available at uref(https://www.zsh.org/mla/). texinode(The Zsh FAQ)(The Zsh Web Page)(Mailing Lists)(Introduction) sect(The Zsh FAQ) diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo index 45502bede..d36a420ab 100644 --- a/Etc/FAQ.yo +++ b/Etc/FAQ.yo @@ -61,7 +61,7 @@ myreport(Z-Shell Frequently-Asked Questions)(Peter Stephenson)(2010/02/15) COMMENT(-- the following are for Usenet and must appear first)\ description(\ mydit(Archive-Name:) unix-faq/shell/zsh -mydit(Last-Modified:) 2020/05/06 +mydit(Last-Modified:) 2020/08/08 mydit(Submitted-By:) email(coordinator@zsh.org (Peter Stephenson)) mydit(Posting-Frequency:) Monthly mydit(Copyright:) (C) P.W. Stephenson, 1995--2020 (see end of document) @@ -342,7 +342,7 @@ label(16) The coordinator of development is currently me; the alias email(coordinator@zsh.org) can be used to contact whoever is in the hot seat. url(https://www.zsh.org/)(https://www.zsh.org/) is the official - archive site, currently in Australia. Test versions are kept in the + archive site. Test versions are kept in the `testing' subdirectory: such up-to-the-minute development versions should only be retrieved if you actually plan to help test the latest version of the shell. @@ -2513,10 +2513,8 @@ label(62) you want someone to mail you directly, say so. Most patches to zsh appear there first. - Note that this location has just changed (January 1999), and the - instructions to go with it are slightly different --- in particular, - if you are already subscribed, the instructions about how to - unsubscribe are different. + Note that this location changed in August 2020, and the + instructions to go with it are slightly different. Please note when reporting bugs that many exist only on certain architectures, which the developers may not have access to. In @@ -2548,16 +2546,15 @@ label(62) zsh-workers-subscribe@zsh.org ) (the actual content is unimportant). Replace tt(subscribe) with - tt(unsubscribe) to unsubscribe. The mailing software (tt(ezmlm)) has + tt(unsubscribe) to unsubscribe. The mailing software (tt(Sympa)) has various bells and whistles: you can retrieve archived messages. - Mail email(zsh-workers-help@zsh.org) for detailed information. + Mail email(sympa@zsh.org?subject=help) for detailed information. Administrative matters are best sent to email(zsh-workers-owner@zsh.org). - real name is email(Geoff Wing ). An archive of mailings for the last few years can be found at url(http://www.zsh.org/mla/)(http://www.zsh.org/mla/) - at the main zsh archive in Australia. + at the main zsh archive site. Of course, you can also post zsh queries to the Usenet group comp.unix.shell; if all else fails, you could even e-mail me. -- cgit v1.2.3 From cdafe31e05570da92cc96159dbb02a75b48a16b0 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 10 Aug 2020 05:50:40 +0000 Subject: 47313: docs: Document explicitly that the :P modifier returns a symlink-less path. --- ChangeLog | 5 +++++ Doc/Zsh/expn.yo | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index d14b527fc..9c45df0c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-08-16 Daniel Shahaf + + * 47313: Doc/Zsh/expn.yo: docs: Document explicitly that the + :P modifier returns a symlink-less path. + 2020-08-13 Oliver Kiddle * Jörg Sommer: 47320: Completion/Linux/Command/_choom: Add diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 21ecf9d6e..cbdae4d58 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -287,8 +287,10 @@ expansion. ) item(tt(P))( Turn a file name into an absolute path, like tt(realpath+LPAR()3+RPAR()). -The resulting path will be absolute, have neither `tt(.)' nor `tt(..)' components, -and refer to the same directory entry as the input filename. +The resulting path will be absolute, +will refer to the same directory entry as the input filename, +and none of its components will be symbolic links or equal to +`tt(.)' or `tt(..)'. Unlike tt(realpath+LPAR()3+RPAR()), non-existent trailing components are permitted and preserved. -- cgit v1.2.3 From 841188439b1b93031b4d4cb195d50958fe88d6a4 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Wed, 5 Aug 2020 16:47:45 +0200 Subject: 47306: edit-command-line: add editor style --- Completion/Zsh/Command/_zstyle | 1 + Doc/Zsh/contrib.yo | 6 ++++++ Functions/Zle/edit-command-line | 8 ++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/Completion/Zsh/Command/_zstyle b/Completion/Zsh/Command/_zstyle index e9a5d800c..bb871762e 100644 --- a/Completion/Zsh/Command/_zstyle +++ b/Completion/Zsh/Command/_zstyle @@ -143,6 +143,7 @@ styles=( cursor e: edit-buffer e:bool edit-previous e:bool + editor e: insert-kept e: leave-cursor e:bool match e: diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 66e6bdc1e..bab1e3023 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2472,6 +2472,12 @@ item(tt(edit-command-line))( Edit the command line using your visual editor, as in tt(ksh). example(bindkey -M vicmd v edit-command-line) + +The editor to be used can also be specified using the tt(editor) style in +the context of the widget. It is specified as an array of command and +arguments: + +example(zstyle :zle:edit-command-line editor gvim -f) ) tindex(expand-absolute-path) item(tt(expand-absolute-path))( diff --git a/Functions/Zle/edit-command-line b/Functions/Zle/edit-command-line index 1103ca556..8aaeb738e 100644 --- a/Functions/Zle/edit-command-line +++ b/Functions/Zle/edit-command-line @@ -22,8 +22,12 @@ fi (( $+zle_bracketed_paste )) && print -r -n - $zle_bracketed_paste[2] # Open the editor, placing the cursor at the right place if we know how. - local editor=( "${(@Q)${(z)${VISUAL:-${EDITOR:-vi}}}}" ) - case $editor in + local -a editor + zstyle -a :zle:$WIDGET editor editor + if (( ! $#editor )); then + editor=( "${(@Q)${(z)${VISUAL:-${EDITOR:-vi}}}}" ) + fi + case $editor in (*vim*) integer byteoffset=$(( $#PREBUFFER + $#LBUFFER + 1 )) "${(@)editor}" -c "normal! ${byteoffset}go" -- $1;; -- cgit v1.2.3 From 5668cace4a2b821b59a5b3ad9daa1049b0ef95e0 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 21 Aug 2020 17:43:12 +0200 Subject: 47328: remove references to old zsh.org mail addresses --- ChangeLog | 3 +++ Doc/Zsh/metafaq.yo | 18 ++++++++---------- Etc/CONTRIBUTORS | 8 ++++---- 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 8c5b64920..83f305356 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-08-21 Oliver Kiddle + * 47328: Doc/Zsh/metafaq.yo, Etc/CONTRIBUTORS: remove references + to old zsh.org mail addresses + * 47322: Completion/Unix/Command/_ssh: allow prefix with ssh cipher completion and add matching control for options diff --git a/Doc/Zsh/metafaq.yo b/Doc/Zsh/metafaq.yo index 0eeda4a13..e69a0976c 100644 --- a/Doc/Zsh/metafaq.yo +++ b/Doc/Zsh/metafaq.yo @@ -10,12 +10,12 @@ endmenu() texinode(Author)(Availability)()(Introduction) sect(Author) cindex(author) -Zsh was originally written by Paul Falstad tt(). -Zsh is now maintained by the members of the zsh-workers mailing -list tt(). The development is currently -coordinated by Peter Stephenson tt(). The coordinator -can be contacted at tt(), but matters relating to -the code should generally go to the mailing list. +Zsh was originally written by Paul Falstad. Zsh is now maintained by +the members of the zsh-workers mailing list tt(). +The development is currently coordinated by Peter Stephenson +tt(). The coordinator can be contacted at +tt(), but matters relating to the code should +generally go to the mailing list. texinode(Availability)(Mailing Lists)(Author)(Introduction) sect(Availability) Zsh is available from the following HTTP and anonymous FTP site. @@ -68,8 +68,7 @@ bf(zsh-users). All submissions to bf(zsh-users) are automatically forwarded to bf(zsh-workers). If you have problems subscribing/unsubscribing to any of the mailing -lists, send mail to tt(). The mailing lists are -maintained by Karsten Thygesen tt(). +lists, send mail to tt(). The mailing lists are archived; the archives can be accessed via the administrative addresses listed above. There is also a hypertext @@ -85,8 +84,7 @@ uref(http://www.zsh.org/FAQ/). The contact address for FAQ-related matters is tt(). texinode(The Zsh Web Page)(The Zsh Userguide)(The Zsh FAQ)(Introduction) sect(The Zsh Web Page) -Zsh has a web page which is located at uref(https://www.zsh.org/). This is -maintained by Karsten Thygesen tt(), of SunSITE Denmark. +Zsh has a web page which is located at uref(https://www.zsh.org/). The contact address for web-related matters is tt(). texinode(The Zsh Userguide)(See Also)(The Zsh Web Page)(Introduction) sect(The Zsh Userguide) diff --git a/Etc/CONTRIBUTORS b/Etc/CONTRIBUTORS index 6a0ea33ce..0c8190a93 100644 --- a/Etc/CONTRIBUTORS +++ b/Etc/CONTRIBUTORS @@ -2,10 +2,10 @@ ZSH CONTRIBUTORS ---------------- -Zsh was originally written by Paul Falstad . Zsh is -now maintained by the members of the zsh-workers mailing list -. The development is currently coordinated -by Peter Stephenson . +Zsh was originally written by Paul Falstad. Zsh is now maintained +by the members of the zsh-workers mailing list . +The development is currently coordinated by Peter Stephenson +. This file credits only the major contributors to the current release. See the ChangeLog files for a complete list of people who have submitted -- cgit v1.2.3 From 63b6398b7017d3850010f47458818a439479a456 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sun, 13 Sep 2020 16:19:52 -0700 Subject: 47364: Enable extendedglob in pattern with ${(*)name/pattern/replacement} Mikael Magnusson: 47382: Completion for 47364 --- ChangeLog | 8 ++++++++ Completion/Zsh/Context/_brace_parameter | 1 + Doc/Zsh/expn.yo | 6 +++++- Src/subst.c | 19 +++++++++++++++---- Src/zsh.h | 1 + Test/D02glob.ztst | 5 +++++ 6 files changed, 35 insertions(+), 5 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 399bc76c2..108508898 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2020-09-13 Bart Schaefer + + * Mikael Magnusson: 47382: Completion/Zsh/Context/_brace_parameter: + Completion for 47364 + + * 47364: Doc/Zsh/expn.yo, Src/subst.c, Src/zsh.h, Test/D02glob.ztst: + Enable extendedglob in pattern with ${(*)name/pattern/replacement} + 2020-09-09 Stephane Chazelas * 47352 (+ extra test cases): Src/prompt.c, Test/D01prompt.ztst: diff --git a/Completion/Zsh/Context/_brace_parameter b/Completion/Zsh/Context/_brace_parameter index 6960cec9b..d4b750c3d 100644 --- a/Completion/Zsh/Context/_brace_parameter +++ b/Completion/Zsh/Context/_brace_parameter @@ -142,6 +142,7 @@ if [[ $PREFIX = *'${('[^\)]# ]]; then flags+=( "#:evaluate as numeric expression" "@:prevent double-quoted joining of arrays" + "*:enable extended globs for pattern" "A:assign as an array parameter" "a:sort in array index order (with O to reverse)" "b:backslash quote pattern characters only" diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index cbdae4d58..b3396721f 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1422,7 +1422,7 @@ error, and the flag itself has no effect. enditem() The following flags are meaningful with the tt(${)...tt(#)...tt(}) or -tt(${)...tt(%)...tt(}) forms. The tt(S) and tt(I) flags may also be +tt(${)...tt(%)...tt(}) forms. The tt(S), tt(I), and tt(*) flags may also be used with the tt(${)...tt(/)...tt(}) forms. startitem() @@ -1488,6 +1488,10 @@ will remove the same matches as for `tt(#)', but in reverse order, and the form using `tt(%%)' will remove the same matches as for `tt(##)' in reverse order. ) +item(tt(*))( +Enable tt(EXTENDED_GLOB) for substitution via tt(${)...tt(/)...tt(}) or +tt(${)...tt(//)...tt(}). +) item(tt(B))( Include the index of the beginning of the match in the result. ) diff --git a/Src/subst.c b/Src/subst.c index b98ddaf02..2af61653a 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1708,7 +1708,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, /* * This expressive name refers to the set of flags which * is applied to matching for #, %, / and their doubled variants: - * (M), (R), (B), (E), (N), (S). + * (M), (R), (B), (E), (N), (S), (*). */ int flags = 0; /* Value from (I) flag, used for ditto. */ @@ -1930,6 +1930,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, case '@': nojoin = 2; /* nojoin = 2 means force */ break; + case '*': + case Star: + flags |= SUB_EGLOB; + break; case 'M': flags |= SUB_MATCH; break; @@ -2810,7 +2814,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, c == '#' || c == Pound || c == '?' || c == Quest || c == '/')) { - + int eglob = isset(EXTENDEDGLOB); /* * Default index is 1 if no (I) or (I) gave zero. But * why don't we set the default explicitly at the start @@ -2832,9 +2836,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, char *ptr; /* * previous flags are irrelevant, except for (S) which - * indicates shortest substring; else look for longest. + * indicates shortest substring; else look for longest, + # and (*) which temporarily enables extended globbing. */ - flags = (flags & SUB_SUBSTR) ? 0 : SUB_LONG; + flags = ((flags & SUB_SUBSTR) ? 0 : SUB_LONG)|(flags & SUB_EGLOB); if ((c = *s) == '/') { /* doubled, so replace all occurrences */ flags |= SUB_GLOBAL; @@ -3136,7 +3141,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, for (ap = aval; *ap; ap++) { untokenize(*ap); } + if (flags & SUB_EGLOB) + opts[EXTENDEDGLOB] = 1; getmatcharr(&aval, s, flags, flnum, replstr); + opts[EXTENDEDGLOB] = eglob; } else { if (vunset) { if (vunset > 0 && unset(UNSET)) { @@ -3151,7 +3159,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, copied = 1; untokenize(val); } + if (flags & SUB_EGLOB) + opts[EXTENDEDGLOB] = 1; getmatch(&val, s, flags, flnum, replstr); + opts[EXTENDEDGLOB] = eglob; } break; } diff --git a/Src/zsh.h b/Src/zsh.h index 94f5099c6..6cf1b4186 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1991,6 +1991,7 @@ struct tieddata { #define SUB_START 0x1000 /* force match at start with SUB_END * and no SUB_SUBSTR */ #define SUB_LIST 0x2000 /* no substitution, return list of matches */ +#define SUB_EGLOB 0x4000 /* use extended globbing in patterns */ /* * Structure recording multiple matches inside a test string. diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst index f250244e7..176846d46 100644 --- a/Test/D02glob.ztst +++ b/Test/D02glob.ztst @@ -792,6 +792,11 @@ *>*/glob.tmp/(flip|flop) *>*/glob.tmp/(flip|flop)/trailing/components + unsetopt extendedglob + print -r -- ${(*)=${(@s.+.):-A+B}/(#b)(?)/-${(L)match[1]} ${match[1]}} +0:the '*' qualfier enables extended_glob for pattern matching +>-a A -b B + %clean # Fix unreadable-directory permissions so ztst can clean up properly -- cgit v1.2.3 From 00d20ed15e18f5af682f0daec140d6b8383c479a Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 26 Sep 2020 10:24:09 +0000 Subject: users/26088: docs: zle -R: Clarify that it needs not be called in the normal course of things, but only when an immediate, interim redisplay is desired. --- ChangeLog | 6 ++++++ Doc/Zsh/zle.yo | 9 ++++----- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 3f69f73a9..17e49f20d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2020-10-03 Daniel Shahaf + + * users/26088: Doc/Zsh/zle.yo: docs: zle -R: Clarify that it + needs not be called in the normal course of things, but only + when an immediate, interim redisplay is desired. + 2020-09-23 Meng Bo * github #65: Completion/Unix/Command/_nmap: Rename option flags diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 84be010e1..9694a1f74 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -501,8 +501,7 @@ ifnzman(noderef(Completion Widgets))\ . ) item(tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])( -Redisplay the command line; this is to be called from within a user-defined -widget to allow changes to become visible. If a var(display-string) is +Redisplay the command line. If a var(display-string) is given and not empty, this is shown in the status line (immediately below the line being edited). @@ -511,9 +510,9 @@ prompt in the same way as completion lists are printed. If no var(string)s are given but the tt(-c) option is used such a list is cleared. -Note that this option is only useful for widgets that do not exit -immediately after using it because the strings displayed will be erased -immediately after return from the widget. +Note that immediately after returning from running widgets, the command line +will be redisplayed and the strings displayed will be erased. Therefore, this +option is only useful for widgets that do not exit immediately after using it. This command can safely be called outside user defined widgets; if zle is active, the display will be refreshed, while if zle is not active, the -- cgit v1.2.3 From da534770fd5c8022e90eff5cf4c993d60e3c56f7 Mon Sep 17 00:00:00 2001 From: Axel Beckert Date: Sun, 18 Oct 2020 01:35:13 +0200 Subject: 47468: Doc/Zsh/contrib.yo: Fix typo --- ChangeLog | 4 ++++ Doc/Zsh/contrib.yo | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 17e49f20d..c6569edb7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2020-10-18 Axel Beckert + + * 47468: Doc/Zsh/contrib.yo: Fix typo + 2020-10-03 Daniel Shahaf * users/26088: Doc/Zsh/zle.yo: docs: zle -R: Clarify that it diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index bab1e3023..00f693664 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -4559,7 +4559,7 @@ the same result, the destination was an existing regular file and tt(-f) was not given) causes the entire function to abort without doing anything. -In addition to pattern replacement, the variable tt($f) can be referrred +In addition to pattern replacement, the variable tt($f) can be referred to in the second (replacement) argument. This makes it possible to use variable substitution to alter the argument; see examples below. -- cgit v1.2.3 From 8773f01f2b7a908af70dc06d7d00481f1c9bec44 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Sat, 24 Oct 2020 13:45:08 +0200 Subject: 47494, 47495: Add -n option to strftime --- ChangeLog | 4 ++++ Completion/Zsh/Command/_strftime | 12 +++++++----- Doc/Zsh/mod_datetime.yo | 7 +++++-- Src/Modules/datetime.c | 5 +++-- Test/V09datetime.ztst | 4 ++++ 5 files changed, 23 insertions(+), 9 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 5a9ef3213..9db67eea0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,10 @@ * 47302: Test/B03print.ztst, Test/D07multibyte.ztst: Test for print -v fix + * 47494, 47495: Completion/Zsh/Command/_strftime, + Doc/Zsh/mod_datetime.yo, Src/Modules/datetime.c, + Test/V09datetime.ztst: Add -n option to strftime + 2020-10-18 Roman Perepelitsa * 47476: Src/Modules/files.c: Fix a race condition in zf_mkdir -p diff --git a/Completion/Zsh/Command/_strftime b/Completion/Zsh/Command/_strftime index 0849f1c85..a57a76ce4 100644 --- a/Completion/Zsh/Command/_strftime +++ b/Completion/Zsh/Command/_strftime @@ -1,14 +1,16 @@ #compdef strftime -local ret=1 expl +local expl two='epoch time' + +if (( words[(I)-r] )); then + two='date string' +fi _arguments -S -A '-*' -s \ + '-n[omit trailing newline]' \ '-q[run quietly]' \ '(3)-r[reverse lookup using strptime]' \ '-s+[assign result to parameter]:param:_parameters' \ '1:format: _date_formats zsh' \ - '2:epoch time (or date string with -r)' \ + "2:$two" \ '3:nanoseconds' \ -&& ret=0 - -return ret diff --git a/Doc/Zsh/mod_datetime.yo b/Doc/Zsh/mod_datetime.yo index da65a9bbd..853656128 100644 --- a/Doc/Zsh/mod_datetime.yo +++ b/Doc/Zsh/mod_datetime.yo @@ -6,8 +6,8 @@ The tt(zsh/datetime) module makes available one builtin command: startitem() findex(strftime) cindex(date string, printing) -xitem(tt(strftime) [ tt(-s) var(scalar) ] var(format) [ var(epochtime) [ var(nanoseconds) ] ] ) -item(tt(strftime) tt(-r) [ tt(-q) ] [ tt(-s) var(scalar) ] var(format) var(timestring) )( +xitem(tt(strftime) [ tt(-s) var(scalar) | tt(-n) ] var(format) [ var(epochtime) [ var(nanoseconds) ] ] ) +item(tt(strftime) tt(-r) [ tt(-q) ] [ tt(-s) var(scalar) | tt(-n) ] var(format) var(timestring) )( Output the date in the var(format) specified. With no var(epochtime), the current system date/time is used; optionally, var(epochtime) may be used to specify the number of seconds since the epoch, and var(nanoseconds) may @@ -18,6 +18,9 @@ ifzman(the section EXPANSION OF PROMPT SEQUENCES in zmanref(zshmisc))\ ifnzman(noderef(Prompt Expansion)) are also available. startitem() +item(tt(-n))( +Suppress printing a newline after the formatted string. +) item(tt(-q))( Run quietly; suppress printing of all error messages described below. Errors for invalid var(epochtime) values are always printed. diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c index 521c15a5b..085e4cc26 100644 --- a/Src/Modules/datetime.c +++ b/Src/Modules/datetime.c @@ -175,7 +175,8 @@ output_strftime(char *nam, char **argv, Options ops, UNUSED(int func)) setsparam(scalar, metafy(buffer, len, META_DUP)); } else { fwrite(buffer, 1, len, stdout); - putchar('\n'); + if (!OPT_ISSET(ops,'n')) + putchar('\n'); } zfree(buffer, bufsize); @@ -235,7 +236,7 @@ getcurrenttime(UNUSED(Param pm)) } static struct builtin bintab[] = { - BUILTIN("strftime", 0, bin_strftime, 1, 3, 0, "qrs:", NULL), + BUILTIN("strftime", 0, bin_strftime, 1, 3, 0, "nqrs:", NULL), }; static const struct gsu_integer epochseconds_gsu = diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst index 9f67ecec3..622bdf6ed 100644 --- a/Test/V09datetime.ztst +++ b/Test/V09datetime.ztst @@ -130,3 +130,7 @@ >%6. 2002-02-02 02:02:02.999999 >%9. 2002-02-02 02:02:02.999999999 >%12. 2002-02-02 02:02:02.999999999 + + strftime -n 'one line%n' 2> /dev/null +0:-n option +>one line -- cgit v1.2.3 From d3a6dee9cd7f874fe543a7daf6165b8beee80eea Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Thu, 12 Nov 2020 01:13:23 +0100 Subject: unposted: Fix typo 'my be' for typeset --- Doc/Zsh/builtins.yo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Doc') diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 4b91db1fe..ebb29f632 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -1939,7 +1939,7 @@ a set of three normal command line arguments to tt(typeset) after expansion. Hence it is not possible to assign to multiple arrays by this means. -Note that each interface to any of the commands my be disabled +Note that each interface to any of the commands may be disabled separately. For example, `tt(disable -r typeset)' disables the reserved word interface to tt(typeset), exposing the builtin interface, while `tt(disable typeset)' disables the builtin. Note that disabling the -- cgit v1.2.3 From 038f537a2a96f903ca604b44c79ad2a11b69648c Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Thu, 12 Nov 2020 20:42:54 +0300 Subject: 47547: docs: Specify the exact kind of quoting which is assumed when parsing arithmetic expressions --- ChangeLog | 5 +++++ Doc/Zsh/arith.yo | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index bd6b0849f..f7bbd0924 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-11-16 ivan tkachenko + + * 47547: Doc/Zsh/arith.yo: docs: Specify the exact kind of + quoting which is assumed when parsing arithmetic expressions + 2020-11-16 Jun-ichi Takimoto * 47560: configure.ac, aczsh.m4: add necessary includes or diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo index c152bf48d..bc3e35ad5 100644 --- a/Doc/Zsh/arith.yo +++ b/Doc/Zsh/arith.yo @@ -20,7 +20,7 @@ The tt(let) builtin command takes arithmetic expressions as arguments; each is evaluated separately. Since many of the arithmetic operators, as well as spaces, require quoting, an alternative form is provided: for any command which begins with a `tt(LPAR()LPAR())', all the characters until a -matching `tt(RPAR()RPAR())' are treated as a quoted expression and +matching `tt(RPAR()RPAR())' are treated as a double-quoted expression and arithmetic expansion performed as for an argument of tt(let). More precisely, `tt(LPAR()LPAR())var(...)tt(RPAR()RPAR())' is equivalent to `tt(let ")var(...)tt(")'. The return status is 0 if the arithmetic value -- cgit v1.2.3 From 5a9e632638bcddcbb0524af7a2108805292bba0e Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sat, 5 Dec 2020 13:29:25 -0800 Subject: unposted: index compprefuncs and comppostfuncs --- ChangeLog | 6 +++++- Doc/Zsh/compsys.yo | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 562e42854..c478a9219 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ +2020-12-05 Bart Schaefer + + * unposted: Doc/Zsh/compsys.yo: index compprefuncs and comppostfuncs + 2020-12-04 Daniel Shahaf - * 47716: Etc/BUGS: Add Alekxandr's vcs_info patch. + * 47716: Etc/BUGS: Add Aleksandr's vcs_info patch. 2020-12-02 Bart Schaefer diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 9cfb4fd04..5f717d522 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -5338,6 +5338,8 @@ match the privileges when calling programs to generate matches. ) enditem() +vindex(compprefuncs, use of) +vindex(comppostfuncs, use of) Two more features are offered by the tt(_main_complete) function. The arrays tt(compprefuncs) and tt(comppostfuncs) may contain names of functions that are to be called immediately before or after -- cgit v1.2.3 From 34eae734900f42f8127c1eda5ed729f02121ae47 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Fri, 11 Dec 2020 17:24:33 +0900 Subject: 47731 (+unposted): add run-help assistant for btrfs also fix format errors in contrib.yo --- ChangeLog | 4 ++++ Doc/Zsh/contrib.yo | 15 +++++++++------ Functions/Misc/run-help-btrfs | 22 ++++++++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 Functions/Misc/run-help-btrfs (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index ea4b1cfab..2d524e81e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2020-12-11 Jun-ichi Takimoto + * 47731 (+unposted): Functions/Misc/run-help-btrfs, + Doc/Zsh/contrib.yo: add run-help assistant for btrfs command. + (based on the patch by Samir Benmendil in 43947⁩) + * Samir Benmendil: 43946: Functions/Misc/run-help-sudo: call run-help (instead of man) for the command given to sudo diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 00f693664..2b567056e 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -4363,6 +4363,7 @@ directory. These must be autoloaded, or placed as executable scripts in your search path, in order to be found and used by tt(run-help). startitem() +findex(run-help-btrfs) findex(run-help-git) findex(run-help-ip) findex(run-help-openssl) @@ -4370,14 +4371,16 @@ findex(run-help-p4) findex(run-help-sudo) findex(run-help-svk) findex(run-help-svn) -xitem(run-help-git) -xitem(run-help-ip) -xitem(run-help-openssl) -xitem(run-help-p4) -xitem(run-help-sudo) -xitem(run-help-svk) +xitem(tt(run-help-btrfs)) +xitem(tt(run-help-git)) +xitem(tt(run-help-ip)) +xitem(tt(run-help-openssl)) +xitem(tt(run-help-p4)) +xitem(tt(run-help-sudo)) +xitem(tt(run-help-svk)) item(tt(run-help-svn))( Assistant functions for the +tt(btrfs), tt(git), tt(ip), tt(openssl), diff --git a/Functions/Misc/run-help-btrfs b/Functions/Misc/run-help-btrfs new file mode 100644 index 000000000..0dc1dabcb --- /dev/null +++ b/Functions/Misc/run-help-btrfs @@ -0,0 +1,22 @@ +while [[ $# != 0 && $1 == -* ]]; do + shift +done + +case $1 in + (b*) man btrfs-balance ;; + (c*) man btrfs-check ;; + (d*) man btrfs-device ;; + (f*) man btrfs-filesystem ;; + (i*) man btrfs-inspect-internal ;; + (p*) man btrfs-property ;; + (qg*) man btrfs-qgroup ;; + (qu*) man btrfs-quota ;; + (rec*) man btrfs-receive ;; + (rep*) man btrfs-replace ;; + (resc*) man btrfs-rescue ;; + (rest*) man btrfs-restore ;; + (sc*) man btrfs-scrub ;; + (se*) man btrfs-send ;; + (su*) man btrfs-subvolume ;; + (*) man btrfs ;; +esac -- cgit v1.2.3 From b8ec0ddba56768e0afff45ffe78bf51ecf60aaa4 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Fri, 5 Feb 2021 13:50:58 -0800 Subject: unposted: Add cindex entries for some subsections --- ChangeLog | 4 ++++ Doc/Zsh/expn.yo | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 6b4855d7b..18f42d383 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2021-02-05 Bart Schaefer + + * unposted: Doc/Zsh/expn.yo: Add cindex entries for subsections + 2021-02-04 Bart Schaefer * 47895: Src/builtin.c, Test/D02glob.ztst: Remove trailing spaces diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index b3396721f..926e9b48b 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1511,7 +1511,9 @@ Include the unmatched portion in the result (the em(R)est). enditem() subsect(Rules) - +cindex(parameter expansion rules) +cindex(rules, parameter expansion) +cindex(substitution, parameter, rules) Here is a summary of the rules for substitution; this assumes that braces are present around the substitution, i.e. tt(${)var(...)tt(}). Some particular examples are given below. Note that the Zsh Development Group accepts @@ -1709,6 +1711,7 @@ expression) and replaced with the corresponding value, with internal flags enditem() subsect(Examples) +cindex(parameter expansion, 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 @@ -1890,7 +1893,6 @@ subsect(Dynamic named directories) cindex(directories, named, dynamic) cindex(named directories, dynamic) cindex(dynamic named directories) - If the function tt(zsh_directory_name) exists, or the shell variable tt(zsh_directory_name_functions) exists and contains an array of function names, then the functions are used to implement dynamic @@ -2016,7 +2018,7 @@ exists by that name, the word is replaced by the full pathname of the command. subsect(Notes) - +cindex(filename expansion, notes) Filename expansion is performed on the right hand side of a parameter assignment, including those appearing after commands of the tt(typeset) family. In this case, the right hand side will be treated @@ -2061,6 +2063,7 @@ No filename generation pattern matches the files `tt(.)' or `tt(..)'. In other instances of pattern matching, the `tt(/)' and `tt(.)' are not treated specially. subsect(Glob Operators) +cindex(glob operators) startitem() item(tt(*))( Matches any string, including the null string. @@ -2291,6 +2294,8 @@ within `tt([[)...tt(]])'), a `tt(/)' is not special; and `tt(/)' is also not special after a `tt(~)' appearing outside parentheses in a filename pattern. subsect(Globbing Flags) +cindex(globbing flags) +cindex(glob flags) There are various flags which affect any text to their right up to the end of the enclosing group or to the end of the pattern; they require the tt(EXTENDED_GLOB) option. All take the form @@ -2485,6 +2490,8 @@ searched for all files which match, so that a pattern of the form tt(LPAR()#i)tt(RPAR()/foo/bar/...) is potentially slow. subsect(Approximate Matching) +cindex(approximate matching) +cindex(matching, approximate) When matching approximately, the shell keeps a count of the errors found, which cannot exceed the number specified in the tt(LPAR()#a)var(num)tt(RPAR()) flags. Four types of error are recognised: @@ -2550,6 +2557,8 @@ approximate match. It is best to place the tt((#a1)) after any path segments which are known to be correct. subsect(Recursive Globbing) +cindex(recursive globbing) +cindex(globbing, recursive) A pathname component of the form `tt(LPAR())var(foo)tt(/RPAR()#)' matches a path consisting of zero or more directories matching the pattern var(foo). -- cgit v1.2.3 From 3714ee0b5868a30d7556acab337889849a3c8226 Mon Sep 17 00:00:00 2001 From: taiyu Date: Sun, 7 Feb 2021 05:15:03 -0800 Subject: github #68: support section suffix completion for man pages Support prepend and suffix values for insert-sections Add values for insert-sections for zstyle completion --- ChangeLog | 4 ++++ Completion/Unix/Command/_man | 22 ++++++++++++++-------- Completion/Zsh/Command/_zstyle | 6 ++++++ Doc/Zsh/compsys.yo | 10 +++++++--- 4 files changed, 31 insertions(+), 11 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 20f7eccf3..8a2161a81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2021-02-13 Oliver Kiddle + * github #68: taiyu.len: Completion/Unix/Command/_man, + Completion/Zsh/Command/_zstyle, Doc/Zsh/compsys.yo: + support section suffix completion for man pages + * 47905: Joshua Krusell: Src/Modules/zutil.c, Test/V12zparseopts.ztst: Add leading '-' to zparseopts option parsing errors diff --git a/Completion/Unix/Command/_man b/Completion/Unix/Command/_man index 7d55201e3..dba1d13dc 100644 --- a/Completion/Unix/Command/_man +++ b/Completion/Unix/Command/_man @@ -6,7 +6,6 @@ # - We assume that Linux distributions are using either man-db or mandoc # - @todo Would be nice to support completing the initial operand as a section # name (on non-Solaris systems) -# - @todo We don't support the man-db syntax .
(e.g., `ls.1`) # - @todo We don't support the man-db feature of 'sub-pages' — that is, treating # pairs of operands like `git diff` as `git-diff` # - @todo Option exclusivity isn't super accurate @@ -415,7 +414,7 @@ _man() { } _man_pages() { - local pages sopt + local pages sopt tmp # What files corresponding to manual pages can end in. local suf='.((?|<->*|ntcl)(|.gz|.bz2|.z|.Z|.lzma))' @@ -444,13 +443,20 @@ _man_pages() { # `POSIX.1.5'. [[ $variant = solaris* ]] && sopt='-s ' - if ((CURRENT > 1 || noinsert)) || - ! zstyle -t ":completion:${curcontext}:manuals.$sect_dirname" insert-sections - then - compadd "$@" - ${pages%$~suf} - else - compadd "$@" -P "$sopt$sect_dirname " - ${pages%$~suf} + if ! ((CURRENT > 1 || noinsert)); then + zstyle -s ":completion:${curcontext}:manuals.$sect_dirname" insert-sections tmp fi + case "$tmp" in + prepend|true|on|yes|1) + compadd "$@" -P "$sopt$sect_dirname " - ${pages%$~suf} + ;; + suffix) + compadd "$@" -s ".$sect_dirname" - ${pages%$~suf} + ;; + *) + compadd "$@" - ${pages%$~suf} + ;; + esac } _man "$@" diff --git a/Completion/Zsh/Command/_zstyle b/Completion/Zsh/Command/_zstyle index bb0e1f5bc..0473dd0fe 100644 --- a/Completion/Zsh/Command/_zstyle +++ b/Completion/Zsh/Command/_zstyle @@ -62,6 +62,7 @@ styles=( ignore-parents c:ignorepar ignored-patterns c: insert-ids c:insert-ids + insert-sections c:insert-sections insert-tab c:bool insert-unambiguous c:insunambig keep-prefix c:keep-prefix @@ -524,6 +525,11 @@ while (( $#state )); do compadd - menu single longer ;; + (insert-sections) + _wanted values expl 'where to insert man page section' \ + compadd - true false prepend suffix + ;; + (fake-files) _message -e fakes 'prefix and names' ;; diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 5f717d522..729b4e5d3 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -1838,14 +1838,18 @@ user is longer than the common prefix to the corresponding IDs. kindex(insert-sections, completion style) item(tt(insert-sections))( This style is used with tags of the form `tt(manuals.)var(X)' when -completing names of manual pages. If set to `true' and the var(X) in the -tag name matches the section number of the page being completed, the -section number is inserted along with the page name. For example, given +completing names of manual pages. If set and the var(X) in the tag name matches +the section number of the page being completed, the section number is inserted +along with the page name. For example, given example(zstyle ':completion:*:manuals.*' insert-sections true) tt(man ssh_) may be completed to tt(man 5 ssh_config). +The value may also be set to one of `tt(prepend)', or `tt(suffix)'. +`tt(prepend)' behaves the same as `true' as in the above example, while +`tt(suffix)' would complete tt(man ssh_) as tt(man ssh_config.5). + This is especially useful in conjunction with tt(separate-sections), as it ensures that the page requested of tt(man) corresponds to the one displayed in the completion listing when there are multiple pages with the -- cgit v1.2.3 From 83cc7c6bf08762c3fdeb76a44e4086734ff1db13 Mon Sep 17 00:00:00 2001 From: Lawrence Velázquez Date: Thu, 14 Jan 2021 01:04:54 -0500 Subject: 47830: Fix some documentation typos --- ChangeLog | 4 ++++ Doc/Zsh/contrib.yo | 4 ++-- README | 12 ++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index a0bc14c99..1648ea243 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2021-02-16 Lawrence Velázquez + + * 47830: Doc/Zsh/contrib.yo, README: Fix some documentation typos + 2021-02-13 Oliver Kiddle * unposted (Daniel): Completion/Unix/Command/_locale: diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 2b567056e..586ac06f5 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -465,7 +465,7 @@ allows you to edit the list of directories, one per line. The list can be edited to any extent you like; no sanity checking is performed. Completion is available. No quoting is necessary (except for newlines, where I have in any case no sympathy); directories are in -unabbreviated from and contain an absolute path, i.e. they start with tt(/). +unabbreviated form and contain an absolute path, i.e. they start with tt(/). Usually the first entry should be left as the current directory. ) item(tt(-p ')var(pattern)tt('))( @@ -708,7 +708,7 @@ that the wrapper function gets. This configuration is described below. Then arrange for the wrapper to be run as a zsh_directory_name hook: -example(autoload -Uz add-zsh-hook zsh_diretory_name_generic zdn_mywrapper +example(autoload -Uz add-zsh-hook zsh_directory_name_generic zdn_mywrapper add-zsh-hook -U zsh_directory_name zdn_mywrapper) subsect(Configuration) diff --git a/README b/README index 3ebf75f1b..1eb38a608 100644 --- a/README +++ b/README @@ -40,7 +40,7 @@ not be built unless --enable-gdbm is passed explicitly. vcs_info quilt: The value of the 'quiltcommand' style used to be taken for the name of an external command. Now it may also be a shell function. Normal -command word precedece rules apply, so if you have a function and a command +command word precedence rules apply, so if you have a function and a command with the same name, the function will be used. The "function" reserved word, used to define functions, gained a new -T option. @@ -206,7 +206,7 @@ been made an error. (The option setting NO_MULTI_FUNC_DEF turned this case into an error, but did not help with other cases and is off by default.) The alternative, of not expanding the alias, was rejected as it was more difficult to achieve in the parser and also would silently -change the shell's behaviur between versions. A new option, +change the shell's behaviour between versions. A new option, ALIAS_FUNC_DEF, has been added, which can be set to make the shell behave as in previous versions. It is in any case recommended to use the "function" keyword, as aliases are not expanded afterwards. @@ -410,19 +410,19 @@ This is also necessary in the unusual eventuality that the builtins are to be overridden by shell functions, since reserved words take precedence over functions. -10) For compatilibity with other shells, the syntax +10) For compatibility with other shells, the syntax array=([index]=value) -can be used with both assoiative arrays and normal arrays. In the +can be used with both associative arrays and normal arrays. In the unlikely event that you wish to create an array with an entry matching a file whose name consists of one of a range of characters matched as a [...] expression, followed by an equal sign, followed by arbitrary other characters, it is now necessary to quote the equals sign. -Incompatibilites between 5.0.7 and 5.0.8 ----------------------------------------- +Incompatibilities between 5.0.7 and 5.0.8 +----------------------------------------- Various arithmetic operations have changed, in particular with respect to the choice of integer or floating point operations. The new -- cgit v1.2.3 From 9c0533931c51b7d512d3e95850404f5aac2dbce1 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Tue, 16 Feb 2021 18:34:41 +0000 Subject: 48073: Add fc -s as POSIX way of rerunning command without starting editor --- ChangeLog | 5 +++++ Doc/Zsh/builtins.yo | 3 ++- Src/builtin.c | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index c89fce748..cbc5eb23b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-02-17 Peter Stephenson + + * 48073: Martijn Dekker: Doc/Zsh/builtins.yo, Src/builtin.c: fc + -s is POSIX version of fc -e -. + 2021-02-16 Peter Stephenson * 47876: Justtine Tunney: Src/exec.c: Add more cases where diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index ebb29f632..a7afe42cf 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -736,7 +736,7 @@ findex(fc) cindex(history, editing) cindex(editing history) redef(SPACES)(0)(tt(ifztexi(NOTRANS(@ @ @ @ @ @ ))ifnztexi( ))) -xitem(tt(fc) [ tt(-e) var(ename) ] [ tt(-LI) ] [ tt(-m) var(match) ] [ var(old)tt(=)var(new) ... ] [ var(first) [ var(last) ] ]) +xitem(tt(fc) [ tt(-e) var(ename) ] [ tt(-s) ] [ tt(-LI) ] [ tt(-m) var(match) ] [ var(old)tt(=)var(new) ... ] [ var(first) [ var(last) ] ]) xitem(tt(fc -l )[ tt(-LI) ] [ tt(-nrdfEiD) ] [ tt(-t) var(timefmt) ] [ tt(-m) var(match) ]) xitem(SPACES()[ var(old)tt(=)var(new) ... ] [ var(first) [ var(last) ] ]) xitem(tt(fc -p )[ tt(-a) ] [ var(filename) [ var(histsize) [ var(savehistsize) ] ] ]) @@ -783,6 +783,7 @@ the parameter tt(EDITOR) is used; if that is not set a builtin default, usually `tt(vi)' is used. If var(ename) is `tt(-)', no editor is invoked. When editing is complete, the edited command is executed. +The flag `tt(-s)' is equivalent to `tt(-e -)'. The flag tt(-r) reverses the order of the events and the flag tt(-n) suppresses event numbers when listing. diff --git a/Src/builtin.c b/Src/builtin.c index 35a0fb2db..3093a3056 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -71,7 +71,7 @@ static struct builtin builtins[] = * But that's actually not useful, so it's more consistent to * cause an error. */ - BUILTIN("fc", 0, bin_fc, 0, -1, BIN_FC, "aAdDe:EfiIlLmnpPrRt:W", NULL), + BUILTIN("fc", 0, bin_fc, 0, -1, BIN_FC, "aAdDe:EfiIlLmnpPrRst:W", NULL), BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL), BUILTIN("float", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "E:%F:%HL:%R:%Z:%ghlp:%rtux", "E"), BUILTIN("functions", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "ckmMstTuUWx:z", NULL), @@ -1643,7 +1643,7 @@ bin_fc(char *nam, char **argv, Options ops, int func) if (!fclist(out, ops, first, last, asgf, pprog, 1)) { char *editor; - if (func == BIN_R) + if (func == BIN_R || OPT_ISSET(ops, 's')) editor = "-"; else if (OPT_HASARG(ops, 'e')) editor = OPT_ARG(ops, 'e'); -- cgit v1.2.3 From 78cf45587100965553a879fc8b026294c79bd756 Mon Sep 17 00:00:00 2001 From: dana Date: Tue, 23 Mar 2021 00:26:21 -0500 Subject: unposted: Improve documentation and add regression test for workers/47745 --- ChangeLog | 3 +++ Doc/Zsh/expn.yo | 3 ++- Test/D07multibyte.ztst | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 8cef6370b..066a806c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-03-23 dana + * unposted: Doc/Zsh/expn.yo, Test/D07multibyte.ztst: Improve + documentation and add regression test for workers/47745 + * 47745: Stephane Chazelas: Src/utils.c: Fix [:IDENT:] vs posixidentifiers diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 926e9b48b..c218ded05 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -2134,7 +2134,8 @@ is not sensitive to the locale: startitem() item(tt([:IDENT:]))( The character is allowed to form part of a shell identifier, such -as a parameter name +as a parameter name; this test respects the tt(POSIX_IDENTIFIERS) +option ) item(tt([:IFS:]))( The character is used as an input field separator, i.e. is contained in the diff --git a/Test/D07multibyte.ztst b/Test/D07multibyte.ztst index 9375dcda4..7f046525a 100644 --- a/Test/D07multibyte.ztst +++ b/Test/D07multibyte.ztst @@ -178,6 +178,13 @@ >3 ?(eval):1: command not found: hähä=3 + expr='[[ é = [[:IDENT:]] ]]' + ( unsetopt posix_identifiers; eval $expr && echo ok unset ) + ( setopt posix_identifiers; eval $expr || echo ok set ) +0:Regression test for workers/47745 +>ok unset +>ok set + foo="Ølaf«Ødd«øpénëd«ån«àpple" print -l ${(s.«.)foo} ioh="Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος." -- cgit v1.2.3 From 3d2814072ac2f8ae5640cc479a23dde5fa03ff9c Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 29 Mar 2021 09:13:43 +0000 Subject: unposted: docs: _arguments: Fix a typo in the example. --- ChangeLog | 5 +++++ Doc/Zsh/compsys.yo | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index e8fa6093e..b7f398933 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-03-29 Daniel Shahaf + + * unposted: Doc/Zsh/compsys.yo: docs: _arguments: Fix a typo + in the example. + 2021-03-28 Oliver Kiddle * Jacob Gelbman: 48166: Completion/Unix/Command/_ctags: diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 729b4e5d3..89b918d60 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -4274,7 +4274,7 @@ The last two descriptions say what should be completed as arguments. The first describes the first argument as a `var(postscript file)' and makes files ending in `tt(ps)' or `tt(eps)' be completed. The last description gives all other arguments the -description `var(page numbers)' but does not offer completions. +description `var(page number)' but does not offer completions. ) findex(_cache_invalid) item(tt(_cache_invalid) var(cache_identifier))( -- cgit v1.2.3 From 714864a87b11b080da92dee7abc29b8bc64107a5 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 2 Apr 2021 22:29:28 +0200 Subject: 48356: clarify (the intended) behaviour for the two anchor forms of matching control --- ChangeLog | 5 +++++ Doc/Zsh/compwid.yo | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index a44e30aeb..8c97f651c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-04-02 Oliver Kiddle + + * 48356: Doc/Zsh/compwid.yo: clarify (the intended) + behaviour for the two anchor forms of matching control + 2021-04-01 Daniel Shahaf * unposted: Etc/BUGS: Add 39319, a named-file process diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo index 0b98d07b2..3e86d3b42 100644 --- a/Doc/Zsh/compwid.yo +++ b/Doc/Zsh/compwid.yo @@ -959,6 +959,9 @@ As tt(l), tt(L), tt(b) and tt(B), with the difference that the command line and trial completion patterns are anchored on the right side. Here an empty var(ranchor) and the tt(e) and tt(E) forms force the match to the end of the command line or trial completion string. + +In the form where var(lanchor) is given, the var(lanchor) only needs +to match the trial completion string. ) item(tt(x:))( This form is used to mark the end of matching specifications: @@ -1022,8 +1025,10 @@ any number of characters in the trial completion. In this case the pattern must be anchored (on either side); in the case of a single star, the var(anchor) then determines how much of the trial completion is to be included DASH()- only the characters up to the next appearance of -the anchor will be matched. With two stars, substrings matched by the -anchor can be matched, too. +the anchor will be matched. With two stars, substrings matched by +the anchor can be matched, too. In the forms that include two +anchors, `tt(*)' can match characters from the additional anchor +DASH()- var(lanchor) with tt(r) or var(ranchor) with tt(l). Examples: -- cgit v1.2.3 From e4a8740c789970178b81162349e4b33104b6f482 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 5 Apr 2021 22:32:41 +0000 Subject: 48410: FAQ, METAFAQ: Mention zsh-security@. --- ChangeLog | 3 +++ Doc/Zsh/metafaq.yo | 8 +++++++- Etc/FAQ.yo | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 461bfeacb..1c7a88bff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-04-08 Daniel Shahaf + * 48410: Doc/Zsh/metafaq.yo, Etc/FAQ.yo: FAQ, METAFAQ: Mention + zsh-security@. + * 48379: Src/subst.c, Test/D04parameter.ztst: Make the parameter expansion subscript flags parse error message, "error in flags", identify the location of the parse error. diff --git a/Doc/Zsh/metafaq.yo b/Doc/Zsh/metafaq.yo index e69a0976c..ca7f26adf 100644 --- a/Doc/Zsh/metafaq.yo +++ b/Doc/Zsh/metafaq.yo @@ -34,7 +34,7 @@ uref(http://zsh.sourceforge.net/). texinode(Mailing Lists)(The Zsh FAQ)(Availability)(Introduction) sect(Mailing Lists) cindex(mailing lists) -Zsh has 3 mailing lists: +Zsh has several mailing lists: startitem() item(tt())( @@ -47,6 +47,12 @@ User discussions. item(tt())( Hacking, development, bug reports and patches. ) +item(tt())( +Private mailing list (the general public cannot subscribe to it) for discussing +bug reports with security implications, i.e., potential vulnerabilities. + +If you find a security problem in zsh itself, please mail this address. +) enditem() To subscribe or unsubscribe, send mail diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo index 3e90a6c4e..171b2f9d7 100644 --- a/Etc/FAQ.yo +++ b/Etc/FAQ.yo @@ -2542,6 +2542,11 @@ label(62) ) (posting to the last one is currently restricted). + Finally, there is a private mailing list (the general public cannot subscribe + to it) for discussing bug reports with security implications, i.e., potential + vulnerabilities: mytt(zsh-security@zsh.org). If you find a security problem + in zsh itself, please mail this address. + Note that you should only join one of these lists: people on zsh-workers receive all the lists, and people on zsh-users will also receive the announcements list. -- cgit v1.2.3 From 408a83048366a22bf7645b71bee7428743793736 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sat, 10 Apr 2021 14:26:46 -0700 Subject: 47913: implement CASE_PATHS option to make NO_CASE_GLOB more sensible --- ChangeLog | 5 +++++ Doc/Zsh/options.yo | 16 ++++++++++++++++ Src/options.c | 1 + Src/pattern.c | 9 ++++++++- Src/zsh.h | 1 + 5 files changed, 31 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 2fe66e4d1..0e8a33f7c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-04-10 Bart Schaefer + + * 47913: Doc/Zsh/options.yo, Src/options.c, Src/pattern.c, Src/zsh.h: + implement CASE_PATHS option to make NO_CASE_GLOB more sensible + 2021-04-10 dana * unposted (see 48415): README: Document incompatibility diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index b3bf11f5c..714e8a1a1 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -474,6 +474,22 @@ item(tt(CASE_MATCH) )( Make regular expressions using the tt(zsh/regex) module (including matches with tt(=~)) sensitive to case. ) +pindex(CASE_PATHS) +pindex(NO_CASE_PATHS) +pindex(CASEPATHS) +pindex(NOCASEPATHS) +cindex(case-sensitive globbing, option) +item(tt(CASE_PATHS))( +If tt(CASE_PATHS) is not set (the default), tt(CASE_GLOB) affects the +interpretation of em(every) path component, whenever a special +character appears in em(any) component. When tt(CASE_PATHS) is set, +file path components that do em(not) contain special filename +generation characters are always sensitive to case, thus restricting +tt(NO_CASE_GLOB) to components that contain globbing characters. + +Note that if the filesystem itself is not sensitive to case, then +tt(CASE_PATHS) has no effect. +) pindex(CSH_NULL_GLOB) pindex(NO_CSH_NULL_GLOB) pindex(CSHNULLGLOB) diff --git a/Src/options.c b/Src/options.c index fba021e7d..6ea6290e5 100644 --- a/Src/options.c +++ b/Src/options.c @@ -105,6 +105,7 @@ static struct optname optns[] = { {{NULL, "bsdecho", OPT_EMULATE|OPT_SH}, BSDECHO}, {{NULL, "caseglob", OPT_ALL}, CASEGLOB}, {{NULL, "casematch", OPT_ALL}, CASEMATCH}, +{{NULL, "casepaths", 0}, CASEPATHS}, {{NULL, "cbases", 0}, CBASES}, {{NULL, "cprecedences", OPT_EMULATE|OPT_NONZSH}, CPRECEDENCES}, {{NULL, "cdablevars", OPT_EMULATE}, CDABLEVARS}, diff --git a/Src/pattern.c b/Src/pattern.c index c28f2c9fb..c0e31b78e 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -509,7 +509,7 @@ void patcompstart(void) { patcompcharsset(); - if (isset(CASEGLOB)) + if (isset(CASEGLOB) || isset(CASEPATHS)) patglobflags = 0; else patglobflags = GF_IGNCASE; @@ -632,6 +632,13 @@ patcompile(char *exp, int inflags, char **endexp) p->patmlen = len; p->patnpar = patnpar-1; +#ifndef __CYGWIN__ /* The filesystem itself is case-insensitive on Cygwin */ + if ((patflags & PAT_FILE) && !isset(CASEGLOB) && !(patflags & PAT_PURES)) { + p->globflags |= GF_IGNCASE; + p->globend |= GF_IGNCASE; + } +#endif + if (!strp) { pscan = (Upat)(patout + startoff); diff --git a/Src/zsh.h b/Src/zsh.h index a26b2d05b..d70a4017c 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2387,6 +2387,7 @@ enum { BSDECHO, CASEGLOB, CASEMATCH, + CASEPATHS, CBASES, CDABLEVARS, CDSILENT, -- cgit v1.2.3 From 32336eab92e7b639c08b05ccfadf4a936e0ad3f6 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 14 Apr 2021 14:12:25 +0000 Subject: 45583/0001: docs: Minor markup tweak --- ChangeLog | 4 ++++ Doc/Zsh/func.yo | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index a35eb6501..b2fca8d90 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2021-04-15 Daniel Shahaf + + * 45583/0001: Doc/Zsh/func.yo: docs: Minor markup tweak + 2021-04-13 dana * Daniel Shahaf: 48522: README: Clarify _alternative change diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo index d500a78ae..0944380b9 100644 --- a/Doc/Zsh/func.yo +++ b/Doc/Zsh/func.yo @@ -212,7 +212,7 @@ example, if tt($chpwd_functions) is an array containing the values execute the functions `tt(chpwd)', `tt(mychpwd)' and `tt(chpwd_save_dirstack)', in that order. Any function that does not exist is silently ignored. A function found by this mechanism is referred to -elsewhere as a `hook function'. An error in any function causes subsequent +elsewhere as a em(hook function). An error in any function causes subsequent functions not to be run. Note further that an error in a tt(precmd) hook causes an immediately following tt(periodic) function not to run (though it may run at the next opportunity). -- cgit v1.2.3 From d07c945e747241f2b10935698880340480ad38e7 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 14 Apr 2021 14:20:23 +0000 Subject: 45583/0002 (tweaked): docs: Fix rendering of an example in the man page output The texi output was unaffected. However, in the man page on my system, everything after the example() was underlined and not indented. --- ChangeLog | 3 +++ Doc/Zsh/contrib.yo | 2 ++ 2 files changed, 5 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index b2fca8d90..8e87c244d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-04-15 Daniel Shahaf + * 45583/0002 (tweaked): Doc/Zsh/contrib.yo: docs: Fix rendering + of an example in the man page output + * 45583/0001: Doc/Zsh/func.yo: docs: Minor markup tweak 2021-04-13 dana diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 586ac06f5..55ea06f34 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2028,7 +2028,9 @@ disabled. item(Declare cleanup)( If your function makes any other changes that should be undone when the theme is disabled, your setup function may call + example(prompt_cleanup var(command)) + where var(command) should be suitably quoted. If your theme is ever disabled or replaced by another, var(command) is executed with tt(eval). You may declare more than one such cleanup hook. -- cgit v1.2.3 From 9b5f80285d392b131198c6690428687d84cd49da Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 14 Apr 2021 14:23:58 +0000 Subject: 45583/0003: docs: Fix rendering in the man page output In the man page output, the text was underlined from the var() to the end of the paragraph. The texi output in affected. For instance, the text `name' in TeX is now slanted Roman (\slshape\rmfamily) rather than slanted teletype (\slshape\ttfamily). --- ChangeLog | 3 +++ Doc/Zsh/contrib.yo | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 8e87c244d..f2f8804a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-04-15 Daniel Shahaf + * 45583/0003: Doc/Zsh/contrib.yo: docs: Fix rendering in the + man page output + * 45583/0002 (tweaked): Doc/Zsh/contrib.yo: docs: Fix rendering of an example in the man page output diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 55ea06f34..5e91f9a8d 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2036,13 +2036,13 @@ disabled or replaced by another, var(command) is executed with tt(eval). You may declare more than one such cleanup hook. ) item(Define preview)( -Define or autoload a function tt(prompt_var(name)_preview) to display +Define or autoload a function tt(prompt_)var(name)tt(_preview) to display a simulated version of your prompt. A simple default previewer is defined by tt(promptinit) for themes that do not define their own. This preview function is called by `tt(prompt -p)'. ) item(Provide help)( -Define or autoload a function tt(prompt_var(name)_help) to display +Define or autoload a function tt(prompt_)var(name)tt(_help) to display documentation or help text for your theme. This help function is called by `tt(prompt -h)'. ) -- cgit v1.2.3 From cc833e01fef8298bc385bcff98f1b7ae85a8642a Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 14 Apr 2021 14:27:10 +0000 Subject: 45583/0004: docs: Document that hook functions may rely on $? (see workers/48570). --- ChangeLog | 3 +++ Doc/Zsh/func.yo | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index f2f8804a2..547780dc8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-04-15 Daniel Shahaf + * 45583/0004: Doc/Zsh/func.yo: docs: Document that hook functions + may rely on $? (see workers/48570). + * 45583/0003: Doc/Zsh/contrib.yo: docs: Fix rendering in the man page output diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo index 0944380b9..7edad7f23 100644 --- a/Doc/Zsh/func.yo +++ b/Doc/Zsh/func.yo @@ -206,7 +206,8 @@ findex(hook functions) For the functions below, it is possible to define an array that has the same name as the function with `tt(_functions)' appended. Any element in such an array is taken as the name of a function to execute; it is executed -in the same context and with the same arguments as the basic function. For +in the same context and with the same arguments and same initial value of tt($?) +as the basic function. For example, if tt($chpwd_functions) is an array containing the values `tt(mychpwd)', `tt(chpwd_save_dirstack)', then the shell attempts to execute the functions `tt(chpwd)', `tt(mychpwd)' and -- cgit v1.2.3 From ebcb20a9c0d3469e5ddf2186054ec5a5f7493e58 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 14 Apr 2021 14:49:13 +0000 Subject: 45583/0005: vcs_info docs: Recommend use of prompt expandos rather than terminal escape sequences. --- ChangeLog | 3 +++ Doc/Zsh/contrib.yo | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 547780dc8..107900c80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-04-15 Daniel Shahaf + * 45583/0005: Doc/Zsh/contrib.yo: vcs_info docs: Recommend use + of prompt expandos rather than terminal escape sequences. + * 45583/0004: Doc/Zsh/func.yo: docs: Document that hook functions may rely on $? (see workers/48570). diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 5e91f9a8d..07bf4e054 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1826,10 +1826,22 @@ example(zstyle ':vcs_info:bzr:*' use-simple true) If you do use tt(use-simple), please report if it does `the-right-thing[tm]'. Display the revision number in yellow for tt(bzr) and tt(svn): +example(zstyle ':vcs_info:(svn|bzr):*' \ + branchformat '%b%%F{yellow}:%r') + +The doubled percent sign is explained in +ifzman(the bf(Oddities) section)ifnzman(noderef(vcs_info Oddities)). + +Alternatively, one can use the raw colour codes directly: + example(zstyle ':vcs_info:(svn|bzr):*' \ branchformat '%b%{'${fg[yellow]}'%}:%r') -If you want colors, make sure you enclose the color codes in tt(%{)var(...)tt(%}) +Normally when a variable is interpolated into a format string, the variable +needs to be tt(%)-escaped. In this example we skipped that because we assume +the value of tt(${fg[yellow]}) doesn't contain any tt(%) signs. + +Make sure you enclose the color codes in tt(%{)var(...)tt(%}) if you want to use the string provided by tt(vcs_info) in prompts. Here is how to print the VCS information as a command (not in a prompt): -- cgit v1.2.3 From 517e1777a52046ac86aca0b8c0b2c7c56d74bf29 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 14 Apr 2021 14:50:34 +0000 Subject: 45583/0006: vcs_info docs: Change user-context name in an example, to avoid confusion with the special-casing of the value `command' in vcs_info_lastmsg. --- ChangeLog | 4 ++++ Doc/Zsh/contrib.yo | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 107900c80..d2b3e19cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2021-04-15 Daniel Shahaf + * 45583/0006: Doc/Zsh/contrib.yo: vcs_info docs: Change + user-context name in an example, to avoid confusion with the + special-casing of the value `command' in vcs_info_lastmsg. + * 45583/0005: Doc/Zsh/contrib.yo: vcs_info docs: Recommend use of prompt expandos rather than terminal escape sequences. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 07bf4e054..ef992bdeb 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1845,10 +1845,10 @@ Make sure you enclose the color codes in tt(%{)var(...)tt(%}) if you want to use the string provided by tt(vcs_info) in prompts. Here is how to print the VCS information as a command (not in a prompt): -example(alias vcsi='vcs_info command; vcs_info_lastmsg') +example(alias vcsi='vcs_info interactive; vcs_info_lastmsg') This way, you can even define different formats for output via -tt(vcs_info_lastmsg) in the 'tt(:vcs_info:*:command:*)' namespace. +tt(vcs_info_lastmsg) in the 'tt(:vcs_info:*:interactive:*)' namespace. Now as promised, some code that uses hooks: say, you'd like to replace the string `svn' by `subversion' in -- cgit v1.2.3 From 2144d0110282e5ab755e2ec159b8604208e671d5 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 14 Apr 2021 15:10:03 +0000 Subject: 45583/0007: vcs_info docs: vcs_info_lastmsg: Correct an ambiguous/wrong description. --- ChangeLog | 3 +++ Doc/Zsh/contrib.yo | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index d2b3e19cf..626016c0d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-04-15 Daniel Shahaf + * 45583/0007: Doc/Zsh/contrib.yo: vcs_info docs: + vcs_info_lastmsg: Correct an ambiguous/wrong description. + * 45583/0006: Doc/Zsh/contrib.yo: vcs_info docs: Change user-context name in an example, to avoid confusion with the special-casing of the value `command' in vcs_info_lastmsg. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index ef992bdeb..5fe5601a7 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1510,7 +1510,7 @@ below for details. ) findex(vcs_info_lastmsg) item(tt(vcs_info_lastmsg))( -Outputs the last tt(${vcs_info_msg_*_}) value. +Outputs the current values of tt(${vcs_info_msg_*_}). Takes into account the value of the tt(use-prompt-escapes) style in tt(':vcs_info:formats:command:-all-'). It also only prints tt(max-exports) values. -- cgit v1.2.3 From e1f5172a4831087399945e9cc38666be78e667ab Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 14 Apr 2021 15:11:01 +0000 Subject: 45583/0008: vcs_info git: Use best practices in an example The alias was vulnerable to SHORT_LOOPS syntax, not invokable from scripts, etc.. --- ChangeLog | 3 +++ Doc/Zsh/contrib.yo | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 626016c0d..6494e0018 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-04-15 Daniel Shahaf + * 45583/0008: Doc/Zsh/contrib.yo: vcs_info git: Use best + practices in an example + * 45583/0007: Doc/Zsh/contrib.yo: vcs_info docs: vcs_info_lastmsg: Correct an ambiguous/wrong description. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 5fe5601a7..3c4fdded0 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1845,7 +1845,7 @@ Make sure you enclose the color codes in tt(%{)var(...)tt(%}) if you want to use the string provided by tt(vcs_info) in prompts. Here is how to print the VCS information as a command (not in a prompt): -example(alias vcsi='vcs_info interactive; vcs_info_lastmsg') +example(vcsi+LPAR()+RPAR() { vcs_info interactive; vcs_info_lastmsg }) This way, you can even define different formats for output via tt(vcs_info_lastmsg) in the 'tt(:vcs_info:*:interactive:*)' namespace. -- cgit v1.2.3 From 82ff9f24f170eea7daa935fdaa09ab75a2f277ff Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sun, 18 Apr 2021 13:58:09 -0700 Subject: 48560: add TYPESET_TO_UNSET option to remove initialization of parameters Changes typeset such that ${newparam-notset} yields "notset" and "typeset -p newparam" does not show an assignment to the parameter. This is similar to the default behavior of bash and ksh, with minor differences in typeset output. Also add tests for some POSIX incompatibilities plus minor changes for test harness robustness. --- ChangeLog | 19 +++++++++++++++++-- Completion/compinit | 1 + Doc/Zsh/builtins.yo | 6 +++++- Doc/Zsh/options.yo | 10 ++++++++++ Doc/Zsh/params.yo | 5 +++++ Src/builtin.c | 14 +++++++++++--- Src/options.c | 1 + Src/params.c | 22 +++++++++++++++++++--- Src/subst.c | 3 ++- Src/zsh.h | 3 +++ Test/D06subscript.ztst | 5 +++++ Test/E01options.ztst | 15 +++++++++++++++ Test/V10private.ztst | 12 ++++++------ Test/runtests.zsh | 2 +- Test/ztst.zsh | 2 +- 15 files changed, 102 insertions(+), 18 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 722a2437c..7dcbbc533 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2021-04-18 Bart Schaefer + + * 48560: Completion/compinit, Doc/Zsh/builtins.yo, + Doc/Zsh/options.yo, Doc/Zsh/params.yo, Src/builtin.c, + Src/options.c, Src/params.c, Src/subst.c, Src/zsh.h, + Test/D06subscript.ztst, Test/E01options.ztst, Test/E03posix.ztst, + Test/V10private.ztst, Test/runtests.zsh, Test/ztst.zsh: add + TYPESET_TO_UNSET option, which removes initialization of newly + declared parameters such that ${newparam-notset} yields "notset" + and "typeset -p newparam" does not show an assignment to the + parameter. This is similar to the default behavior of bash and + ksh, with minor differences in typeset output. Also add tests for + some POSIX incompatibilities plus minor changes for test harness + robustness. + 2021-04-18 Jun-ichi Takimoto * unposted: Etc/BUGS: remove a bug fixed by 47301 @@ -2909,7 +2924,7 @@ g 2019-02-14 Peter Stephenson - * see 44062: back off change to ZLE per-line initiialisation, + * see 44062: back off change to ZLE per-line initialisation, causing problems after failed reads and apparently not needed for the intended fix of interrupt handling (40305 / 34656ec2). @@ -15632,7 +15647,7 @@ g * 32338: Doc/Makefile.in: create Doc/help.txt as an empty file when Util/helpfiles fails, so that the rest of the build does not - yeild a spurious error + yield a spurious error * 32337: Src/params.c: initialize several special parameters to unset for better compatibility in emulation modes; for the same diff --git a/Completion/compinit b/Completion/compinit index e81cd1604..1f2e7c634 100644 --- a/Completion/compinit +++ b/Completion/compinit @@ -165,6 +165,7 @@ _comp_options=( NO_posixidentifiers NO_shwordsplit NO_shglob + NO_typesettounset NO_warnnestedvar NO_warncreateglobal ) diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index a7afe42cf..61dc6986f 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -1872,7 +1872,11 @@ ifnzman(noderef(Local Parameters))\ retain their special attributes when made local. For each var(name)tt(=)var(value) assignment, the parameter -var(name) is set to var(value). +var(name) is set to var(value). If the assignment is omitted and var(name) +does em(not) refer to an existing parameter, a new parameter is intialized +to empty string, zero, or empty array (as appropriate), em(unless) the +shell option tt(TYPESET_TO_UNSET) is set. When that option is set, +the parameter attributes are recorded but the parameter remains unset. If the shell option tt(TYPESET_SILENT) is not set, for each remaining var(name) that refers to a parameter that is already set, the name and diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 714e8a1a1..6e862fae8 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1942,6 +1942,16 @@ If the option is set, they will only be shown when parameters are selected with the `tt(-m)' option. The option `tt(-p)' is available whether or not the option is set. ) +pindex(TYPESET_TO_UNSET) +pindex(NO_TYPESET_TO_UNSET) +pindex(TYPESETTOUNSET) +pindex(NOTYPESETTOUNSET) +item(tt(TYPESET_TO_UNSET) )( +When declaring a new parameter with any of the `tt(typeset)' family of +related commands, the parameter remains unset unless and until a +value is explicity assigned to it, either in the `tt(typeset)' command +itself or as a later assignment statement. +) pindex(VERBOSE) pindex(NO_VERBOSE) pindex(NOVERBOSE) diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 36c1ae4c2..a9044336f 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -393,6 +393,11 @@ is compared to the pattern, and the first matching key found is the result. On failure substitutes the length of the array plus one, as discussed under the description of `tt(r)', or the empty string for an associative array. + +Note: Although `tt(i)' may be applied to a scalar substitution to find +the offset of a substring, the results are likely to be misleading when +searching within substitutions that yield an empty string, or when +searching for the empty substring. ) item(tt(I))( Like `tt(i)', but gives the index of the last match, or all possible diff --git a/Src/builtin.c b/Src/builtin.c index 26335a2e8..6d119f7a5 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -2491,6 +2491,8 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), return NULL; } } + if (isset(TYPESETTOUNSET)) + pm->node.flags |= PM_DEFAULTED; } else { if (idigit(*pname)) zerrnam(cname, "not an identifier: %s", pname); @@ -2836,7 +2838,7 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) unqueue_signals(); return 1; } else if (pm) { - if (!(pm->node.flags & PM_UNSET) + if ((!(pm->node.flags & PM_UNSET) || pm->node.flags & PM_DECLARED) && (locallevel == pm->level || !(on & PM_LOCAL))) { if (pm->node.flags & PM_TIED) { if (PM_TYPE(pm->node.flags) != PM_SCALAR) { @@ -2889,6 +2891,8 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) * * Don't attempt to set it yet, it's too early * to be exported properly. + * + * This may create the array with PM_DEFAULTED. */ asg2.name = asg->name; asg2.flags = 0; @@ -2930,8 +2934,12 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) if (asg->value.array) { int flags = (asg->flags & ASG_KEY_VALUE) ? ASSPM_KEY_VALUE : 0; assignaparam(asg->name, zlinklist2array(asg->value.array, 1), flags); - } else if (oldval) - assignsparam(asg0.name, oldval, 0); + } else if (asg0.value.scalar || oldval) { + /* We have to undo what we did wrong with asg2 */ + apm->node.flags &= ~PM_DEFAULTED; + if (oldval) + assignsparam(asg0.name, oldval, 0); + } unqueue_signals(); return 0; diff --git a/Src/options.c b/Src/options.c index 6ea6290e5..783022591 100644 --- a/Src/options.c +++ b/Src/options.c @@ -259,6 +259,7 @@ static struct optname optns[] = { {{NULL, "transientrprompt", 0}, TRANSIENTRPROMPT}, {{NULL, "trapsasync", 0}, TRAPSASYNC}, {{NULL, "typesetsilent", OPT_EMULATE|OPT_BOURNE}, TYPESETSILENT}, +{{NULL, "typesettounset", OPT_EMULATE|OPT_BOURNE}, TYPESETTOUNSET}, {{NULL, "unset", OPT_EMULATE|OPT_BSHELL}, UNSET}, {{NULL, "verbose", 0}, VERBOSE}, {{NULL, "vi", 0}, VIMODE}, diff --git a/Src/params.c b/Src/params.c index 122f5da7d..33bbc54f6 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2093,7 +2093,8 @@ fetchvalue(Value v, char **pptr, int bracks, int flags) if (sav) *s = sav; *pptr = s; - if (!pm || (pm->node.flags & PM_UNSET)) + if (!pm || ((pm->node.flags & PM_UNSET) && + !(pm->node.flags & PM_DECLARED))) return NULL; if (v) memset(v, 0, sizeof(*v)); @@ -3055,6 +3056,7 @@ assignsparam(char *s, char *val, int flags) * Don't warn about anything. */ flags &= ~ASSPM_WARN; + v->pm->node.flags &= ~PM_DEFAULTED; } *ss = '['; v = NULL; @@ -3080,6 +3082,7 @@ assignsparam(char *s, char *val, int flags) } if (flags & ASSPM_WARN) check_warn_pm(v->pm, "scalar", created, 1); + v->pm->node.flags &= ~PM_DEFAULTED; if (flags & ASSPM_AUGMENT) { if (v->start == 0 && v->end == -1) { switch (PM_TYPE(v->pm->node.flags)) { @@ -3232,6 +3235,7 @@ assignaparam(char *s, char **val, int flags) if (flags & ASSPM_WARN) check_warn_pm(v->pm, "array", created, may_warn_about_nested_vars); + v->pm->node.flags &= ~PM_DEFAULTED; /* * At this point, we may have array entries consisting of @@ -3444,6 +3448,7 @@ sethparam(char *s, char **val) return NULL; } check_warn_pm(v->pm, "associative array", checkcreate, 1); + v->pm->node.flags &= ~PM_DEFAULTED; setarrvalue(v, val); unqueue_signals(); return v->pm; @@ -3515,6 +3520,7 @@ assignnparam(char *s, mnumber val, int flags) if (flags & ASSPM_WARN) check_warn_pm(v->pm, "numeric", 0, 1); } + v->pm->node.flags &= ~PM_DEFAULTED; setnumvalue(v, val); unqueue_signals(); return v->pm; @@ -3619,6 +3625,7 @@ unsetparam_pm(Param pm, int altflag, int exp) else altremove = NULL; + pm->node.flags &= ~PM_DECLARED; /* like ksh, not like bash */ if (!(pm->node.flags & PM_UNSET)) pm->gsu.s->unsetfn(pm, exp); if (pm->env) @@ -3652,6 +3659,8 @@ unsetparam_pm(Param pm, int altflag, int exp) } zsfree(altremove); + if (!(pm->node.flags & PM_SPECIAL)) + pm->gsu.s = &stdscalar_gsu; } /* @@ -4116,6 +4125,11 @@ tiedarrsetfn(Param pm, char *x) if (*dptr->arrptr) freearray(*dptr->arrptr); + else if (pm->ename) { + Param altpm = (Param) paramtab->getnode(paramtab, pm->ename); + if (altpm) + altpm->node.flags &= ~PM_DEFAULTED; + } if (x) { char sepbuf[3]; if (imeta(dptr->joinchar)) @@ -5035,6 +5049,7 @@ arrfixenv(char *s, char **t) if (isset(ALLEXPORT)) pm->node.flags |= PM_EXPORTED; + pm->node.flags &= ~PM_DEFAULTED; /* * Do not "fix" parameters that were not exported @@ -5839,8 +5854,9 @@ printparamnode(HashNode hn, int printflags) Param peer = NULL; if (p->node.flags & PM_UNSET) { - if (printflags & (PRINT_POSIX_READONLY|PRINT_POSIX_EXPORT) && - p->node.flags & (PM_READONLY|PM_EXPORTED)) { + if ((printflags & (PRINT_POSIX_READONLY|PRINT_POSIX_EXPORT) && + p->node.flags & (PM_READONLY|PM_EXPORTED)) || + (p->node.flags & PM_DEFAULTED) == PM_DEFAULTED) { /* * Special POSIX rules: show the parameter as readonly/exported * even though it's unset, but with no value. diff --git a/Src/subst.c b/Src/subst.c index 96e0914eb..9928be0e9 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2563,7 +2563,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, * Handle the (t) flag: value now becomes the type * information for the parameter. */ - if (v && v->pm && !(v->pm->node.flags & PM_UNSET)) { + if (v && v->pm && ((v->pm->node.flags & PM_DECLARED) || + !(v->pm->node.flags & PM_UNSET))) { int f = v->pm->node.flags; switch (PM_TYPE(f)) { diff --git a/Src/zsh.h b/Src/zsh.h index d70a4017c..af9b4fb67 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1929,8 +1929,10 @@ struct tieddata { made read-only by the user */ #define PM_READONLY_SPECIAL (PM_SPECIAL|PM_READONLY|PM_RO_BY_DESIGN) #define PM_DONTIMPORT (1<<22) /* do not import this variable */ +#define PM_DECLARED (1<<22) /* explicitly named with typeset */ #define PM_RESTRICTED (1<<23) /* cannot be changed in restricted mode */ #define PM_UNSET (1<<24) /* has null value */ +#define PM_DEFAULTED (PM_DECLARED|PM_UNSET) #define PM_REMOVABLE (1<<25) /* special can be removed from paramtab */ #define PM_AUTOLOAD (1<<26) /* autoloaded from module */ #define PM_NORESTORE (1<<27) /* do not restore value of local special */ @@ -2536,6 +2538,7 @@ enum { TRANSIENTRPROMPT, TRAPSASYNC, TYPESETSILENT, + TYPESETTOUNSET, UNSET, VERBOSE, VIMODE, diff --git a/Test/D06subscript.ztst b/Test/D06subscript.ztst index c1a8d79cf..adbd398c4 100644 --- a/Test/D06subscript.ztst +++ b/Test/D06subscript.ztst @@ -289,3 +289,8 @@ F:Regression test for workers/42297 >14 24 >b b >b?rbaz foob?r + + i=1,3 + [[ ${a[$i]} = ${a[i]} ]] +0f:Math evaluation of commas in array subscripts +F:In math, (($i)) should be the same as ((i)), see workers/47748. diff --git a/Test/E01options.ztst b/Test/E01options.ztst index 415f46cd7..72749e6ab 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -1451,3 +1451,18 @@ F:If this test fails at the first unsetopt, refer to P01privileged.ztst. 0q:RM_STAR_SILENT *>zsh: sure you want to delete all 15 files in ${PWD:h}/options.tmp \[yn\]\? ${BEL}(|n) *>zsh: sure you want to delete (all <->|more than <->) files in / \[yn\]\? ${BEL}(|n) + + () { + local var + print ${(t)var} + } +0:(t) returns correct type +>scalar-local + + () { + readonly var + typeset -p var + } +0:readonly with typeset -p +F:compare E03posix.ztst +>typeset -r var='' diff --git a/Test/V10private.ztst b/Test/V10private.ztst index a3a63867b..03e8259d5 100644 --- a/Test/V10private.ztst +++ b/Test/V10private.ztst @@ -19,14 +19,14 @@ () { print $scalar_test private scalar_test - print $+scalar_test + typeset +m scalar_test unset scalar_test print $+scalar_test } print $scalar_test 0:basic scope hiding >toplevel ->1 +>local scalar_test >0 >toplevel @@ -45,14 +45,14 @@ print $+unset_test () { private unset_test - print $+unset_test + typeset +m unset_test unset_test=setme print $unset_test } print $+unset_test 0:variable defined only in scope >0 ->1 +>local unset_test >setme >0 @@ -62,13 +62,13 @@ local -Pa array_test=(in function) () { private array_test - print $+array_test + typeset +m array_test } print $array_test } print $array_test 0:nested scope with different type, correctly restored ->1 +>local array_test >in function >top level diff --git a/Test/runtests.zsh b/Test/runtests.zsh index 562234d91..b66d579b6 100644 --- a/Test/runtests.zsh +++ b/Test/runtests.zsh @@ -7,7 +7,7 @@ emulate zsh # protect from catastrophic failure of an individual test. # We could probably do that with subshells instead. -integer success failure skipped retval +integer success=0 failure=0 skipped=0 retval for file in "${(f)ZTST_testlist}"; do $ZTST_exe +Z -f $ZTST_srcdir/ztst.zsh $file retval=$? diff --git a/Test/ztst.zsh b/Test/ztst.zsh index e668ae942..a59c06dcf 100755 --- a/Test/ztst.zsh +++ b/Test/ztst.zsh @@ -60,7 +60,7 @@ ZTST_mainopts=(${(kv)options}) ZTST_testdir=$PWD ZTST_testname=$1 -integer ZTST_testfailed +integer ZTST_testfailed=0 # This is POSIX nonsense. Because of the vague feeling someone, somewhere # may one day need to examine the arguments of "tail" using a standard -- cgit v1.2.3 From b110d6d5afe2c8529799b4ebd433399f080bcdf0 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 7 Apr 2021 20:22:58 +0000 Subject: 48435 (tweaked): vcs_info docs: applied-string/unapplied-string: Correct an omission in the documentation and add an example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The example code is a reduced version of my function from workers/47519, with one bug fixed. (In workers/47519, if $1 doesn't contain spaces - which is the case under hg mq - then $H and $s will be set to the same value.) Tweaked: Extended the contrib.yo hunk with details about mq. --- ChangeLog | 4 ++++ Doc/Zsh/contrib.yo | 15 ++++++++++++--- Misc/vcs_info-examples | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 10447cccd..01f1eeb4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2021-04-20 Daniel Shahaf + * 48435 (tweaked): Doc/Zsh/contrib.yo, Misc/vcs_info-examples: + vcs_info docs: applied-string/unapplied-string: Correct an + omission in the documentation and add an example. + * 48528/0002: Misc/vcs_info-examples: vcs_info git docs: ahead/behind commits: Reduce the number of forks diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 3c4fdded0..8bf1a208e 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1652,10 +1652,17 @@ Called in the tt(git) (with tt(stgit) or during rebase or merge), and tt(hg) is generated; the tt(use-quilt) zstyle must be true for tt(quilt) (the tt(mq) and tt(stgit) backends are active by default). -This hook gets the names of all applied patches which tt(vcs_info) collected -so far in the opposite order, which means that the first argument is the +The arguments to this hook describe applied patches +in the opposite order, which means that the first argument is the top-most patch and so forth. +When the patches' log messages can be extracted, those are embedded +within each argument after a space, so each argument is of the form +`var(patch-name) var(first line of the log message)', where var(patch-name) +contains no whitespace. The tt(mq) backend passes arguments of +the form `var(patch name)', with possible embedded spaces, but without +extracting the patch's log message. + When setting tt(ret) to non-zero, the string in tt(${hook_com[applied-string]}) will be available as tt(%p) in the tt(patch-format) and tt(nopatch-format) styles. @@ -1669,9 +1676,11 @@ tt(mq)) backend and in tt(quilt) support when the tt(unapplied-string) is generated; the tt(get-unapplied) style must be true. This hook gets the names of all unapplied patches which tt(vcs_info) -collected so far in order, which means that the first argument is +in order, which means that the first argument is the patch next-in-line to be applied and so forth. +The format of each argument is as for tt(gen-applied-string), above. + When setting tt(ret) to non-zero, the string in tt(${hook_com[unapplied-string]}) will be available as tt(%u) in the tt(patch-format) and tt(nopatch-format) styles. diff --git a/Misc/vcs_info-examples b/Misc/vcs_info-examples index ba94cca29..edb0760d1 100644 --- a/Misc/vcs_info-examples +++ b/Misc/vcs_info-examples @@ -285,6 +285,54 @@ function +vi-hg-branchhead() { } +### Show information about patch series +# This is used with with hg mq, quilt, and git rebases and conflicts. +# +# All these cases have a notion of a "series of patches/commits" that is being +# applied. The following shows the information about the most recent patch to +# have been applied: +zstyle ':vcs_info:*+gen-applied-string:*' hooks gen-applied-string +function +vi-gen-applied-string() { + # Separate the patch id from the patch log message. + if [[ $1 == *\ * ]]; then + local patch_name_or_filename="${1%% *}" + local patch_description="${1#* }" + else + local patch_name_or_filename="$1" + local patch_description="" + fi + + # Apply escaping; see `Oddities' in the manual. + patch_name_or_filename=${patch_name_or_filename//'%'/%%} + patch_description=${patch_description//'%'/%%} + + # Apply different colouring to the patch description. + if [[ -n ${patch_description} ]]; then + patch_description="%F{yellow}${patch_description}%f" + fi + + # Re-assemble $1, escaped and coloured. + hook_com[applied-string]="${patch_name_or_filename} ${patch_description}" + ret=1 +} +# The value of hook_com[applied-string] is incorporated into the %m expando +# (see the 'patch-format' style for details), which is not included in the +# 'formats' and 'actionformats' style by default, so to actually use this, +# you'll need to add %m (or %Q under quilt in add-on mode) to your 'formats' +# and 'actionformats' styles, as in: +# +# zstyle ':vcs_info:*' actionformats ' (%s)-[%b|%a]%u%c- %m' +# zstyle ':vcs_info:*' formats ' (%s)-[%b]%u%c- %m' +# +# Or you could add it as a new word, as in: +# +# zstyle ':vcs_info:*' actionformats ' (%s)-[%b|%a]%u%c-' '%m' +# zstyle ':vcs_info:*' formats ' (%s)-[%b]%u%c-' '%m' +# +# In the latter case, you will need to arrange to print ${vcs_info_msg_1_} in +# addition to ${vcs_info_msg_0_}; see the top of this file for details. + + ### Run vcs_info selectively to increase speed in large repos ################ # The following example shows a possible setup for vcs_info which displays @@ -547,6 +595,9 @@ function +vi-set-quilt-patches() { # This would take care of all the dedicated-patches-directory-in-${HOME} # from earlier examples, too. +# Finally, the "Show information about patch series" example above this section +# may also be useful. + ### Using vcs_info from CVS ################################################## -- cgit v1.2.3 From 2da0d8b52fc90ce82891ae161fe6df89111c5e5c Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 3 May 2021 15:56:55 +0000 Subject: 48767: docs: $SECONDS: Clarify what types may be set --- ChangeLog | 5 +++++ Doc/Zsh/params.yo | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 17a385fcb..c522dfa80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-05-03 Daniel Shahaf + + * 48767: Doc/Zsh/params.yo: docs: $SECONDS: Clarify what types + may be set + 2021-04-28 Jun-ichi Takimoto * 48702: Completion/Unix/Command/_pandoc: do not use cache, diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index a9044336f..dc28a45ae 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -845,8 +845,9 @@ will be the value that was assigned plus the number of seconds since the assignment. Unlike other special parameters, the type of the tt(SECONDS) parameter can -be changed using the tt(typeset) command. Only integer and one of the -floating point types are allowed. For example, `tt(typeset -F SECONDS)' +be changed using the tt(typeset) command. The type may be changed only +to one of the floating point types or back to integer. For example, +`tt(typeset -F SECONDS)' causes the value to be reported as a floating point number. The value is available to microsecond accuracy, although the shell may show more or fewer digits depending on the use of tt(typeset). See -- cgit v1.2.3 From c23a0d84b029676832ea0f2eeb0caa8c47d0500d Mon Sep 17 00:00:00 2001 From: dana Date: Mon, 3 May 2021 18:08:11 -0500 Subject: 48614: getopts: Calculate OPTIND according to POSIX_BUILTINS --- ChangeLog | 6 ++++++ Doc/Zsh/builtins.yo | 3 ++- Doc/Zsh/options.yo | 3 ++- README | 3 +++ Src/builtin.c | 10 ++++++++++ Test/B10getopts.ztst | 29 +++++++++++++++++++++++++++++ 6 files changed, 52 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index c522dfa80..882b15ce9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2021-05-03 dana + + * 48614 (tweaked per 48630): Doc/Zsh/builtins.yo, + Doc/Zsh/options.yo, README, Src/builtin.c, Test/B10getopts.ztst: + Calculate OPTIND according to POSIX_BUILTINS + 2021-05-03 Daniel Shahaf * 48767: Doc/Zsh/params.yo: docs: $SECONDS: Clarify what types diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 61dc6986f..022921bfa 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -982,7 +982,8 @@ vindex(OPTARG, use of) The first option to be examined may be changed by explicitly assigning to tt(OPTIND). tt(OPTIND) has an initial value of tt(1), and is normally set to tt(1) upon entry to a shell function and restored -upon exit (this is disabled by the tt(POSIX_BUILTINS) option). tt(OPTARG) +upon exit. (The tt(POSIX_BUILTINS) option disables this, and also changes +the way the value is calculated to match other shells.) tt(OPTARG) is not reset and retains its value from the most recent call to tt(getopts). If either of tt(OPTIND) or tt(OPTARG) is explicitly unset, it remains unset, and the index or option argument is not diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 6e862fae8..546b16b65 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -2249,7 +2249,8 @@ command found in the path. Furthermore, the tt(getopts) builtin behaves in a POSIX-compatible fashion in that the associated variable tt(OPTIND) is not made -local to functions. +local to functions, and its value is calculated differently to match +other shells. Moreover, the warning and special exit code from tt([[ -o )var(non_existent_option)tt( ]]) are suppressed. diff --git a/README b/README index 76bf4ec35..3ef8afcd1 100644 --- a/README +++ b/README @@ -99,6 +99,9 @@ emulate sh: When zsh emulates sh, the final command in a pipeline is now run in a subshell. This differs from the behavior in the native (zsh) mode, but is consistent with most other sh implementations. +getopts now calculates OPTIND in a similar manner to other shells when the +POSIX_BUILTINS option is enabled. + Incompatibilities between 5.7.1 and 5.8 --------------------------------------- diff --git a/Src/builtin.c b/Src/builtin.c index efa20607e..b7ceefd55 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -5568,6 +5568,11 @@ bin_getopts(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int fun /* check for legality */ if(opch == ':' || !(p = memchr(optstr, opch, lenoptstr))) { p = "?"; + /* Keep OPTIND correct if the user doesn't return after the error */ + if (isset(POSIXBUILTINS)) { + optcind = 0; + zoptind++; + } zsfree(zoptarg); setsparam(var, ztrdup(p)); if(quiet) { @@ -5584,6 +5589,11 @@ bin_getopts(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int fun if(p[1] == ':') { if(optcind == lenstr) { if(!args[zoptind]) { + /* Fix OPTIND as above */ + if (isset(POSIXBUILTINS)) { + optcind = 0; + zoptind++; + } zsfree(zoptarg); if(quiet) { setsparam(var, ztrdup(":")); diff --git a/Test/B10getopts.ztst b/Test/B10getopts.ztst index 72c9e209e..e50d177c7 100644 --- a/Test/B10getopts.ztst +++ b/Test/B10getopts.ztst @@ -96,3 +96,32 @@ done 0:missing option-argument (quiet mode) >:,x + + # This function is written so it can be easily referenced against other shells + t() { + local o i=0 n=$1 + shift + while [ $i -lt $n ]; do + i=$(( i + 1 )) + getopts a: o "$@" 2> /dev/null + done + printf '<%d>' "$OPTIND" + } + # Try all these the native way, then the POSIX_BUILTINS way + for 1 in no_posix_builtins posix_builtins; do ( + setopt $1 + print -rn - "$1: " + t 1 + t 1 foo + t 1 -- foo + t 1 -a + t 1 -b + t 2 -a -b + t 4 -a -b -c -d -a + t 5 -a -b -c -a -b -c + t 5 -a -b -c -d -ax -a + print + ); done +0:OPTIND calculation with and without POSIX_BUILTINS (workers/42248) +>no_posix_builtins: <1><1><2><1><1><3><5><7><6> +>posix_builtins: <1><1><2><2><2><3><6><7><7> -- cgit v1.2.3 From d4b78f6c54af50cb4724785fbc72185932119941 Mon Sep 17 00:00:00 2001 From: dana Date: Mon, 3 May 2021 18:22:02 -0500 Subject: 48551: docs: Add disclaimer about POSIX compliance and emulation of other shells --- ChangeLog | 3 +++ Doc/Zsh/compat.yo | 6 ++++++ 2 files changed, 9 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 882b15ce9..dd9fa8050 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-05-03 dana + * 48551 (tweaked per 48565, 48629): Doc/Zsh/compat.yo: Add + disclaimer about POSIX compliance and emulation of other shells + * 48614 (tweaked per 48630): Doc/Zsh/builtins.yo, Doc/Zsh/options.yo, README, Src/builtin.c, Test/B10getopts.ztst: Calculate OPTIND according to POSIX_BUILTINS diff --git a/Doc/Zsh/compat.yo b/Doc/Zsh/compat.yo index f1be15fee..6e4dbcfa4 100644 --- a/Doc/Zsh/compat.yo +++ b/Doc/Zsh/compat.yo @@ -74,3 +74,9 @@ tt(PROMPT_SUBST) and tt(SINGLE_LINE_ZLE) options are set if zsh is invoked as tt(ksh). + +Please note that, whilst reasonable efforts are taken to address +incompatibilities when they arise, zsh does not guarantee complete +emulation of other shells, nor POSIX compliance. For more information on +the differences between zsh and other shells, please refer to chapter 2 +of the shell FAQ, uref(https://www.zsh.org/FAQ/). -- cgit v1.2.3 From 093ba119702561a4ec255ca5893eb44aae2f7f6e Mon Sep 17 00:00:00 2001 From: dana Date: Mon, 3 May 2021 18:26:19 -0500 Subject: unposted: docs: Update http:// FAQ links to https:// See 48613 --- ChangeLog | 3 +++ Doc/Zsh/metafaq.yo | 2 +- Doc/Zsh/roadmap.yo | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index dd9fa8050..399acc385 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-05-03 dana + * unposted (see 48613): Doc/Zsh/metafaq.yo, Doc/Zsh/roadmap.yo: + Update http:// FAQ links to https:// + * 48551 (tweaked per 48565, 48629): Doc/Zsh/compat.yo: Add disclaimer about POSIX compliance and emulation of other shells diff --git a/Doc/Zsh/metafaq.yo b/Doc/Zsh/metafaq.yo index ca7f26adf..4cefa4d71 100644 --- a/Doc/Zsh/metafaq.yo +++ b/Doc/Zsh/metafaq.yo @@ -86,7 +86,7 @@ Zsh has a list of Frequently Asked Questions (FAQ), maintained by Peter Stephenson tt(). It is regularly posted to the newsgroup bf(comp.unix.shell) and the bf(zsh-announce) mailing list. The latest version can be found at any of the Zsh FTP sites, or at -uref(http://www.zsh.org/FAQ/). The contact address for FAQ-related matters +uref(https://www.zsh.org/FAQ/). The contact address for FAQ-related matters is tt(). texinode(The Zsh Web Page)(The Zsh Userguide)(The Zsh FAQ)(Introduction) sect(The Zsh Web Page) diff --git a/Doc/Zsh/roadmap.yo b/Doc/Zsh/roadmap.yo index 94ef74d1f..3f9a122af 100644 --- a/Doc/Zsh/roadmap.yo +++ b/Doc/Zsh/roadmap.yo @@ -49,7 +49,7 @@ The shell now supports the UTF-8 character set (and also others if supported by the operating system). This is (mostly) handled transparently by the shell, but the degree of support in terminal emulators is variable. There is some discussion of this in the shell FAQ, -uref(http://www.zsh.org/FAQ/). Note in particular that for combining +uref(https://www.zsh.org/FAQ/). Note in particular that for combining characters to be handled the option tt(COMBINING_CHARS) needs to be set. Because the shell is now more sensitive to the definition of the character set, note that if you are upgrading from an older version of -- cgit v1.2.3 From 231c049c022963f65f869b9c12e763473207b42a Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sat, 15 May 2021 13:23:31 -0700 Subject: 48707: fix keymap handling when zed invokes read-from-minibuffer; update doc --- ChangeLog | 5 +++++ Doc/Zsh/contrib.yo | 21 +++++++++++---------- Functions/Zle/zed-set-file-name | 27 ++++++++++++++++++++++----- 3 files changed, 38 insertions(+), 15 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 9392e39d9..63341d2bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-05-15 Bart Schaefer + + * 48707: Doc/Zsh/contrib.yo, Functions/Zle/zed-set-file-name: + fix keymap handling when zed invokes read-from-minibuffer + 2021-05-06 Peter Stephenson * 48787: Src/loop.c, Test/A01grammar.ztst: status was incorrect diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 8bf1a208e..da7ab2a7c 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -4534,16 +4534,17 @@ suitable for putting into a startup file. Note that, if rerun, this will overwrite the existing tt(zed) and tt(zed-vicmd) keymaps. Completion is available, and styles may be set with the context prefix -`tt(:completion:zed)'. - -A zle widget tt(zed-set-file-name) is available. This can be called by -name from within zed using `tt(\ex zed-set-file-name)' (note, however, that -because of zed's rebindings you will have to type tt(^j) at the end instead -of the return key), or can be bound to a key in either of the tt(zed) or -tt(zed-vicmd) keymaps after `tt(zed -b)' has been run. When the widget is -called, it prompts for a new name for the file being edited. When zed -exits the file will be written under that name and the original file will -be left alone. The widget has no effect with `tt(zed -f)'. +`tt(:completion:zed:)'. + +findex(zed-set-file-name) +A zle widget tt(zed-set-file-name) is available. This can be called +by name from within zed using `tt(\ex zed-set-file-name)' or can be +bound to a key in either of the tt(zed) or tt(zed-vicmd) keymaps after +`tt(zed -b)' has been run. When the widget is called, it prompts for +a new name for the file being edited. When zed exits the file will be +written under that name and the original file will be left alone. The +widget has no effect when invoked from `tt(zed -f)'. The completion +context is changed to `tt(:completion:zed-set-file-name:)'. While tt(zed-set-file-name) is running, zed uses the keymap tt(zed-normal-keymap), which is linked from the main keymap in effect diff --git a/Functions/Zle/zed-set-file-name b/Functions/Zle/zed-set-file-name index da3421e71..745610660 100644 --- a/Functions/Zle/zed-set-file-name +++ b/Functions/Zle/zed-set-file-name @@ -2,8 +2,25 @@ emulate -L zsh autoload -Uz read-from-minibuffer -zle -K zed-normal-keymap - -local REPLY -read-from-minibuffer "File name: " -zed_file_name=$REPLY +case $curcontext in + (zed:::) + local curcontext=zed-set-file-name::: + # The call to vared from zed does the equivalent of + # bindkey -A zed main + # which confuses read-from-minibuffer. Fix it. + bindkey -A zed-normal-keymap main;; + (zed-set-file-name:::) + zle -M "zed-set-file-name: may not be called recursively" + return 1;; + (*) + zle -M "zed-set-file-name: not called from within zed" + return 1;; +esac +{ + local REPLY + read-from-minibuffer "File name: " + zed_file_name=$REPLY +} always { + # Re-install the zed keymap in the way vared should have all along + zle -K zed +} -- cgit v1.2.3 From acd20254b58ea689d8046ff127bc320d5fa91cf6 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sat, 15 May 2021 13:37:35 -0700 Subject: 48710: histed + other zed updates --- ChangeLog | 4 +++ Completion/Zsh/Command/_zed | 16 ++++++++---- Doc/Zsh/contrib.yo | 21 +++++++++++++-- Functions/Misc/zed | 62 +++++++++++++++++++++++++++++++++++---------- 4 files changed, 83 insertions(+), 20 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 52fd4be27..973455232 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2021-05-15 Bart Schaefer + * 48710: Completion/Zsh/Command/_zed, Doc/Zsh/contrib.yo, + Functions/Misc/zed: add "zed -h" aka "histed", update doc and + completion; improve compatibility with SH_WORD_SPLIT + * 48709: Completion/Base/Widget/_complete_help: suppress error messages from comptry diff --git a/Completion/Zsh/Command/_zed b/Completion/Zsh/Command/_zed index 6b68fadf0..f84993d73 100644 --- a/Completion/Zsh/Command/_zed +++ b/Completion/Zsh/Command/_zed @@ -1,10 +1,16 @@ -#compdef zed fned +#compdef zed fned histed case $service in (fned) _arguments -S : ':shell function:_functions';; +(histed) _arguments -S : \ + '1:history file:_files' \ + '2:history size: ';; (zed) _arguments -S : \ - '(- 2):file:_files' \ - '(1):shell function:_functions' \ - '(1)-x+[specify spaces to use for indentation in function expansion]:spaces' \ - '(1)-f[edit function]';; + '(-h 1 3 4)-f[edit function]' \ + '(-h 1 3 4)-x+[specify spaces to use for indentation in function expansion]:spaces' \ + '(-f -x 1 2)-h[edit history]' \ + '(- 2 3 4)1:file:_files' \ + '(3 4)2:shell function:_functions' \ + '3:history file:_files -g "*(D)"' \ + '4:history size';; esac diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index da7ab2a7c..b777703b3 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -4295,6 +4295,12 @@ Same as tt(zed -f). This function does not appear in the zsh distribution, but can be created by linking tt(zed) to the name tt(fned) in some directory in your tt(fpath). ) +findex(histed) +item(tt(histed) [ [ var(name) ] var(size) ])( +Same as tt(zed -h). This function does not appear in the zsh +distribution, but can be created by linking tt(zed) to the name tt(histed) +in some directory in your tt(fpath). +) findex(is-at-least) item(tt(is-at-least) var(needed) [ var(present) ])( Perform a greater-than-or-equal-to comparison of two strings having the @@ -4504,6 +4510,7 @@ tt(zargs) with the tt(-)tt(-help) option. ) findex(zed) xitem(tt(zed) [ tt(-f) [ tt(-x) var(num) ] ] var(name)) +xitem(tt(zed) [ tt(-h) [ var(name) ] var(size) ]) item(tt(zed -b))( This function uses the ZLE editor to edit a file or function. @@ -4518,7 +4525,14 @@ the given number of spaces; `tt(-x 2)' is consistent with the layout of functions distributed with the shell. Without tt(-f), var(name) is the path name of the file to edit, which need -not exist; it is created on write, if necessary. +not exist; it is created on write, if necessary. With tt(-h), the file is +presumed to contain history events. + +When no file name is provided for tt(-h) the current shell history is edited +in place. The history is renumbered when zed exits successfully. + +When editing history, multi-line events must have a trailing backslash on +every line before the last. While editing, the function sets the main keymap to tt(zed) and the vi command keymap to tt(zed-vicmd). These will be copied from the existing @@ -4544,7 +4558,10 @@ bound to a key in either of the tt(zed) or tt(zed-vicmd) keymaps after a new name for the file being edited. When zed exits the file will be written under that name and the original file will be left alone. The widget has no effect when invoked from `tt(zed -f)'. The completion -context is changed to `tt(:completion:zed-set-file-name:)'. +context is changed to `tt(:completion:zed-set-file-name:)'. When editing +the current history with `tt(zed -h)', the history is first updated and +then the file is written, but the global setting of tt(HISTFILE) is not +altered. While tt(zed-set-file-name) is running, zed uses the keymap tt(zed-normal-keymap), which is linked from the main keymap in effect diff --git a/Functions/Misc/zed b/Functions/Misc/zed index 9eb4b2d93..7d0d590db 100644 --- a/Functions/Misc/zed +++ b/Functions/Misc/zed @@ -5,16 +5,18 @@ # Edit small files with the command line editor. # Use ^X^W to save (or ZZ in vicmd mode), ^C to abort. # Option -f: edit shell functions. (Also if called as fned.) +# Option -h: edit shell history. (Also if called as histed.) setopt localoptions noksharrays local var opts zed_file_name # We do not want timeout while we are editing a file -integer TMOUT=0 okargs=1 fun bind +integer TMOUT=0 okargs=1 fun hist bind local -a expand -zparseopts -D -A opts f b x: +zparseopts -D -A opts f h b x: fun=$+opts[-f] +hist=$+opts[-h] bind=$+opts[-b] if [[ $opts[-x] == <-> ]]; then expand=(-x $opts[-x]) @@ -24,23 +26,28 @@ elif (( $+opts[-x] )); then fi [[ $0 = fned ]] && fun=1 +[[ $0 = histed ]] && hist=1 +(( hist && $# <= 2 )) && okargs=$# (( bind )) && okargs=0 -if (( $# != okargs )); then +if (( $# != okargs || bind + fun + hist > 1 )); then echo 'Usage: zed filename zed -f [ -x N ] function +zed -h [ filename [ size ] ] zed -b' >&2 return 1 fi local curcontext=zed::: -# Matching used in zstyle -m: hide result from caller. -# Variables not used directly here. -local -a match mbegin mend -zstyle -m ":completion:zed:*" insert-tab '*' || - zstyle ":completion:zed:*" insert-tab yes +() { + # Matching used in zstyle -m: hide result from caller. + # Variables not used directly here. + local -a match mbegin mend + zstyle -m ":completion:zed:*" insert-tab '*' || + zstyle ":completion:zed:*" insert-tab yes +} zmodload zsh/terminfo 2>/dev/null @@ -124,22 +131,51 @@ fi setopt localoptions nobanghist if ((fun)) then - var="$(functions $expand -- $1)" + var="$(functions $expand -- "$1")" # If function is undefined but autoloadable, load it if [[ $var = *\#\ undefined* ]] then - var="$(autoload +X $1; functions -- $1)" + var="$(autoload +X "$1"; functions -- "$1")" elif [[ -z $var ]] then var="${(q-)1} () { }" fi vared -M zed -m zed-vicmd -i __zed_init var && eval function "$var" +elif ((hist)) then + if [[ -n $1 ]]; then + { fc -p -a "$1" ${2:-$({ wc -l <"$1" } 2>/dev/null)} || return } + let HISTSIZE++ + print -s "" # Work around fc -p limitation + fi + # When editing the current shell history, the "zed -h" command is not + # itself included because the current event is not added to the ring + # until the next prompt is printed. This means "zed -h" is prepended + # to the result of the edit, because of the way "print -s" is defined. + var=( "${(@Oav)history}" ) + IFS=$'\n' vared -M zed -m zed-vicmd -i __zed_init var + if (( ? )); then + [[ -n $1 ]] && unset HISTFILE + else + local HISTSIZE=0 savehist=$#var + fc -R /dev/null # Remove entries other than those added here + HISTSIZE=$savehist # Resets on function exit because local + [[ -n $1 ]] && SAVEHIST=$savehist # Resets via foregoing fc -a + for (( hist=1; hist <= savehist; hist++ )) + do print -rs -- "$var[hist]" + done + if [[ -n $zed_file_name ]]; then + fc -W "$zed_file_name" + [[ -n $1 ]] && unset HISTFILE + fi + # Note prepend effect when global HISTSIZE greater than $savehist. + # This does not affect file editing. + fi else - zed_file_name=$1 - [[ -f $1 ]] && var="$(<$1)" + zed_file_name="$1" + [[ -f $1 ]] && var="$(<"$1")" while vared -M zed -m zed-vicmd -i __zed_init var do { - print -r -- "$var" >| $zed_file_name + print -r -- "$var" >| "$zed_file_name" } always { (( TRY_BLOCK_ERROR = 0 )) } && break -- cgit v1.2.3 From 7383baf4cff9a1621b9b5517689a5653ae86e123 Mon Sep 17 00:00:00 2001 From: Marlon Richert Date: Sun, 16 May 2021 21:18:06 -0700 Subject: 48853: improved handling of theme resets when changing prompt themes, especially for theme preview --- ChangeLog | 4 ++ Doc/Zsh/contrib.yo | 10 +-- Functions/Prompts/promptinit | 165 +++++++++++++++++++------------------------ 3 files changed, 81 insertions(+), 98 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 7a50c3529..0eca118a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2021-05-16 Bart Schaefer + * Marlon Richert: 48853: Doc/Zsh/contrib.yo, + Functions/Prompts/promptinit: improved handling of theme resets + when changing prompt themes, especially for theme preview + * 48860: Etc/BUGS: remove mention of bugs that were fixed * 48857: Src/builtin.c, Src/exec.c, Src/loop.c, Src/makepro.awk, diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index b777703b3..a972f08d6 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2041,10 +2041,12 @@ setopts (tt(promptbang), etc.) are turned on, all other prompt-related options are turned off. The tt(prompt_opts) array preserves setopts even beyond the scope of tt(localoptions), should your function need that. ) -item(Modify precmd and preexec)( -Use of tt(add-zsh-hook) is recommended. The tt(precmd) and tt(preexec) -hooks are automatically adjusted if the prompt theme changes or is -disabled. +item(Modify hooks)( +Use of tt(add-zsh-hook) and tt(add-zle-hook-widget) is recommended (see +ifzman(the bf(Manipulating Hook Functions) section above)\ +ifnzman(noderef(Manipulating Hook Functions))\ +). All hooks that follow the naming pattern tt(prompt_)var(theme)tt(_)var(hook) +are automatically removed when the prompt theme changes or is disabled. ) item(Declare cleanup)( If your function makes any other changes that should be undone when the diff --git a/Functions/Prompts/promptinit b/Functions/Prompts/promptinit index 37d69f100..20503d78b 100644 --- a/Functions/Prompts/promptinit +++ b/Functions/Prompts/promptinit @@ -14,6 +14,8 @@ prompt_themes=() promptinit () { emulate -L zsh setopt extendedglob + autoload -Uz add-zsh-hook add-zle-hook-widget + local ppath='' name theme local -a match mbegin mend @@ -32,9 +34,6 @@ promptinit () { fi done - # To manipulate precmd and preexec hooks... - autoload -Uz add-zsh-hook - # Variables common to all prompt styles prompt_newline=$'\n%{\r%}' } @@ -47,38 +46,23 @@ prompt_preview_safely() { return fi - # This handles all the stuff from the default :prompt-theme restore - local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1 RPS2=$RPS2 - local +h PROMPT=$PROMPT RPROMPT=$RPROMPT RPROMPT2=$RPROMPT2 PSVAR=$PSVAR - local -a precmd_functions preexec_functions prompt_preview_restore - local -aLl +h zle_highlight + # Run this in a subshell, so we don't need to clean up afterwards. + ( + # Execute current theme's cleanup sequence, if any. + zstyle -t :prompt-theme cleanup - { - # Save and clear current restore-point if any - zstyle -g prompt_preview_restore :prompt-theme restore - { - zstyle -d :prompt-theme restore - # Execute current cleanup sequence, if any. - zstyle -t :prompt-theme cleanup - - # The next line is a bit ugly. It (perhaps unnecessarily) - # runs the prompt theme setup function to ensure that if - # the theme has a _preview function that it's been autoloaded. + # If we can't find a _preview function, run the _setup function to see if + # it will create one. + typeset +f prompt_${1}_preview >&/dev/null || prompt_${1}_setup - if typeset +f prompt_${1}_preview >&/dev/null; then - prompt_${1}_preview "$@[2,-1]" - else - prompt_preview_theme "$@" - fi - } always { - # Run any theme-specific cleanup, then reset restore point - zstyle -t :prompt-theme cleanup - } - } always { - (( $#prompt_preview_restore )) && - zstyle -e :prompt-theme restore "${prompt_preview_restore[@]}" - } + # ...then try again. + if typeset +f prompt_${1}_preview >&/dev/null; then + prompt_${1}_preview "$@[2,-1]" + else + prompt_preview_theme "$@" + fi + ) } set_prompt() { @@ -97,21 +81,6 @@ Options: Use prompt -h for help on specific themes.' getopts "chlps:" opt - case "$opt" in - (h|p) - setopt localtraps - if [[ -z "$prompt_theme[1]" ]]; then - # Not using a prompt theme; save settings - local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1 RPS2=$RPS2 - local +h PROMPT=$PROMPT RPROMPT=$RPROMPT RPROMPT2=$RPROMPT2 PSVAR=$PSVAR - local -a precmd_functions preexec_functions - local theme_reset='' - else - local theme_reset='prompt_${prompt_theme[1]}_setup "${(@)prompt_theme[2,-1]}"' - fi - trap 'zstyle -t :prompt-theme cleanup;'"${theme_reset:+ $theme_reset}" 0 - ;; - esac case "$opt" in c) if [[ -n $prompt_theme ]]; then print -n "Current prompt theme" @@ -123,21 +92,26 @@ Use prompt -h for help on specific themes.' return ;; h) if [[ -n "$2" && -n $prompt_themes[(r)$2] ]]; then - if functions prompt_$2_setup >/dev/null; then + # Run this in a subshell, so we don't need to clean up afterwards. + ( + # Execute current theme's cleanup sequence, if any. zstyle -t :prompt-theme cleanup - # The next line is a bit ugly. It (perhaps unnecessarily) - # runs the prompt theme setup function to ensure that if - # the theme has a _help function that it's been autoloaded. - prompt_$2_setup - fi - if functions prompt_$2_help >/dev/null; then - print "Help for $2 theme:\n" - prompt_$2_help - else - print "No help available for $2 theme." - fi - print "\nType \`prompt -p $2' to preview the theme, \`prompt $2'" - print "to try it out, and \`prompt -s $2' to use it in future sessions." + + # If we can't find a _help function, run the _setup function to see + # if it will create one. + typeset +f prompt_$2_help >/dev/null || + prompt_$2_setup + + # ...then try again. + if typeset +f prompt_$2_help >/dev/null; then + print "Help for $2 theme:\n" + prompt_$2_help + else + print "No help available for $2 theme." + fi + print "\nType \`prompt -p $2' to preview the theme, \`prompt $2'" + print "to try it out, and \`prompt -s $2' to use it in future sessions." + ) else print "$usage" fi @@ -178,8 +152,13 @@ Use prompt -h for help on specific themes.' # Reset some commonly altered bits to the default local hook - for hook in chpwd precmd preexec periodic zshaddhistory zshexit; do - add-zsh-hook -D "${hook}" "prompt_*_${hook}" + for hook in chpwd precmd preexec periodic zshaddhistory zshexit \ + zsh_directory_name; do + add-zsh-hook -D "$hook" "prompt_*_$hook" + done + for hook in isearch-exit isearch-update line-pre-redraw line-init \ + line-finish history-line-set keymap-select; do + add-zle-hook-widget -D "$hook" "prompt_*_$hook" done typeset -ga zle_highlight=( ${zle_highlight:#default:*} ) (( ${#zle_highlight} )) || unset zle_highlight @@ -192,11 +171,8 @@ Use prompt -h for help on specific themes.' prompt_cleanup () { local -a cleanup_hooks theme_active - if ! zstyle -g cleanup_hooks :prompt-theme cleanup - then - (( $+prompt_preview_restore == 0 )) && - if ! zstyle -g theme_active :prompt-theme restore - then + if ! zstyle -g cleanup_hooks :prompt-theme cleanup; then + if ! zstyle -g theme_active :prompt-theme restore; then print -u2 "prompt_cleanup: no prompt theme active" return 1 fi @@ -225,22 +201,21 @@ prompt () { [[ -o promptpercent ]] && prompt_opts+=(percent) [[ -o promptsp ]] && prompt_opts+=(sp) [[ -o promptsubst ]] && prompt_opts+=(subst) - zstyle -e :prompt-theme restore \ - 'zstyle -d :prompt-theme restore;' \ - 'prompt_default_setup;' \ - ${PS1+PS1="${(q)PS1}"} \ - ${PS2+PS2="${(q)PS2}"} \ - ${PS3+PS3="${(q)PS3}"} \ - ${PS4+PS4="${(q)PS4}"} \ - ${RPS1+RPS1="${(q)RPS1}"} \ - ${RPS2+RPS2="${(q)RPS2}"} \ - ${RPROMPT+RPROMPT="${(q)RPROMPT}"} \ - ${RPROMPT2+RPROMPT2="${(q)RPROMPT2}"} \ - ${PSVAR+PSVAR="${(q)PSVAR}"} \ - "precmd_functions=(${(q)precmd_functions[@]})" \ - "preexec_functions=(${(q)preexec_functions[@]})" \ - "prompt_opts=( ${prompt_opts[*]} )" \ - 'reply=(yes)' + zstyle -e :prompt-theme restore " + zstyle -d :prompt-theme restore + prompt_default_setup + ${PS1+PS1=${(q+)PS1}} + ${PS2+PS2=${(q+)PS2}} + ${PS3+PS3=${(q+)PS3}} + ${PS4+PS4=${(q+)PS4}} + ${RPS1+RPS1=${(q+)RPS1}} + ${RPS2+RPS2=${(q+)RPS2}} + ${RPROMPT+RPROMPT=${(q+)RPROMPT}} + ${RPROMPT2+RPROMPT2=${(q+)RPROMPT2}} + ${PSVAR+PSVAR=${(q+)PSVAR}} + prompt_opts=( $prompt_opts[*] ) + reply=( yes ) + " } set_prompt "$@" @@ -253,12 +228,6 @@ prompt () { prompt_preview_theme () { emulate -L zsh - # Check for proper state handling - (( $+prompt_preview_restore )) || { - prompt_preview_safely "$@" - return - } - # Minimal preview for prompts that don't supply one local -a prompt_opts print -n "$1 theme" @@ -268,12 +237,20 @@ prompt_preview_theme () { prompt_${1}_setup "$@[2,-1]" (( ${#prompt_opts} )) && setopt noprompt{bang,cr,percent,sp,subst} "prompt${^prompt_opts[@]}" + + [[ -n ${chpwd_functions[(r)prompt_${1}_chpwd]} ]] && + prompt_${1}_chpwd [[ -n ${precmd_functions[(r)prompt_${1}_precmd]} ]] && - prompt_${1}_precmd - [[ -o promptcr ]] && print -n $'\r'; : - print -P "${PS1}command arg1 arg2 ... argn" + prompt_${1}_precmd + + # We'd like to call zle-line-init/finish hooks, too, but that's not possible + # while the ZLE is not active. + + [[ -o promptcr ]] && print -n $'\r' + :; print -P -- "${PS1}command arg1 arg2 ... argn" + [[ -n ${preexec_functions[(r)prompt_${1}_preexec]} ]] && - prompt_${1}_preexec + prompt_${1}_preexec } [[ -o kshautoload ]] || promptinit "$@" -- cgit v1.2.3 From 6913eb677684e679487ca4462f693d1008052b82 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 16 Apr 2021 17:33:52 +0000 Subject: 48601/0001: docs: functions -M: Move an example to be near the specification of the relevant flag --- ChangeLog | 3 +++ Doc/Zsh/builtins.yo | 13 ++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index fe375b093..e2999b051 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-05-18 Daniel Shahaf + * 48601/0001: Doc/Zsh/builtins.yo: docs: functions -M: Move an + example to be near the specification of the relevant flag + * 48594 (plus an "F:" line corresponding to the question there): Test/E02xtrace.ztst: New tests for functions -t / functions -T diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 022921bfa..03fc69a04 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -924,6 +924,12 @@ opening and matching closing parenthesis is passed to the function as a single argument, even if it includes commas or white space. The minimum and maximum argument specifiers must therefore be 1 if given. An empty argument list is passed as a zero-length string. +Thus, the following string function takes a single argument, including +the commas, and prints 11: + +example(stringfn+LPAR()RPAR() { (( $#1 )) } +functions -Ms stringfn +print $(( stringfn+LPAR()foo,bar,rod+RPAR() ))) tt(functions -M) with no arguments lists all such user-defined functions in the same form as a definition. With the additional option tt(-m) and @@ -941,13 +947,6 @@ For example, the following prints the cube of 3: example(zmath_cube+LPAR()RPAR() { (( $1 * $1 * $1 )) } functions -M cube 1 1 zmath_cube print $(( cube+LPAR()3+RPAR() ))) - -The following string function takes a single argument, including -the commas, so prints 11: - -example(stringfn+LPAR()RPAR() { (( $#1 )) } -functions -Ms stringfn -print $(( stringfn+LPAR()foo,bar,rod+RPAR() ))) ) module(getcap)(zsh/cap) findex(getln) -- cgit v1.2.3 From f571aff1b2d56d8354ba2530eca30dd45785c714 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 16 Apr 2021 18:03:30 +0000 Subject: 48601/0002: docs: functions -M: Document the return status / result interdependency gotchas (cf. 48147). --- ChangeLog | 3 +++ Doc/Zsh/builtins.yo | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 10 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index e2999b051..6381e4f4a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-05-18 Daniel Shahaf + * 48601/0002: Doc/Zsh/builtins.yo: docs: functions -M: Document + the return status / result interdependency gotchas (cf. 48147). + * 48601/0001: Doc/Zsh/builtins.yo: docs: functions -M: Move an example to be near the specification of the relevant flag diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 03fc69a04..51b1f1744 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -914,9 +914,53 @@ expressions. The name of the function in tt($0) is var(mathfn) (not var(shellfn) as would usually be the case), provided the option tt(FUNCTION_ARGZERO) is in effect. The positional parameters in the shell function correspond to the arguments of the mathematical function call. -The result of the last arithmetical expression evaluated -inside the shell function (even if it is a form that normally only returns -a status) gives the result of the mathematical function. + +The result of the last arithmetical expression evaluated inside the shell +function gives the result of the mathematical function. This is not limited to +arithmetic substitutions of the form tt($+LPAR()+LPAR())var(...)tt(+RPAR()+RPAR()), +but also includes arithmetical expressions evaluated in any other way, including +by the tt(let) builtin, +by tt(+LPAR()+LPAR())var(...)tt(+RPAR()+RPAR()) statements, +and even +by the tt(return) builtin +and +by array subscripts. +Therefore, care must be taken not to use syntactical constructs that perform +arithmetic evaluation after evaluating what is to be the result of the function. +For example: + +example(# WRONG +zmath_cube+LPAR()+RPAR() { + (( $1 * $1 * $1 )) + return 0 +} +functions -M cube 1 1 zmath_cube +print $(( cube+LPAR()3+RPAR() ))) + +This will print `tt(0)' because of the tt(return). + +Commenting the tt(return) out would lead to a different problem: the +tt(+LPAR()+LPAR())var(...)tt(+RPAR()+RPAR()) statement would become +the last statement in the function, so the em(return status) (tt($?)) of the +function would be non-zero (indicating failure) whenever the em(arithmetic +result) of the function would happen to be zero (numerically): + +example(# WRONG +zmath_cube+LPAR()+RPAR() { + (( $1 * $1 * $1 )) +} +functions -M cube 1 1 zmath_cube +print $(( cube+LPAR()0+RPAR() ))) + +Instead, the tt(true) builtin can be used: + +example(# RIGHT +zmath_cube+LPAR()+RPAR() { + (( $1 * $1 * $1 )) + true +} +functions -M cube 1 1 zmath_cube +print $(( cube+LPAR()3+RPAR() ))) If the additional option tt(-s) is given to tt(functions -M), the argument to the function is a single string: anything between the @@ -927,7 +971,7 @@ argument list is passed as a zero-length string. Thus, the following string function takes a single argument, including the commas, and prints 11: -example(stringfn+LPAR()RPAR() { (( $#1 )) } +example(stringfn+LPAR()RPAR() { (( $#1 )); true } functions -Ms stringfn print $(( stringfn+LPAR()foo,bar,rod+RPAR() ))) @@ -941,12 +985,6 @@ additional option tt(-m) the arguments are treated as patterns and all functions whose var(mathfn) matches the pattern are removed. Note that the shell function implementing the behaviour is not removed (regardless of whether its name coincides with var(mathfn)). - -For example, the following prints the cube of 3: - -example(zmath_cube+LPAR()RPAR() { (( $1 * $1 * $1 )) } -functions -M cube 1 1 zmath_cube -print $(( cube+LPAR()3+RPAR() ))) ) module(getcap)(zsh/cap) findex(getln) -- cgit v1.2.3 From b992d91059b0a6bf2da7519aafcab9dff865498c Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 16 Apr 2021 18:03:45 +0000 Subject: 48601/0003: docs: functions -M: Add a subheading and index entries. --- ChangeLog | 3 +++ Doc/Zsh/builtins.yo | 6 ++++++ 2 files changed, 9 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 6381e4f4a..b9ffd9471 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-05-18 Daniel Shahaf + * 48601/0003: Doc/Zsh/builtins.yo: docs: functions -M: Add a + subheading and index entries. + * 48601/0002: Doc/Zsh/builtins.yo: docs: functions -M: Document the return status / result interdependency gotchas (cf. 48147). diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 51b1f1744..0129c6b57 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -893,6 +893,10 @@ without affecting the other. A typical idiom is that var(oldfn) is the name of a library shell function which is then redefined to call tt(newfn), thereby installing a modified version of the function. +em(The )tt(-M)em( and )tt(+M)em( flags) +cindex(defining mathematical functions) +cindex(functions, defining mathematical) + Use of the tt(-M) option may not be combined with any of the options handled by tt(typeset -f). @@ -929,6 +933,8 @@ Therefore, care must be taken not to use syntactical constructs that perform arithmetic evaluation after evaluating what is to be the result of the function. For example: +findex(zmath_cube) +findex(cube) example(# WRONG zmath_cube+LPAR()+RPAR() { (( $1 * $1 * $1 )) -- cgit v1.2.3 From 4202c0bbe35fbdc2c93b4bfe97dfe52db1b0331e Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 16 Apr 2021 18:04:13 +0000 Subject: 48601/0004: docs: return: Give examples of using arithmetic evaluation. --- ChangeLog | 3 +++ Doc/Zsh/builtins.yo | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index b9ffd9471..38ce503a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-05-18 Daniel Shahaf + * 48601/0004: Doc/Zsh/builtins.yo: docs: return: Give examples + of using arithmetic evaluation. + * 48601/0003: Doc/Zsh/builtins.yo: docs: functions -M: Add a subheading and index entries. diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 0129c6b57..f8e11d79d 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -1627,7 +1627,13 @@ cindex(functions, returning from) item(tt(return) [ var(n) ])( Causes a shell function or `tt(.)' script to return to the invoking script with the return status specified by -an arithmetic expression var(n). If var(n) +an arithmetic expression var(n). +For example, the following prints `tt(42)': + +example(() { integer foo=40; return "foo + 2" } +echo $?) + +If var(n) is omitted, the return status is that of the last command executed. @@ -1638,7 +1644,7 @@ will return to whatever it was previously processing; with a non-zero status, the shell will behave as interrupted except that the return status of the trap is retained. Note that the numeric value of the signal which caused the trap is passed as the first argument, so the statement -`tt(return $((128PLUS()$1)))' will return the same status as if the signal +`tt(return "128PLUS()$1")' will return the same status as if the signal had not been trapped. ) module(sched)(zsh/sched) -- cgit v1.2.3 From 667901b6ba8ea7871bfdb6364fb14cbcb70536b4 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sun, 13 Jun 2021 12:06:31 -0700 Subject: 49065: remove bad cross-reference --- Doc/Zsh/contrib.yo | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index a972f08d6..e74528341 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2043,9 +2043,8 @@ beyond the scope of tt(localoptions), should your function need that. ) item(Modify hooks)( Use of tt(add-zsh-hook) and tt(add-zle-hook-widget) is recommended (see -ifzman(the bf(Manipulating Hook Functions) section above)\ -ifnzman(noderef(Manipulating Hook Functions))\ -). All hooks that follow the naming pattern tt(prompt_)var(theme)tt(_)var(hook) +the bf(Manipulating Hook Functions) section above). +All hooks that follow the naming pattern tt(prompt_)var(theme)tt(_)var(hook) are automatically removed when the prompt theme changes or is disabled. ) item(Declare cleanup)( -- cgit v1.2.3 From 2912139261960da1229e49cd33f7ed90e8f37e99 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 22 Jun 2021 11:29:55 +0100 Subject: 48096: Update Sourceforge links to https://zsh.sourceforge.io/ --- ChangeLog | 6 ++++++ Doc/Zsh/manual.yo | 2 +- Doc/Zsh/metafaq.yo | 4 ++-- Etc/FAQ.yo | 20 ++++++++++---------- Etc/changelog2html.pl | 2 +- 5 files changed, 20 insertions(+), 14 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 648f030e0..0fdb58445 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2021-06-22 Peter Stephenson + + * 48906: Doc/Zsh/manual.yo, Doc/Zsh/metafaq.yo, Etc/FAQ.yo, + Etc/changelog2html.pl: Update Sourceforge links to + https://zsh.sourceforge.io/. + 2021-06-14 dana * 48920: Completion/Unix/Command/_pgrep: Address issues related to diff --git a/Doc/Zsh/manual.yo b/Doc/Zsh/manual.yo index 119849e4c..51601adbd 100644 --- a/Doc/Zsh/manual.yo +++ b/Doc/Zsh/manual.yo @@ -196,7 +196,7 @@ produce a nicely formatted printed manual. item(The HTML manual)( An HTML version of this manual is available at the Zsh web site via: -uref(http://zsh.sourceforge.net/Doc/). +uref(https://zsh.sourceforge.io/Doc/). (The HTML version is produced with bf(texi2html), which may be obtained from uref(http://www.nongnu.org/texi2html/). The command is diff --git a/Doc/Zsh/metafaq.yo b/Doc/Zsh/metafaq.yo index 4cefa4d71..c780808e3 100644 --- a/Doc/Zsh/metafaq.yo +++ b/Doc/Zsh/metafaq.yo @@ -29,7 +29,7 @@ uref(https://www.zsh.org/pub/)) The up-to-date source code is available via Git from Sourceforge. See uref(https://sourceforge.net/projects/zsh/) for details. A summary of instructions for the archive can be found at -uref(http://zsh.sourceforge.net/). +uref(https://zsh.sourceforge.io/). texinode(Mailing Lists)(The Zsh FAQ)(Availability)(Introduction) sect(Mailing Lists) @@ -98,6 +98,6 @@ A userguide is currently in preparation. It is intended to complement the manual, with explanations and hints on issues where the manual can be cabbalistic, hierographic, or downright mystifying (for example, the word `hierographic' does not exist). It can be viewed in its current state at -uref(http://zsh.sourceforge.net/Guide/). At the time of writing, chapters +uref(https://zsh.sourceforge.io/Guide/). At the time of writing, chapters dealing with startup files and their contents and the new completion system were essentially complete. diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo index 9f0d99d45..20f6449f1 100644 --- a/Etc/FAQ.yo +++ b/Etc/FAQ.yo @@ -171,20 +171,20 @@ sect(Sources of information) label(11) Information on zsh is available via the World Wide Web. The URL - is url(http://zsh.sourceforge.net/)(http://zsh.sourceforge.net/) . + is url(https://zsh.sourceforge.io/)(https://zsh.sourceforge.io/) . The server provides this FAQ and much else and is now maintained by the zsh workers (email email(zsh-workers@zsh.org)). The FAQ is at \ -url(http://zsh.sourceforge.net/FAQ/)(http://zsh.sourceforge.net/FAQ/) . +url(https://zsh.sourceforge.io/FAQ/)(https://zsh.sourceforge.io/FAQ/) . The site also contains some contributed zsh scripts and functions; we are delighted to add more, or simply links to your own collection. This document was originally written in YODL, allowing it to be converted easily into various other formats. The master source file lives at - url(http://zsh.sourceforge.net/FAQ/zshfaq.yo) -(http://zsh.sourceforge.net/FAQ/zshfaq.yo) and the plain text version - can be found at url(http://zsh.sourceforge.net/FAQ/zshfaq.txt) -(http://zsh.sourceforge.net/FAQ/zshfaq.txt) . + url(https://zsh.sourceforge.io/FAQ/zshfaq.yo) +(https://zsh.sourceforge.io/FAQ/zshfaq.yo) and the plain text version + can be found at url(https://zsh.sourceforge.io/FAQ/zshfaq.txt) +(https://zsh.sourceforge.io/FAQ/zshfaq.txt) . Another useful source of information is the collection of FAQ articles posted frequently to the Usenet news groups comp.unix.questions, @@ -213,7 +213,7 @@ email(mail-server@rtfm.mit.edu) I have put together a user guide to complement the manual by explaining the most useful features of zsh in a more easy to read way. This can be found at the zsh web site: - url(http://zsh.sourceforge.net/Guide/)(http://zsh.sourceforge.net/Guide/) + url(https://zsh.sourceforge.io/Guide/)(https://zsh.sourceforge.io/Guide/) (As a method of reading the following in Emacs, you can type tt(\M-2 \C-x $) to make all the indented text vanish, then tt(\M-0 \C-x $) @@ -367,8 +367,8 @@ label(16) link(1.1)(11)) at: description( - mydit() url(http://zsh.sourceforge.net/Patches/) -(http://zsh.sourceforge.net/Patches/) + mydit() url(https://zsh.sourceforge.io/Patches/) +(https://zsh.sourceforge.io/Patches/) ) sect(I don't have root access: how do I make zsh my login shell?) @@ -2727,4 +2727,4 @@ notice appears in all copies of this documentation. Remember, however, that this document changes monthly and it may be more useful to provide a pointer to it rather than the entire text. A suitable pointer is "information on the Z-shell can be obtained on the World -Wide Web at URL http://zsh.sourceforge.net/". +Wide Web at URL https://zsh.sourceforge.io/". diff --git a/Etc/changelog2html.pl b/Etc/changelog2html.pl index 82416bff9..de6877d97 100755 --- a/Etc/changelog2html.pl +++ b/Etc/changelog2html.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl -w # This programme turns the ChangeLog into changelog.html for display -# on the website. That lives at http://zsh.sourceforge.net/Etc/changelog.html. +# on the website. That lives at https://zsh.sourceforge.io/Etc/changelog.html. my $out = "changelog.html"; -- cgit v1.2.3 From 1449f81183cbb8aef7e7bc49159331f9d6a950bb Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 13 May 2021 14:36:19 +0000 Subject: users/26734: docs: read: Notate the parameter name argument as optional. --- ChangeLog | 5 +++++ Doc/Zsh/builtins.yo | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index b7ba668f4..7c16bbf29 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-08-14 Daniel Shahaf + + * users/26734: Doc/Zsh/builtins.yo: docs: read: Notate the + parameter name argument as optional. + 2021-08-10 Peter Stephenson * 49269: Src/parse.c, Test/C02cond.ztst: "[ ! -o ]" should diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index f8e11d79d..ddbcd4363 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -1493,7 +1493,7 @@ findex(read) vindex(IFS, use of) redef(SPACES)(0)(tt(ifztexi(NOTRANS(@ @ @ @ @ ))ifnztexi( ))) xitem(tt(read )[ tt(-rszpqAclneE) ] [ tt(-t) [ var(num) ] ] [ tt(-k) [ var(num) ] ] [ tt(-d) var(delim) ]) -item(SPACES()[ tt(-u) var(n) ] [ var(name)[tt(?)var(prompt)] ] [ var(name) ... ])( +item(SPACES()[ tt(-u) var(n) ] [ [var(name)][tt(?)var(prompt)] ] [ var(name) ... ])( vindex(REPLY, use of) vindex(reply, use of) Read one line and break it into fields using the characters -- cgit v1.2.3 From 0a80579ed18b4004a99b5dc062ce874c0bdc3201 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 26 Aug 2021 09:46:39 +0100 Subject: 49307 with doc update: POSIX_TRAPS fix. With POSIX_TRAPS set, an ignored signal stays ignored when entering a subshell. --- ChangeLog | 6 ++++++ Doc/Zsh/grammar.yo | 4 +++- Doc/Zsh/options.yo | 13 +++++++++---- Src/exec.c | 3 ++- 4 files changed, 20 insertions(+), 6 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 428998717..f558bd47c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2021-08-26 Peter Stephenson + + * 49307 with documentation updated: Src/exec, + Doc/Zsh/grammar.yo, Doc/Zsh/options.yo: With POSIX_TRAPS, + ignored signals stay that way in subshell. + 2021-08-24 Peter Stephenson * 49297 with quoting updated: Src/Modules/files.c: check diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index 2eb2018d2..f8f4ada86 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -288,7 +288,9 @@ for each selection until a break or end-of-file is encountered. cindex(subshell) item(tt(LPAR()) var(list) tt(RPAR()))( Execute var(list) in a subshell. Traps set by the tt(trap) builtin -are reset to their default values while executing var(list). +are reset to their default values while executing var(list); an +exception is that ignored signals will continue to be ignored +if the option tt(POSIXTRAPS) is set. ) item(tt({) var(list) tt(}))( Execute var(list). diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 546b16b65..4a8b85e08 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -2330,10 +2330,15 @@ When this option is set, the usual zsh behaviour of executing traps for tt(EXIT) on exit from shell functions is suppressed. In that case, manipulating tt(EXIT) traps always alters the global trap for exiting the shell; the tt(LOCAL_TRAPS) option is -ignored for the tt(EXIT) trap. Furthermore, a tt(return) statement -executed in a trap with no argument passes back from the function the -value from the surrounding context, not from code executed within the -trap. +ignored for the tt(EXIT) trap. + +Also, a tt(return) statement executed in a trap with no argument passes +back from the function the value from the surrounding context, not from +code executed within the trap. + +Furthermore, if a trap is set to be ignored, this state persists when +a subshell is entered. Without the option, the trap would be reset to +its default state at this point. ) pindex(SH_FILE_EXPANSION) pindex(NO_SH_FILE_EXPANSION) diff --git a/Src/exec.c b/Src/exec.c index 49ff88b80..79d8064b6 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1033,7 +1033,8 @@ entersubsh(int flags, struct entersubsh_ret *retp) if (!(flags & ESUB_KEEPTRAP)) for (sig = 0; sig < SIGCOUNT; sig++) - if (!(sigtrapped[sig] & ZSIG_FUNC)) + if (!(sigtrapped[sig] & ZSIG_FUNC) && + !(isset(POSIXTRAPS) && (sigtrapped[sig] & ZSIG_IGNORED))) unsettrap(sig); monitor = isset(MONITOR); job_control_ok = monitor && (flags & ESUB_JOB_CONTROL) && isset(POSIXJOBS); -- cgit v1.2.3 From a31fd3077d64bb319e9caabf4109721b9778a02d Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Mon, 6 Sep 2021 12:46:28 -0700 Subject: 48888: improve doc for $$ and $PPID, add fail test for PPID readonly-ness --- ChangeLog | 3 +++ Doc/Zsh/mod_system.yo | 6 +++--- Doc/Zsh/params.yo | 15 ++++++++------- Test/E03posix.ztst | 3 +++ 4 files changed, 17 insertions(+), 10 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 85132c36e..50f719fce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-09-06 Bart Schaefer + * 48888: Doc/Zsh/mod_system.yo, Doc/Zsh/params.yo, Test/E03posix.ztst: + improve doc for $$ and $PPID, add fail test for PPID readonly-ness + * 48832: Completion/Unix/Type/_urls: try _gnu_generic first 2021-09-04 Oliver Kiddle diff --git a/Doc/Zsh/mod_system.yo b/Doc/Zsh/mod_system.yo index 8f525c576..399b6fe03 100644 --- a/Doc/Zsh/mod_system.yo +++ b/Doc/Zsh/mod_system.yo @@ -263,9 +263,9 @@ tt($$), which returns the process ID of the main shell process. ) item(tt(ppid))( vindex(ppid, sysparams) -Returns the process ID of the parent of the current process, even in -subshells. Compare tt($PPID), which returns the process ID of the parent -of the main shell process. +Returns the current process ID of the parent of the current process, even +in subshells. Compare tt($PPID), which returns the process ID of the +initial parent of the main shell process. ) item(tt(procsubstpid))( Returns the process ID of the last process started for process diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index dc28a45ae..b514eb072 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -654,10 +654,11 @@ Same as tt(#). ) vindex($) item(tt($) )( -The process ID of this shell. Note that this indicates the original -shell started by invoking tt(zsh); all processes forked from the shells -without executing a new program, such as subshells started by -tt(LPAR())var(...)tt(RPAR()), substitute the same value. +The process ID of this shell, set when the shell initializes. Processes +forked from the shell without executing a new program, such as command +substitutions and commands grouped with tt(LPAR())var(...)tt(RPAR()), +are subshells that duplicate the current shell, and thus substitute the +same value for tt($$) as their parent shell. ) vindex(-) item(tt(-) )( @@ -817,9 +818,9 @@ The operating system, as determined at compile time. ) vindex(PPID) item(tt(PPID) )( -The process ID of the parent of the shell. As for tt($$), the -value indicates the parent of the original shell and does not -change in subshells. +The process ID of the parent of the shell, set when the shell initializes. +As with tt($$), the value does not change in subshells created as a +duplicate of the current shell. ) vindex(PWD) item(tt(PWD))( diff --git a/Test/E03posix.ztst b/Test/E03posix.ztst index 7db4c0c84..564afac29 100644 --- a/Test/E03posix.ztst +++ b/Test/E03posix.ztst @@ -161,3 +161,6 @@ F:POSIX has neither math functions nor floating point 0f:Width of %s is computed in bytes not characters F:This is considered a bugfix in zsh >< Stéphane> + + PPID=foo +-f:PPID is not a readonly variable -- cgit v1.2.3 From a6139bb0a9392c2c90071e7f4013af6e93ceae6c Mon Sep 17 00:00:00 2001 From: zerkous Date: Mon, 6 Sep 2021 14:28:54 -0700 Subject: 49154: clarify status on exec failure --- ChangeLog | 2 ++ Doc/Zsh/exec.yo | 23 +++++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 23388056b..4eea4b614 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2021-09-06 Bart Schaefer + * zeurkous: 49154: Doc/Zsh/exec.yo: clarify status on exec failure + * Marlon Richert: 49378: Src/parse.c: skip check for collision of aliases and functions when NO_EXEC diff --git a/Doc/Zsh/exec.yo b/Doc/Zsh/exec.yo index 5f79967de..2b3d29500 100644 --- a/Doc/Zsh/exec.yo +++ b/Doc/Zsh/exec.yo @@ -14,9 +14,20 @@ a shell builtin by that name, the builtin is invoked. vindex(path, use of) Otherwise, the shell searches each element of tt($path) for a -directory containing an executable file by that name. If the -search is unsuccessful, the shell prints an error message and returns -a nonzero exit status. +directory containing an executable file by that name. + +If execution fails: an error message is printed, and one of the +following values is returned. + +startsitem() +sitem(127)(The search was unsuccessful. The error message is +`tt(command not found:) var(cmd)'.) +sitem(126)(The executable file has insufficient permissions, is a +directory or special file, or is not a script and is in a format +unrecognized by the operating system. The exact conditions and error +message are operating system-dependent; see +manref(execve)(2).) +endsitem() If execution fails because the file is not in executable format, and the file is not a directory, it is assumed to be a shell @@ -29,10 +40,6 @@ not handle this executable format in the kernel. If no external command is found but a function tt(command_not_found_handler) exists the shell executes this function with all command line arguments. The return status of the function becomes the -status of the command. If the function wishes to mimic the -behaviour of the shell when the command is not found, it should -print the message `tt(command not found:) var(cmd)' to standard error -and return status 127. Note that the handler is executed in a +status of the command. Note that the handler is executed in a subshell forked to execute an external command, hence changes to directories, shell parameters, etc. have no effect on the main shell. - -- cgit v1.2.3 From bb61da36aaeeaa70413cdf5bc66d7a71194f93e5 Mon Sep 17 00:00:00 2001 From: Stephane Chazelas Date: Mon, 6 Sep 2021 14:43:01 -0700 Subject: 45180: clarify doc for POSIX EREs, fix an issue with PCRE when the replacement was empty or generated more than one element --- ChangeLog | 5 +++ Doc/Zsh/contrib.yo | 5 ++- Functions/Example/zpgrep | 15 +++++-- Functions/Misc/regexp-replace | 102 +++++++++++++++++++++++++++++++----------- 4 files changed, 95 insertions(+), 32 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 4eea4b614..eb75cf235 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2021-09-06 Bart Schaefer + * Stephane Chazelas: 45180: Doc/Zsh/contrib.yo, + Functions/Example/zpgrep, Functions/Misc/regexp-replace: clarify + doc for POSIX EREs, fix an issue with PCRE when the replacement + was empty or generated more than one element + * zeurkous: 49154: Doc/Zsh/exec.yo: clarify status on exec failure * Marlon Richert: 49378: Src/parse.c: skip check for collision diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index e74528341..94059eff6 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -4335,7 +4335,7 @@ See also the tt(pager), tt(prompt) and tt(rprompt) styles below. findex(regexp-replace) item(tt(regexp-replace) var(var) var(regexp) var(replace))( Use regular expressions to perform a global search and replace operation -on a variable. POSIX extended regular expressions are used, +on a variable. POSIX extended regular expressions (ERE) are used, unless the option tt(RE_MATCH_PCRE) has been set, in which case Perl-compatible regular expressions are used (this requires the shell to be linked against the tt(pcre) @@ -4353,6 +4353,9 @@ and arithmetic expressions which will be replaced: in particular, a reference to tt($MATCH) will be replaced by the text matched by the pattern. The return status is 0 if at least one match was performed, else 1. + +Note that if using POSIX EREs, the tt(^) or word boundary operators +(where available) may not work properly. ) findex(run-help) item(tt(run-help) var(cmd))( diff --git a/Functions/Example/zpgrep b/Functions/Example/zpgrep index 8b1edaa1c..556e58cd6 100644 --- a/Functions/Example/zpgrep +++ b/Functions/Example/zpgrep @@ -2,24 +2,31 @@ # zpgrep() { -local file pattern +local file pattern ret pattern=$1 shift +ret=1 if ((! ARGC)) then set -- - fi -pcre_compile $pattern +zmodload zsh/pcre || return +pcre_compile -- "$pattern" pcre_study for file do if [[ "$file" == - ]] then - while read -u0 buf; do pcre_match $buf && print $buf; done + while IFS= read -ru0 buf; do + pcre_match -- "$buf" && ret=0 && print -r -- "$buf" + done else - while read -u0 buf; do pcre_match $buf && print $buf; done < "$file" + while IFS= read -ru0 buf; do + pcre_match -- "$buf" && ret=0 && print -r -- "$buf" + done < "$file" fi done +return "$ret" } diff --git a/Functions/Misc/regexp-replace b/Functions/Misc/regexp-replace index dec105524..0d5948075 100644 --- a/Functions/Misc/regexp-replace +++ b/Functions/Misc/regexp-replace @@ -8,36 +8,84 @@ # $ and backtick substitutions; in particular, $MATCH will be replaced # by the portion of the string matched by the regular expression. -integer pcre +# we use positional parameters instead of variables to avoid +# clashing with the user's variable. Make sure we start with 3 and only +# 3 elements: +argv=("$1" "$2" "$3") -[[ -o re_match_pcre ]] && pcre=1 +# $4 records whether pcre is enabled as that information would otherwise +# be lost after emulate -L zsh +4=0 +[[ -o re_match_pcre ]] && 4=1 emulate -L zsh -(( pcre )) && setopt re_match_pcre - -# $4 is the string to be matched -4=${(P)1} -# $5 is the final string -5= -# 6 indicates if we made a change -6= + + local MATCH MBEGIN MEND local -a match mbegin mend -while [[ -n $4 ]]; do - if [[ $4 =~ $2 ]]; then - # append initial part and subsituted match - 5+=${4[1,MBEGIN-1]}${(e)3} - # truncate remaining string - 4=${4[MEND+1,-1]} - # indicate we did something - 6=1 - else - break - fi -done -5+=$4 - -eval ${1}=${(q)5} -# status 0 if we did something, else 1. -[[ -n $6 ]] +if (( $4 )); then + # if using pcre, we're using pcre_match and a running offset + # That's needed for ^, \A, \b, and look-behind operators to work + # properly. + + zmodload zsh/pcre || return 2 + pcre_compile -- "$2" && pcre_study || return 2 + + # $4 is the current *byte* offset, $5, $6 reserved for later use + 4=0 6= + + local ZPCRE_OP + while pcre_match -b -n $4 -- "${(P)1}"; do + # append offsets and computed replacement to the array + # we need to perform the evaluation in a scalar assignment so that if + # it generates an array, the elements are converted to string (by + # joining with the first chararacter of $IFS as usual) + 5=${(e)3} + argv+=(${(s: :)ZPCRE_OP} "$5") + + # for 0-width matches, increase offset by 1 to avoid + # infinite loop + 4=$((argv[-2] + (argv[-3] == argv[-2]))) + done + + (($# > 6)) || return # no match + + set +o multibyte + + # $5 contains the result, $6 the current offset + 5= 6=1 + for 2 3 4 in "$@[7,-1]"; do + 5+=${(P)1[$6,$2]}$4 + 6=$(($3 + 1)) + done + 5+=${(P)1[$6,-1]} +else + # in ERE, we can't use an offset so ^, (and \<, \b, \B, [[:<:]] where + # available) won't work properly. + + # $4 is the string to be matched + 4=${(P)1} + + while [[ -n $4 ]]; do + if [[ $4 =~ $2 ]]; then + # append initial part and substituted match + 5+=${4[1,MBEGIN-1]}${(e)3} + # truncate remaining string + if ((MEND < MBEGIN)); then + # zero-width match, skip one character for the next match + ((MEND++)) + 5+=${4[1]} + fi + 4=${4[MEND+1,-1]} + # indicate we did something + 6=1 + else + break + fi + done + [[ -n $6 ]] || return # no match + 5+=$4 +fi + +eval $1=\$5 -- cgit v1.2.3 From 68c0fa68e2888ee26d082a2b2ba42d5f4d95374b Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Wed, 8 Sep 2021 16:06:37 -0700 Subject: 49391: Document default bracketed-paste bindings --- ChangeLog | 2 ++ Doc/Zsh/zle.yo | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 35f337f6e..81975d5ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2021-09-08 Bart Schaefer + * 49391: Doc/Zsh/zle.yo: document default bracketed-paste bindings + * 49389: Completion/Zsh/Command/_typeset: leading variables in autoload file completion diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 9694a1f74..6d517b81b 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -2222,7 +2222,7 @@ item(tt(beep))( Beep, unless the tt(BEEP) option is unset. ) tindex(bracketed-paste) -item(tt(bracketed-paste))( +item(tt(bracketed-paste) (tt(^[[200~)) (tt(^[[200~)) (tt(^[[200~)))( This widget is invoked when text is pasted to the terminal emulator. It is not intended to be bound to actual keys but instead to the special sequence generated by the terminal emulator when text is pasted. -- cgit v1.2.3 From ca94d3acdaf30057c91b2f82f6268c3ffb2e3f6f Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 16 Nov 2020 18:05:02 +0000 Subject: unposted: Fix typos --- ChangeLog | 6 ++++++ Doc/Zsh/contrib.yo | 2 +- Doc/Zsh/mod_curses.yo | 2 +- Doc/Zsh/mod_zselect.yo | 2 +- Test/A05execution.ztst | 2 +- Test/C04funcdef.ztst | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 1331c1d10..b1f295bd7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2021-09-26 Daniel Shahaf + + * unposted: Doc/Zsh/contrib.yo, Doc/Zsh/mod_curses.yo, + Doc/Zsh/mod_zselect.yo, Test/A05execution.ztst, + Test/C04funcdef.ztst: Fix typos + 2021-09-22 Jun-ichi Takimoto * 49422: Src/Modules/parameter.c, Src/hashnameddir.c, Src/options.c, diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 94059eff6..cbd850231 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1941,7 +1941,7 @@ subsect(Installation) You should make sure all the functions from the tt(Functions/Prompts) directory of the source distribution are available; they all begin with -the string `tt(prompt_)' except for the special function`tt(promptinit)'. +the string `tt(prompt_)' except for the special function `tt(promptinit)'. You also need the `tt(colors)' and `tt(add-zsh-hook)' functions from tt(Functions/Misc). All these functions may already be installed on your system; if not, diff --git a/Doc/Zsh/mod_curses.yo b/Doc/Zsh/mod_curses.yo index 6e4831abe..e2d5690e2 100644 --- a/Doc/Zsh/mod_curses.yo +++ b/Doc/Zsh/mod_curses.yo @@ -157,7 +157,7 @@ input. This is only available with the ncurses library; mouse handling can be detected by checking for the exit status of `tt(zcurses mouse)' with no arguments. If a mouse button is clicked (or double- or triple-clicked, or pressed or released with -a configurable delay from being clicked) then tt(kparam) is set to the string +a configurable delay from being clicked) then var(kparam) is set to the string tt(MOUSE), and var(mparam) is set to an array consisting of the following elements: startitem() diff --git a/Doc/Zsh/mod_zselect.yo b/Doc/Zsh/mod_zselect.yo index e0651571e..faf59c165 100644 --- a/Doc/Zsh/mod_zselect.yo +++ b/Doc/Zsh/mod_zselect.yo @@ -12,7 +12,7 @@ The tt(zselect) builtin is a front-end to the `select' system call, which blocks until a file descriptor is ready for reading or writing, or has an error condition, with an optional timeout. If this is not available on your system, the command prints an error message and returns status 2 -(normal errors return status 1). For more information, see your systems +(normal errors return status 1). For more information, see your system's documentation for manref(select)(3). Note there is no connection with the shell builtin of the same name. diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst index c65642988..d95ee363c 100644 --- a/Test/A05execution.ztst +++ b/Test/A05execution.ztst @@ -258,7 +258,7 @@ F:side of a pipe to block on write after the right side has exited print -u $ZTST_fd "Skipping pipe leak test, requires MONITOR option" print "[0] 0 0" fi -0:Bug regression: piping to anonymous function; piping to backround function +0:Bug regression: piping to anonymous function; piping to background function *>\[<->\] <-> <-> F:This test checks for two different bugs, a parser segfault piping to an F:anonymous function, and a descriptor leak when backgrounding a pipeline diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst index 88321c432..af469c527 100644 --- a/Test/C04funcdef.ztst +++ b/Test/C04funcdef.ztst @@ -307,7 +307,7 @@ # lsfoo should not be expanded as an anonymous function argument alias lsfoo='This is not ls.' () (echo anon func; echo "$@") lsfoo -0:Anonmous function with arguments in a form nobody sane would ever use but unfortunately we have to support anyway +0:Anonymous function with arguments in a form nobody sane would ever use but unfortunately we have to support anyway >anon func >lsfoo -- cgit v1.2.3 From 02f75cf38699b99340c1d2c8f5a9d9aaf81432e7 Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Thu, 23 Sep 2021 00:17:18 +0300 Subject: 49435: Remove trailing whitespaces in expn.yo --- ChangeLog | 2 ++ Doc/Zsh/expn.yo | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 79d7708f1..735ea25ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2021-09-28 Oliver Kiddle + * ivan tkachenko: 49435: Doc/Zsh/expn.yo: Remove trailing whitespace + * Alex Xu: 49444: Completion/Unix/Type/_tar_archive: libarchive tar can actually extract much more formats diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index c218ded05..eea147bde 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -84,7 +84,7 @@ vindex(histchars, use of) A history expansion begins with the first character of the tt(histchars) parameter, which is `tt(!)' by default, and may occur anywhere on the command line, including inside double quotes (but not inside single quotes -tt('...') or C-style quotes tt($'...') nor when escaped with a backslash). +tt('...') or C-style quotes tt($'...') nor when escaped with a backslash). The first character is followed by an optional event designator (ifzman(see )noderef(Event Designators)) and then an optional word @@ -496,7 +496,7 @@ which treats var(arg) as a file name and replaces it with the file's contents. The tt(=) form is useful as both the tt(/dev/fd) and the named pipe -implementation of tt( >LPAR())var(process1)tt(RPAR() > >LPAR())var(process2)tt(RPAR())) The shell uses pipes instead of FIFOs to implement the latter @@ -974,7 +974,7 @@ If the tt(MULTIBYTE) option is set and the number is greater than 127 ) item(tt(%))( Expand all tt(%) escapes in the resulting words in the same way as in -prompts (see +prompts (see ifzman(EXPANSION OF PROMPT SEQUENCES in zmanref(zshmisc))\ ifnzman(noderef(Prompt Expansion))). If this flag is given twice, full prompt expansion is done on the resulting words, depending on the @@ -1729,7 +1729,7 @@ This produces the result tt(b). First, the inner substitution tt("${foo}"), which has no array (tt(@)) flag, produces a single word result tt("bar baz"). The outer substitution tt("${(@)...[1]}") detects that this is a scalar, so that (despite the `tt((@))' flag) the subscript -picks the first character. +picks the first character. ) item(tt("${${(@)foo}[1]}"))( This produces the result `tt(bar)'. In this case, the inner substitution @@ -1763,7 +1763,7 @@ sect(Command Substitution) cindex(command substitution) cindex(substitution, command) A command enclosed in parentheses preceded by a dollar sign, like -`tt($LPAR())...tt(RPAR())', or quoted with grave +`tt($LPAR())...tt(RPAR())', or quoted with grave accents, like `tt(`)...tt(`)', is replaced with its standard output, with any trailing newlines deleted. If the substitution is not enclosed in double quotes, the @@ -2461,7 +2461,7 @@ qualifiers are also not applied in ordinary pattern matching. ) item(tt(u))( Respect the current locale in determining the presence of multibyte -characters in a pattern, provided the shell was compiled with +characters in a pattern, provided the shell was compiled with tt(MULTIBYTE_SUPPORT). This overrides the tt(MULTIBYTE) option; the default behaviour is taken from the option. Compare tt(U). (Mnemonic: typically multibyte characters are from Unicode in the UTF-8 @@ -2712,18 +2712,18 @@ expected, if combined with a `tt(=)', the value given must match the file-modes exactly, with a `tt(PLUS())', at least the bits in the given number must be set in the file-modes, and with a `tt(-)', the bits in the number must not be set. Giving a `tt(?)' instead of a -octal digit anywhere in the number ensures that the corresponding bits +octal digit anywhere in the number ensures that the corresponding bits in the file-modes are not checked, this is only useful in combination with `tt(=)'. If the qualifier `tt(f)' is followed by any other character anything -up to the next matching character (`tt([)', `tt({)', and `tt(<)' match +up to the next matching character (`tt([)', `tt({)', and `tt(<)' match `tt(])', `tt(})', and `tt(>)' respectively, any other character matches itself) is taken as a list of comma-separated var(sub-spec)s. Each var(sub-spec) may be either an octal number as described above or a list of any of the characters `tt(u)', `tt(g)', `tt(o)', and `tt(a)', followed by a `tt(=)', a `tt(PLUS())', or a -`tt(-)', followed by a list of any of the characters `tt(r)', `tt(w)', +`tt(-)', followed by a list of any of the characters `tt(r)', `tt(w)', `tt(x)', `tt(s)', and `tt(t)', or an octal digit. The first list of characters specify which access rights are to be checked. If a `tt(u)' is given, those for the owner of the file are used, if a `tt(g)' is @@ -2732,7 +2732,7 @@ of other users, and the `tt(a)' says to test all three groups. The `tt(=)', `tt(PLUS())', and `tt(-)' again says how the modes are to be checked and have the same meaning as described for the first form above. The second list of characters finally says which access rights -are to be expected: `tt(r)' for read access, `tt(w)' for write access, +are to be expected: `tt(r)' for read access, `tt(w)' for write access, `tt(x)' for the right to execute the file (or to search a directory), `tt(s)' for the setuid and setgid bits, and `tt(t)' for the sticky bit. @@ -2741,7 +2741,7 @@ Thus, `tt(*(f70?))' gives the files for which the owner has read, write, and execute permission, and for which other group members have no rights, independent of the permissions for other users. The pattern `tt(*(f-100))' gives all files for which the owner does not have -execute permission, and `tt(*(f:gu+w,o-rx:))' gives the files for which +execute permission, and `tt(*(f:gu+w,o-rx:))' gives the files for which the owner and the other members of the group have at least write permission, and for which other users don't have read or execute permission. @@ -2942,7 +2942,7 @@ item(tt([)var(beg)[tt(,)var(end)]tt(]))( specifies which of the matched filenames should be included in the returned list. The syntax is the same as for array subscripts. var(beg) and the optional var(end) may be mathematical -expressions. As in parameter subscripting they may be negative to make +expressions. As in parameter subscripting they may be negative to make them count from the last match backward. E.g.: `tt(*(-OL[1,3]))' gives a list of the names of the three largest files. ) -- cgit v1.2.3 From 99d915330aa470e5ca723084f54910d82aec444d Mon Sep 17 00:00:00 2001 From: ivan tkachenko Date: Thu, 23 Sep 2021 15:49:41 +0300 Subject: 49440: Make double-flag parameter expansion syntax more discoverable in docs --- ChangeLog | 3 +++ Doc/Zsh/expn.yo | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 735ea25ee..b116ec4f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-09-28 Oliver Kiddle + * ivan tkachenko: 49440: Doc/Zsh/expn.yo: Make double-flag + parameter expansion syntax more discoverable in docs + * ivan tkachenko: 49435: Doc/Zsh/expn.yo: Remove trailing whitespace * Alex Xu: 49444: Completion/Unix/Type/_tar_archive: diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index eea147bde..d40d1b439 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -872,7 +872,8 @@ of the string tt($-) and the array tt($*) respectively. If tt(POSIX_IDENTIFIERS) is set, then braces are required for the tt(#) to be treated in this fashion. ) -item(tt(${^)var(spec)tt(}))( +xitem(tt(${^)var(spec)tt(})) +item(tt(${^^)var(spec)tt(}))( pindex(RC_EXPAND_PARAM, toggle) cindex(array expansion style, rc) cindex(rc, array expansion style) @@ -895,7 +896,8 @@ happening later. If word splitting is also in effect the tt($var[)var(N)tt(]) may themselves be split into different list elements. ) -item(tt(${=)var(spec)tt(}))( +xitem(tt(${=)var(spec)tt(})) +item(tt(${==)var(spec)tt(}))( pindex(SH_WORD_SPLIT, toggle) cindex(field splitting, sh style, parameter) cindex(sh, field splitting style, parameter) @@ -911,7 +913,8 @@ Note that splitting is applied to var(word) in the assignment forms of var(spec) em(before) the assignment to var(name) is performed. This affects the result of array assignments with the tt(A) flag. ) -item(tt(${~)var(spec)tt(}))( +xitem(tt(${~)var(spec)tt(})) +item(tt(${~~)var(spec)tt(}))( pindex(GLOB_SUBST, toggle) Turn on the tt(GLOB_SUBST) option for the evaluation of var(spec); if the `tt(~)' is doubled, turn it off. When this option is -- cgit v1.2.3 From fa4c88ca25f587f52074698d4ff7eb263de07930 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Mon, 4 Oct 2021 09:02:27 -0700 Subject: 49456: clean up detection of private params in nested scopes, update doc --- ChangeLog | 6 ++++++ Doc/Zsh/mod_private.yo | 9 +++++++-- Doc/Zsh/params.yo | 8 ++++++++ Src/Modules/param_private.c | 12 +++++++----- Src/params.c | 5 +++++ Test/V10private.ztst | 6 +++--- 6 files changed, 36 insertions(+), 10 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index b116ec4f7..62470ba0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2021-10-04 Bart Schaefer + + * 49456: Doc/Zsh/mod_private.yo, Doc/Zsh/params.yo, + Src/Modules/param_private.c, Src/params.c, Test/V10private.ztst: + clean up detection of private params in nested scopes, update doc + 2021-09-28 Oliver Kiddle * ivan tkachenko: 49440: Doc/Zsh/expn.yo: Make double-flag diff --git a/Doc/Zsh/mod_private.yo b/Doc/Zsh/mod_private.yo index 78aee0acf..184fa2be8 100644 --- a/Doc/Zsh/mod_private.yo +++ b/Doc/Zsh/mod_private.yo @@ -10,12 +10,16 @@ ifnzman() startitem() findex(private) cindex(private parameter, creating) -item(tt(private) [ {tt(PLUS())|tt(-)}tt(AHUahlprtux) ] \ +item(tt(private) [ {tt(PLUS())|tt(-)}tt(AHUahlmrtux) ] \ [ {tt(PLUS())|tt(-)}tt(EFLRZi) [ var(n) ] ] [ var(name)[tt(=)var(value)] ... ])( The tt(private) builtin accepts all the same options and arguments as tt(local) (ifzman(zmanref(zshbuiltins))ifnzman(noderef(Shell Builtin Commands))) except for the `tt(-)tt(T)' option. Tied parameters may not be made private. +The `tt(-)tt(p)' option is presently a no-op because the state of +private parameters cannot reliably be reloaded. This also applies +to printing private parameters with `tt(typeset -p)'. + If used at the top level (outside a function scope), tt(private) creates a normal parameter in the same manner as tt(declare) or tt(typeset). A warning about this is printed if tt(WARN_CREATE_GLOBAL) is set @@ -75,7 +79,8 @@ itemiz(Within any other function called by the declaring function, the private parameter does em(NOT) hide other parameters of the same name, so for example a global parameter of the same name is visible and may be assigned or unset. This includes calls to anonymous functions, although -that may also change in the future.) +that may also change in the future. However, the private name may not be +created outside the local scope when it was not previously declared.) itemiz(An exported private remains in the environment of inner scopes but appears unset for the current shell in those scopes. Generally, exporting private parameters should be avoided.) diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index b514eb072..a88e44d4f 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -632,6 +632,14 @@ In the parameter lists that follow, the mark `' indicates that the parameter is special. `' indicates that the parameter does not exist when the shell initializes in tt(sh) or tt(ksh) emulation mode. +The parameters `tt(!)', `tt(#)', `tt(*)', `tt(-)', `tt(?)', `tt(@)', +`tt($)', `tt(ARGC)', `tt(HISTCMD)', `tt(LINENO)', `tt(PPID)', +`tt(status)', `tt(TTYIDLE)', `tt(zsh_eval_context)', +`tt(ZSH_EVAL_CONTEXT)', and `tt(ZSH_SUBSHELL)' are read-only and thus +cannot be restored by the user, so they are not output by +`tt(typeset -p)'. This also applies to many read-only parameters loaded +from modules. + The following parameters are automatically set by the shell: startitem() diff --git a/Src/Modules/param_private.c b/Src/Modules/param_private.c index 24545819d..c53839152 100644 --- a/Src/Modules/param_private.c +++ b/Src/Modules/param_private.c @@ -125,7 +125,7 @@ makeprivate(HashNode hn, UNUSED(int flags)) break; } /* PM_HIDE so new parameters in deeper scopes do not shadow */ - pm->node.flags |= (PM_HIDE|PM_SPECIAL|PM_REMOVABLE); + pm->node.flags |= (PM_HIDE|PM_SPECIAL|PM_REMOVABLE|PM_RO_BY_DESIGN); pm->level -= 1; } } @@ -171,7 +171,7 @@ bin_private(char *nam, char **args, LinkList assigns, Options ops, int func) { int from_typeset = 1; int ofake = fakelevel; /* paranoia in case of recursive call */ - int hasargs = *args != NULL || (assigns && firstnode(assigns)); + int hasargs = /* *args != NULL || */ (assigns && firstnode(assigns)); makeprivate_error = 0; if (!OPT_ISSET(ops, 'P')) { @@ -190,8 +190,10 @@ bin_private(char *nam, char **args, LinkList assigns, Options ops, int func) return bin_typeset("private", args, assigns, ops, func); } - ops->ind['g'] = 2; /* force bin_typeset() to behave as "local" */ - if (OPT_ISSET(ops, 'p') || (!hasargs && OPT_ISSET(ops, '+'))) { + if (!(OPT_ISSET(ops, 'm') || OPT_ISSET(ops, '+'))) + ops->ind['g'] = 2; /* force bin_typeset() to behave as "local" */ + if (OPT_ISSET(ops, 'p') || OPT_ISSET(ops, 'm') || + (!hasargs && OPT_ISSET(ops, '+'))) { return bin_typeset("private", args, assigns, ops, func); } @@ -559,7 +561,7 @@ printprivatenode(HashNode hn, int printflags) static struct builtin bintab[] = { /* Copied from BUILTIN("local"), "P" added */ - BUILTIN("private", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_private, 0, -1, 0, "AE:%F:%HL:%PR:%TUZ:%ahi:%lprtux", "P") + BUILTIN("private", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_private, 0, -1, 0, "AE:%F:%HL:%PR:%TUZ:%ahi:%lmprtux", "P") }; static struct features module_features = { diff --git a/Src/params.c b/Src/params.c index 704aad588..b703a97ce 100644 --- a/Src/params.c +++ b/Src/params.c @@ -1013,6 +1013,11 @@ createparam(char *name, int flags) (oldpm->node.flags & PM_SPECIAL) || /* POSIXBUILTINS horror: we need to retain 'export' flags */ (isset(POSIXBUILTINS) && (oldpm->node.flags & PM_EXPORTED))) { + if (oldpm->node.flags & PM_RO_BY_DESIGN) { + zerr("%s: can't change parameter attribute", + name); + return NULL; + } oldpm->node.flags &= ~PM_UNSET; if ((oldpm->node.flags & PM_SPECIAL) && oldpm->ename) { Param altpm = diff --git a/Test/V10private.ztst b/Test/V10private.ztst index 03e8259d5..56ffbc5b4 100644 --- a/Test/V10private.ztst +++ b/Test/V10private.ztst @@ -116,14 +116,14 @@ } outer () { local -PA hash_test=(in function) - typeset -p hash_test + private + hash_test inner } outer print ${(kv)hash_test} 0:private hides value from surrounding scope in nested scope >typeset -a hash_test=( top level ) ->typeset -A hash_test=( [in]=function ) +>hash_test=( [in]=function ) >typeset -g -a hash_test=( top level ) >array-local top level >top level @@ -246,7 +246,7 @@ F:note "typeset" rather than "private" in output from outer 1:privates are not visible in anonymous functions, part 3 >X top level >array_test not set -?(anon):4: array_test: attempt to assign private in nested scope +?(anon):4: array_test: can't change parameter attribute F:future revision will create a global with this assignment typeset -a array_test -- cgit v1.2.3 From f2b6650b43688eb38ffe88b3ed3c819b48fa141c Mon Sep 17 00:00:00 2001 From: Marlon Richert Date: Mon, 25 Oct 2021 21:33:29 +0300 Subject: 49521: Define correct behavior of || completion matchers * Add xfail tests to show how :||= matchers should behave in order to provide completion features that cannot be implemented with :|= matchers. * Update compwid.yo to further describe the correct behavior. * Update compwid.yo to use completion terminology more consistently. --- ChangeLog | 3 + Doc/Zsh/compwid.yo | 671 +++++++++++++++++++++++++------------------------ Test/Y02compmatch.ztst | 126 ++++++++-- 3 files changed, 453 insertions(+), 347 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index ff8a738c2..39efef8eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-10-26 Oliver Kiddle + * Marlon: 49521: Doc/Zsh/compwid.yo, Test/Y02compmatch.ztst: + Define correct behavior of || completion matchers + * 49519: Completion/Base/Utility/_arguments, Completion/Darwin/Command/_qtplay, Completion/Unix/Command/_less, Completion/Unix/Command/_nm, Completion/Unix/Command/_php, diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo index 3e86d3b42..9f67f13b7 100644 --- a/Doc/Zsh/compwid.yo +++ b/Doc/Zsh/compwid.yo @@ -39,7 +39,7 @@ using the tt(bindkey) builtin command defined in the tt(zsh/zle) module ifzman(see zmanref(zshzle))\ ifnzman(noderef(Zsh Line Editor))\ ), typing that key will call the shell function `tt(completer)'. This -function is responsible for generating the possible matches using the +function is responsible for generating completion matches using the builtins described below. As with other ZLE widgets, the function is called with its standard input closed. @@ -213,7 +213,7 @@ The string of an exact match if one was found, otherwise unset. ) vindex(ignored, compstate) item(tt(ignored))( -The number of words that were ignored because they matched one of the +The number of completions that were ignored because they matched one of the patterns given with the tt(-F) option to the tt(compadd) builtin command. ) @@ -309,8 +309,7 @@ will be used in the same way as the value of tt(LISTMAX). ) vindex(nmatches, compstate) item(tt(nmatches))( -The number of matches generated and accepted by the completion code so -far. +The number of matches added by the completion code so far. ) vindex(old_insert, compstate) item(tt(old_insert))( @@ -346,7 +345,8 @@ value of a parameter assignment. vindex(pattern_insert, compstate) item(tt(pattern_insert))( Normally this is set to tt(menu), which specifies that menu completion will -be used whenever a set of matches was generated using pattern matching. If +be used whenever a set of matches was generated using tt(pattern_match) +(see below). If it is set to any other non-empty string by the user and menu completion is not selected by other option settings, the code will instead insert any common prefix for the generated matches as with normal completion. @@ -362,7 +362,7 @@ command line will be treated as patterns; if it is `tt(*)', then additionally a wildcard `tt(*)' is assumed at the cursor position; if it is empty or unset, metacharacters will be treated literally. -Note that the matcher specifications given to the tt(compadd) builtin +Note that the match specifications given to the tt(compadd) builtin command are not used if this is set to a non-empty string. ) vindex(quote, compstate) @@ -456,17 +456,16 @@ xitem(SPACES()[tt(-V) var(group-name) ] [ tt(-o) [ var(order) ] ]) xitem(SPACES()[tt(-r) var(remove-chars) ] [ tt(-R) var(remove-func) ]) xitem(SPACES()[tt(-D) var(array) ] [ tt(-O) var(array) ] [ tt(-A) var(array) ]) xitem(SPACES()[tt(-E) var(number) ]) -item(SPACES()[tt(-M) var(match-spec) ] [ tt(-)tt(-) ] [ var(words) ... ])( +item(SPACES()[tt(-M) var(match-spec) ] [ tt(-)tt(-) ] [ var(completions) ... ])( This builtin command can be used to add matches directly and control all the information the completion code stores with each possible -match. The return status is zero if at least one match was added and +completion. The return status is zero if at least one match was added and non-zero if no matches were added. -The completion code breaks the string to complete into seven fields in -the order: +The completion code breaks each match into seven fields in the order: -indent(var()) +indent(var()) The first field is an ignored prefix taken from the command line, the contents of the @@ -474,12 +473,12 @@ tt(IPREFIX) parameter plus the string given with the tt(-i) option. With the tt(-U) option, only the string from the tt(-i) option is used. The field var() is an optional prefix string given with the tt(-P) option. The var() field is a string -that is considered part of the match but that should not be shown when +that is considered part of the match but that should not be shown when listing completions, given with the tt(-p) option; for example, functions that do filename generation might specify -a common path prefix this way. var() is the part of the match that -should appear in the list of completions, i.e. one of the var(words) given -at the end of the tt(compadd) command line. The suffixes var(), +a common path prefix this way. var() is the part of the match that +should appear in the list of matches shown to the user. +The suffixes var(), var() and var() correspond to the prefixes var(), var() and var() and are given by the options tt(-s), tt(-S) and tt(-I), respectively. @@ -488,52 +487,52 @@ The supported flags are: startitem() item(tt(-P) var(prefix))( -This gives a string to be inserted before the given var(words). The +This gives a string to be inserted before each match. The string given is not considered as part of the match and any shell metacharacters in it will not be quoted when the string is inserted. ) item(tt(-S) var(suffix))( -Like tt(-P), but gives a string to be inserted after the match. +Like tt(-P), but gives a string to be inserted after each match. ) item(tt(-p) var(hidden-prefix))( -This gives a string that should be inserted into the command line before the +This gives a string that should be inserted before each match but that should not appear in the list of matches. Unless the tt(-U) option is given, this string must be matched as part of the string on the command line. ) item(tt(-s) var(hidden-suffix))( -Like `tt(-p)', but gives a string to insert after the match. +Like `tt(-p)', but gives a string to insert after each match. ) item(tt(-i) var(ignored-prefix))( -This gives a string to insert into the command line just before any +This gives a string to insert just before any string given with the `tt(-P)' option. Without `tt(-P)' the string is -inserted before the string given with `tt(-p)' or directly before the +inserted before the string given with `tt(-p)' or directly before each match. ) item(tt(-I) var(ignored-suffix))( Like tt(-i), but gives an ignored suffix. ) item(tt(-a))( -With this flag the var(words) are taken as names of arrays and the -possible matches are their values. If only some elements of the -arrays are needed, the var(words) may also contain subscripts, as in +With this flag the var(completions) are taken as names of arrays and the +actual completions are their values. If only some elements of the +arrays are needed, the var(completions) may also contain subscripts, as in `tt(foo[2,-1])'. ) item(tt(-k))( -With this flag the var(words) are taken as names of associative arrays -and the possible matches are their keys. As for tt(-a), the +With this flag the var(completions) are taken as names of associative arrays +and the actual completions are their keys. As for tt(-a), the var(words) may also contain subscripts, as in `tt(foo[(R)*bar*])'. ) item(tt(-d) var(array))( -This adds per-match display strings. The var(array) should contain one -element per var(word) given. The completion code will then display the -first element instead of the first var(word), and so on. The +This adds per-completion display strings. The var(array) should contain one +element per var(completion) given. The completion code will then display the +first element instead of the first var(completion), and so on. The var(array) may be given as the name of an array parameter or directly as a space-separated list of words in parentheses. -If there are fewer display strings than var(words), the leftover -var(words) will be displayed unchanged and if there are more display -strings than var(words), the leftover display strings will be silently +If there are fewer display strings than var(completions), the leftover +var(completions) will be displayed unchanged and if there are more display +strings than var(completions), the leftover display strings will be silently ignored. ) item(tt(-l))( @@ -556,7 +555,8 @@ by the tt(-d) option). This is the default if `tt(-o)' is specified but the var(order) argument is omitted. ) item(tt(nosort))( -This specifies that the matches are pre-sorted and their order should be +This specifies that the var(completions) +are pre-sorted and their order should be preserved. This value only makes sense alone and cannot be combined with any others. ) @@ -570,7 +570,7 @@ Arrange the matches backwards by reversing the sort ordering. enditem() ) item(tt(-J) var(group-name))( -Gives the name of the group of matches the words should be stored in. +Gives the name of the group that the matches should be stored in. ) item(tt(-V) var(group-name))( Like tt(-J) but naming an unsorted group. This option is identical to @@ -616,13 +616,13 @@ produce unexpected results. If arbitrary text is to be passed in a description, it can be escaped using e.g. tt(${my_str//\%/%%}). ) item(tt(-x) var(message))( -Like tt(-X), but the var(message) will be printed even if there are no +Like tt(-X), but the var(message) will be printed even if there are no matches in the group. ) item(tt(-q))( -The suffix given with tt(-S) will be automatically removed if +The suffix given with tt(-S) will be automatically removed if the next character typed is a blank or does not insert anything, or if -the suffix consists of only one character and the next character typed +the suffix consists of only one character and the next character typed is the same character. ) item(tt(-r) var(remove-chars))( @@ -644,8 +644,8 @@ automatically added space will be removed when one of the characters in the list is typed. ) item(tt(-R) var(remove-func))( -This is another form of the tt(-r) option. When a suffix -has been inserted and the completion accepted, the function +This is another form of the tt(-r) option. When a match +has been accepted and a suffix has been inserted, the function var(remove-func) will be called after the next character typed. It is passed the length of the suffix as an argument and can use the special parameters available in ordinary (non-completion) zle widgets (see @@ -654,7 +654,7 @@ ifnzman(noderef(Zsh Line Editor))\ ) to analyse and modify the command line. ) item(tt(-f))( -If this flag is given, all of the matches built from var(words) are +If this flag is given, all of the matches built from the var(completions) are marked as being the names of files. They are not required to be actual filenames, but if they are, and the option tt(LIST_TYPES) is set, the characters describing the types of the files in the completion lists will @@ -668,15 +668,14 @@ the tt(AUTO_PARAM_SLASH) and tt(AUTO_PARAM_KEYS) options be used for the matches. ) item(tt(-W) var(file-prefix))( -This string is a pathname that will be -prepended to each of the matches formed by the given var(words) together +This string is a pathname that will be prepended to each match together with any prefix specified by the tt(-p) option to form a complete filename for testing. Hence it is only useful if combined with the tt(-f) flag, as the tests will not otherwise be performed. ) item(tt(-F) var(array))( -Specifies an array containing patterns. Words matching one of these -patterns are ignored, i.e. not considered to be possible matches. +Specifies an array containing patterns. var(completions) that match one of +these patterns are ignored, that is, not considered to be matches. The var(array) may be the name of an array parameter or a list of literal patterns enclosed in parentheses and quoted, as in `tt(-F "(*?.o @@ -684,8 +683,8 @@ literal patterns enclosed in parentheses and quoted, as in `tt(-F "(*?.o taken as the patterns. ) item(tt(-Q))( -This flag instructs the completion -code not to quote any metacharacters in the words when inserting them +This flag instructs the completion +code not to quote any metacharacters in the matches when inserting them into the command line. ) item(tt(-M) var(match-spec))( @@ -696,47 +695,48 @@ between them to form the specification string to use. Note that they will only be used if the tt(-U) option is not given. ) item(tt(-n))( -Specifies that the words added are to be used as possible -matches, but are not to appear in the completion listing. +Specifies that matching var(completions) are to be added to the set of +matches, but are not to be listed to the user. ) item(tt(-U))( -If this flag is given, all words given will be accepted and no matching +If this flag is given, all var(completions) are added +to the set of matches and no matching will be done by the completion code. Normally this is used in functions that do the matching themselves. ) item(tt(-O) var(array))( -If this option is given, the var(words) are em(not) added to the set of -possible completions. Instead, matching is done as usual and all of the -var(words) given as arguments that match the string on the command line +If this option is given, the var(completions) are em(not) added to the set of +matches. Instead, matching is done as usual and all of the +var(completions) that match will be stored in the array parameter whose name is given as var(array). ) item(tt(-A) var(array))( -As the tt(-O) option, except that instead of those of the var(words) which +As the tt(-O) option, except that instead of those of the var(completions) +which match being stored in var(array), the strings generated internally by the -completion code are stored. For example, -with a matching specification of `tt(-M "L:|no=")', the string `tt(nof)' -on the command line and the string `tt(foo)' as one of the var(words), this +completion code are stored. For example, +with a match specification of `tt(-M "L:|no=")', a current word of `tt(nof)' +and var(completions) of `tt(foo)', this option stores the string `tt(nofoo)' in the array, whereas the tt(-O) option stores the `tt(foo)' originally given. ) item(tt(-D) var(array))( -As with tt(-O), the var(words) are not added to the set of possible -completions. Instead, the completion code tests whether each var(word) -in turn matches what is on the line. If the var(n)th var(word) does not +As with tt(-O), the var(completions) are not added to the set of matches. +Instead, whenever the var(n)th var(completion) does not match, the var(n)th element of the var(array) is removed. Elements -for which the corresponding var(word) is matched are retained. +for which the corresponding var(completion) matches are retained. ) item(tt(-C))( This option adds a special match which expands to all other matches when inserted into the line, even those that are added after this option is used. Together with the tt(-d) option it is possible to -specify a string that should be displayed in the list for this special -match. If no string is given, it will be shown as a string containing -the strings that would be inserted for the other matches, truncated to +specify a string that should be displayed in the list for this special +match. If no string is given, it will be shown as a string containing +the strings that would be inserted for the other matches, truncated to the width of the screen. ) item(tt(-E) var(number))( -This option adds var(number) empty matches after the var(words) have +This option adds var(number) empty matches after matching var(completions) have been added. An empty match takes up space in completion listings but will never be inserted in the line and can't be selected with menu completion or menu selection. This makes empty matches only useful to @@ -751,7 +751,7 @@ added. xitem(tt(-)) item(tt(-)tt(-))( This flag ends the list of flags and options. All arguments after it -will be taken as the words to use as matches even if they begin with +will be taken as the var(completions) even if they begin with hyphens. ) enditem() @@ -788,7 +788,7 @@ Without the optional var(number), the longest match is taken, but if var(number) is given, anything up to the var(number)th match is moved. If the var(number) is negative, the var(number)th longest match is moved. For example, if tt(PREFIX) contains the string -`tt(a=b=c)', then tt(compset -P '*\=') will move the string `tt(a=b=)' +`tt(a=b=c)', then tt(compset -P '*\=') will move the string `tt(a=b=)' into the tt(IPREFIX) parameter, but tt(compset -P 1 '*\=') will move only the string `tt(a=)'. ) @@ -801,7 +801,7 @@ As tt(-P), but match the last portion of tt(SUFFIX) and transfer the matched portion to the front of the value of tt(ISUFFIX). ) item(tt(-n) var(begin) [ var(end) ])( -If the current word position as specified by the parameter tt(CURRENT) +If the current word position as specified by the parameter tt(CURRENT) is greater than or equal to var(begin), anything up to the var(begin)th word is removed from the tt(words) array and the value of the parameter tt(CURRENT) is decremented by var(begin). @@ -824,7 +824,7 @@ point to the same word in the changed array. If the optional pattern var(end-pat) is also given, and there is an element in the tt(words) array matching this pattern, the parameters are modified only if the index of this word is higher than the one -given by the tt(CURRENT) parameter (so that the matching word has +given by the tt(CURRENT) parameter (so that the matching word has to be after the cursor). In this case, the words starting with the one matching tt(end-pat) are also removed from the tt(words) array. If tt(words) contains no word matching var(end-pat), the @@ -833,7 +833,7 @@ testing and modification is performed as if it were not given. item(tt(-q))( The word currently being completed is split on spaces into separate words, -respecting the usual shell quoting conventions. The +respecting the usual shell quoting conventions. The resulting words are stored in the tt(words) array, and tt(CURRENT), tt(PREFIX), tt(SUFFIX), tt(QIPREFIX), and tt(QISUFFIX) are modified to reflect the word part that is completed. @@ -885,7 +885,7 @@ item(tt(-suffix) [ var(number) ] var(pattern))( true if the test for the tt(-S) option of tt(compset) would succeed. ) item(tt(-after) var(beg-pat))( -true if the test of the tt(-N) option with only the var(beg-pat) given +true if the test of the tt(-N) option with only the var(beg-pat) given would succeed. ) item(tt(-between) var(beg-pat end-pat))( @@ -896,275 +896,286 @@ enditem() texinode(Completion Matching Control)(Completion Widget Example)(Completion Condition Codes)(Completion Widgets) sect(Completion Matching Control) -It is possible by use of the -tt(-M) option of the tt(compadd) builtin command to specify how the -characters in the string to be completed (referred to here as the -command line) map onto the characters in the list of matches produced by -the completion code (referred to here as the trial completions). Note -that this is not used if the command line contains a glob pattern and -the tt(GLOB_COMPLETE) option is set or the tt(pattern_match) of the -tt(compstate) special association is set to a non-empty string. +When the user invokes completion, the current em(word) on the command line +(that is, the word the cursor is currently on) is used to generate a em(match +pattern). Only those em(completions) that match the pattern are offered to the +user as em(matches). -The var(match-spec) given as the argument to the tt(-M) option (see +The default match pattern is generated from the current word by either + +startitemize() +itemiz(\ +appending a `tt(*)' (matching any number of characters in a completion) +em(or,)\ +) +itemiz(\ +if the shell option tt(COMPLETE_IN_WORD) is set, inserting a `tt(*)' at the +cursor position.\ +) +enditemize() + +This narrow pattern can be broadened selectively by passing a em(match +specification) to the tt(compadd) builtin command through its tt(-M) option +(see ifzman(`Completion Builtin Commands' above)\ ifnzman(noderef(Completion Builtin Commands))\ -) consists of one or more matching descriptions separated by -whitespace. Each description consists of a letter followed by a colon -and then the patterns describing which character sequences on the line match -which character sequences in the trial completion. Any sequence of -characters not handled in this fashion must match exactly, as usual. - -The forms of var(match-spec) understood are as follows. In each case, the -form with an upper case initial character retains the string already -typed on the command line as the final result of completion, while with -a lower case initial character the string on the command line is changed -into the corresponding part of the trial completion. +). A match specification consists of one or more var(matchers) separated by +whitespace. Matchers in a match specification are applied one at a time, from +left to right. Once all matchers have been applied, completions are compared +to the final match pattern and non-matching ones are discarded. + +startitemize() +itemiz(\ +Note that the tt(-M) option is ignored if the current word contains a glob +pattern and the shell option tt(GLOB_COMPLETE) is set or if the +tt(pattern_match) key of the special associative array tt(compstate) is set to +a non-empty value (see +ifzman(`Completion Special Parameters' above)\ +ifnzman(noderef(Completion Special Parameters))\ +).\ +) +itemiz(\ +Users of the \ +ifzman(completion system (see zmanref(zshcompsys))) \ +ifnzman(noderef(Completion System)) \ +should generally not use the tt(-M) option directly, but rather use the +tt(matcher-list) and tt(matcher) styles (see the subsection em(Standard Styles) +in +ifzman(\ +the documentation for COMPLETION SYSTEM CONFIGURATION in zmanref(zshcompsys))\ +ifnzman(noderef(Completion System Configuration))\ +).\ +) +enditemize() + +Each matcher consists of + +startitemize() +itemiz(a case-sensitive letter) +itemiz(a `tt(:)',) +itemiz(one or more patterns separated by pipes (`tt(|)'),) +itemiz(an equals sign (`tt(=)'), and) +itemiz(another pattern.) +enditemize() + +The patterns before the `tt(=)' are used to match substrings of the current +word. For each matched substring, the corresponding part of the match pattern +is broadened with the pattern after the `tt(=)', by means of a logical tt(OR). + +Each pattern in a matcher cosists of either + +startitemize() +itemiz(the empty string or) +itemiz(a sequence of + +startitemize() +itemiz(literal characters (which may be quoted with a `tt(\)'),) +itemiz(question marks (`tt(?)'),) +itemiz(\ +bracket expressions (`tt([...])'; see the subsection em(Glob Operators) in +ifnzman(noderef(Filename Generation))\ +ifzman(the documentation for GLOB OPERATORS in zmanref(zshexpn))\ +), and/or\ +) +itemiz(brace expressions (see below).) +enditemize() +) +enditemize() + +Other shell patterns are not allowed. + +A brace expression, like a bracket expression, consists of a list of + +startitemize() +itemiz(literal characters,) +itemiz(ranges (`tt(0-9)'), and/or) +itemiz(character classes (`tt([:)var(name)tt(:])').) +enditemize() + +However, they differ from each other as follows: + +startitemize() +itemiz(\ +A brace expression is delimited by a pair of braces (`tt({...})').\ +) +itemiz(\ +Brace expressions do not support negations. That is, an initial +`tt(!)' or `tt(^)' has no special meaning and will be interpreted as a literal +character.\ +) +itemiz(\ +When a character in the current word matches the var(n)th pattern in a brace +expression, the corresponding part of the match pattern is broadened only with +the var(n)th pattern of the brace expression on the other side of the `tt(=)', +if there is one; if there is no brace expression on the other side, then this +pattern is the empty string. However, if either brace expression has more +elements than the other, then the excess entries are simply ignored. When +comparing indexes, each literal character or character class counts as one +element, but each range is instead expanded to the full list of literal +characters it represents. Additionally, if on em(both) sides of the +`tt(=)', the var(n)th pattern is `tt([:upper:])' or `tt([:lower:])', then these +are expanded as ranges, too.\ +) +enditemize() + +Note that, although the matching system does not yet handle multibyte +characters, this is likely to be a future extension. Hence, using +`tt([:upper:])' and `tt([:lower:])' is recommended over +`tt(A-Z)' and `tt(a-z)'. + +Below are the different forms of matchers supported. Each em(uppercase) form +behaves exactly like its lowercase counterpart, but adds an additional step +em(after) the match pattern has filtered out non-matching completions: Each of +a match's substrings that was matched by a subpattern from an uppercase matcher +is replaced with the corresponding substring of the current word. However, +patterns from em(lowercase) matchers have higher weight: If a substring of the +current word was matched by patterns from both a lowercase and an uppercase +matcher, then the lowercase matcher's pattern wins and the corresponding part +of the match is not modified. + +Unless indicated otherwise, each example listed assumes tt(COMPLETE_IN_WORD) to +be unset (as it is by default). startitem() -xitem(tt(m:)var(lpat)tt(=)var(tpat)) -item(tt(M:)var(lpat)tt(=)var(tpat))( -Here, var(lpat) is a pattern that matches on the command line, -corresponding to var(tpat) which matches in the trial completion. -) -xitem(tt(l:)var(lanchor)tt(|)var(lpat)tt(=)var(tpat)) -xitem(tt(L:)var(lanchor)tt(|)var(lpat)tt(=)var(tpat)) -xitem(tt(l:)var(lanchor)tt(||)var(ranchor)tt(=)var(tpat)) -xitem(tt(L:)var(lanchor)tt(||)var(ranchor)tt(=)var(tpat)) -xitem(tt(b:)var(lpat)tt(=)var(tpat)) -item(tt(B:)var(lpat)tt(=)var(tpat))( -These letters are for patterns that are anchored by another pattern on -the left side. Matching for var(lpat) and var(tpat) is as for tt(m) and -tt(M), but the pattern var(lpat) matched on the command line must be -preceded by the pattern var(lanchor). The var(lanchor) can be blank to -anchor the match to the start of the command line string; otherwise the -anchor can occur anywhere, but must match in both the command line and -trial completion strings. - -If no var(lpat) is given but a var(ranchor) is, this matches the gap -between substrings matched by var(lanchor) and var(ranchor). Unlike -var(lanchor), the var(ranchor) only needs to match the trial -completion string. - -The tt(b) and tt(B) forms are similar to tt(l) and tt(L) with an empty -anchor, but need to match only the beginning of the word on the command line -or trial completion, respectively. -) -xitem(tt(r:)var(lpat)tt(|)var(ranchor)tt(=)var(tpat)) -xitem(tt(R:)var(lpat)tt(|)var(ranchor)tt(=)var(tpat)) -xitem(tt(r:)var(lanchor)tt(||)var(ranchor)tt(=)var(tpat)) -xitem(tt(R:)var(lanchor)tt(||)var(ranchor)tt(=)var(tpat)) -xitem(tt(e:)var(lpat)tt(=)var(tpat)) -item(tt(E:)var(lpat)tt(=)var(tpat))( -As tt(l), tt(L), tt(b) and tt(B), with the difference that the command -line and trial completion patterns are anchored on the right side. -Here an empty var(ranchor) and the tt(e) and tt(E) forms force the -match to the end of the command line or trial completion string. - -In the form where var(lanchor) is given, the var(lanchor) only needs -to match the trial completion string. +xitem(tt(m:)var(word-pat)tt(=)var(match-pat)) +item(tt(M:)var(word-pat)tt(=)var(match-pat))( + +For each substring of the current word that matches var(word-pat), broaden the +corresponding part of the match pattern to additionally match var(match-pat). + +startitem() +item(Examples:)( + +tt(m:{[:lower:]}={[:upper:]}) lets any lower case character in the current word +be completed to itself or its uppercase counterpart. So, the completions +`tt(foo)', `tt(FOO)' and `tt(Foo)' will are be considered matches for the word +`tt(fo)'. + +tt(M:_=) inserts every underscore from the current word into each match, in the +same relative position, determined by matching the substrings around it. So, +given a completion `tt(foo)', the word `tt(f_o)' will be completed to the match +`tt(f_oo)', even though the latter was not present as a completion. ) -item(tt(x:))( -This form is used to mark the end of matching specifications: -subsequent specifications are ignored. In a single standalone list -of specifications this has no use but where matching specifications -are accumulated, such as from nested function calls, it can allow one -function to override another. +enditem() +) +xitem(tt(b:)var(word-pat)tt(=)var(match-pat)) +xitem(tt(B:)var(word-pat)tt(=)var(match-pat)) +xitem(tt(e:)var(word-pat)tt(=)var(match-pat)) +item(tt(E:)var(word-pat)tt(=)var(match-pat))( + +For each consecutive substring at the tt(b:)eginning or tt(e:)nd of the current +word that matches var(word-pat), broaden the corresponding part of the match +pattern to additionally match var(match-pat). + +startitem() +item(Examples:)( + +`tt(b:-=+)' lets any number of minuses at the start of the current word be +completed to a minus or a plus. + +`tt(B:0=)' adds all zeroes at the beginning of the current word to the +beginning of each match. ) enditem() +) +xitem(tt(l:)tt(|)var(word-pat)tt(=)var(match-pat)) +xitem(tt(L:)tt(|)var(word-pat)tt(=)var(match-pat)) +xitem(tt(R:)var(word-pat)tt(|)tt(=)var(match-pat)) +item(tt(r:)var(word-pat)tt(|)tt(=)var(match-pat))( -Each var(lpat), var(tpat) or var(anchor) is either an empty string or -consists of a sequence of literal characters (which may be quoted with a -backslash), question marks, character classes, and correspondence -classes; ordinary shell patterns are not used. Literal characters match -only themselves, question marks match any character, and character -classes are formed as for globbing and match any character in the given -set. - -Correspondence classes are defined like character classes, but with two -differences: they are delimited by a pair of braces, and negated classes -are not allowed, so the characters tt(!) and tt(^) have no special -meaning directly after the opening brace. They indicate that a range of -characters on the line match a range of characters in the trial -completion, but (unlike ordinary character classes) paired according to -the corresponding position in the sequence. For example, to make any -ASCII lower case letter on the line match the corresponding upper case -letter in the trial completion, you can use `tt(m:{a-z}={A-Z})' -(however, see below for the recommended form for this). More -than one pair of classes can occur, in which case the first class before -the tt(=) corresponds to the first after it, and so on. If one side has -more such classes than the other side, the superfluous classes behave -like normal character classes. In anchor patterns correspondence classes -also behave like normal character classes. - -The standard `tt([:)var(name)tt(:])' forms described for standard shell -patterns (see -ifnzman(noderef(Filename Generation))\ -ifzman(the section FILENAME GENERATION in zmanref(zshexpn))) -may appear in correspondence classes as well as normal character -classes. The only special behaviour in correspondence classes is if -the form on the left and the form on the right are each one of -tt([:upper:]), tt([:lower:]). In these cases the -character in the word and the character on the line must be the same up -to a difference in case. Hence to make any lower case character on the -line match the corresponding upper case character in the trial -completion you can use `tt(m:{[:lower:]}={[:upper:]})'. Although the -matching system does not yet handle multibyte characters, this is likely -to be a future extension, at which point this syntax will handle -arbitrary alphabets; hence this form, rather than the use of explicit -ranges, is the recommended form. In other cases -`tt([:)var(name)tt(:])' forms are allowed. If the two forms on the left -and right are the same, the characters must match exactly. In remaining -cases, the corresponding tests are applied to both characters, but they -are not otherwise constrained; any matching character in one set goes -with any matching character in the other set: this is equivalent to the -behaviour of ordinary character classes. - -The pattern var(tpat) may also be one or two stars, `tt(*)' or -`tt(**)'. This means that the pattern on the command line can match -any number of characters in the trial completion. In this case the -pattern must be anchored (on either side); in the case of a single -star, the var(anchor) then determines how much of the trial completion -is to be included DASH()- only the characters up to the next appearance of -the anchor will be matched. With two stars, substrings matched by -the anchor can be matched, too. In the forms that include two -anchors, `tt(*)' can match characters from the additional anchor -DASH()- var(lanchor) with tt(r) or var(ranchor) with tt(l). - -Examples: - -The keys of the tt(options) association defined by the tt(parameter) -module are the option names in all-lower-case form, without -underscores, and without the optional tt(no) at the beginning even -though the builtins tt(setopt) and tt(unsetopt) understand option names -with upper case letters, underscores, and the optional tt(no). The -following alters the matching rules so that the prefix tt(no) and any -underscore are ignored when trying to match the trial completions -generated and upper case letters on the line match the corresponding -lower case letters in the words: - -example(compadd -M 'L:|[nN][oO]= M:_= M:{[:upper:]}={[:lower:]}' - \ - ${(k)options} ) - -The first part says that the pattern `tt([nN][oO])' at the beginning -(the empty anchor before the pipe symbol) of the string on the -line matches the empty string in the list of words generated by -completion, so it will be ignored if present. The second part does the -same for an underscore anywhere in the command line string, and the -third part uses correspondence classes so that any -upper case letter on the line matches the corresponding lower case -letter in the word. The use of the upper case forms of the -specification characters (tt(L) and tt(M)) guarantees that what has -already been typed on the command line (in particular the prefix -tt(no)) will not be deleted. - -Note that the use of tt(L) in the first part means that it matches -only when at the beginning of both the command line string and the -trial completion. I.e., the string `tt(_NO_f)' would not be -completed to `tt(_NO_foo)', nor would `tt(NONO_f)' be completed to -`tt(NONO_foo)' because of the leading underscore or the second -`tt(NO)' on the line which makes the pattern fail even though they are -otherwise ignored. To fix this, one would use `tt(B:[nN][oO]=)' -instead of the first part. As described above, this matches at the -beginning of the trial completion, independent of other characters or -substrings at the beginning of the command line word which are ignored -by the same or other var(match-spec)s. - -The second example makes completion case insensitive. This is just -the same as in the option example, except here we wish to retain the -characters in the list of completions: - -example(compadd -M 'm:{[:lower:]}={[:upper:]}' ... ) - -This makes lower case letters match their upper case counterparts. -To make upper case letters match the lower case forms as well: - -example(compadd -M 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' ... ) - -A nice example for the use of tt(*) patterns is partial word -completion. Sometimes you would like to make strings like `tt(c.s.u)' -complete to strings like `tt(comp.source.unix)', i.e. the word on the -command line consists of multiple parts, separated by a dot in this -example, where each part should be completed separately DASH()- note, -however, that the case where each part of the word, i.e. `tt(comp)', -`tt(source)' and `tt(unix)' in this example, is to be completed from -separate sets of matches -is a different problem to be solved by the implementation of the -completion widget. The example can be handled by: - -example(compadd -M 'r:|.=* r:|=*' \ - - comp.sources.unix comp.sources.misc ...) - -The first specification says that var(lpat) is the empty string, while -var(anchor) is a dot; var(tpat) is tt(*), so this can match anything -except for the `tt(.)' from the anchor in -the trial completion word. So in `tt(c.s.u)', the matcher sees `tt(c)', -followed by the empty string, followed by the anchor `tt(.)', and -likewise for the second dot, and replaces the empty strings before the -anchors, giving `tt(c)[tt(omp)]tt(.s)[tt(ources)]tt(.u)[tt(nix)]', where -the last part of the completion is just as normal. - -With the pattern shown above, the string `tt(c.u)' could not be -completed to `tt(comp.sources.unix)' because the single star means -that no dot (matched by the anchor) can be skipped. By using two stars -as in `tt(r:|.=**)', however, `tt(c.u)' could be completed to -`tt(comp.sources.unix)'. This also shows that in some cases, -especially if the anchor is a real pattern, like a character class, -the form with two stars may result in more matches than one would like. - -The second specification is needed to make this work when the cursor is -in the middle of the string on the command line and the option -tt(COMPLETE_IN_WORD) is set. In this case the completion code would -normally try to match trial completions that end with the string as -typed so far, i.e. it will only insert new characters at the cursor -position rather than at the end. However in our example we would like -the code to recognise matches which contain extra characters after the -string on the line (the `tt(nix)' in the example). Hence we say that the -empty string at the end of the string on the line matches any characters -at the end of the trial completion. - -More generally, the specification - -example(compadd -M 'r:|[.,_-]=* r:|=*' ... ) - -allows one to complete words with abbreviations before any of the -characters in the square brackets. For example, to -complete tt(veryverylongfile.c) rather than tt(veryverylongheader.h) -with the above in effect, you can just type tt(very.c) before attempting -completion. - -The specifications with both a left and a right anchor are useful to -complete partial words whose parts are not separated by some -special character. For example, in some places strings have to be -completed that are formed `tt(LikeThis)' (i.e. the separate parts are -determined by a leading upper case letter) or maybe one has to -complete strings with trailing numbers. Here one could use the simple -form with only one anchor as in: - -example(compadd -M 'r:|[[:upper:]0-9]=* r:|=*' LikeTHIS FooHoo 5foo123 5bar234) - -But with this, the string `tt(H)' would neither complete to `tt(FooHoo)' -nor to `tt(LikeTHIS)' because in each case there is an upper case -letter before the `tt(H)' and that is matched by the anchor. Likewise, -a `tt(2)' would not be completed. In both cases this could be changed -by using `tt(r:|[[:upper:]0-9]=**)', but then `tt(H)' completes to both -`tt(LikeTHIS)' and `tt(FooHoo)' and a `tt(2)' matches the other -strings because characters can be inserted before every upper case -letter and digit. To avoid this one would use: - -example(compadd -M 'r:[^[:upper:]0-9]||[[:upper:]0-9]=** r:|=*' \ - LikeTHIS FooHoo foo123 bar234) - -By using these two anchors, a `tt(H)' matches only upper case `tt(H)'s that -are immediately preceded by something matching the left anchor -`tt([^[:upper:]0-9])'. The effect is, of course, that `tt(H)' matches only -the string `tt(FooHoo)', a `tt(2)' matches only `tt(bar234)' and so on. - -When using the completion system (see -ifzman(zmanref(zshcompsys))\ +If there is a substring at the tt(l:)eft or tt(r:)ight edge of the current word +that matches var(word-pat), then broaden the corresponding part of the match +pattern to additionally match var(match-pat). + +For each tt(l:), tt(L:), tt(r:) and tt(R:) matcher (including the ones below), +the pattern var(match-pat) may also be a `tt(*)'. This matches any number of +characters in a completion. + +startitem() +item(Examples:)( + +`tt(r:|=*)' appends a `tt(*)' to the match pattern, even when +tt(COMPLETE_IN_WORD) is set and the cursor is not at the end of the current +word. + +If the current word starts with a minus, then `tt(L:|-=)' will prepend it to +each match. +) +enditem() +) +xitem(tt(l:)var(anchor)tt(|)var(word-pat)tt(=)var(match-pat)) +xitem(tt(L:)var(anchor)tt(|)var(word-pat)tt(=)var(match-pat)) +xitem(tt(r:)var(word-pat)tt(|)var(anchor)tt(=)var(match-pat)) +item(tt(R:)var(word-pat)tt(|)var(anchor)tt(=)var(match-pat))( + +For each substring of the current word that matches var(word-pat) and has on +its tt(l:)eft or tt(r:)ight another substring matching var(anchor), broaden the +corresponding part of the match pattern to additionally match var(match-pat). + +Note that these matchers (and the ones below) modify only what is matched by +var(word-pat); they do not change the matching behavior of what is matched by +var(anchor) (or var(coanchor); see the matchers below). Thus, unless its +corresponding part of the match pattern has been modified, the anchor in the +current word has to match literally in each completion, just like any other +substring of the current word. + +If a matcher includes at least one anchor (which includes the matchers with two +anchors, below), then var(match-pat) may also be `tt(*)' or `tt(**)'. `tt(*)' +can match any part of a completion that does not contain any substrings +matching var(anchor), whereas a `tt(**)' can match any part of a completion, +period. (Note that this is different from the behavior of `tt(*)' in the +anchorless forms of `tt(l:)' and `tt(r:)' and and also different from `tt(*)' +and `tt(**)' in glob expressions.) + +startitem() +item(Examples:)( + +`tt(r:|.=*)' makes the completion `tt(comp.sources.unix)' a match for the word +`tt(..u)' DASH()- but em(not) for the word `tt(.u)'. + +Given a completion `tt(-)tt(-foo)', the matcher `tt(L:--|no-=)' will complete +the word `tt(-)tt(-no-)' to the match `tt(-)tt(-no-foo)'. +) +enditem() +) +xitem(tt(l:)var(anchor)tt(||)var(coanchor)tt(=)var(match-pat)) +xitem(tt(L:)var(anchor)tt(||)var(coanchor)tt(=)var(match-pat)) +xitem(tt(r:)var(coanchor)tt(||)var(anchor)tt(=)var(match-pat)) +item(tt(R:)var(coanchor)tt(||)var(anchor)tt(=)var(match-pat))( + +For any two consecutive substrings of the current word that match var(anchor) +and var(coanchor), in the order given, insert the pattern var(match-pat) +between their corresponding parts in the match pattern. + +Note that, unlike var(anchor), the pattern var(coanchor) does not change what +`tt(*)' can match. + +startitem() +item(Examples:)( + +`tt(r:?||[[:upper:]]=*)' will complete the current word `tt(fB)' to +`tt(fooBar)', but it will not complete it to `tt(fooHooBar)' (because `tt(*)' +here cannot match anything that includes a match for `tt([[:upper:]])), nor +will it complete `tt(B)' to `tt(fooBar)' (because there is no character in the +current word to match var(coanchor)). + +Given the current word `tt(pass.n)' and a completion `tt(pass.byname)', the +matcher `tt(L:.||[[:alpha:]]=by)' will produce the match `tt(pass.name)'. +) +enditem() +) +item(tt(x:))( + +Ignore this matcher and all matchers to its right. + +This matcher is used to mark the end of a match specification. In a single +standalone list of matchers, this has no use, but where match specifications +are concatenated, as is often the case when using the +ifzman(completion system (see zmanref(zshcompsys)))\ ifnzman(noderef(Completion System))\ -), users can define match specifications that are to be used for -specific contexts by using the tt(matcher) and tt(matcher-list) -styles. The values for the latter will be used everywhere. +, it can allow one match specification to override another. +) +enditem() texinode(Completion Widget Example)()(Completion Matching Control)(Completion Widgets) sect(Completion Widget Example) @@ -1185,5 +1196,5 @@ matches, e.g.: example(complete-files LPAR()RPAR() { compadd - * }) -This function will complete files in the current directory matching the +This function will complete files in the current directory matching the current word. diff --git a/Test/Y02compmatch.ztst b/Test/Y02compmatch.ztst index 621707482..4a0a1a060 100644 --- a/Test/Y02compmatch.ztst +++ b/Test/Y02compmatch.ztst @@ -378,15 +378,26 @@ comp.graphics.rendering.misc comp.graphics.rendering.raytracing comp.graphics.rendering.renderman) test_code $example4_matcher example4_list - comptest $'tst c.s.u\t' -0:Documentation example using input c.s.u + comptest $'tst .s.u\t' +0:r:|.=* should complete .s.u +>line: {tst comp.sources.unix }{} +>COMPADD:{} +>INSERT_POSITIONS:{21} + + example4b_matcher='r:[^.]||.=* r:|=*' + test_code $example4b_matcher example4_list + comptest $'tst .s.u\t^[bc\t' +0f:r:[^.]||.=* should not complete .s.u, but should complete c.s.u +>line: {tst .s.u}{} +>COMPADD:{} +>INSERT_POSITIONS:{} >line: {tst comp.sources.unix }{} >COMPADD:{} >INSERT_POSITIONS:{21} test_code $example4_matcher example4_list - comptest $'tst c.g.\ta\t.\tp\ta\tg\t' -0:Documentation example using input c.g.\ta\t.\tp\ta\tg\t + comptest $'tst .g.\ta\t.\tp\ta\tg\t' +0f:r:|.=* should complete .g. >line: {tst comp.graphics.}{} >COMPADD:{} >INSERT_POSITIONS:{18} @@ -424,9 +435,32 @@ >COMPADD:{} >INSERT_POSITIONS:{32} + test_code $example4b_matcher example4_list + comptest $'tst .g.\t^[bc\t' +0f:r:[^.]||.=* should not complete .g., but should complete c.g. +>line: {tst .g.}{} +>COMPADD:{} +>INSERT_POSITIONS:{} +>line: {tst comp.graphics.}{} +>COMPADD:{} +>INSERT_POSITIONS:{18} + test_code $example4_matcher example4_list - comptest $'tst c...pag\t' -0:Documentation example using input c...pag\t + comptest $'tst ...pag\t' +0:r:|.=* should complete ...pag +>line: {tst comp.graphics.apps.pagemaker }{} +>COMPADD:{} +>INSERT_POSITIONS:{32} + + test_code $example4b_matcher example4_list + comptest $'tst ...pag\t^[bc\t^Fg^F^Fa\t' +0f:r:[^.]||.=* should not complete ...pag or c...pag, but should complete c.g.a.p +>line: {tst ...pag}{} +>COMPADD:{} +>INSERT_POSITIONS:{} +>line: {tst c...pag}{} +>COMPADD:{} +>INSERT_POSITIONS:{} >line: {tst comp.graphics.apps.pagemaker }{} >COMPADD:{} >INSERT_POSITIONS:{32} @@ -444,8 +478,8 @@ example5_matcher='r:|[.,_-]=* r:|=*' example5_list=(veryverylongfile.c veryverylongheader.h) test_code $example5_matcher example5_list - comptest $'tst v.c\tv.h\t' -0:Documentation example using input v.c\t + comptest $'tst .c\t.h\t' +0:r:|[.,_-]=* should complete .c and .h >line: {tst veryverylongfile.c }{} >COMPADD:{} >INSERT_POSITIONS:{23} @@ -453,6 +487,23 @@ >COMPADD:{} >INSERT_POSITIONS:{44} + example5b_matcher='r:[^.,_-]||[.,_-]=* r:|=*' + test_code $example5b_matcher example5_list + comptest $'tst .c\t^[bv\t.h\t^[bv\t' +0f:r:[^.,_-]||[.,_-]=* should not complete .c or .h, but should complete v.c and v.h +>line: {tst .c}{} +>COMPADD:{} +>INSERT_POSITIONS:{} +>line: {tst veryverylongfile.c }{} +>COMPADD:{} +>INSERT_POSITIONS:{23} +>line: {tst veryverylongfile.c .h}{} +>COMPADD:{} +>INSERT_POSITIONS:{} +>line: {tst veryverylongfile.c veryverylongheader.h }{} +>COMPADD:{} +>INSERT_POSITIONS:{44} + example6_list=(LikeTHIS FooHoo 5foo123 5bar234) test_code 'r:|[A-Z0-9]=* r:|=*' example6_list @@ -493,16 +544,57 @@ example7_matcher="r:[^A-Z0-9]||[A-Z0-9]=** r:|=*" example7_list=($example6_list) test_code $example7_matcher example7_list - comptest $'tst H\t2\t' -0:Documentation example using "r:[^A-Z0-9]||[A-Z0-9]=** r:|=*" + comptest $'tst H\t^BF\to\t2\t^B5\tb\t' +0f:r:[^A-Z0-9]||[A-Z0-9]=** should not complete H, FH, 2 or 52, but should complete FoH and 5b2. +>line: {tst H}{} +>COMPADD:{} +>INSERT_POSITIONS:{} +>line: {tst F}{H} +>COMPADD:{} +>INSERT_POSITIONS:{} >line: {tst FooHoo }{} >COMPADD:{} >INSERT_POSITIONS:{10} +>line: {tst FooHoo 2}{} +>COMPADD:{} +>INSERT_POSITIONS:{} +>line: {tst FooHoo 5}{2} +>COMPADD:{} +>INSERT_POSITIONS:{} +>line: {tst FooHoo 5bar234 }{} +>COMPADD:{} +>INSERT_POSITIONS:{18} + + example7b_matcher="r:?||[A-Z0-9]=* r:|=*" + test_code $example7b_matcher example7_list + comptest $'tst H\t^BF2\t^B5\t' +0f:r:?||[A-Z0-9]=* r:|=* should not complete H or 2, but should complete FH and 52. +>line: {tst H}{} +>COMPADD:{} +>INSERT_POSITIONS:{} +>line: {tst FooHoo }{} +>COMPADD:{} +>INSERT_POSITIONS:{10} +>line: {tst FooHoo 2}{} +>COMPADD:{} +>INSERT_POSITIONS:{} >line: {tst FooHoo 5bar234 }{} >COMPADD:{} >INSERT_POSITIONS:{18} + example8_list=(passwd.byname) + test_code 'r:[^.]||.=* l:.||[^.]=*' + comptest $'tst .^B\tpass^Fname\t' +0f:r:[^.]||.=* and l:.||[^.]=* should work symmetrically. +>line: {tst }{.} +>COMPADD:{} +>INSERT_POSITIONS:{} +>line: {tst passwd.byname }{} +>COMPADD:{} +>INSERT_POSITIONS:{17} + + workers_7311_matcher="m:{a-z}={A-Z} r:|[.,_-]=* r:|=*" workers_7311_list=(Abc-Def-Ghij.txt Abc-def.ghi.jkl_mno.pqr.txt Abc_def_ghi_jkl_mno_pqr.txt) test_code $workers_7311_matcher workers_7311_list @@ -537,11 +629,11 @@ >COMPADD:{} >INSERT_POSITIONS:{5} - workers_11081_matcher='m:{a-zA-Z}={A-Za-z} r:|[.,_-]=* r:[^A-Z0-9]||[A-Z0-9]=* r:[A-Z0-9]||[^A-Z0-9]=* r:[^0-9]||[0-9]=* r:|=*' + workers_11081_matcher='m:{a-zA-Z}={A-Za-z} r:|[.,_-]=* r:|=*' workers_11081_list=(build.out build.out1 build.out2) test_code $workers_11081_matcher workers_11081_list comptest $'tst bui\t\t\t' -0:Bug from workers 11081 +0:Erratic completion bug from workers 11081: bui > build.out[] > build[.]out > build.out[] > build.out1[] > build.out2[] >line: {tst build.out}{} >COMPADD:{} >INSERT_POSITIONS:{13} @@ -578,7 +670,7 @@ workers_11586_list=(c00.abc c01.abc.def.00.0) test_code $workers_11586_matcher workers_11586_list comptest $'tst c00\t.\ta\t' -0:Bug from workers 11586 +0:Disappearing characters bug from workers 11586: c00\t -> c0[], c00\t -> c0.abc[], c00.\t -> c0.abc[] >line: {tst c00}{} >COMPADD:{} >INSERT_POSITIONS:{6} @@ -611,12 +703,12 @@ >COMPADD:{} >INSERT_POSITIONS:{22} - workers_13320_matcher='r:|[.,_-]=** r:[^0-9]||[0-9]=**' + workers_13320_matcher='r:|[.,_-]=**' workers_13320_list=(glibc-2.1.94-3.i386.rpm glibc-devel-2.1.94-3.i386.rpm) workers_13320_list=($workers_13320_list glibc-profile-2.1.94-3.i386.rpm) test_code $workers_13320_matcher workers_13320_list comptest $'tst glibc-2.1\t' -0:Test from workers 13320 +0:Incorrect cursor position bug from workers 13320: glibc-2.1\t -> glibc-2[.]1.94-3.i386.rpm >line: {tst glibc}{-2.1.94-3.i386.rpm} >COMPADD:{} >INSERT_POSITIONS:{9:27} @@ -641,11 +733,11 @@ >NO:{A.C} - workers_13345b_matcher='r:|[.,_-]=** r:[^0-9]||[0-9]=**' + workers_13345b_matcher='r:|[.,_-]=** r:|[0-9]=**' workers_13345b_list=(a-b_1_2_2 a-b_2_0.gz a-b_2_0.zip) test_code $workers_13345b_matcher workers_13345b_list comptest $'tst a-b_2\t' -0:Second test from workers 13345 +0:Disappearing character bug from workers 13345: a-b_2\t -> a-b__ >line: {tst a-b_2_}{} >COMPADD:{} >INSERT_POSITIONS:{8:10} -- cgit v1.2.3 From 632fee7cdfcd234a5c7c53f17777ca18e62d82e3 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Sat, 30 Oct 2021 23:27:29 +0200 Subject: 49528: allow multiple -D options to compadd --- ChangeLog | 4 +++ Completion/X/Command/_xinput | 3 +-- Completion/Zsh/Command/_compadd | 2 +- Doc/Zsh/compwid.yo | 2 ++ Src/Zle/comp.h | 2 +- Src/Zle/compcore.c | 59 ++++++++++++++++++++++++++++------------- Src/Zle/complete.c | 21 ++++++++++++--- 7 files changed, 68 insertions(+), 25 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 0f1886220..7721ccc8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2021-10-30 Oliver Kiddle + * 49528: Src/Zle/comp.h, Src/Zle/compcore.c, Src/Zle/complete.c, + Completion/X/Command/_xinput, Completion/Zsh/Command/_compadd, + Doc/Zsh/compwid.yo: allow multiple -D options to compadd + * unposted (c.f. Bart: 49531): Test/Y02compmatch.ztst: fix test 2021-10-27 Matthew Martin diff --git a/Completion/X/Command/_xinput b/Completion/X/Command/_xinput index 00a976d5d..2bbadd65a 100644 --- a/Completion/X/Command/_xinput +++ b/Completion/X/Command/_xinput @@ -106,8 +106,7 @@ case $state in if [[ $PREFIX$SUFFIX = [^-]*[^0-9]* ]]; then # match based on the names but insert IDs - compadd "$expl[@]" -M 'b:=* m:{[:lower:]}={[:upper:]}' -D ids -a names - compadd "$expl[@]" -M 'b:=* m:{[:lower:]}={[:upper:]}' -D disp -a names + compadd "$expl[@]" -M 'b:=* m:{[:lower:]}={[:upper:]}' -D ids -D disp -a names compadd "$expl[@]" -U -ld disp -a ids && ret=0 zstyle -s ":completion:${curcontext}:input-devices" insert-ids out || out=menu diff --git a/Completion/Zsh/Command/_compadd b/Completion/Zsh/Command/_compadd index 9c92cda76..4456cf71e 100644 --- a/Completion/Zsh/Command/_compadd +++ b/Completion/Zsh/Command/_compadd @@ -31,7 +31,7 @@ args=( '-n[hide matches in completion listing]' '-O+[populate array with matches instead of adding them]:array:_parameters -g "*array*"' '-A+[populate array with expanded matches instead of adding them]:array:_parameters -g "*array*"' - '-D+[delete elements from array corresponding to non-matching candidates]:array:_parameters -g "*array*"' + '*-D+[delete elements from array corresponding to non-matching candidates]:array:_parameters -g "*array*"' ) case $service in diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo index 9f67f13b7..d32a0702f 100644 --- a/Doc/Zsh/compwid.yo +++ b/Doc/Zsh/compwid.yo @@ -725,6 +725,8 @@ As with tt(-O), the var(completions) are not added to the set of matches. Instead, whenever the var(n)th var(completion) does not match, the var(n)th element of the var(array) is removed. Elements for which the corresponding var(completion) matches are retained. +This option can be used more than once to remove elements from multiple +arrays. ) item(tt(-C))( This option adds a special match which expands to all other matches diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index 2e3249b52..0c5fbd4f0 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -329,7 +329,7 @@ struct cadata { char *exp; /* explanation (-X) */ char *apar; /* array to store matches in (-A) */ char *opar; /* array to store originals in (-O) */ - char *dpar; /* array to delete non-matches in (-D) */ + char **dpar; /* arrays to delete non-matches in (-D) */ char *disp; /* array with display lists (-d) */ char *mesg; /* message to show unconditionally (-x) */ int dummies; /* add that many dummy matches */ diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 63136854e..2f3d53834 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -2081,10 +2081,10 @@ addmatches(Cadata dat, char **argv) /* ms: "match string" - string to use as completion. * Overloaded at one place as a temporary. */ char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL; - char **aign = NULL, **dparr = NULL, *oaq = autoq, *oppre = dat->ppre; + char **aign = NULL, ***dparr = NULL, *oaq = autoq, *oppre = dat->ppre; char *oqp = qipre, *oqs = qisuf, qc, **disp = NULL, *ibuf = NULL; char **arrays = NULL; - int lpl, lsl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0; + int dind, lpl, lsl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0; int ppl = 0, psl = 0, ilen = 0; int llpl = 0, llsl = 0, nm = mnum, gflags = 0, ohp = haspattern; int isexact, doadd, ois = instring, oib = inbackt; @@ -2092,7 +2092,7 @@ addmatches(Cadata dat, char **argv) struct cmlist mst; Cmlist oms = mstack; Patprog cp = NULL, *pign = NULL; - LinkList aparl = NULL, oparl = NULL, dparl = NULL; + LinkList aparl = NULL, oparl = NULL, *dparl = NULL; Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl; Heap oldheap; @@ -2186,11 +2186,24 @@ addmatches(Cadata dat, char **argv) if (dat->opar) oparl = newlinklist(); if (dat->dpar) { - if (*(dat->dpar) == '(') - dparr = NULL; - else if ((dparr = get_user_var(dat->dpar)) && !*dparr) - dparr = NULL; - dparl = newlinklist(); + int darr = 0, dparlen = arrlen(dat->dpar); + char **tail = dat->dpar + dparlen; + + dparr = (char ***)hcalloc((1 + dparlen) * sizeof(char **)); + dparl = (LinkList *)hcalloc((1 + dparlen) * sizeof(LinkList)); + queue_signals(); + while (darr < dparlen) { + if ((dparr[darr] = getaparam(dat->dpar[darr])) && *dparr[darr]) { + dparr[darr] = arrdup(dparr[darr]); + dparl[darr++] = newlinklist(); + } else { + /* swap in the last -D argument if we didn't get a non-empty array */ + dat->dpar[darr] = *--tail; + *tail = NULL; + --dparlen; + } + } + unqueue_signals(); } /* Store the matcher in our stack of matchers. */ if (dat->match) { @@ -2507,8 +2520,10 @@ addmatches(Cadata dat, char **argv) } if (!addit) { compignored++; - if (dparr && !*++dparr) - dparr = NULL; + for (dind = 0; dparl && dparl[dind]; dind++) { + if (dparr[dind] && !*++dparr[dind]) + dparr[dind] = NULL; + } goto next_array; } } @@ -2525,8 +2540,10 @@ addmatches(Cadata dat, char **argv) !(dat->flags & CMF_FILE) ? 1 : 2) : 0), &bpl, bcp, &bsl, bcs, &isexact))) { - if (dparr && !*++dparr) - dparr = NULL; + for (dind = 0; dparl && dparl[dind]; dind++) { + if (dparr[dind] && !*++dparr[dind]) + dparr[dind] = NULL; + } goto next_array; } if (doadd) { @@ -2553,10 +2570,14 @@ addmatches(Cadata dat, char **argv) addlinknode(aparl, ms); if (dat->opar) addlinknode(oparl, s); - if (dat->dpar && dparr) { - addlinknode(dparl, *dparr); - if (!*++dparr) - dparr = NULL; + if (dat->dpar) { + for (dind = 0; dparl[dind]; dind++) { + if (dparr[dind]) { + addlinknode(dparl[dind], *dparr[dind]); + if (!*++dparr[dind]) + dparr[dind] = NULL; + } + } } free_cline(lc); } @@ -2584,8 +2605,10 @@ addmatches(Cadata dat, char **argv) set_list_array(dat->apar, aparl); if (dat->opar) set_list_array(dat->opar, oparl); - if (dat->dpar) - set_list_array(dat->dpar, dparl); + if (dat->dpar) { + for (dind = 0; dparl[dind]; dind++) + set_list_array(dat->dpar[dind], dparl[dind]); + } if (dat->exp) addexpl(0); if (!hasallmatch && (dat->aflags & CAF_ALL)) { diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index 71d114de9..67a60963e 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -607,6 +607,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) char *oarg = NULL; /* argument of -o option */ int added; /* return value */ Cmatcher match = NULL; + size_t dparlen = 0, dparsize = 0; /* no. of -D options and array size */ if (incompfunc != 1) { zwarnnam(name, "can only be called from completion function"); @@ -614,7 +615,8 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) } dat.ipre = dat.isuf = dat.ppre = dat.psuf = dat.prpre = dat.mesg = dat.pre = dat.suf = dat.group = dat.rems = dat.remf = dat.disp = - dat.ign = dat.exp = dat.apar = dat.opar = dat.dpar = NULL; + dat.ign = dat.exp = dat.apar = dat.opar = NULL; + dat.dpar = NULL; dat.match = NULL; dat.flags = 0; dat.aflags = CAF_MATCH; @@ -741,7 +743,12 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) e = "parameter name expected after -%c"; break; case 'D': - sp = &(dat.dpar); + if (dparsize <= dparlen + 1) { + dparsize = (dparsize + 1) * 2; + dat.dpar = (char **)zrealloc(dat.dpar, sizeof(char *) * dparsize); + } + sp = dat.dpar + dparlen++; + *sp = dat.dpar[dparlen] = NULL; e = "parameter name expected after -%c"; break; case 'd': @@ -768,11 +775,13 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) } else { zwarnnam(name, "number expected after -%c", *p); zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } if (dat.dummies < 0) { zwarnnam(name, "invalid number: %d", dat.dummies); zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } break; @@ -782,6 +791,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) default: zwarnnam(name, "bad option: -%c", *p); zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } if (sp) { @@ -802,6 +812,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) /* Missing argument: argv[N] == "-X", argv[N+1] == NULL. */ zwarnnam(name, e, *p); zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } if (m) { @@ -820,17 +831,21 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) if (mstr && (match = parse_cmatcher(name, mstr)) == pcm_err) { zsfree(mstr); + zfree(dat.dpar, dparsize); return 1; } zsfree(mstr); if (!*argv && !dat.group && !dat.mesg && - !(dat.aflags & (CAF_NOSORT|CAF_UNIQALL|CAF_UNIQCON|CAF_ALL))) + !(dat.aflags & (CAF_NOSORT|CAF_UNIQALL|CAF_UNIQCON|CAF_ALL))) { + zfree(dat.dpar, dparsize); return 1; + } dat.match = match = cpcmatcher(match); added = addmatches(&dat, argv); freecmatcher(match); + zfree(dat.dpar, dparsize); return added; } -- cgit v1.2.3 From 271cfc685b17938e67a8212f2df78c32989411d7 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Tue, 2 Nov 2021 21:39:52 +0100 Subject: 49534, 49539: separate watch/log functionality out into a module --- ChangeLog | 6 + Doc/Makefile.in | 1 + Doc/Zsh/builtins.yo | 8 - Doc/Zsh/compat.yo | 3 +- Doc/Zsh/mod_watch.yo | 140 ++++++++++ Doc/Zsh/params.yo | 118 --------- Src/Modules/watch.c | 716 ++++++++++++++++++++++++++++++++++++++++++++++++++ Src/Modules/watch.mdd | 7 + Src/builtin.c | 1 - Src/init.c | 1 - Src/params.c | 16 +- Src/utils.c | 16 -- Src/watch.c | 626 ------------------------------------------- Src/zsh.mdd | 2 +- 14 files changed, 878 insertions(+), 783 deletions(-) create mode 100644 Doc/Zsh/mod_watch.yo create mode 100644 Src/Modules/watch.c create mode 100644 Src/Modules/watch.mdd delete mode 100644 Src/watch.c (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 5179555ca..00c0d5be6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2021-11-02 Oliver Kiddle + * 49534, 49539: Doc/Makefile.in, Doc/Zsh/builtins.yo, + Doc/Zsh/compat.yo, Doc/Zsh/mod_watch.yo, Doc/Zsh/params.yo, + Src/Modules/watch.mdd, Src/builtin.c, Src/init.c, Src/params.c, + Src/utils.c, Src/Modules/watch.c, Src/zsh.mdd: separate watch/log + functionality out into a module + * 49537: aczsh.m4, configure.ac: fix finding utmpx file on FreeBSD 2021-11-01 Jun-ichi Takimoto diff --git a/Doc/Makefile.in b/Doc/Makefile.in index 5a6a705ff..23e5fc7e2 100644 --- a/Doc/Makefile.in +++ b/Doc/Makefile.in @@ -69,6 +69,7 @@ Zsh/mod_parameter.yo Zsh/mod_pcre.yo Zsh/mod_private.yo \ Zsh/mod_regex.yo Zsh/mod_sched.yo Zsh/mod_socket.yo \ Zsh/mod_stat.yo Zsh/mod_system.yo Zsh/mod_tcp.yo \ Zsh/mod_termcap.yo Zsh/mod_terminfo.yo \ +Zsh/mod_watch.yo \ Zsh/mod_zftp.yo Zsh/mod_zle.yo Zsh/mod_zleparameter.yo \ Zsh/mod_zprof.yo Zsh/mod_zpty.yo Zsh/mod_zselect.yo \ Zsh/mod_zutil.yo diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index ddbcd4363..733d8f185 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -1235,14 +1235,6 @@ Same as tt(typeset), except that the options tt(-g), and tt(-f) are not permitted. In this case the tt(-x) option does not force the use of tt(-g), i.e. exported variables will be local to functions. ) -findex(log) -vindex(watch, use of) -cindex(watching users) -cindex(users, watching) -item(tt(log))( -List all users currently logged in who are affected by -the current setting of the tt(watch) parameter. -) findex(logout) item(tt(logout) [ var(n) ])( Same as tt(exit), except that it only works in a login shell. diff --git a/Doc/Zsh/compat.yo b/Doc/Zsh/compat.yo index 6e4dbcfa4..4d3567d45 100644 --- a/Doc/Zsh/compat.yo +++ b/Doc/Zsh/compat.yo @@ -30,8 +30,7 @@ tt(PROMPT2), tt(PROMPT3), tt(PROMPT4), tt(psvar), -tt(status), -tt(watch). +tt(status). vindex(ENV, use of) The usual zsh startup/shutdown scripts are not executed. Login shells diff --git a/Doc/Zsh/mod_watch.yo b/Doc/Zsh/mod_watch.yo new file mode 100644 index 000000000..4eea89e23 --- /dev/null +++ b/Doc/Zsh/mod_watch.yo @@ -0,0 +1,140 @@ +COMMENT(!MOD!zsh/watch +Reporting of login and logout events. +!MOD!) +The tt(zsh/watch) module can be used to report when specific users log in or +out. This is controlled via the following parameters. + +startitem() +vindex(LOGCHECK) +item(tt(LOGCHECK))( +The interval in seconds between checks for login/logout activity +using the tt(watch) parameter. +) +vindex(watch) +vindex(WATCH) +item(tt(watch) (tt(WATCH) ))( +An array (colon-separated list) of login/logout events to report. + +If it contains the single word `tt(all)', then all login/logout events +are reported. If it contains the single word `tt(notme)', then all +events are reported as with `tt(all)' except tt($USERNAME). + +An entry in this list may consist of a username, +an `tt(@)' followed by a remote hostname, +and a `tt(%)' followed by a line (tty). Any of these may +be a pattern (be sure to quote this during the assignment to +tt(watch) so that it does not immediately perform file generation); +the setting of the tt(EXTENDED_GLOB) option is respected. +Any or all of these components may be present in an entry; +if a login/logout event matches all of them, +it is reported. + +For example, with the tt(EXTENDED_GLOB) option set, the following: + +example(watch=('^(pws|barts)')) + +causes reports for activity associated with any user other than tt(pws) +or tt(barts). +) +vindex(WATCHFMT) +item(tt(WATCHFMT))( +The format of login/logout reports if the tt(watch) parameter is set. +Default is `tt(%n has %a %l from %m)'. +Recognizes the following escape sequences: + +startitem() +item(tt(%n))( +The name of the user that logged in/out. +) +item(tt(%a))( +The observed action, i.e. "logged on" or "logged off". +) +item(tt(%l))( +The line (tty) the user is logged in on. +) +item(tt(%M))( +The full hostname of the remote host. +) +item(tt(%m))( +The hostname up to the first `tt(.)'. If only the +IP address is available or the utmp field contains +the name of an X-windows display, the whole name is printed. + +em(NOTE:) +The `tt(%m)' and `tt(%M)' escapes will work only if there is a host name +field in the utmp on your machine. Otherwise they are +treated as ordinary strings. +) +item(tt(%S) LPAR()tt(%s)RPAR())( +Start (stop) standout mode. +) +item(tt(%U) LPAR()tt(%u)RPAR())( +Start (stop) underline mode. +) +item(tt(%B) LPAR()tt(%b)RPAR())( +Start (stop) boldface mode. +) +xitem(tt(%t)) +item(tt(%@))( +The time, in 12-hour, am/pm format. +) +item(tt(%T))( +The time, in 24-hour format. +) +item(tt(%w))( +The date in `var(day)tt(-)var(dd)' format. +) +item(tt(%W))( +The date in `var(mm)tt(/)var(dd)tt(/)var(yy)' format. +) +item(tt(%D))( +The date in `var(yy)tt(-)var(mm)tt(-)var(dd)' format. +) +item(tt(%D{)var(string)tt(}))( +The date formatted as var(string) using the tt(strftime) function, with +zsh extensions as described by +ifzman(EXPANSION OF PROMPT SEQUENCES in zmanref(zshmisc))\ +ifnzman(noderef(Prompt Expansion)). +) +item(tt(%LPAR())var(x)tt(:)var(true-text)tt(:)var(false-text)tt(RPAR()))( +Specifies a ternary expression. +The character following the var(x) is +arbitrary; the same character is used to separate the text +for the "true" result from that for the "false" result. +Both the separator and the right parenthesis may be escaped +with a backslash. +Ternary expressions may be nested. + +The test character var(x) may be any one of `tt(l)', `tt(n)', `tt(m)' +or `tt(M)', which indicate a `true' result if the corresponding +escape sequence would return a non-empty value; or it may be `tt(a)', +which indicates a `true' result if the watched user has logged in, +or `false' if he has logged out. +Other characters evaluate to neither true nor false; the entire +expression is omitted in this case. + +If the result is `true', then the var(true-text) +is formatted according to the rules above and printed, +and the var(false-text) is skipped. +If `false', the var(true-text) is skipped and the var(false-text) +is formatted and printed. +Either or both of the branches may be empty, but +both separators must be present in any case. +) +enditem() +) +enditem() + +Furthermore, the tt(zsh/watch) module makes available one builtin +command: + +startitem() +findex(log) +vindex(watch, use of) +cindex(watching users) +cindex(users, watching) +item(tt(log))( +List all users currently logged in who are affected by +the current setting of the tt(watch) parameter. +) +enditem() diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index a88e44d4f..1f2f01f55 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -1332,11 +1332,6 @@ most as many lines as given by the absolute value. If set to zero, the shell asks only if the top of the listing would scroll off the screen. ) -vindex(LOGCHECK) -item(tt(LOGCHECK))( -The interval in seconds between checks for login/logout activity -using the tt(watch) parameter. -) vindex(MAIL) item(tt(MAIL))( If this parameter is set and tt(mailpath) is not set, @@ -1670,119 +1665,6 @@ to be interpreted as a file extension. The default is not to append any suffix, thus this parameter should be assigned only when needed and then unset again. ) -vindex(watch) -vindex(WATCH) -item(tt(watch) (tt(WATCH) ))( -An array (colon-separated list) of login/logout events to report. - -If it contains the single word `tt(all)', then all login/logout events -are reported. If it contains the single word `tt(notme)', then all -events are reported as with `tt(all)' except tt($USERNAME). - -An entry in this list may consist of a username, -an `tt(@)' followed by a remote hostname, -and a `tt(%)' followed by a line (tty). Any of these may -be a pattern (be sure to quote this during the assignment to -tt(watch) so that it does not immediately perform file generation); -the setting of the tt(EXTENDED_GLOB) option is respected. -Any or all of these components may be present in an entry; -if a login/logout event matches all of them, -it is reported. - -For example, with the tt(EXTENDED_GLOB) option set, the following: - -example(watch=('^(pws|barts)')) - -causes reports for activity associated with any user other than tt(pws) -or tt(barts). -) -vindex(WATCHFMT) -item(tt(WATCHFMT))( -The format of login/logout reports if the tt(watch) parameter is set. -Default is `tt(%n has %a %l from %m)'. -Recognizes the following escape sequences: - -startitem() -item(tt(%n))( -The name of the user that logged in/out. -) -item(tt(%a))( -The observed action, i.e. "logged on" or "logged off". -) -item(tt(%l))( -The line (tty) the user is logged in on. -) -item(tt(%M))( -The full hostname of the remote host. -) -item(tt(%m))( -The hostname up to the first `tt(.)'. If only the -IP address is available or the utmp field contains -the name of an X-windows display, the whole name is printed. - -em(NOTE:) -The `tt(%m)' and `tt(%M)' escapes will work only if there is a host name -field in the utmp on your machine. Otherwise they are -treated as ordinary strings. -) -item(tt(%S) LPAR()tt(%s)RPAR())( -Start (stop) standout mode. -) -item(tt(%U) LPAR()tt(%u)RPAR())( -Start (stop) underline mode. -) -item(tt(%B) LPAR()tt(%b)RPAR())( -Start (stop) boldface mode. -) -xitem(tt(%t)) -item(tt(%@))( -The time, in 12-hour, am/pm format. -) -item(tt(%T))( -The time, in 24-hour format. -) -item(tt(%w))( -The date in `var(day)tt(-)var(dd)' format. -) -item(tt(%W))( -The date in `var(mm)tt(/)var(dd)tt(/)var(yy)' format. -) -item(tt(%D))( -The date in `var(yy)tt(-)var(mm)tt(-)var(dd)' format. -) -item(tt(%D{)var(string)tt(}))( -The date formatted as var(string) using the tt(strftime) function, with -zsh extensions as described by -ifzman(EXPANSION OF PROMPT SEQUENCES in zmanref(zshmisc))\ -ifnzman(noderef(Prompt Expansion)). -) -item(tt(%LPAR())var(x)tt(:)var(true-text)tt(:)var(false-text)tt(RPAR()))( -Specifies a ternary expression. -The character following the var(x) is -arbitrary; the same character is used to separate the text -for the "true" result from that for the "false" result. -Both the separator and the right parenthesis may be escaped -with a backslash. -Ternary expressions may be nested. - -The test character var(x) may be any one of `tt(l)', `tt(n)', `tt(m)' -or `tt(M)', which indicate a `true' result if the corresponding -escape sequence would return a non-empty value; or it may be `tt(a)', -which indicates a `true' result if the watched user has logged in, -or `false' if he has logged out. -Other characters evaluate to neither true nor false; the entire -expression is omitted in this case. - -If the result is `true', then the var(true-text) -is formatted according to the rules above and printed, -and the var(false-text) is skipped. -If `false', the var(true-text) is skipped and the var(false-text) -is formatted and printed. -Either or both of the branches may be empty, but -both separators must be present in any case. -) -enditem() -) vindex(WORDCHARS) item(tt(WORDCHARS) )( A list of non-alphanumeric characters considered part of a word diff --git a/Src/Modules/watch.c b/Src/Modules/watch.c new file mode 100644 index 000000000..02f0562fc --- /dev/null +++ b/Src/Modules/watch.c @@ -0,0 +1,716 @@ +/* + * watch.c - login/logout watching + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 1992-1997 Paul Falstad + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Paul Falstad or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Paul Falstad and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Paul Falstad and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Paul Falstad and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +#include "watch.mdh" + +/* Headers for utmp/utmpx structures */ +#ifdef HAVE_UTMP_H +# include +#endif +#ifdef HAVE_UTMPX_H +# include +#endif + +/* Find utmp file */ +#if !defined(REAL_UTMP_FILE) && defined(UTMP_FILE) +# define REAL_UTMP_FILE UTMP_FILE +#endif +#if !defined(REAL_UTMP_FILE) && defined(_PATH_UTMP) +# define REAL_UTMP_FILE _PATH_UTMP +#endif +#if !defined(REAL_UTMP_FILE) && defined(PATH_UTMP_FILE) +# define REAL_UTMP_FILE PATH_UTMP_FILE +#endif + +/* Find wtmp file */ +#if !defined(REAL_WTMP_FILE) && defined(WTMP_FILE) +# define REAL_WTMP_FILE WTMP_FILE +#endif +#if !defined(REAL_WTMP_FILE) && defined(_PATH_WTMP) +# define REAL_WTMP_FILE _PATH_WTMP +#endif +#if !defined(REAL_WTMP_FILE) && defined(PATH_WTMP_FILE) +# define REAL_WTMP_FILE PATH_WTMP_FILE +#endif + +/* Find utmpx file */ +#if !defined(REAL_UTMPX_FILE) && defined(UTMPX_FILE) +# define REAL_UTMPX_FILE UTMPX_FILE +#endif +#if !defined(REAL_UTMPX_FILE) && defined(_PATH_UTMPX) +# define REAL_UTMPX_FILE _PATH_UTMPX +#endif +#if !defined(REAL_UTMPX_FILE) && defined(PATH_UTMPX_FILE) +# define REAL_UTMPX_FILE PATH_UTMPX_FILE +#endif + +/* Find wtmpx file */ +#if !defined(REAL_WTMPX_FILE) && defined(WTMPX_FILE) +# define REAL_WTMPX_FILE WTMPX_FILE +#endif +#if !defined(REAL_WTMPX_FILE) && defined(_PATH_WTMPX) +# define REAL_WTMPX_FILE _PATH_WTMPX +#endif +#if !defined(REAL_WTMPX_FILE) && defined(PATH_WTMPX_FILE) +# define REAL_WTMPX_FILE PATH_WTMPX_FILE +#endif + +/* Decide which structure to use. We use a structure that exists in * + * the headers, and require that its corresponding utmp file exist. * + * (wtmp is less important.) */ + +#if !defined(WATCH_STRUCT_UTMP) && defined(HAVE_STRUCT_UTMPX) && defined(REAL_UTMPX_FILE) +# define WATCH_STRUCT_UTMP struct utmpx +# if defined(HAVE_SETUTXENT) && defined(HAVE_GETUTXENT) && defined(HAVE_ENDUTXENT) +# define setutent setutxent +# define getutent getutxent +# define endutent endutxent +# ifndef HAVE_GETUTENT +# define HAVE_GETUTENT 1 +# endif +# endif + +/* + * In utmpx, the ut_name field is replaced by ut_user. + * However, on some systems ut_name may already be defined this + * way for the purposes of utmp. + */ +# ifndef ut_name +# define ut_name ut_user +# endif +# ifdef HAVE_STRUCT_UTMPX_UT_XTIME +# undef ut_time +# define ut_time ut_xtime +# else /* !HAVE_STRUCT_UTMPX_UT_XTIME */ +# ifdef HAVE_STRUCT_UTMPX_UT_TV +# undef ut_time +# define ut_time ut_tv.tv_sec +# endif /* HAVE_STRUCT_UTMPX_UT_TV */ +# endif /* !HAVE_STRUCT_UTMPX_UT_XTIME */ +# define WATCH_UTMP_FILE REAL_UTMPX_FILE +# ifdef REAL_WTMPX_FILE +# define WATCH_WTMP_FILE REAL_WTMPX_FILE +# endif +# ifdef HAVE_STRUCT_UTMPX_UT_HOST +# define WATCH_UTMP_UT_HOST 1 +# endif +#endif + +#if !defined(WATCH_STRUCT_UTMP) && defined(HAVE_STRUCT_UTMP) && defined(REAL_UTMP_FILE) +# define WATCH_STRUCT_UTMP struct utmp +# define WATCH_UTMP_FILE REAL_UTMP_FILE +# ifdef REAL_WTMP_FILE +# define WATCH_WTMP_FILE REAL_WTMP_FILE +# endif +# ifdef HAVE_STRUCT_UTMP_UT_HOST +# define WATCH_UTMP_UT_HOST 1 +# endif +#endif + +#ifdef WATCH_UTMP_UT_HOST +# define DEFAULT_WATCHFMT "%n has %a %l from %m." +#else /* !WATCH_UTMP_UT_HOST */ +# define DEFAULT_WATCHFMT "%n has %a %l." +#endif /* !WATCH_UTMP_UT_HOST */ + +#ifdef WATCH_STRUCT_UTMP + +# include "watch.pro" + +# ifndef WATCH_WTMP_FILE +# define WATCH_WTMP_FILE "/dev/null" +# endif + +static int wtabsz = 0; +static WATCH_STRUCT_UTMP *wtab = NULL; + +/* the last time we checked the people in the WATCH variable */ +static time_t lastwatch; + +static time_t lastutmpcheck = 0; + +/* get the time of login/logout for WATCH */ + +static time_t +getlogtime(WATCH_STRUCT_UTMP *u, int inout) +{ + FILE *in; + WATCH_STRUCT_UTMP uu; + int first = 1; + int srchlimit = 50; /* max number of wtmp records to search */ + + if (inout) + return u->ut_time; + if (!(in = fopen(WATCH_WTMP_FILE, "r"))) + return time(NULL); + fseek(in, 0, SEEK_END); + do { + if (fseek(in, ((first) ? -1 : -2) * sizeof(WATCH_STRUCT_UTMP), SEEK_CUR)) { + fclose(in); + return time(NULL); + } + first = 0; + if (!fread(&uu, sizeof(WATCH_STRUCT_UTMP), 1, in)) { + fclose(in); + return time(NULL); + } + if (uu.ut_time < lastwatch || !srchlimit--) { + fclose(in); + return time(NULL); + } + } + while (memcmp(&uu, u, sizeof(uu))); + + do + if (!fread(&uu, sizeof(WATCH_STRUCT_UTMP), 1, in)) { + fclose(in); + return time(NULL); + } + while (strncmp(uu.ut_line, u->ut_line, sizeof(u->ut_line))); + fclose(in); + return uu.ut_time; +} + +/* Mutually recursive call to handle ternaries in $WATCHFMT */ + +# define BEGIN3 '(' +# define END3 ')' + +static char * +watch3ary(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt) +{ + int truth = 1, sep; + + switch (*fmt++) { + case 'n': + truth = (u->ut_name[0] != 0); + break; + case 'a': + truth = inout; + break; + case 'l': + if (!strncmp(u->ut_line, "tty", 3)) + truth = (u->ut_line[3] != 0); + else + truth = (u->ut_line[0] != 0); + break; +# ifdef WATCH_UTMP_UT_HOST + case 'm': + case 'M': + truth = (u->ut_host[0] != 0); + break; +# endif /* WATCH_UTMP_UT_HOST */ + default: + prnt = 0; /* Skip unknown conditionals entirely */ + break; + } + sep = *fmt++; + fmt = watchlog2(inout, u, fmt, (truth && prnt), sep); + return watchlog2(inout, u, fmt, (!truth && prnt), END3); +} + +/* print a login/logout event */ + +/**/ +static char * +watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini) +{ + char buf[40], buf2[80]; + time_t timet; + struct tm *tm; + char *fm2; + int len; +# ifdef WATCH_UTMP_UT_HOST + char *p; + int i; +# endif /* WATCH_UTMP_UT_HOST */ + + while (*fmt) + if (*fmt == '\\') { + if (*++fmt) { + if (prnt) + putchar(*fmt); + ++fmt; + } else if (fini) + return fmt; + else + break; + } + else if (*fmt == fini) + return ++fmt; + else if (*fmt != '%') { + if (prnt) + putchar(*fmt); + ++fmt; + } else { + if (*++fmt == BEGIN3) + fmt = watch3ary(inout, u, ++fmt, prnt); + else if (!prnt) + ++fmt; + else + switch (*(fm2 = fmt++)) { + case 'n': + printf("%.*s", (int)sizeof(u->ut_name), u->ut_name); + break; + case 'a': + printf("%s", (!inout) ? "logged off" : "logged on"); + break; + case 'l': + if (!strncmp(u->ut_line, "tty", 3)) + printf("%.*s", (int)sizeof(u->ut_line) - 3, u->ut_line + 3); + else + printf("%.*s", (int)sizeof(u->ut_line), u->ut_line); + break; +# ifdef WATCH_UTMP_UT_HOST + case 'm': + for (p = u->ut_host, i = sizeof(u->ut_host); i && *p; i--, p++) { + if (*p == '.' && !idigit(p[1])) + break; + putchar(*p); + } + break; + case 'M': + printf("%.*s", (int)sizeof(u->ut_host), u->ut_host); + break; +# endif /* WATCH_UTMP_UT_HOST */ + case 'T': + case 't': + case '@': + case 'W': + case 'w': + case 'D': + switch (*fm2) { + case '@': + case 't': + fm2 = "%l:%M%p"; + break; + case 'T': + fm2 = "%K:%M"; + break; + case 'w': + fm2 = "%a %f"; + break; + case 'W': + fm2 = "%m/%d/%y"; + break; + case 'D': + if (fm2[1] == '{') { + char *dd, *ss; + int n = 79; + + for (ss = fm2 + 2, dd = buf2; + n-- && *ss && *ss != '}'; ++ss, ++dd) + *dd = *((*ss == '\\' && ss[1]) ? ++ss : ss); + if (*ss == '}') { + *dd = '\0'; + fmt = ss + 1; + fm2 = buf2; + } + else fm2 = "%y-%m-%d"; + } + else fm2 = "%y-%m-%d"; + break; + } + timet = getlogtime(u, inout); + tm = localtime(&timet); + len = ztrftime(buf, 40, fm2, tm, 0L); + if (len > 0) + metafy(buf, len, META_NOALLOC); + printf("%s", (*buf == ' ') ? buf + 1 : buf); + break; + case '%': + putchar('%'); + break; + case 'S': + txtset(TXTSTANDOUT); + tsetcap(TCSTANDOUTBEG, TSC_RAW); + break; + case 's': + txtunset(TXTSTANDOUT); + tsetcap(TCSTANDOUTEND, TSC_RAW|TSC_DIRTY); + break; + case 'B': + txtset(TXTBOLDFACE); + tsetcap(TCBOLDFACEBEG, TSC_RAW|TSC_DIRTY); + break; + case 'b': + txtunset(TXTBOLDFACE); + tsetcap(TCALLATTRSOFF, TSC_RAW|TSC_DIRTY); + break; + case 'U': + txtset(TXTUNDERLINE); + tsetcap(TCUNDERLINEBEG, TSC_RAW); + break; + case 'u': + txtunset(TXTUNDERLINE); + tsetcap(TCUNDERLINEEND, TSC_RAW|TSC_DIRTY); + break; + default: + putchar('%'); + putchar(*fm2); + break; + } + } + if (prnt) + putchar('\n'); + + return fmt; +} + +/* See if the watch entry matches */ + +static int +watchlog_match(char *teststr, char *actual, int len) +{ + int ret = 0; + Patprog pprog; + char *str = dupstring(teststr); + + tokenize(str); + + if ((pprog = patcompile(str, PAT_STATIC, 0))) { + queue_signals(); + if (pattry(pprog, actual)) + ret = 1; + unqueue_signals(); + } else if (!strncmp(actual, teststr, len)) + ret = 1; + return ret; +} + +/* check the List for login/logouts */ + +static void +watchlog(int inout, WATCH_STRUCT_UTMP *u, char **w, char *fmt) +{ + char *v, *vv, sav; + int bad; + + if (!*u->ut_name) + return; + + if (*w && !strcmp(*w, "all")) { + (void)watchlog2(inout, u, fmt, 1, 0); + return; + } + if (*w && !strcmp(*w, "notme") && + strncmp(u->ut_name, get_username(), sizeof(u->ut_name))) { + (void)watchlog2(inout, u, fmt, 1, 0); + return; + } + for (; *w; w++) { + bad = 0; + v = *w; + if (*v != '@' && *v != '%') { + for (vv = v; *vv && *vv != '@' && *vv != '%'; vv++); + sav = *vv; + *vv = '\0'; + if (!watchlog_match(v, u->ut_name, sizeof(u->ut_name))) + bad = 1; + *vv = sav; + v = vv; + } + for (;;) + if (*v == '%') { + for (vv = ++v; *vv && *vv != '@'; vv++); + sav = *vv; + *vv = '\0'; + if (!watchlog_match(v, u->ut_line, sizeof(u->ut_line))) + bad = 1; + *vv = sav; + v = vv; + } +# ifdef WATCH_UTMP_UT_HOST + else if (*v == '@') { + for (vv = ++v; *vv && *vv != '%'; vv++); + sav = *vv; + *vv = '\0'; + if (!watchlog_match(v, u->ut_host, strlen(v))) + bad = 1; + *vv = sav; + v = vv; + } +# endif /* WATCH_UTMP_UT_HOST */ + else + break; + if (!bad) { + (void)watchlog2(inout, u, fmt, 1, 0); + return; + } + } +} + +/* compare 2 utmp entries */ + +static int +ucmp(WATCH_STRUCT_UTMP *u, WATCH_STRUCT_UTMP *v) +{ + if (u->ut_time == v->ut_time) + return strncmp(u->ut_line, v->ut_line, sizeof(u->ut_line)); + return u->ut_time - v->ut_time; +} + +/* initialize the user List */ + +static int +readwtab(WATCH_STRUCT_UTMP **head, int initial_sz) +{ + WATCH_STRUCT_UTMP *uptr; + int wtabmax = initial_sz < 2 ? 32 : initial_sz; + int sz = 0; +# ifdef HAVE_GETUTENT + WATCH_STRUCT_UTMP *tmp; +# else + FILE *in; +# endif + + uptr = *head = (WATCH_STRUCT_UTMP *) + zalloc(wtabmax * sizeof(WATCH_STRUCT_UTMP)); +# ifdef HAVE_GETUTENT + setutent(); + while ((tmp = getutent()) != NULL) { + memcpy(uptr, tmp, sizeof (WATCH_STRUCT_UTMP)); +# else + if (!(in = fopen(WATCH_UTMP_FILE, "r"))) + return 0; + while (fread(uptr, sizeof(WATCH_STRUCT_UTMP), 1, in)) { +# endif +# ifdef USER_PROCESS + if (uptr->ut_type == USER_PROCESS) +# else /* !USER_PROCESS */ + if (uptr->ut_name[0]) +# endif /* !USER_PROCESS */ + { + uptr++; + if (++sz == wtabmax) { + uptr = (WATCH_STRUCT_UTMP *) + realloc(*head, (wtabmax *= 2) * sizeof(WATCH_STRUCT_UTMP)); + if (uptr == NULL) { + /* memory pressure - so stop consuming and use, what we have + * Other option is to exit() here, as zmalloc does on error */ + sz--; + break; + } + *head = uptr; + uptr += sz; + } + } + } +# ifdef HAVE_GETUTENT + endutent(); +# else + fclose(in); +# endif + + if (sz) + qsort((void *) *head, sz, sizeof(WATCH_STRUCT_UTMP), + (int (*) _((const void *, const void *)))ucmp); + return sz; +} + +/* Check for login/logout events; executed before * + * each prompt if WATCH is set */ + +/**/ +void +dowatch(void) +{ + WATCH_STRUCT_UTMP *utab, *uptr, *wptr; + struct stat st; + char **s; + char *fmt; + int utabsz, uct, wct; + + s = watch; + + holdintr(); + if (!wtab) + wtabsz = readwtab(&wtab, 32); + if ((stat(WATCH_UTMP_FILE, &st) == -1) || (st.st_mtime <= lastutmpcheck)) { + noholdintr(); + return; + } + lastutmpcheck = st.st_mtime; + utabsz = readwtab(&utab, wtabsz + 4); + noholdintr(); + if (errflag) { + free(utab); + return; + } + + wct = wtabsz; + uct = utabsz; + uptr = utab; + wptr = wtab; + if (errflag) { + free(utab); + return; + } + queue_signals(); + if (!(fmt = getsparam_u("WATCHFMT"))) + fmt = DEFAULT_WATCHFMT; + while ((uct || wct) && !errflag) { + if (!uct || (wct && ucmp(uptr, wptr) > 0)) + wct--, watchlog(0, wptr++, s, fmt); + else if (!wct || (uct && ucmp(uptr, wptr) < 0)) + uct--, watchlog(1, uptr++, s, fmt); + else + uptr++, wptr++, wct--, uct--; + } + unqueue_signals(); + free(wtab); + wtab = utab; + wtabsz = utabsz; + fflush(stdout); + lastwatch = time(NULL); +} + +static void +checksched(void) +{ + /* Do nothing if WATCH is not set, or LOGCHECK has not elapsed */ + if (watch && (int) difftime(time(NULL), lastwatch) > getiparam("LOGCHECK")) + dowatch(); +} + +/**/ +static int +bin_log(UNUSED(char *nam), UNUSED(char **argv), UNUSED(Options ops), UNUSED(int func)) +{ + if (!watch) + return 1; + if (wtab) + free(wtab); + wtab = (WATCH_STRUCT_UTMP *)zalloc(1); + wtabsz = 0; + lastutmpcheck = 0; + dowatch(); + return 0; +} + +#else /* !WATCH_STRUCT_UTMP */ + +static void +checksched(void) +{ +} + +/**/ +static int +bin_log(char *nam, char **argv, Options ops, int func) +{ + return bin_notavail(nam, argv, ops, func); +} + +#endif /* !WATCH_STRUCT_UTMP */ + +/**/ +static char **watch; /* $watch */ + +/* module setup */ + +static struct builtin bintab[] = { + BUILTIN("log", 0, bin_log, 0, 0, 0, NULL, NULL), +}; + +static struct paramdef partab[] = { + PARAMDEF("WATCH", PM_TIED|PM_SCALAR|PM_SPECIAL, &watch, &colonarr_gsu), + PARAMDEF("watch", PM_TIED|PM_ARRAY|PM_SPECIAL, &watch, &vararray_gsu), +}; + +static struct features module_features = { + bintab, sizeof(bintab)/sizeof(*bintab), + NULL, 0, + NULL, 0, + partab, sizeof(partab)/sizeof(*partab), + 0 +}; + +/**/ +int +setup_(UNUSED(Module m)) +{ + return 0; +} + +/**/ +int +features_(Module m, char ***features) +{ + *features = featuresarray(m, &module_features); + return 0; +} + +/**/ +int +enables_(Module m, int **enables) +{ + return handlefeatures(m, &module_features, enables); +} + +/**/ +int +boot_(UNUSED(Module m)) +{ + static char const * const default_watchfmt = DEFAULT_WATCHFMT; + Param pm; + + if ((pm = (Param) paramtab->getnode(paramtab, "watch"))) + pm->ename = "WATCH"; + if ((pm = (Param) paramtab->getnode(paramtab, "WATCH"))) + pm->ename = "watch"; + watch = mkarray(NULL); + + /* These two parameters are only set to defaults if not set. + * So setting them in .zshrc will not be enough to load the + * module. It's useless until the watch array is set anyway. */ + if (!paramtab->getnode(paramtab, "WATCHFMT")) + setsparam("WATCHFMT", ztrdup_metafy(default_watchfmt)); + if (!paramtab->getnode(paramtab, "LOGCHECK")) + setiparam("LOGCHECK", 60); + + addprepromptfn(&checksched); + + return 0; +} + +/**/ +int +cleanup_(Module m) +{ + delprepromptfn(&checksched); + return setfeatureenables(m, &module_features, NULL); +} + +/**/ +int +finish_(UNUSED(Module m)) +{ + return 0; +} diff --git a/Src/Modules/watch.mdd b/Src/Modules/watch.mdd new file mode 100644 index 000000000..7e8454ede --- /dev/null +++ b/Src/Modules/watch.mdd @@ -0,0 +1,7 @@ +name=zsh/watch +link=dynamic +load=yes + +autofeatures="b:log p:WATCH p:watch" + +objects="watch.o" diff --git a/Src/builtin.c b/Src/builtin.c index 89bcd98db..8ef678b22 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -89,7 +89,6 @@ static struct builtin builtins[] = BUILTIN("kill", BINF_HANDLES_OPTS, bin_kill, 0, -1, 0, NULL, NULL), BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL), BUILTIN("local", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%ahi:%lp:%rtux", NULL), - BUILTIN("log", 0, bin_log, 0, 0, 0, NULL, NULL), BUILTIN("logout", 0, bin_break, 0, 1, BIN_LOGOUT, NULL, NULL), #if defined(ZSH_MEM) & defined(ZSH_MEM_DEBUG) diff --git a/Src/init.c b/Src/init.c index 878a53a37..871d46b12 100644 --- a/Src/init.c +++ b/Src/init.c @@ -1042,7 +1042,6 @@ setupvals(char *cmd, char *runscript, char *zsh_name) #endif /* FPATH_NEEDS_INIT */ mailpath = mkarray(NULL); - watch = mkarray(NULL); psvar = mkarray(NULL); module_path = mkarray(ztrdup(MODULE_DIR)); modulestab = newmoduletable(17, "modules"); diff --git a/Src/params.c b/Src/params.c index b703a97ce..dadf83129 100644 --- a/Src/params.c +++ b/Src/params.c @@ -63,7 +63,6 @@ char **pparams, /* $argv */ **mailpath, /* $mailpath */ **manpath, /* $manpath */ **psvar, /* $psvar */ - **watch, /* $watch */ **zsh_eval_context; /* $zsh_eval_context */ /**/ mod_export @@ -194,6 +193,10 @@ mod_export const struct gsu_hash stdhash_gsu = mod_export const struct gsu_hash nullsethash_gsu = { hashgetfn, nullsethashfn, nullunsetfn }; +/**/ +mod_export const struct gsu_scalar colonarr_gsu = +{ colonarrgetfn, colonarrsetfn, stdunsetfn }; + /* Non standard methods (not exported) */ static const struct gsu_integer pound_gsu = @@ -259,9 +262,6 @@ static const struct gsu_integer varint_readonly_gsu = static const struct gsu_integer zlevar_gsu = { intvargetfn, zlevarsetfn, stdunsetfn }; -static const struct gsu_scalar colonarr_gsu = -{ colonarrgetfn, colonarrsetfn, stdunsetfn }; - static const struct gsu_integer argc_gsu = { poundgetfn, nullintsetfn, stdunsetfn }; static const struct gsu_array pipestatus_gsu = @@ -398,7 +398,6 @@ IPDEF8("CDPATH", &cdpath, "cdpath", PM_TIED), IPDEF8("FIGNORE", &fignore, "fignore", PM_TIED), IPDEF8("FPATH", &fpath, "fpath", PM_TIED), IPDEF8("MAILPATH", &mailpath, "mailpath", PM_TIED), -IPDEF8("WATCH", &watch, "watch", PM_TIED), IPDEF8("PATH", &path, "path", PM_RESTRICTED|PM_TIED), IPDEF8("PSVAR", &psvar, "psvar", PM_TIED), IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, "zsh_eval_context", PM_READONLY_SPECIAL|PM_TIED), @@ -430,7 +429,6 @@ IPDEF9("fpath", &fpath, "FPATH", PM_TIED), IPDEF9("mailpath", &mailpath, "MAILPATH", PM_TIED), IPDEF9("manpath", &manpath, "MANPATH", PM_TIED), IPDEF9("psvar", &psvar, "PSVAR", PM_TIED), -IPDEF9("watch", &watch, "WATCH", PM_TIED), IPDEF9("zsh_eval_context", &zsh_eval_context, "ZSH_EVAL_CONTEXT", PM_TIED|PM_READONLY_SPECIAL), @@ -453,7 +451,6 @@ IPDEF8("CDPATH", &cdpath, NULL, 0), IPDEF8("FIGNORE", &fignore, NULL, 0), IPDEF8("FPATH", &fpath, NULL, 0), IPDEF8("MAILPATH", &mailpath, NULL, 0), -IPDEF8("WATCH", &watch, NULL, 0), IPDEF8("PATH", &path, NULL, PM_RESTRICTED), IPDEF8("PSVAR", &psvar, NULL, 0), IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, NULL, PM_READONLY_SPECIAL), @@ -836,7 +833,6 @@ createparamtable(void) */ setsparam("TMPPREFIX", ztrdup_metafy(DEFAULT_TMPPREFIX)); setsparam("TIMEFMT", ztrdup_metafy(DEFAULT_TIMEFMT)); - setsparam("WATCHFMT", ztrdup_metafy(default_watchfmt)); hostnam = (char *)zalloc(256); gethostname(hostnam, 256); @@ -4093,7 +4089,7 @@ arrvarsetfn(Param pm, char **x) } /**/ -char * +mod_export char * colonarrgetfn(Param pm) { char ***dptr = (char ***)pm->u.data; @@ -4101,7 +4097,7 @@ colonarrgetfn(Param pm) } /**/ -void +mod_export void colonarrsetfn(Param pm, char *x) { char ***dptr = (char ***)pm->u.data; diff --git a/Src/utils.c b/Src/utils.c index ed3690172..8adab2bd7 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1494,11 +1494,6 @@ deltimedfn(voidvoidfnptr_t func) /**/ time_t lastmailcheck; -/* the last time we checked the people in the WATCH variable */ - -/**/ -time_t lastwatch; - /* * Call a function given by "name" with optional arguments * "lnklst". If these are present the first argument is the function name. @@ -1637,17 +1632,6 @@ preprompt(void) if (errflag) return; - /* If WATCH is set, then check for the * - * specified login/logout events. */ - if (watch) { - if ((int) difftime(time(NULL), lastwatch) > getiparam("LOGCHECK")) { - dowatch(); - lastwatch = time(NULL); - } - } - if (errflag) - return; - /* Check mail */ currentmailcheck = time(NULL); if (mailcheck && diff --git a/Src/watch.c b/Src/watch.c deleted file mode 100644 index c41704315..000000000 --- a/Src/watch.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * watch.c - login/logout watching - * - * This file is part of zsh, the Z shell. - * - * Copyright (c) 1992-1997 Paul Falstad - * All rights reserved. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and to distribute modified versions of this software for any - * purpose, provided that the above copyright notice and the following - * two paragraphs appear in all copies of this software. - * - * In no event shall Paul Falstad or the Zsh Development Group be liable - * to any party for direct, indirect, special, incidental, or consequential - * damages arising out of the use of this software and its documentation, - * even if Paul Falstad and the Zsh Development Group have been advised of - * the possibility of such damage. - * - * Paul Falstad and the Zsh Development Group specifically disclaim any - * warranties, including, but not limited to, the implied warranties of - * merchantability and fitness for a particular purpose. The software - * provided hereunder is on an "as is" basis, and Paul Falstad and the - * Zsh Development Group have no obligation to provide maintenance, - * support, updates, enhancements, or modifications. - * - */ - -#include "zsh.mdh" - -/* Headers for utmp/utmpx structures */ -#ifdef HAVE_UTMP_H -# include -#endif -#ifdef HAVE_UTMPX_H -# include -#endif - -/* Find utmp file */ -#if !defined(REAL_UTMP_FILE) && defined(UTMP_FILE) -# define REAL_UTMP_FILE UTMP_FILE -#endif -#if !defined(REAL_UTMP_FILE) && defined(_PATH_UTMP) -# define REAL_UTMP_FILE _PATH_UTMP -#endif -#if !defined(REAL_UTMP_FILE) && defined(PATH_UTMP_FILE) -# define REAL_UTMP_FILE PATH_UTMP_FILE -#endif - -/* Find wtmp file */ -#if !defined(REAL_WTMP_FILE) && defined(WTMP_FILE) -# define REAL_WTMP_FILE WTMP_FILE -#endif -#if !defined(REAL_WTMP_FILE) && defined(_PATH_WTMP) -# define REAL_WTMP_FILE _PATH_WTMP -#endif -#if !defined(REAL_WTMP_FILE) && defined(PATH_WTMP_FILE) -# define REAL_WTMP_FILE PATH_WTMP_FILE -#endif - -/* Find utmpx file */ -#if !defined(REAL_UTMPX_FILE) && defined(UTMPX_FILE) -# define REAL_UTMPX_FILE UTMPX_FILE -#endif -#if !defined(REAL_UTMPX_FILE) && defined(_PATH_UTMPX) -# define REAL_UTMPX_FILE _PATH_UTMPX -#endif -#if !defined(REAL_UTMPX_FILE) && defined(PATH_UTMPX_FILE) -# define REAL_UTMPX_FILE PATH_UTMPX_FILE -#endif - -/* Find wtmpx file */ -#if !defined(REAL_WTMPX_FILE) && defined(WTMPX_FILE) -# define REAL_WTMPX_FILE WTMPX_FILE -#endif -#if !defined(REAL_WTMPX_FILE) && defined(_PATH_WTMPX) -# define REAL_WTMPX_FILE _PATH_WTMPX -#endif -#if !defined(REAL_WTMPX_FILE) && defined(PATH_WTMPX_FILE) -# define REAL_WTMPX_FILE PATH_WTMPX_FILE -#endif - -/* Decide which structure to use. We use a structure that exists in * - * the headers, and require that its corresponding utmp file exist. * - * (wtmp is less important.) */ - -#if !defined(WATCH_STRUCT_UTMP) && defined(HAVE_STRUCT_UTMPX) && defined(REAL_UTMPX_FILE) -# define WATCH_STRUCT_UTMP struct utmpx -# if defined(HAVE_SETUTXENT) && defined(HAVE_GETUTXENT) && defined(HAVE_ENDUTXENT) -# define setutent setutxent -# define getutent getutxent -# define endutent endutxent -# ifndef HAVE_GETUTENT -# define HAVE_GETUTENT 1 -# endif -# endif - -/* - * In utmpx, the ut_name field is replaced by ut_user. - * However, on some systems ut_name may already be defined this - * way for the purposes of utmp. - */ -# ifndef ut_name -# define ut_name ut_user -# endif -# ifdef HAVE_STRUCT_UTMPX_UT_XTIME -# undef ut_time -# define ut_time ut_xtime -# else /* !HAVE_STRUCT_UTMPX_UT_XTIME */ -# ifdef HAVE_STRUCT_UTMPX_UT_TV -# undef ut_time -# define ut_time ut_tv.tv_sec -# endif /* HAVE_STRUCT_UTMPX_UT_TV */ -# endif /* !HAVE_STRUCT_UTMPX_UT_XTIME */ -# define WATCH_UTMP_FILE REAL_UTMPX_FILE -# ifdef REAL_WTMPX_FILE -# define WATCH_WTMP_FILE REAL_WTMPX_FILE -# endif -# ifdef HAVE_STRUCT_UTMPX_UT_HOST -# define WATCH_UTMP_UT_HOST 1 -# endif -#endif - -#if !defined(WATCH_STRUCT_UTMP) && defined(HAVE_STRUCT_UTMP) && defined(REAL_UTMP_FILE) -# define WATCH_STRUCT_UTMP struct utmp -# define WATCH_UTMP_FILE REAL_UTMP_FILE -# ifdef REAL_WTMP_FILE -# define WATCH_WTMP_FILE REAL_WTMP_FILE -# endif -# ifdef HAVE_STRUCT_UTMP_UT_HOST -# define WATCH_UTMP_UT_HOST 1 -# endif -#endif - -#ifdef WATCH_UTMP_UT_HOST -# define DEFAULT_WATCHFMT "%n has %a %l from %m." -#else /* !WATCH_UTMP_UT_HOST */ -# define DEFAULT_WATCHFMT "%n has %a %l." -#endif /* !WATCH_UTMP_UT_HOST */ - -/**/ -char const * const default_watchfmt = DEFAULT_WATCHFMT; - -#ifdef WATCH_STRUCT_UTMP - -# include "watch.pro" - -# ifndef WATCH_WTMP_FILE -# define WATCH_WTMP_FILE "/dev/null" -# endif - -static int wtabsz = 0; -static WATCH_STRUCT_UTMP *wtab = NULL; -static time_t lastutmpcheck = 0; - -/* get the time of login/logout for WATCH */ - -/**/ -static time_t -getlogtime(WATCH_STRUCT_UTMP *u, int inout) -{ - FILE *in; - WATCH_STRUCT_UTMP uu; - int first = 1; - int srchlimit = 50; /* max number of wtmp records to search */ - - if (inout) - return u->ut_time; - if (!(in = fopen(WATCH_WTMP_FILE, "r"))) - return time(NULL); - fseek(in, 0, SEEK_END); - do { - if (fseek(in, ((first) ? -1 : -2) * sizeof(WATCH_STRUCT_UTMP), SEEK_CUR)) { - fclose(in); - return time(NULL); - } - first = 0; - if (!fread(&uu, sizeof(WATCH_STRUCT_UTMP), 1, in)) { - fclose(in); - return time(NULL); - } - if (uu.ut_time < lastwatch || !srchlimit--) { - fclose(in); - return time(NULL); - } - } - while (memcmp(&uu, u, sizeof(uu))); - - do - if (!fread(&uu, sizeof(WATCH_STRUCT_UTMP), 1, in)) { - fclose(in); - return time(NULL); - } - while (strncmp(uu.ut_line, u->ut_line, sizeof(u->ut_line))); - fclose(in); - return uu.ut_time; -} - -/* Mutually recursive call to handle ternaries in $WATCHFMT */ - -# define BEGIN3 '(' -# define END3 ')' - -/**/ -static char * -watch3ary(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt) -{ - int truth = 1, sep; - - switch (*fmt++) { - case 'n': - truth = (u->ut_name[0] != 0); - break; - case 'a': - truth = inout; - break; - case 'l': - if (!strncmp(u->ut_line, "tty", 3)) - truth = (u->ut_line[3] != 0); - else - truth = (u->ut_line[0] != 0); - break; -# ifdef WATCH_UTMP_UT_HOST - case 'm': - case 'M': - truth = (u->ut_host[0] != 0); - break; -# endif /* WATCH_UTMP_UT_HOST */ - default: - prnt = 0; /* Skip unknown conditionals entirely */ - break; - } - sep = *fmt++; - fmt = watchlog2(inout, u, fmt, (truth && prnt), sep); - return watchlog2(inout, u, fmt, (!truth && prnt), END3); -} - -/* print a login/logout event */ - -/**/ -static char * -watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini) -{ - char buf[40], buf2[80]; - time_t timet; - struct tm *tm; - char *fm2; - int len; -# ifdef WATCH_UTMP_UT_HOST - char *p; - int i; -# endif /* WATCH_UTMP_UT_HOST */ - - while (*fmt) - if (*fmt == '\\') { - if (*++fmt) { - if (prnt) - putchar(*fmt); - ++fmt; - } else if (fini) - return fmt; - else - break; - } - else if (*fmt == fini) - return ++fmt; - else if (*fmt != '%') { - if (prnt) - putchar(*fmt); - ++fmt; - } else { - if (*++fmt == BEGIN3) - fmt = watch3ary(inout, u, ++fmt, prnt); - else if (!prnt) - ++fmt; - else - switch (*(fm2 = fmt++)) { - case 'n': - printf("%.*s", (int)sizeof(u->ut_name), u->ut_name); - break; - case 'a': - printf("%s", (!inout) ? "logged off" : "logged on"); - break; - case 'l': - if (!strncmp(u->ut_line, "tty", 3)) - printf("%.*s", (int)sizeof(u->ut_line) - 3, u->ut_line + 3); - else - printf("%.*s", (int)sizeof(u->ut_line), u->ut_line); - break; -# ifdef WATCH_UTMP_UT_HOST - case 'm': - for (p = u->ut_host, i = sizeof(u->ut_host); i && *p; i--, p++) { - if (*p == '.' && !idigit(p[1])) - break; - putchar(*p); - } - break; - case 'M': - printf("%.*s", (int)sizeof(u->ut_host), u->ut_host); - break; -# endif /* WATCH_UTMP_UT_HOST */ - case 'T': - case 't': - case '@': - case 'W': - case 'w': - case 'D': - switch (*fm2) { - case '@': - case 't': - fm2 = "%l:%M%p"; - break; - case 'T': - fm2 = "%K:%M"; - break; - case 'w': - fm2 = "%a %f"; - break; - case 'W': - fm2 = "%m/%d/%y"; - break; - case 'D': - if (fm2[1] == '{') { - char *dd, *ss; - int n = 79; - - for (ss = fm2 + 2, dd = buf2; - n-- && *ss && *ss != '}'; ++ss, ++dd) - *dd = *((*ss == '\\' && ss[1]) ? ++ss : ss); - if (*ss == '}') { - *dd = '\0'; - fmt = ss + 1; - fm2 = buf2; - } - else fm2 = "%y-%m-%d"; - } - else fm2 = "%y-%m-%d"; - break; - } - timet = getlogtime(u, inout); - tm = localtime(&timet); - len = ztrftime(buf, 40, fm2, tm, 0L); - if (len > 0) - metafy(buf, len, META_NOALLOC); - printf("%s", (*buf == ' ') ? buf + 1 : buf); - break; - case '%': - putchar('%'); - break; - case 'S': - txtset(TXTSTANDOUT); - tsetcap(TCSTANDOUTBEG, TSC_RAW); - break; - case 's': - txtunset(TXTSTANDOUT); - tsetcap(TCSTANDOUTEND, TSC_RAW|TSC_DIRTY); - break; - case 'B': - txtset(TXTBOLDFACE); - tsetcap(TCBOLDFACEBEG, TSC_RAW|TSC_DIRTY); - break; - case 'b': - txtunset(TXTBOLDFACE); - tsetcap(TCALLATTRSOFF, TSC_RAW|TSC_DIRTY); - break; - case 'U': - txtset(TXTUNDERLINE); - tsetcap(TCUNDERLINEBEG, TSC_RAW); - break; - case 'u': - txtunset(TXTUNDERLINE); - tsetcap(TCUNDERLINEEND, TSC_RAW|TSC_DIRTY); - break; - default: - putchar('%'); - putchar(*fm2); - break; - } - } - if (prnt) - putchar('\n'); - - return fmt; -} - -/* See if the watch entry matches */ - -static int -watchlog_match(char *teststr, char *actual, int len) -{ - int ret = 0; - Patprog pprog; - char *str = dupstring(teststr); - - tokenize(str); - - if ((pprog = patcompile(str, PAT_STATIC, 0))) { - queue_signals(); - if (pattry(pprog, actual)) - ret = 1; - unqueue_signals(); - } else if (!strncmp(actual, teststr, len)) - ret = 1; - return ret; -} - -/* check the List for login/logouts */ - -/**/ -static void -watchlog(int inout, WATCH_STRUCT_UTMP *u, char **w, char *fmt) -{ - char *v, *vv, sav; - int bad; - - if (!*u->ut_name) - return; - - if (*w && !strcmp(*w, "all")) { - (void)watchlog2(inout, u, fmt, 1, 0); - return; - } - if (*w && !strcmp(*w, "notme") && - strncmp(u->ut_name, get_username(), sizeof(u->ut_name))) { - (void)watchlog2(inout, u, fmt, 1, 0); - return; - } - for (; *w; w++) { - bad = 0; - v = *w; - if (*v != '@' && *v != '%') { - for (vv = v; *vv && *vv != '@' && *vv != '%'; vv++); - sav = *vv; - *vv = '\0'; - if (!watchlog_match(v, u->ut_name, sizeof(u->ut_name))) - bad = 1; - *vv = sav; - v = vv; - } - for (;;) - if (*v == '%') { - for (vv = ++v; *vv && *vv != '@'; vv++); - sav = *vv; - *vv = '\0'; - if (!watchlog_match(v, u->ut_line, sizeof(u->ut_line))) - bad = 1; - *vv = sav; - v = vv; - } -# ifdef WATCH_UTMP_UT_HOST - else if (*v == '@') { - for (vv = ++v; *vv && *vv != '%'; vv++); - sav = *vv; - *vv = '\0'; - if (!watchlog_match(v, u->ut_host, strlen(v))) - bad = 1; - *vv = sav; - v = vv; - } -# endif /* WATCH_UTMP_UT_HOST */ - else - break; - if (!bad) { - (void)watchlog2(inout, u, fmt, 1, 0); - return; - } - } -} - -/* compare 2 utmp entries */ - -/**/ -static int -ucmp(WATCH_STRUCT_UTMP *u, WATCH_STRUCT_UTMP *v) -{ - if (u->ut_time == v->ut_time) - return strncmp(u->ut_line, v->ut_line, sizeof(u->ut_line)); - return u->ut_time - v->ut_time; -} - -/* initialize the user List */ - -/**/ -static int -readwtab(WATCH_STRUCT_UTMP **head, int initial_sz) -{ - WATCH_STRUCT_UTMP *uptr; - int wtabmax = initial_sz < 2 ? 32 : initial_sz; - int sz = 0; -# ifdef HAVE_GETUTENT - WATCH_STRUCT_UTMP *tmp; -# else - FILE *in; -# endif - - uptr = *head = (WATCH_STRUCT_UTMP *) - zalloc(wtabmax * sizeof(WATCH_STRUCT_UTMP)); -# ifdef HAVE_GETUTENT - setutent(); - while ((tmp = getutent()) != NULL) { - memcpy(uptr, tmp, sizeof (WATCH_STRUCT_UTMP)); -# else - if (!(in = fopen(WATCH_UTMP_FILE, "r"))) - return 0; - while (fread(uptr, sizeof(WATCH_STRUCT_UTMP), 1, in)) { -# endif -# ifdef USER_PROCESS - if (uptr->ut_type == USER_PROCESS) -# else /* !USER_PROCESS */ - if (uptr->ut_name[0]) -# endif /* !USER_PROCESS */ - { - uptr++; - if (++sz == wtabmax) { - uptr = (WATCH_STRUCT_UTMP *) - realloc(*head, (wtabmax *= 2) * sizeof(WATCH_STRUCT_UTMP)); - if (uptr == NULL) { - /* memory pressure - so stop consuming and use, what we have - * Other option is to exit() here, as zmalloc does on error */ - sz--; - break; - } - *head = uptr; - uptr += sz; - } - } - } -# ifdef HAVE_GETUTENT - endutent(); -# else - fclose(in); -# endif - - if (sz) - qsort((void *) *head, sz, sizeof(WATCH_STRUCT_UTMP), - (int (*) _((const void *, const void *)))ucmp); - return sz; -} - -/* Check for login/logout events; executed before * - * each prompt if WATCH is set */ - -/**/ -void -dowatch(void) -{ - WATCH_STRUCT_UTMP *utab, *uptr, *wptr; - struct stat st; - char **s; - char *fmt; - int utabsz, uct, wct; - - s = watch; - - holdintr(); - if (!wtab) - wtabsz = readwtab(&wtab, 32); - if ((stat(WATCH_UTMP_FILE, &st) == -1) || (st.st_mtime <= lastutmpcheck)) { - noholdintr(); - return; - } - lastutmpcheck = st.st_mtime; - utabsz = readwtab(&utab, wtabsz + 4); - noholdintr(); - if (errflag) { - free(utab); - return; - } - - wct = wtabsz; - uct = utabsz; - uptr = utab; - wptr = wtab; - if (errflag) { - free(utab); - return; - } - queue_signals(); - if (!(fmt = getsparam_u("WATCHFMT"))) - fmt = DEFAULT_WATCHFMT; - while ((uct || wct) && !errflag) { - if (!uct || (wct && ucmp(uptr, wptr) > 0)) - wct--, watchlog(0, wptr++, s, fmt); - else if (!wct || (uct && ucmp(uptr, wptr) < 0)) - uct--, watchlog(1, uptr++, s, fmt); - else - uptr++, wptr++, wct--, uct--; - } - unqueue_signals(); - free(wtab); - wtab = utab; - wtabsz = utabsz; - fflush(stdout); -} - -/**/ -int -bin_log(UNUSED(char *nam), UNUSED(char **argv), UNUSED(Options ops), UNUSED(int func)) -{ - if (!watch) - return 1; - if (wtab) - free(wtab); - wtab = (WATCH_STRUCT_UTMP *)zalloc(1); - wtabsz = 0; - lastutmpcheck = 0; - dowatch(); - return 0; -} - -#else /* !WATCH_STRUCT_UTMP */ - -/**/ -void dowatch(void) -{ -} - -/**/ -int -bin_log(char *nam, char **argv, Options ops, int func) -{ - return bin_notavail(nam, argv, ops, func); -} - -#endif /* !WATCH_STRUCT_UTMP */ diff --git a/Src/zsh.mdd b/Src/zsh.mdd index 9bcaccae5..da8d58322 100644 --- a/Src/zsh.mdd +++ b/Src/zsh.mdd @@ -13,7 +13,7 @@ objects="builtin.o compat.o cond.o context.o \ exec.o glob.o hashtable.o hashnameddir.o \ hist.o init.o input.o jobs.o lex.o linklist.o loop.o math.o \ mem.o module.o options.o params.o parse.o pattern.o prompt.o signals.o \ -signames.o sort.o string.o subst.o text.o utils.o watch.o \ +signames.o sort.o string.o subst.o text.o utils.o \ openssh_bsd_setres_id.o" headers="../config.h zsh_system.h zsh.h sigcount.h signals.h \ -- cgit v1.2.3 From dfb7ac94bb4c28472d759a61ea3c2dab30cf9cd3 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 12 Nov 2021 20:33:52 +0100 Subject: 49561: add zformat -F option, similar to -f but ternary expressions check for existence instead of doing math evaluation --- ChangeLog | 8 +++++++ Completion/Base/Core/_description | 2 +- Completion/Base/Core/_message | 2 +- Doc/Zsh/mod_zutil.yo | 11 +++++++-- Src/Modules/zutil.c | 48 ++++++++++++++++++++++++++------------- Test/V13zformat.ztst | 24 ++++++++++++++++++++ 6 files changed, 75 insertions(+), 20 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 5865cb727..65c0dfa8f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2021-11-12 Oliver Kiddle + + * 49561: Src/Modules/zutil.c, Doc/Zsh/mod_zutil.yo, + Completion/Base/Core/_description, Completion/Base/Core/_message, + Test/V13zformat.ztst: Add zformat -F option, similar to -f but + ternary expressions check for existence instead of doing math + evaluation. Make use it with the format style. + 2021-11-07 Oliver Kiddle * 49544: Src/Modules/watch.c: only tie watch/WATCH if both come diff --git a/Completion/Base/Core/_description b/Completion/Base/Core/_description index bdb4007a6..5b54484c7 100644 --- a/Completion/Base/Core/_description +++ b/Completion/Base/Core/_description @@ -78,7 +78,7 @@ shift 2 if [[ -z "$1" && $# -eq 1 ]]; then format= elif [[ -n "$format" ]]; then - zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}" + zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}" fi if [[ -n "$gname" ]]; then diff --git a/Completion/Base/Core/_message b/Completion/Base/Core/_message index 4d5645eaf..dbeed4a88 100644 --- a/Completion/Base/Core/_message +++ b/Completion/Base/Core/_message @@ -39,7 +39,7 @@ else fi if [[ -n "$format$raw" ]]; then - [[ -z "$raw" ]] && zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}" + [[ -z "$raw" ]] && zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}" builtin compadd "$gopt[@]" -x "$format" _comp_mesg=yes fi diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 41d3dfdb0..3cf9e5028 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -150,8 +150,9 @@ enditem() ) findex(zformat) xitem(tt(zformat -f) var(param) var(format) var(spec) ...) +xitem(tt(zformat -F) var(param) var(format) var(spec) ...) item(tt(zformat -a) var(array) var(sep) var(spec) ...)( -This builtin provides two different forms of formatting. The first form +This builtin provides different forms of formatting. The first form is selected with the tt(-f) option. In this case the var(format) string will be modified by replacing sequences starting with a percent sign in it with strings from the var(spec)s. Each var(spec) should be @@ -195,7 +196,13 @@ outputs "The answer is 'yes'." to tt(REPLY) since the value for the format specifier tt(c) is 3, agreeing with the digit argument to the ternary expression. -The second form, using the tt(-a) option, can be used for aligning +With tt(-F) instead of tt(-f), ternary expressions choose between the +`true' or `false' text on the basis of whether the format specifier is +present and non-empty. A test number indicates a minimum width for the +value given in the format specifier. Negative numbers reverse this, +so the test is for whether the value exceeds a maximum width. + +The form, using the tt(-a) option, can be used for aligning strings. Here, the var(spec)s are of the form `var(left)tt(:)var(right)' where `var(left)' and `var(right)' are arbitrary strings. These strings are modified by replacing the colons diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 691ba6c2f..2f17c03f1 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -776,10 +776,12 @@ bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) * ousedp (*outp)[*ousedp] is where to write next * olenp *olenp is the size allocated for *outp * endchar Terminator character in addition to `\0' (may be '\0') + * presence -F: Ternary expressions test emptyness instead * skip If 1, don't output, just parse. */ static char *zformat_substring(char* instr, char **specs, char **outp, - int *ousedp, int *olenp, int endchar, int skip) + int *ousedp, int *olenp, int endchar, + int presence, int skip) { char *s; @@ -813,20 +815,29 @@ static char *zformat_substring(char* instr, char **specs, char **outp, if (testit && STOUC(*s)) { int actval, testval, endcharl; - /* - * One one number is useful for ternary expressions. - * Remember to put the sign back. - */ + /* Only one number is useful for ternary expressions. */ testval = (min >= 0) ? min : (max >= 0) ? max : 0; - if (right) - testval *= -1; - if (specs[STOUC(*s)]) - actval = (int)mathevali(specs[STOUC(*s)]); - else - actval = 0; - /* zero means values are equal, i.e. true */ - actval -= testval; + if (specs[STOUC(*s)] && *specs[STOUC(*s)]) { + if (presence) { + if (testval) +#ifdef MULTIBYTE_SUPPORT + if (isset(MULTIBYTE)) + actval = MB_METASTRWIDTH(specs[STOUC(*s)]); + else +#endif + actval = strlen(specs[STOUC(*s)]); + else + actval = 1; + actval = right ? (testval < actval) : (testval >= actval); + } else { + if (right) /* put the sign back */ + testval *= -1; + /* zero means values are equal, i.e. true */ + actval = (int)mathevali(specs[STOUC(*s)]) - testval; + } + } else + actval = presence ? !right : testval; /* careful about premature end of string */ if (!(endcharl = *++s)) @@ -837,10 +848,10 @@ static char *zformat_substring(char* instr, char **specs, char **outp, * vice versa... unless we are already skipping. */ if (!(s = zformat_substring(s+1, specs, outp, ousedp, - olenp, endcharl, skip || actval))) + olenp, endcharl, presence, skip || actval))) return NULL; if (!(s = zformat_substring(s+1, specs, outp, ousedp, - olenp, ')', skip || !actval))) + olenp, ')', presence, skip || !actval))) return NULL; } else if (skip) { continue; @@ -912,6 +923,7 @@ static int bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { char opt; + int presence = 0; if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) { zwarnnam(nam, "invalid argument: %s", args[0]); @@ -920,6 +932,9 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) args++; switch (opt) { + case 'F': + presence = 1; + /* fall-through */ case 'f': { char **ap, *specs[256] = {0}, *out; @@ -939,7 +954,8 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } out = (char *) zhalloc(olen = 128); - zformat_substring(args[1], specs, &out, &oused, &olen, '\0', 0); + zformat_substring(args[1], specs, &out, &oused, &olen, '\0', + presence, 0); out[oused] = '\0'; setsparam(args[0], ztrdup(out)); diff --git a/Test/V13zformat.ztst b/Test/V13zformat.ztst index 982866e13..035a0a495 100644 --- a/Test/V13zformat.ztst +++ b/Test/V13zformat.ztst @@ -58,6 +58,30 @@ 0:nested conditionals test >yes + () { + zformat -f 1 '%(w.zero.fail) %(x.fail.present) %(y.empty.fail) %(z.missing.fail)' w:0 x:1 y: + zformat -F 2 '%(w.zero.fail) %(x.present.fail) %(y.fail.empty) %(z.fail.missing)' w:0 x:1 y: + echo $1 + echo $2 + } +0:conditionals with empty and missing values +>zero present empty missing +>zero present empty missing + + () { + local l + for l in 0 1 2 3; do + zformat -F 1 "%$l(a.a.A)%$l(b.b.B)%$l(c.c.C)%$l(d.d.D)" a: b:1 c:12 d:123 + zformat -F 2 "%-$l(a.a.A)%-$l(b.b.B)%-$l(c.c.C)%-$l(d.d.D)" a: b:1 c:12 d:123 + print - $1 $2 + done + } +0:minimum and maximum widths +>Abcd aBCD +>ABcd abCD +>ABCd abcD +>ABCD abcd + zformat -a argv . foo:lorem ipsum:bar bazbaz '\\esc\:ape' print -rl -- "$@" 0:basic -a test -- cgit v1.2.3 From 9bdaf0197f074b6dff70569f60c583b18e35f755 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 12 Nov 2021 20:36:51 +0100 Subject: 49562: remove old documentation for other-files tag that was removed in 36165 --- ChangeLog | 3 +++ Doc/Zsh/compsys.yo | 9 +-------- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 65c0dfa8f..2422e4120 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-11-12 Oliver Kiddle + * 49562: Doc/Zsh/compsys.yo: remove old documentation for + other-files tag that was removed in 36165 + * 49561: Src/Modules/zutil.c, Doc/Zsh/mod_zutil.yo, Completion/Base/Core/_description, Completion/Base/Core/_message, Test/V13zformat.ztst: Add zformat -F option, similar to -f but diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 89b918d60..a8beece2d 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -979,11 +979,6 @@ kindex(other-accounts, completion tag) item(tt(other-accounts))( used to look up the tt(users-hosts) style ) -kindex(other-files, completion tag) -item(tt(other-files))( -for the names of any non-directory files. This is used instead -of tt(all-files) when the tt(list-dirs-first) style is in effect. -) kindex(packages, completion tag) item(tt(packages))( for packages (e.g. tt(rpm) or installed tt(Debian) packages) @@ -1978,9 +1973,7 @@ kindex(list-dirs-first, completion style) item(tt(list-dirs-first))( This is used by file completion. If set, directories to be completed are listed separately from and before completion for other files, -regardless of tag ordering. In addition, the tag tt(other-files) -is used in place of tt(all-files) for the remaining files, to indicate -that no directories are presented with that tag. +regardless of tag ordering. ) kindex(list-grouped, completion style) item(tt(list-grouped))( -- cgit v1.2.3 From 8ea597722287a9a2f827f754364491bb5f033c15 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 12 Nov 2021 20:41:04 +0100 Subject: 49564: always use descriptions included in the file-patterns style and allow the recursive-files style to also work in those cases --- ChangeLog | 4 ++++ Completion/Unix/Type/_files | 45 ++++++++++++++++++++++++++------------------- Doc/Zsh/compsys.yo | 23 +++++++++++++++++------ 3 files changed, 47 insertions(+), 25 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 2422e4120..0ad9c4609 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2021-11-12 Oliver Kiddle + * 49564: Completion/Unix/Type/_files, Doc/Zsh/compsys.yo: always + use descriptions included in the file-patterns style and allow + the recursive-files style to also work in those cases + * 49562: Doc/Zsh/compsys.yo: remove old documentation for other-files tag that was removed in 36165 diff --git a/Completion/Unix/Type/_files b/Completion/Unix/Type/_files index 4ddec1e12..f03b4a148 100644 --- a/Completion/Unix/Type/_files +++ b/Completion/Unix/Type/_files @@ -92,7 +92,10 @@ for def in "$pats[@]"; do pat="${${sdef%%:${tag}*}//\\:/:}" if [[ "$sdef" = *:${tag}:* ]]; then + # If the file-patterns spec includes a description, use it and give the + # group/description options from it precedence over passed in parameters. descr="${(Q)sdef#*:${tag}:}" + end= else if (( $opts[(I)-X] )); then descr= @@ -108,26 +111,30 @@ for def in "$pats[@]"; do while _next_label "$tag" expl "$descr"; do _comp_ignore=( $_comp_ignore $ign ) if [[ -n "$end" ]]; then - if _path_files -g "$pat" "$opts[@]" "$expl[@]"; then - ret=0 - elif [[ $PREFIX$SUFFIX != */* ]] && zstyle -a ":completion:${curcontext}:$tag" recursive-files rfiles; then - for rfile in $rfiles; do - if [[ $PWD/ = ${~rfile} ]]; then - if [[ -z $subtree ]]; then - subtree=( **/*(/) ) - fi - for prepath in $subtree; do - oprefix=$PREFIX - PREFIX=$prepath/$PREFIX - _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0 - PREFIX=$oprefix - done - break - fi - done - fi + expl=( "$opts[@]" "$expl[@]" ) else - _path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0 + expl+=( "$opts[@]" ) + fi + + if _path_files -g "$pat" "$expl[@]"; then + ret=0 + elif [[ $PREFIX$SUFFIX != */* ]] && \ + zstyle -a ":completion:${curcontext}:$tag" recursive-files rfiles + then + for rfile in $rfiles; do + if [[ $PWD/ = ${~rfile} ]]; then + if [[ -z $subtree ]]; then + subtree=( **/*(/) ) + fi + for prepath in $subtree; do + oprefix=$PREFIX + PREFIX=$prepath/$PREFIX + _path_files -g "$pat" "$expl[@]" && ret=0 + PREFIX=$oprefix + done + break + fi + done fi done (( ret )) || break diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index a8beece2d..1adceb536 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -1524,9 +1524,10 @@ If no `tt(:)var(tag)' is given the `tt(files)' tag will be used. The var(tag) may also be followed by an optional second colon and a description, which will be used for the `tt(%d)' in the value of the tt(format) style (if that is set) instead of the default -description supplied by the completion function. If the description -given here contains itself a `tt(%d)', that is replaced with the -description supplied by the completion function. +description supplied by the completion function. The inclusion +of a description also gives precedence to associated options such as +for completion grouping so it can be used where files should be +separated. For example, to make the tt(rm) command first complete only names of object files and then the names of all files if there is no matching @@ -1548,6 +1549,15 @@ all files using the pattern `tt(*)' at the first step and stops when it sees this pattern. Note also it will never try a pattern more than once for a single completion attempt. +To separate directories into a separate group from the files but still +complete them at the first attempt, a description needs to be given. +Note that directories need to be explicitly excluded from the +globbed-files because `tt(*)' will match directories. For grouping, it +is also necessary to set the tt(group-name) style. + +example(zstyle ':completion:*' file-patterns \ + '%p+LPAR()^-/RPAR():globbed-files *(-/):directories:location') + During the execution of completion functions, the tt(EXTENDED_GLOB) option is in effect, so the characters `tt(#)', `tt(~)' and `tt(^)' have special meanings in the patterns. @@ -1971,9 +1981,10 @@ obtained by setting the style to an empty string (i.e. tt('')). ) kindex(list-dirs-first, completion style) item(tt(list-dirs-first))( -This is used by file completion. If set, directories to be completed -are listed separately from and before completion for other files, -regardless of tag ordering. +This is used by file completion and corresponds to a particular +setting of the tt(file-patterns) style. +If set, the default directories to be completed +are listed separately from and before completion for other files. ) kindex(list-grouped, completion style) item(tt(list-grouped))( -- cgit v1.2.3 From 2fe9ab281380f56a4f492eb644da5bab2e0e7b0d Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 12 Nov 2021 20:44:48 +0100 Subject: 49566: document the _default function --- ChangeLog | 2 ++ Doc/Zsh/compsys.yo | 9 +++++++++ 2 files changed, 11 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 0ad9c4609..1be5a36e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2021-11-12 Oliver Kiddle + * 49566: Doc/Zsh/compsys.yo: document the _default function + * 49564: Completion/Unix/Type/_files, Doc/Zsh/compsys.yo: always use descriptions included in the file-patterns style and allow the recursive-files style to also work in those cases diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 1adceb536..e65f2956b 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -4404,6 +4404,15 @@ Include the leading underscore (`tt(_)') in the matches. ) enditem() ) +findex(_default) +item(tt(_default))( +This function corresponds to the tt(-default-) special context which is +applied where no completion is defined. It is useful to call it under +certain error conditions such as completion after an unrecognised +subcommand. This applies the concept of graceful degradation to the +completion system, allowing it to fallback on basic completion of +commonly useful things like filenames. +) findex(_describe) redef(SPACES)(0)(tt(ifztexi(NOTRANS(@ @ @ @ @ @ @ @ @ @ ))ifnztexi( ))) xitem(tt(_describe )[tt(-12JVx)] [ tt(-oO) | tt(-t) var(tag) ] var(descr) var(name1) [ var(name2) ] [ var(opt) ... ]) -- cgit v1.2.3 From 12dc20832d3db73b80ab282cc667abe86a17917b Mon Sep 17 00:00:00 2001 From: Arseny Maslennikov Date: Sat, 13 Nov 2021 00:19:54 +0300 Subject: 49575: clarify _alternative's action syntax --- ChangeLog | 5 +++++ Doc/Zsh/compsys.yo | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index db166f7ee..eb5eb5ed1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-11-19 Oliver Kiddle + + * Arseny Maslennikov: 49575: Doc/Zsh/compsys.yo: + clarify _alternative's action syntax + 2021-11-15 Jun-ichi Takimoto * 49563: Src/Modules/watch.c: fix build problem of watch module diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index e65f2956b..8c6bf9c40 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -3620,8 +3620,18 @@ described using the var(spec)s which are of the form: `var(tag)tt(:)var(descr)tt(:)var(action)'. The var(tag)s are offered using tt(_tags) and if the tag is requested, the var(action) is executed with the given description var(descr). The var(action)s are those accepted -by the tt(_arguments) function (described below), excluding the -`tt(->)var(state)' and `tt(=)var(...)' forms. +by the tt(_arguments) function (described below), with the following +exceptions: +startitemize() +itemiz(\ +The `tt(->)var(state)' and `tt(=)var(...)' forms are not supported. +) +itemiz(\ +The `tt(LPAR()LPAR()a\:bar b\:baz)tt(RPAR()RPAR())' form does not need +the colon to be escaped, since the var(spec)s have no colon-separated fields +after the var(action). +) +enditemize() For example, the var(action) may be a simple function call: -- cgit v1.2.3 From 16d5d6a9dae526355caf16f2de9d57d84b5d9993 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Wed, 24 Nov 2021 23:07:18 +0100 Subject: 49597: add a helper for completing numbers with unit suffixes and separate out defaults, ranges and units in completion descriptions --- ChangeLog | 14 +++++++ Completion/BSD/Command/_ipfw | 4 +- Completion/Base/Core/_description | 8 ++++ Completion/Base/Utility/_numbers | 87 +++++++++++++++++++++++++++++++++++++++ Completion/Linux/Command/_btrfs | 8 ++-- Completion/Unix/Command/_dd | 14 ++++--- Completion/Unix/Command/_git | 6 +-- Completion/Unix/Command/_head | 22 ++++------ Completion/Unix/Command/_killall | 12 ++---- Completion/Unix/Command/_pv | 18 ++------ Completion/Unix/Command/_rclone | 10 ++--- Completion/Unix/Command/_rsync | 10 ++--- Completion/Unix/Command/_stdbuf | 6 ++- Completion/Unix/Command/_tail | 22 ++++------ Completion/Unix/Command/_timeout | 2 +- Completion/Unix/Command/_zfs | 20 ++++++--- Completion/X/Command/_xset | 4 +- Doc/Zsh/compsys.yo | 81 +++++++++++++++++++++++++++++++++++- 18 files changed, 258 insertions(+), 90 deletions(-) create mode 100644 Completion/Base/Utility/_numbers (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index bb8b73085..d7b225d42 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2021-11-24 Oliver Kiddle + + * 49597: Completion/Base/Core/_description, Doc/Zsh/compsys.yo, + Completion/Base/Utility/_numbers, Completion/BSD/Command/_ipfw, + Completion/Linux/Command/_btrfs, Completion/Unix/Command/_dd, + Completion/Unix/Command/_git, Completion/Unix/Command/_head, + Completion/Unix/Command/_killall, Completion/Unix/Command/_pv, + Completion/Unix/Command/_rclone, Completion/Unix/Command/_rsync, + Completion/Unix/Command/_stdbuf, Completion/Unix/Command/_tail, + Completion/Unix/Command/_timeout, Completion/Unix/Command/_zfs, + Completion/X/Command/_xset: add a helper for completing numbers + with unit suffixes and separate out defaults, ranges and units + in completion descriptions + 2021-11-22 Jun-ichi Takimoto * 49586: Src/hist.c: fix :a and :A modifiers (with PWD="/") on diff --git a/Completion/BSD/Command/_ipfw b/Completion/BSD/Command/_ipfw index 2354a70fe..49d0ef1e8 100644 --- a/Completion/BSD/Command/_ipfw +++ b/Completion/BSD/Command/_ipfw @@ -249,8 +249,8 @@ actions=( $'/(pipe|queue|sched)[ \t\0]/' -'pqs=${match%?}' ':dummynet-commands:dummynet configuration:$ca pipe queue sched' $word ': _message -e numbers number' $word ':options:config:$ca config' - \( $'/bw[ \t\0]/' \( $'/<->/' ': _guard "[0-9]#" bandwidth' - $word ':units:unit:compadd -M "m:{a-z}={A-Z}" {K,M,G}{bit,Byte}/s' + \( $'/bw[ \t\0]/' + \( $word ':bandwidths: :_numbers -M "m:{a-z}={A-Z}" bandwidth {K,M,G}{bit,Byte}/s' \| $word ':devices:device:_net_interfaces -qS " "' \) \| $'/delay[ \t\0]/' $word ': _message -e numbers "propagation delay (ms)"' \| $'/burst[ \t\0]/' $word ': _message -e numbers "size (bytes)"' diff --git a/Completion/Base/Core/_description b/Completion/Base/Core/_description index 5b54484c7..368b41ee2 100644 --- a/Completion/Base/Core/_description +++ b/Completion/Base/Core/_description @@ -2,6 +2,7 @@ local name nopt xopt format gname hidden hide match opts tag local -a ign gropt sort +local -a match mbegin mend opts=() @@ -78,6 +79,13 @@ shift 2 if [[ -z "$1" && $# -eq 1 ]]; then format= elif [[ -n "$format" ]]; then + if [[ -z $2 ]]; then + argv+=( h:${1%%( ##\((#b)([^\)]#[^0-9-][^\)]#)(#B)\)|)( ##\((#b)([0-9-]##)(#B)\)|)( ##\[(#b)([^\]]##)(#B)\]|)} ) + [[ -n $match[1] ]] && argv+=( m:$match[1] ) + [[ -n $match[2] ]] && argv+=( r:$match[2] ) + [[ -n $match[3] ]] && argv+=( o:$match[3] ) + fi + zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}" fi diff --git a/Completion/Base/Utility/_numbers b/Completion/Base/Utility/_numbers new file mode 100644 index 000000000..97bb8b4c8 --- /dev/null +++ b/Completion/Base/Utility/_numbers @@ -0,0 +1,87 @@ +#autoload + +# Usage: _numbers [compadd options] [-t tag] [-f|-N] [-u units] [-l min] [-m max] \ +# [-d default] ["description"] [unit-suffix...] + +# -t : specify a tag (defaults to 'numbers') +# -u : indicate the units, e.g. seconds +# -l : lowest possible value +# -m : maximum possible value +# -d : default value +# -N : allow negative numbers (implied by range including a negative) +# -f : allow decimals (float) + +# For a unit-suffix, an initial colon indicates a unit that asserts the default +# otherwise, colons allow for descriptions, e.g: + +# :s:seconds m:minutes h:hours + +# unit-suffixes are not sorted by the completion system when listed +# Specify them in order of magnitude, this tends to be ascending unless +# the default is of a higher magnitude, in which case, descending. +# So for, example +# bytes kB MB GB +# s ms us ns +# Where the compadd options include matching control or suffixes, these +# are applied to the units + +# For each unit-suffix, the format style is looked up with the +# unit-suffixes tag and the results concatenated. Specs used are: +# x : the suffix +# X : suffix description +# d : indicate suffix is for the default unit +# i : list index +# r : reverse list index +# The latter three of these are useful with ternary expressions. + +# _description is called with the x token set to make the completed +# list of suffixes available to the normal format style + +local desc tag range suffixes suffix suffixfmt pat='<->' partial='' +local -a expl formats +local -a default max min keep tags units +local -i i +local -A opts + +zparseopts -K -D -A opts M+:=keep q:=keep s+:=keep S+:=keep J+: V+: 1 2 o+: n F: x+: X+: \ + t:=tags u:=units l:=min m:=max d:=default f=type e=type N=type + +desc="${1:-number}" tag="${tags[2]:-numbers}" +(( $# )) && shift + +[[ -n ${(M)type:#-f} ]] && pat='(<->.[0-9]#|[0-9]#.<->|<->)' partial='(|.)' +[[ -n ${(M)type:#-N} || $min[2] = -* || $max[2] = -* ]] && \ + pat="(|-)$pat" partial="(|-)$partial" + +if (( $#argv )) && compset -P "$pat"; then + zstyle -s ":completion:${curcontext}:units" list-separator sep || sep=-- + _description -V units expl unit + disp=( ${${argv#:}/:/ $sep } ) + compadd -M 'r:|/=* r:|=*' -d disp "$keep[@]" "$expl[@]" - ${${argv#:}%%:*} + return +elif [[ -prefix $~pat || $PREFIX = $~partial ]]; then + formats=( "h:$desc" ) + (( $#units )) && formats+=( m:${units[2]} ) desc+=" ($units[2])" + (( $#min )) && range="$min[2]-" + (( $#max )) && range="${range:--}$max[2]" + [[ -n $range ]] && formats+=( r:$range ) desc+=" ($range)" + (( $#default )) && formats+=( o:${default[2]} ) desc+=" [$default[2]]" + + zstyle -s ":completion:${curcontext}:unit-suffixes" format suffixfmt || \ + suffixfmt='%(d.%U.)%x%(d.%u.)%(r..|)' + for ((i=0;i<$#;i++)); do + zformat -f suffix "$suffixfmt" "x:${${argv[i+1]#:}%%:*}" \ + "X:${${argv[i+1]#:}#*:}" "d:${#${argv[i+1]}[1]#:}" \ + i:i r:$(( $# - i - 1)) + suffixes+="$suffix" + done + [[ -n $suffixes ]] && formats+=( x:$suffixes ) + + _comp_mesg=yes + _description -x $tag expl "$desc" $formats + [[ $compstate[insert] = *unambiguous* ]] && compstate[insert]= + compadd "$expl[@]" + return 0 +fi + +return 1 diff --git a/Completion/Linux/Command/_btrfs b/Completion/Linux/Command/_btrfs index bb0f724e6..65cf067aa 100644 --- a/Completion/Linux/Command/_btrfs +++ b/Completion/Linux/Command/_btrfs @@ -147,16 +147,16 @@ while (( $#state )); do '--tbytes[show sizes in TiB, or TB with --si]' ) ;| - filesystem:resize) args+=( '1:size:_guard "(|+|-)[0-9]#[GKM]"' '2:path:->mounts' );; + filesystem:resize) args+=( '1: :_numbers -u bytes -N size K M G T P E' '2:path:->mounts' );; filesystem:defragment) args+=( '!-v' '-r[defragment files recursively]' '-c+[compress files while defragmenting]::compression algorithm:(zlib lzo zstd)' '-r[defragment files recursively]' '-f[flush after defragmenting]' - '-s[start position]:byte position' - '-l[defragment limited number of bytes]:length (bytes)' - '-t[defragment only files over a certain size]:minimum size (bytes) [32M]' + '-s[start position]: :_numbers -u bytes -d "beginning of file" offset K M G T P E' + '-l[defragment limited number of bytes]: :_numbers -u bytes length K M G T P E' + '-t[defragment only extents up to a certain size]: :_numbers -u bytes -d 32M "maximum extent size" K M G T P E' '*:file:_files' ) ;; diff --git a/Completion/Unix/Command/_dd b/Completion/Unix/Command/_dd index e5c5e63ce..10682bc8e 100644 --- a/Completion/Unix/Command/_dd +++ b/Completion/Unix/Command/_dd @@ -1,18 +1,19 @@ #compdef dd gdd -local -a vals conv flags +local -a vals conv flags units local variant +units=( w:word b:block k:1024 m g t ) _pick_variant -r variant gnu=GNU $OSTYPE --version vals=( - '(ibs obs)bs[block size]:block size (bytes)' - 'cbs[conversion buffer size]:buffer size (bytes)' + '(ibs obs)bs[block size]: :_numbers -u bytes "block size" $units' + 'cbs[conversion buffer size]: :_numbers -u bytes "buffer size" $units' 'conv[specify conversions to apply]: :_values -s , conversion $conv' 'count[number of input blocks to copy]:blocks' - '(bs)ibs[input block size]:block size (bytes)' + '(bs)ibs[input block size]: :_numbers -u bytes -d 512 "block size" $units' 'if[specify input file]:input file:_tilde_files' - '(bs)obs[output block size]:block size (bytes)' + '(bs)obs[output block size]: :_numbers -u bytes -d 512 "block size" $units' 'of[specify output file]:output file:_tilde_files' 'seek[output blocks initially skipped]:blocks' 'skip[input blocks initially skipped]:blocks' @@ -63,7 +64,7 @@ case $variant in freebsd*) vals+=( 'fillchar[specify padding character]:character' - 'speed[limit copying speed]:speed (bytes/second)' + 'speed[limit copying speed]: :_numbers -u bytes/second speed $units' ) conv+=( '(pareven parnone parodd parset)'{pareven,parnone,parodd,parset} @@ -75,6 +76,7 @@ case $variant in ) flags+=( fullblock noatime nocache count_bytes skip_bytes seek_bytes ) conv+=( excl nocreat fdatasync fsync ) + units=( c:1 w:2 b:512 kB:1000 K:1024 MB:1000^2 M:1024\^2 GB G TB T PB P EB E ZB Z YB Y ) ;; netbsd*) vals+=( diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 7c7fb22bc..c757376b0 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -3720,8 +3720,8 @@ _git-fast-import () { now\:"use current time and timezone"' \ '--done[terminate with error if there is no "done" command at the end of the stream]' \ '--force[force updating modified existing branches]' \ - '--max-pack-size=-[maximum size of each packfile]: : __git_guard_bytes' \ - '--big-file-threshold=-[maximum size of blob to create deltas for]: : __git_guard_bytes' \ + '--max-pack-size=-[maximum size of each packfile]: : __git_guard_bytes -d unlimited size' \ + '--big-file-threshold=-[maximum size of blob to create deltas for]: : __git_guard_bytes -d 512m size' \ '--depth=-[maximum delta depth for blob and tree deltification]: :__git_guard_number "maximum delta depth"' \ '--active-branches=-[maximum number of branches to maintain active at once]: :__git_guard_number "maximum number of branches"' \ '--export-marks=-[dump internal marks table when complete]: :_files' \ @@ -7506,7 +7506,7 @@ __git_guard_number () { (( $+functions[__git_guard_bytes] )) || __git_guard_bytes () { - _guard '[[:digit:]]#([kKmMgG]|)' ${*:-size} + _numbers -u bytes ${*:-size} k m g } (( $+functions[__git_datetimes] )) || diff --git a/Completion/Unix/Command/_head b/Completion/Unix/Command/_head index f25c97c83..0771b1e4d 100644 --- a/Completion/Unix/Command/_head +++ b/Completion/Unix/Command/_head @@ -32,20 +32,14 @@ _arguments -C -s -S $opts : $args '*:file:_files' && return 0 case $state in (number) - local mlt sign digit - mlt='multiplier:multiplier:((b\:512 K\:1024 KB\:1000 M\:1024\^2' - mlt+=' MB\:1000\^2 G\:1024\^3 GB\:1000\^3 T\:1024\^4 TB\:1000\^4))' - sign='sign:sign:((-\:"print all but the last specified bytes/lines"' - sign+=' +\:"print the first specified bytes/lines (default)"))' - digit='digits:digit:(0 1 2 3 4 5 6 7 8 9)' - if compset -P '(-|+|)[0-9]##'; then - _alternative $mlt $digit && ret=0 - elif [[ -z $PREFIX ]]; then - _alternative $sign $digit && ret=0 - elif compset -P '(+|-)'; then - _alternative $digit && ret=0 - fi - ;; + local alts + [[ -z $PREFIX ]] && alts=( + 'sign:sign:((-\:"print all but the last specified bytes/lines" +\:"print the first specified bytes/lines (default)"))' + ) + compset -P '+' + alts+=( 'numbers: :_numbers -N $state_descr b\:512 K\:1024 KB\:1000 M\:1024\^2 MB\:1000\^2 G\:1024\^3 GB\:1000\^3 T\:1024\^4 TB\:1000\^4' ) + _alternative $alts && ret=0 + ;; esac return ret diff --git a/Completion/Unix/Command/_killall b/Completion/Unix/Command/_killall index 36accb2e0..3ddd36341 100644 --- a/Completion/Unix/Command/_killall +++ b/Completion/Unix/Command/_killall @@ -38,15 +38,9 @@ if _pick_variant psmisc=PSmisc unix --version; then case $state in (time) - local -a units=( 's:seconds' 'm:minutes' 'h:hours' 'd:days' - 'w:weeks' 'M:months' 'y:years' ) - if compset -P '[0-9]##(|.[0-9]#)'; then - _alternative 'float-numbers:: _message "float number"' \ - 'units:: _describe unit units' && ret=0 - else - _message 'float number and unit' && ret=0 - fi - ;; + _numbers -fN age 's:seconds' 'm:minutes' 'h:hours' 'd:days' \ + 'w:weeks' 'M:months' 'y:years' + ;; esac return ret diff --git a/Completion/Unix/Command/_pv b/Completion/Unix/Command/_pv index 68f8e8586..d02d3a35d 100644 --- a/Completion/Unix/Command/_pv +++ b/Completion/Unix/Command/_pv @@ -25,7 +25,7 @@ _arguments -s -S $args \ '(-q --quiet)'{-q,--quiet}"[don't output any transfer information at all, useful with -L]" \ '(-W --wait)'{-W,--wait}'[display nothing until first byte transferred]' \ '(-D --delay-start -R --remote)'{-D+,--delay-start=}'[display nothing until delay has passed]:delay (seconds)' \ - '(-s --size)'{-s+,--size=}'[set estimated data size]:size (bytes):->size-unit' \ + '(-s --size)'{-s+,--size=}'[set estimated data size]: :_numbers -u bytes size K M G T' \ '(-l --line-mode -R --remote)'{-l,--line-mode}'[count lines instead of bytes]' \ '(-0 --null -l --line-mode)'{-0,--null}'[lines are null-terminated]' \ '(-i --interval)'{-i+,--interval=}'[update every after specified interval]:interval (seconds) [1]' \ @@ -34,8 +34,8 @@ _arguments -s -S $args \ '(-N --name)'{-N+,--name=}'[prefix visual information with given name]:name' \ '(-f --force -R --remote)'{-f,--force}'[output even if standard error is not a terminal]' \ '(-c --cursor -R --remote)'{-c,--cursor}'[use cursor positioning escape sequences]' \ - '(-L --rate-limit)'{-L+,--rate-limit=}'[limit transfer rate]:rate (bytes per second):->size-unit' \ - '(-B --buffer-size)'{-B+,--buffer-size=}'[use a buffer size of given size]:size (bytes):->size-unit' \ + '(-L --rate-limit)'{-L+,--rate-limit=}'[limit transfer rate]: :_numbers -u "bytes per second" rate K M G T' \ + '(-B --buffer-size)'{-B+,--buffer-size=}'[use a buffer size of given size]: :_numbers -u bytes size K M G T' \ '(-C --no-splice)'{-C,--no-splice}'[never use splice(), always use read/write]' \ '(-R --remote)*'{-E,--skip-errors}"[skip read errors in input${Edesc}]" \ '(-S --stop-at-size -R --remote)'{-S,--stop-at-size}'[stop after --size bytes have been transferred]' \ @@ -70,18 +70,6 @@ case $state in _pids $suf && ret=0 fi ;; - size-unit) - if compset -P '<->'; then - _tags values units - else - _tags values - fi - while _tags; do - _requested values && _message -e values "$state_descr" && ret=0 - _requested units expl unit compadd -o nosort - K M G T && ret=0 - (( ret )) || break - done - ;; esac return ret diff --git a/Completion/Unix/Command/_rclone b/Completion/Unix/Command/_rclone index 27b4dd926..a2e3429f5 100644 --- a/Completion/Unix/Command/_rclone +++ b/Completion/Unix/Command/_rclone @@ -62,7 +62,7 @@ _arguments -C \ '--backup-dir[make backups into hierarchy based at specified directory]:directory:_directories' \ '--bind[specify socal address to bind to for outgoing connections]:IPv4, IPv6 or name' \ '--buffer-size[specify in memory buffer size when reading files for each --transfer]:size [16M]' \ - '--bwlimit[specify bandwidth limit]:BwTimetable (kBytes/s or b|k|M|G suffix)' \ + '--bwlimit[specify bandwidth limit]: :_numbers -u kBytes/s limit b k M G' \ '--cache-dir[specify directory rclone will use for caching]:directory [~/.cache/rclone]:_directories' \ '--checkers[specify number of checkers to run in parallel]:number [8]': \ '(-c --checksum)'{-c,--checksum}'[skip based on checksum & size, not mod-time & size]' \ @@ -99,15 +99,15 @@ _arguments -C \ '--log-format[specify comma separated list of log format options]:string ["date,time"]' \ '--log-level[specify log level]:string [NOTICE]:(DEBUG INFO NOTICE ERROR)' \ '--low-level-retries[number of low level retries to do]:int [10]' \ - '--max-age[only transfer files younger than this in s or suffix ms|s|m|h|d|w|M|y]:duration [default off]' \ + '--max-age[only transfer files younger than specified age]: :_numbers -u seconds age ms\:milliseconds \:s\:seconds m\:minutes h\:hours d\:days w\:weeks M\:months y\:years' \ '--max-backlog[maximum number of objects in sync or check backlog]:int [10000]' \ '--max-delete[when synchronizing, limit the number of deletes]:delete limit [-1]' \ '--max-depth[limit the recursion depth]:depth [-1]' \ - '--max-size[only transfer files smaller than this in k or suffix b|k|M|G]:int [default off]' \ + '--max-size[only transfer files smaller than specified size]: :_numbers -u kBytes size \:k M G' \ '--max-transfer[maximum size of data to transfer]:int [default off]' \ '--memprofile[write memory profile to file]:file:_files' \ - '--min-age[only transfer files older than this in s or suffix ms|s|m|h|d|w|M|y]:duration [default off]' \ - '--min-size[only transfer files bigger than this in k or suffix b|k|M|G]:int [default off]' \ + '--min-age[only transfer files older than specified age]: :_numbers -u seconds age ms\:milliseconds \:s\:seconds m\:minutes h\:hours d\:days w\:weeks M\:months y\:years' \ + '--min-size[only transfer files bigger than specified size]: :_numbers -u kBytes size \:k M G' \ '--modify-window[specify max time delta to be considered the same]:duration [1ns]' \ '--multi-thread-cutoff[use multi-threaded downloads for files above specified size]:size (250M)' \ '--multi-thread-streams[specify max number of streams to use for multi-threaded downloads]:number (4)' \ diff --git a/Completion/Unix/Command/_rsync b/Completion/Unix/Command/_rsync index b1a4f6046..eb906e974 100644 --- a/Completion/Unix/Command/_rsync +++ b/Completion/Unix/Command/_rsync @@ -99,7 +99,7 @@ _rsync() { _arguments -s \ '*'{-v,--verbose}'[increase verbosity]' \ {--no-v,--no-verbose}'[turn off --verbose]' \ - '--bwlimit=[limit I/O bandwidth]:limit (KiB per second)' \ + '--bwlimit=[limit I/O bandwidth]: :_numbers -f -u "KiB per second" -d 1g limit B K M G T P' \ '--outbuf=[set output buffering]:buffering:(none line block)' \ '--port=[specify alternate port number]:port:(873)' \ '--address=[bind to the specified address]:bind address:_bind_addresses' \ @@ -181,7 +181,7 @@ _rsync() { {--no-W,--no-whole-file}'[turn off --whole-file]' \ '(--cc --checksum-choice)'{--cc,--checksum-choice}'=[choose the checksum algorithms]:algorithm:_sequence -n 2 compadd - auto md4 md5 none' \ '(-x --one-file-system)'{-x,--one-file-system}"[don't cross filesystem boundaries]" \ - '(-B --block-size)'{-B+,--block-size=}'[force a fixed checksum block-size]:block size (bytes)' \ + '(-B --block-size)'{-B+,--block-size=}'[force a fixed checksum block-size]: :_numbers -f -u bytes -d 1g "block size" B K M G T P' \ '(-e --rsh)'{-e+,--rsh=}'[specify the remote shell to use]:remote-shell command:(rsh ssh)' \ '--rsync-path=[specify path to rsync on the remote machine]:remote command' \ '--ignore-existing[ignore files that already exist on receiving side]' \ @@ -199,10 +199,10 @@ _rsync() { '--force-change[affect user-/system-immutable files/dirs]' \ '--force-uchange[affect user-immutable files/dirs]' \ '--force-schange[affect system-immutable files/dirs]' \ - '--max-delete=[do not delete more than NUM files]:number' \ - '--max-size=[do not transfer any file larger than specified size]:number' \ + "--max-delete=[don't delete more than NUM files]: :_numbers -f -u bytes size B K M G T P" \ + "--max-size=[don't transfer any file larger than specified size]: :_numbers -f -u bytes size B K M G T P" \ '--min-size=[do not transfer any file smaller than specified size]:number' \ - '--max-alloc=[set limit to individual memory allocation]:size (bytes) [1g]' \ + '--max-alloc=[set limit to individual memory allocation]: :_numbers -f -u bytes -d 1g size B K M G T P' \ '(-P)--partial[keep partially transferred files]' \ '--no-partial[turn off --partial]' \ '--partial-dir=[put a partially transferred file into specified directory]:directory:_directories' \ diff --git a/Completion/Unix/Command/_stdbuf b/Completion/Unix/Command/_stdbuf index a18938ee1..4b7d98ba0 100644 --- a/Completion/Unix/Command/_stdbuf +++ b/Completion/Unix/Command/_stdbuf @@ -7,7 +7,9 @@ short=( -e -i -o ) long=( --error --input --output ) buf=( err in out ) -opt='[set initial buffering for std${buf[i]}]:mode or size:((0\:unbuffered L\:line\ buffered' +opt='[set initial buffering for std${buf[i]}]: : _alternative + "sizes\: \: _numbers -u bytes size k M G" + "modes\:mode\:((0\:unbuffered L\:line\ buffered' if _pick_variant gnu=GNU freebsd --version; then gnu=1 args=( @@ -17,7 +19,7 @@ if _pick_variant gnu=GNU freebsd --version; then else opt+=' B\:fully\ buffered' fi -opt+='))' +opt+='))"' for ((i=1;i<=3;i++)); do args+=( "(${long[i]})${short[i]}+${(e)opt}" ) diff --git a/Completion/Unix/Command/_tail b/Completion/Unix/Command/_tail index 6d6e9b2d5..e54a0b06e 100644 --- a/Completion/Unix/Command/_tail +++ b/Completion/Unix/Command/_tail @@ -53,20 +53,14 @@ _arguments -C -s -S $opts : $args '*:file:_files' && return case $state in (number) - local mlt sign digit - mlt='multipliers:multiplier:((b\:512 K\:1024 KB\:1000 M\:1024\^2' - mlt+=' MB\:1000\^2 G\:1024\^3 GB\:1000\^3 T\:1024\^4 TB\:1000\^4))' - sign='signs:sign:((+\:"start at the specified byte/line"' - sign+=' -\:"output the last specified bytes/lines (default)"))' - digit='digits:digit:(0 1 2 3 4 5 6 7 8 9)' - if compset -P '(-|+|)[0-9]##'; then - _alternative $mlt $digit && ret=0 - elif [[ -z $PREFIX ]]; then - _alternative $sign $digit && ret=0 - elif compset -P '(+|-)'; then - _alternative $digit && ret=0 - fi - ;; + local alts + [[ -z $PREFIX ]] && alts=( + 'sign:sign:((-\:"print all but the last specified bytes/lines" +\:"print the first specified bytes/lines (default)"))' + ) + compset -P '+' + alts+=( 'numbers: :_numbers -N $state_descr b\:512 K\:1024 KB\:1000 M\:1024\^2 MB\:1000\^2 G\:1024\^3 GB\:1000\^3 T\:1024\^4 TB\:1000\^4' ) + _alternative $alts && ret=0 + ;; esac return ret diff --git a/Completion/Unix/Command/_timeout b/Completion/Unix/Command/_timeout index 2235fa5ec..c041283ac 100644 --- a/Completion/Unix/Command/_timeout +++ b/Completion/Unix/Command/_timeout @@ -16,5 +16,5 @@ _arguments -S -A "-" $args \ "--foreground[don't propagate timeout to the command children]" \ '(-s --signal)'{-s,--signal}'[specify the signal to send on timeout]:signal:_signals' \ '(-k --kill-after)'{-k,--kill-after}'[followup first signal with SIGKILL if command persists after specified time]:time' \ - '1: :_guard "[0-9.]#([smhd]|)" duration' \ + '1: :_numbers -f -u seconds duration :s:seconds m:minutes h:hours d:days' \ '*:::command:_normal' diff --git a/Completion/Unix/Command/_zfs b/Completion/Unix/Command/_zfs index 452e1160d..51da9170b 100644 --- a/Completion/Unix/Command/_zfs +++ b/Completion/Unix/Command/_zfs @@ -162,12 +162,20 @@ _zfs() { "multilevel:value:(on off)" "nbmand:value:(on off)" "primarycache:value:(all none metadata)" - "quota:number or 'none':{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == quota= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'quota' compadd none; fi}" + "quota: : _alternative \ + 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \ + 'properties:property:(none)'" "readonly:value:(on off)" "recordsize:value:(512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M)" - "refquota:number or 'none':{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == refquota= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'refquota' compadd none; fi}" - "refreservation:number or 'none':{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == refreservation= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'refreservation' compadd none; fi}" - "reservation:value:{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == reservation= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'reservation' compadd none; fi}" + "refquota: : _alternative \ + 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \ + 'properties:property:(none)'" + "refreservation: : _alternative \ + 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \ + 'properties:property:(auto none)'" + "reservation: : _alternative \ + 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \ + 'properties:property:(none)'" "rstchown:value:(on off)" "secondarycache:value:(all none metadata)" "setuid:value:(on off)" @@ -238,8 +246,8 @@ _zfs() { ':filesystem:_zfs_dataset -t fs -e "parent dataset"' \ - set2 \ '-s[Create sparse volume]' \ - '-b[Set volblocksize]:blocksize:' \ - '-V[Set size]:size:' \ + '-b+[set volblocksize]: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes blocksize :B {k,M,G,T,P,E,Z}{,B}' \ + '-V+[set size]: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \ ':volume:_zfs_dataset -t fs -e "parent dataset"' ;; diff --git a/Completion/X/Command/_xset b/Completion/X/Command/_xset index b35a6466b..adda47f01 100644 --- a/Completion/X/Command/_xset +++ b/Completion/X/Command/_xset @@ -91,8 +91,8 @@ _regex_arguments _xset_parse \ \( "/(blank|noblank|expose|noexpose|default|on|activate|reset)$nul/" \ ':option-s:screen saver:(blank noblank expose noexpose default on activate reset off)' \ \| "/off$nul/" \( "/off$nul/" ':option-s-off-period:period off:(off)' \| \) \ - \| "/[0-9]##$nul/" ':option-s-timeout:length:' \ - \( "/[0-9]##$nul/" ':option-s-period:period:' \ + \| "/[0-9]##$nul/" ':option-s-timeout: :_numbers -u seconds length' \ + \( "/[0-9]##$nul/" ':option-s-period: :_numbers -u seconds period' \ \| \) \ \| \) \ \| "/-r$nul/" "$guard" \ diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 8c6bf9c40..40238c4b9 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -4496,8 +4496,22 @@ not contain an explanation string to be displayed above the matches. If tt(_description) is called with more than three arguments, the additional var(spec)s should be of the form `var(char)tt(:)var(str)'. These supply escape sequence replacements for the tt(format) style: -every appearance of `tt(%)var(char)' will be -replaced by var(string). +every appearance of `tt(%)var(char)' will be replaced by var(string). +If no additional var(spec)s are given but the description in var(descr) +conforms to a common form then further escape sequences are set for +elements of that description. These elements correspond to a default +value (`tt(%o)'), the units (`tt(%m)') range of acceptable values +(`tt(%r)') and the remaining initial part of the description (`tt(%h)'). +The form the description takes consists of specifying the units and +range in parentheses and the default value in square brackets, for +example: + +example(_description times expl 'timeout (seconds) (0-60) [20]') + +It is possible to use tt(zformat) conditional expressions when styling +these elements. So, for example, to add `tt(default:)' as a tag but only +when there is a default value to show, the tt(format) style might +include `tt(%(o.default: %o.))'. If the tt(-x) option is given, the description will be passed to tt(compadd) using the tt(-x) option instead of the default tt(-X). This @@ -4773,6 +4787,69 @@ checked. If it is set completion is terminated at that point even if no matches have been found. This is the same effect as in the tt(-first-) context. ) +findex(_numbers) +item(tt(_numbers) [ var(option) ... ] [ var(description) ] [ var(suffix) ... ])( +This can be used where a number is followed by a suffix to indicate the units. +The unit suffixes are completed and can also be included in the description +used when completion is invoked for the preceding number. + +In addition to common tt(compadd) options, tt(_numbers) accepts the following +options: + +startitem() +item(tt(-t) var(tag))( +Specify a tag to use instead of the default of tt(numbers). +) +item(tt(-u) var(units))( +Indicate the default units for the number, e.g. tt(bytes). +) +item(tt(-l) var(min))( +Specify the lowest possible value for the number. +) +item(tt(-m) var(max))( +Specify the highest possible value for the number. +) +item(tt(-d) var(default))( +Specify the default value. +) +item(tt(-N))( +Allow negative numbers. This is implied if the range includes a negative. +) +item(tt(-f))( +Allow decimal numbers. +) +enditem() + +Where a particular suffix represents the default units for a number, it +should be prefixed with a colon. Additionally, suffixes can be followed +by a colon and a description. So for example, the following allows the +age of something to be specified, either in seconds or with an optional +suffix with a longer unit of time: + +example(_numbers -u seconds age :s:seconds m:minutes h:hours d:days) + +It is typically helpful for units to be presented in order of magnitude +when completed. To facilitate this, the order in which they are given +is preserved. + +When the tt(format) style is looked up with the tt(descriptions) tag or +the tag specified with tt(-t), the list of suffixes is available as a +`tt(%x)' escape sequence. This is in addition to the usual sequences +documented under the tt(format) style. The form this list takes can also +be configured. To this end, the tt(format) style is first looked up with +the tag tt(unit-suffixes). The retrieved format is applied to each +suffix in turn and the results are then concatenated to form the +completed list. For the tt(unit-suffixes) format, `tt(%x)' expands to +the individual suffix and `tt(%X)' to its description. tt(%d)' indicates +a default suffix and can be used in a condition. The index and reverse +index are set in `tt(%i)' and `tt(%r)' respectively and are useful for +text included only with the first and last suffixes in the list. So for +example, the following joins the suffixes together as a comma-separated +list: + +example(zstyle ':completion:*:unit-suffixes' format '%x%(r::,)') +) + findex(_options) item(tt(_options))( This can be used to complete the names of shell options. It provides a -- cgit v1.2.3 From 94563d5ad14a0eb6effefd4c2c42a7ac84e91230 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 26 Sep 2021 08:43:44 +0000 Subject: 49445: docs: Clean up some subsection references. --- ChangeLog | 5 +++++ Doc/Zsh/calsys.yo | 2 +- Doc/Zsh/contrib.yo | 6 +++--- Doc/Zsh/expn.yo | 2 +- Doc/Zsh/intro.yo | 2 +- Doc/Zsh/jobs.yo | 2 +- Doc/Zsh/mod_newuser.yo | 2 +- Doc/Zsh/options.yo | 4 ++-- Doc/Zsh/params.yo | 2 +- Doc/Zsh/roadmap.yo | 2 +- Doc/Zsh/zle.yo | 2 +- 11 files changed, 18 insertions(+), 13 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index d093ffb83..3773b8170 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2021-11-26 Daniel Shahaf + * 49445: Doc/Zsh/calsys.yo, Doc/Zsh/contrib.yo, Doc/Zsh/expn.yo, + Doc/Zsh/intro.yo, Doc/Zsh/jobs.yo, Doc/Zsh/mod_newuser.yo, + Doc/Zsh/options.yo, Doc/Zsh/params.yo, Doc/Zsh/roadmap.yo, + Doc/Zsh/zle.yo: docs: Clean up some subsection references. + * 49449: Completion/Unix/Command/_stat: _zstat: Don't offer -o after -s, since -s is ignored when both -s and -o are specified. diff --git a/Doc/Zsh/calsys.yo b/Doc/Zsh/calsys.yo index c20c87e61..a8fd876a5 100644 --- a/Doc/Zsh/calsys.yo +++ b/Doc/Zsh/calsys.yo @@ -478,7 +478,7 @@ item(tt(calendar_add) [ tt(-BL) ] var(event) ...)( Adds a single event to the calendar in the appropriate location. The event can contain multiple lines, as described in ifnzman(noderef(Calendar File and Date Formats))\ -ifzman(the section Calendar File Format above). +ifzman(the section `Calendar File Format' above). Using this function ensures that the calendar file is sorted in date and time order. It also makes special arrangements for locking the file while it is altered. The old calendar is left in a file diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index cbd850231..e8311eb55 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2341,7 +2341,7 @@ directly. ) tindex(bracketed-paste-magic) item(tt(bracketed-paste-magic))( -The tt(bracketed-paste) widget (see ifzman(subsection Miscellaneous in +The tt(bracketed-paste) widget (see ifzman(the subsection `Miscellaneous' in zmanref(zshzle))ifnzman(noderef(Miscellaneous) in noderef(Zle Widgets))) inserts pasted text literally into the editor buffer rather than interpret it as keystrokes. This disables some common usages where the self-insert @@ -3190,7 +3190,7 @@ investigate the command word found. The default is tt(whence -c). tindex(zcalc-auto-insert) item(tt(zcalc-auto-insert))( This function is useful together with the tt(zcalc) function described in -ifzman(the section Mathematical Functions)\ +ifzman(the section `Mathematical Functions')\ ifnzman(noderef(Mathematical Functions)). It should be bound to a key representing a binary operator such as `tt(PLUS())', `tt(-)', `tt(*)' or `tt(/)'. When running in zcalc, @@ -3664,7 +3664,7 @@ types even if they are executable. As this example shows, the complete file name is matched against the pattern, regardless of how the file was passed to the handler. The file is resolved to a full path using the tt(:P) modifier described in -ifzman(the subsection Modifiers in zmanref(zshexpn))\ +ifzman(the subsection `Modifiers' in zmanref(zshexpn))\ ifnzman(noderef(Modifiers)); this means that symbolic links are resolved where possible, so that links into other file systems behave in the correct fashion. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index d40d1b439..00f93e402 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1857,7 +1857,7 @@ has similar effects. To combine brace expansion with array expansion, see the tt(${^)var(spec)tt(}) form described -ifzman(in the section Parameter Expansion)\ +ifzman(in the section `Parameter Expansion')\ ifnzman(in noderef(Parameter Expansion)) above. diff --git a/Doc/Zsh/intro.yo b/Doc/Zsh/intro.yo index 75d25ce27..474e537c2 100644 --- a/Doc/Zsh/intro.yo +++ b/Doc/Zsh/intro.yo @@ -45,7 +45,7 @@ zsh most closely resembles bf(ksh) but includes many enhancements. It does not provide compatibility with POSIX or other shells in its default operating mode: see ifnzman(the section noderef(Compatibility))\ -ifzman(the section Compatibility below). +ifzman(the section `Compatibility' below). Zsh has command line editing, builtin spelling correction, programmable command completion, shell functions (with autoloading), a history diff --git a/Doc/Zsh/jobs.yo b/Doc/Zsh/jobs.yo index 331b91d8d..3ab0698ae 100644 --- a/Doc/Zsh/jobs.yo +++ b/Doc/Zsh/jobs.yo @@ -135,4 +135,4 @@ ifzman(the section PROCESS SUBSTITUTION in the zmanref(zshexpn) manual page)\ ifnzman(noderef(Process Substitution)), and the handler processes for multios, see ifzman(the section MULTIOS in the zmanref(zshmisc) manual page)\ -ifnzman(the section Multios in noderef(Redirection)). +ifnzman(the section em(Multios) in noderef(Redirection)). diff --git a/Doc/Zsh/mod_newuser.yo b/Doc/Zsh/mod_newuser.yo index 92a64a013..7937e43c3 100644 --- a/Doc/Zsh/mod_newuser.yo +++ b/Doc/Zsh/mod_newuser.yo @@ -44,4 +44,4 @@ even if the tt(zsh/newuser) module is disabled. Note, however, that if the module is not installed the function will not be installed either. The function is documented in ifnzman(noderef(User Configuration Functions))\ -ifzman(the section User Configuration Functions in zmanref(zshcontrib)). +ifzman(the section `User Configuration Functions' in zmanref(zshcontrib)). diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 4a8b85e08..cf4600769 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -602,7 +602,7 @@ Substitutions using the tt(:s) and tt(:&) history modifiers are performed with pattern matching instead of string matching. This occurs wherever history modifiers are valid, including glob qualifiers and parameters. See -ifzman(the section Modifiers in zmanref(zshexpn))\ +ifzman(the section `Modifiers' in zmanref(zshexpn))\ ifnzman(noderef(Modifiers)). ) pindex(IGNORE_BRACES) @@ -1483,7 +1483,7 @@ The check is omitted if the commands run from the previous command line included a `tt(jobs)' command, since it is assumed the user is aware that there are background or suspended jobs. A `tt(jobs)' command run from one of the hook functions defined in -ifnzman(the section Special Functions in noderef(Functions))\ +ifnzman(the section `Special Functions' in noderef(Functions))\ ifzman(the section SPECIAL FUNCTIONS in zmanref(zshmisc)) is not counted for this purpose. ) diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 1f2f01f55..6b52d3b1c 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -106,7 +106,7 @@ may be in any order. Note that this syntax is strict: tt([) and tt(]=) must not be quoted, and var(key) may not consist of the unquoted string tt(]=), but is otherwise treated as a simple string. The enhanced forms of subscript expression that may be used when directly subscripting a -variable name, described in the section Array Subscripts below, are not +variable name, described in the section `Array Subscripts' below, are not available. The syntaxes with and without the explicit key may be mixed. An implicit diff --git a/Doc/Zsh/roadmap.yo b/Doc/Zsh/roadmap.yo index 3f9a122af..2db90889b 100644 --- a/Doc/Zsh/roadmap.yo +++ b/Doc/Zsh/roadmap.yo @@ -20,7 +20,7 @@ The function is designed to be self-explanatory. You can run it by hand with `tt(autoload -Uz zsh-newuser-install; zsh-newuser-install -f)'. See also ifnzman(noderef(User Configuration Functions))\ -ifzman(the section User Configuration Functions in zmanref(zshcontrib)). +ifzman(the section `User Configuration Functions' in zmanref(zshcontrib)). sect(Interactive Use) diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 6d517b81b..70dfec333 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -50,7 +50,7 @@ argument causes the next command entered to be repeated the specified number of times, unless otherwise noted below; this is implemented by the tt(digit-argument) widget. See also ifzman(the em(Arguments) subsection of the em(Widgets) section )\ -ifnzman(noderef(Arguments) )\ +ifnzman(noderef(Arguments))\ for some other ways the numeric argument can be modified. startmenu() -- cgit v1.2.3 From ff1f7769ee7da1908fb040c5a74f29a83a84b5ff Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 26 Sep 2021 08:43:45 +0000 Subject: 49446: docs: Add texinode()s, so the next commit can link directly to a subsection. --- ChangeLog | 3 +++ Doc/Zsh/expn.yo | 4 ++++ 2 files changed, 7 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 3773b8170..12253d684 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-11-26 Daniel Shahaf + * 49446: Doc/Zsh/expn.yo: docs: Add texinode()s, so the next + commit can link directly to a subsection. + * 49445: Doc/Zsh/calsys.yo, Doc/Zsh/contrib.yo, Doc/Zsh/expn.yo, Doc/Zsh/intro.yo, Doc/Zsh/jobs.yo, Doc/Zsh/mod_newuser.yo, Doc/Zsh/options.yo, Doc/Zsh/params.yo, Doc/Zsh/roadmap.yo, diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 00f93e402..753e5a008 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1892,6 +1892,7 @@ The tt(PUSHD_MINUS) option exchanges the effects of `tt(~PLUS())' and `tt(~-)' where they are followed by a number. +texinode(Dynamic named directories)(Static named directories)()(Filename Expansion) subsect(Dynamic named directories) cindex(directories, named, dynamic) cindex(named directories, dynamic) @@ -1985,6 +1986,7 @@ example(zsh_directory_name+LPAR()RPAR() { return 0 }) +texinode(Static named directories)(`=' expansion)(Dynamic named directories)(Filename Expansion) subsect(Static named directories) cindex(directories, named, static) cindex(named directories, static) @@ -2011,6 +2013,7 @@ i.e. either the directory name or the full path; the name is used if they are the same length. The parameters tt($PWD) and tt($OLDPWD) are never abbreviated in this fashion. +texinode(`=' expansion)(Notes)(Static named directories)(Filename Expansion) subsect(`=' expansion) If a word begins with an unquoted `tt(=)' @@ -2020,6 +2023,7 @@ name of a command. If a command exists by that name, the word is replaced by the full pathname of the command. +texinode(Notes)()(`=' expansion)(Filename Expansion) subsect(Notes) cindex(filename expansion, notes) Filename expansion is performed on the right hand side of a parameter -- cgit v1.2.3 From e8d49addc049a77293fd015824ecde31e2901b8d Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 26 Sep 2021 08:43:46 +0000 Subject: 49447: docs: _wanted: Clarify the example and point to another one. --- ChangeLog | 3 +++ Doc/Zsh/compsys.yo | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 12253d684..f83bc2164 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-11-26 Daniel Shahaf + * 49447: Doc/Zsh/compsys.yo: docs: _wanted: Clarify the example + and point to another one. + * 49446: Doc/Zsh/expn.yo: docs: Add texinode()s, so the next commit can link directly to a subsection. diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 40238c4b9..f85293ac7 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -5395,7 +5395,11 @@ matches with the given description: example(local expl _wanted tag expl 'description' \ - compadd matches...) + compadd -- var(match1) var(match2)...) + +See also the use of tt(_wanted) in the example function in +ifzman(the subsection `Dynamic named directories' in zmanref(zshexpn))\ +ifnzman(noderef(Dynamic named directories)). Note that, as for tt(_requested), the var(command) must be able to accept options to be passed down to tt(compadd). -- cgit v1.2.3 From 1168c6c3ea7df938460403cca36037707ee211f2 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 26 Sep 2021 08:43:47 +0000 Subject: 49448: docs: Fix pointers to the `Widgets', `User-defined Widgets', and `Standard Widgets' sections. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The latter two didn't have their own texinode()s. Various places, both those sections' subsections and elsewhere in the manual, linked to the first section rather than to the third. For instance, zshcontrib(1) pointed to "noderef(Miscellaneous) in noderef(Zle Widgets)", even though the former (currently §18.6.6) is not under the latter (currently §18.4). Add texinode()s and fix those pointers. --- ChangeLog | 4 ++++ Doc/Zsh/contrib.yo | 2 +- Doc/Zsh/zle.yo | 22 +++++++++++++--------- 3 files changed, 18 insertions(+), 10 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index f83bc2164..493eabda7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2021-11-26 Daniel Shahaf + * 49448: Doc/Zsh/contrib.yo, Doc/Zsh/zle.yo: docs: Fix pointers + to the `Widgets', `User-defined Widgets', and `Standard Widgets' + sections. + * 49447: Doc/Zsh/compsys.yo: docs: _wanted: Clarify the example and point to another one. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index e8311eb55..0800fa52b 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2342,7 +2342,7 @@ directly. tindex(bracketed-paste-magic) item(tt(bracketed-paste-magic))( The tt(bracketed-paste) widget (see ifzman(the subsection `Miscellaneous' in -zmanref(zshzle))ifnzman(noderef(Miscellaneous) in noderef(Zle Widgets))) +zmanref(zshzle))ifnzman(noderef(Miscellaneous) in noderef(Standard Widgets))) inserts pasted text literally into the editor buffer rather than interpret it as keystrokes. This disables some common usages where the self-insert widget is replaced in order to accomplish some extra processing. An diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 70dfec333..6948aa5ac 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -728,7 +728,7 @@ enditem() ) enditem() -texinode(Zle Widgets)(Character Highlighting)(Zle Builtins)(Zsh Line Editor) +texinode(Zle Widgets)(User-Defined Widgets)(Zle Builtins)(Zsh Line Editor) sect(Widgets) cindex(widgets) All actions in the editor are performed by `widgets'. A widget's job is @@ -736,7 +736,9 @@ simply to perform some small action. The ZLE commands that key sequences in keymaps are bound to are in fact widgets. Widgets can be user-defined or built in. -The standard widgets built into ZLE are listed in Standard Widgets below. +The standard widgets built into ZLE are listed in +ifzman(the section `Standard Widgets' below)\ +ifnzman(noderef(Standard Widgets)). Other built-in widgets can be defined by other modules (see ifzman(zmanref(zshmodules))\ ifnzman(noderef(Zsh Modules))\ @@ -750,6 +752,7 @@ as shell functions. When the widget is executed, the corresponding shell function is executed, and can perform editing (or other) actions. It is recommended that user-defined widgets should not have names starting with `tt(.)'. +texinode(User-Defined Widgets)(Standard Widgets)(Zle Widgets)(Zsh Line Editor) sect(User-Defined Widgets) cindex(widgets, user-defined) User-defined widgets, being implemented as shell functions, @@ -1206,6 +1209,7 @@ This can be used for detecting switches between the vi command ) enditem() +texinode(Standard Widgets)(Character Highlighting)(User-Defined Widgets)(Zsh Line Editor) sect(Standard Widgets) cindex(widgets, standard) The following is a list of all the standard widgets, @@ -1231,7 +1235,7 @@ menu(Completion) menu(Miscellaneous) menu(Text Objects) endmenu() -texinode(Movement)(History Control)()(Zle Widgets) +texinode(Movement)(History Control)()(Standard Widgets) subsect(Movement) startitem() tindex(vi-backward-blank-word) @@ -1378,7 +1382,7 @@ item(tt(up-line) (unbound) (unbound) (unbound))( Move up a line in the buffer. ) enditem() -texinode(History Control)(Modifying Text)(Movement)(Zle Widgets) +texinode(History Control)(Modifying Text)(Movement)(Standard Widgets) subsect(History Control) startitem() tindex(beginning-of-buffer-or-history) @@ -1726,7 +1730,7 @@ the numeric argument. Zero for both local and imported lines and nonzero for only local lines. ) enditem() -texinode(Modifying Text)(Arguments)(History Control)(Zle Widgets) +texinode(Modifying Text)(Arguments)(History Control)(Standard Widgets) subsect(Modifying Text) startitem() tindex(vi-add-eol) @@ -2052,7 +2056,7 @@ into the kill buffer. Arguably, this is what Y should do in vi, but it isn't what it actually does. ) enditem() -texinode(Arguments)(Completion)(Modifying Text)(Zle Widgets) +texinode(Arguments)(Completion)(Modifying Text)(Standard Widgets) subsect(Arguments) startitem() tindex(digit-argument) @@ -2100,7 +2104,7 @@ example(zle argument-base 16 zle universal-argument) ) enditem() -texinode(Completion)(Miscellaneous)(Arguments)(Zle Widgets) +texinode(Completion)(Miscellaneous)(Arguments)(Standard Widgets) subsect(Completion) startitem() tindex(accept-and-menu-complete) @@ -2175,7 +2179,7 @@ When a previous completion displayed a list below the prompt, this widget can be used to move the prompt below the list. ) enditem() -texinode(Miscellaneous)(Text Objects)(Completion)(Zle Widgets) +texinode(Miscellaneous)(Text Objects)(Completion)(Standard Widgets) subsect(Miscellaneous) startitem() tindex(accept-and-hold) @@ -2573,7 +2577,7 @@ If the last command executed was a digit as part of an argument, continue the argument. Otherwise, execute vi-beginning-of-line. ) enditem() -texinode(Text Objects)()(Miscellaneous)(Zle Widgets) +texinode(Text Objects)()(Miscellaneous)(Standard Widgets) subsect(Text Objects) cindex(text objects) Text objects are commands that can be used to select a block of text -- cgit v1.2.3 From b2632cd21bcbf41bc171a0de45cb407bc5dd32e4 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 1 Dec 2021 03:08:14 +0000 Subject: 49621: Fix the info Doc build, broken in 49448. --- ChangeLog | 5 +++++ Doc/Zsh/manual.yo | 2 ++ Doc/Zsh/zle.yo | 2 ++ 3 files changed, 9 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 426bfb1e6..29fac263f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-12-01 Daniel Shahaf + + * 49621: Doc/Zsh/manual.yo, Doc/Zsh/zle.yo: Fix the info Doc + build, broken in 49448. + 2021-11-30 Oliver Kiddle * 49612: Src/module.c: avoid startup error with clashing non-local diff --git a/Doc/Zsh/manual.yo b/Doc/Zsh/manual.yo index 51601adbd..dc4d6ed07 100644 --- a/Doc/Zsh/manual.yo +++ b/Doc/Zsh/manual.yo @@ -108,6 +108,8 @@ Zsh Line Editor menu(Keymaps) menu(Zle Builtins) menu(Zle Widgets) +menu(User-Defined Widgets) +menu(Standard Widgets) menu(Character Highlighting) Completion Widgets diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 6948aa5ac..aaeeddf26 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -57,6 +57,8 @@ startmenu() menu(Keymaps) menu(Zle Builtins) menu(Zle Widgets) +menu(User-Defined Widgets) +menu(Standard Widgets) menu(Character Highlighting) endmenu() -- cgit v1.2.3 From 9cc6f8d8c9992ff65ce8580967122ac3c6722f60 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 1 Dec 2021 03:09:04 +0000 Subject: unposted: Add whitespace and comments. No functional change. --- ChangeLog | 3 +++ Doc/Zsh/zle.yo | 3 +++ Doc/ztexi.yo | 1 + 3 files changed, 7 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 29fac263f..78fc86749 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-12-01 Daniel Shahaf + * unposted: Doc/Zsh/zle.yo, Doc/ztexi.yo: Add whitespace and + comments. No functional change. + * 49621: Doc/Zsh/manual.yo, Doc/Zsh/zle.yo: Fix the info Doc build, broken in 49448. diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index aaeeddf26..f0165c7c1 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -109,6 +109,7 @@ In the `tt(.safe)' keymap, each single key is bound to tt(self-insert), except for ^J (line feed) and ^M (return) which are bound to tt(accept-line). This is deliberately not pleasant to use; if you are using it, it means you deleted the main keymap, and you should put it back. + subsect(Reading Commands) When ZLE is reading a command from the terminal, it may read a sequence that is bound to some command and is also a prefix of a longer bound string. @@ -139,6 +140,7 @@ in user-defined widgets with the tt(read-command) widget, described in ifzman(the subsection `Miscellaneous' of the section `Standard Widgets' below)\ ifnzman(noderef(Miscellaneous) below)\ . + subsect(Local Keymaps) cindex(local keymaps) While for normal editing a single keymap is used exclusively, in many @@ -754,6 +756,7 @@ as shell functions. When the widget is executed, the corresponding shell function is executed, and can perform editing (or other) actions. It is recommended that user-defined widgets should not have names starting with `tt(.)'. + texinode(User-Defined Widgets)(Standard Widgets)(Zle Widgets)(Zsh Line Editor) sect(User-Defined Widgets) cindex(widgets, user-defined) diff --git a/Doc/ztexi.yo b/Doc/ztexi.yo index 50bae6d48..c105c3e71 100644 --- a/Doc/ztexi.yo +++ b/Doc/ztexi.yo @@ -110,6 +110,7 @@ def(texiauthor)(1)(\ NOTRANS(@author )ARG1\ ) +COMMENT(Arguments are node identifiers: this, next, previous, up) def(texinode)(4)(\ NOTRANS(@node )ARG1, ARG2, ARG3, ARG4\ ) -- cgit v1.2.3 From 91b7baf25929a20ee776100f406021a422d56e98 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Mon, 13 Dec 2021 21:06:57 +0100 Subject: 49646: allow colors in WATCHFMT with %F/%K --- ChangeLog | 3 +++ Doc/Zsh/mod_watch.yo | 6 ++++++ Src/Modules/watch.c | 35 +++++++++++++++++++++++++++++++++++ Src/prompt.c | 9 +++++---- 4 files changed, 49 insertions(+), 4 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index cb5d4564e..2fd7926ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-12-13 Oliver Kiddle + * 49646: Doc/Zsh/mod_watch.yo, Src/Modules/watch.c, Src/prompt.c: + allow colors in WATCHFMT with %F/%K + * 49645: Completion/Unix/Type/_path_commands: when completing for the path_dirs option, add a / suffix and follow symlinks diff --git a/Doc/Zsh/mod_watch.yo b/Doc/Zsh/mod_watch.yo index 4eea89e23..d97a41d13 100644 --- a/Doc/Zsh/mod_watch.yo +++ b/Doc/Zsh/mod_watch.yo @@ -65,6 +65,12 @@ The `tt(%m)' and `tt(%M)' escapes will work only if there is a host name field in the utmp on your machine. Otherwise they are treated as ordinary strings. ) +item(tt(%F{)var(color)tt(}) LPAR()tt(%f)RPAR())( +Start (stop) using a different foreground color. +) +item(tt(%K{)var(color)tt(}) LPAR()tt(%k)RPAR())( +Start (stop) using a different background color. +) item(tt(%S) LPAR()tt(%s)RPAR())( Start (stop) standout mode. ) diff --git a/Src/Modules/watch.c b/Src/Modules/watch.c index 95d591a67..d45c3cf3d 100644 --- a/Src/Modules/watch.c +++ b/Src/Modules/watch.c @@ -246,6 +246,7 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini) struct tm *tm; char *fm2; int len; + zattr atr; # ifdef WATCH_UTMP_UT_HOST char *p; int i; @@ -347,6 +348,40 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini) case '%': putchar('%'); break; + case 'F': + if (*fmt == '{') { + fmt++; + atr = match_colour((const char**)&fmt, 1, 0); + if (*fmt == '}') + fmt++; + if (!(atr & (TXT_ERROR | TXTNOFGCOLOUR))) { + txtunset(TXT_ATTR_FG_COL_MASK); + txtset(atr & TXT_ATTR_FG_ON_MASK); + set_colour_attribute(atr, COL_SEQ_FG, TSC_RAW); + } + } + break; + case 'f': + txtunset(TXT_ATTR_FG_ON_MASK); + set_colour_attribute(TXTNOFGCOLOUR, COL_SEQ_FG, TSC_RAW); + break; + case 'K': + if (*fmt == '{') { + fmt++; + atr = match_colour((const char**)&fmt, 0, 0); + if (*fmt == '}') + fmt++; + if (!(atr & (TXT_ERROR | TXTNOBGCOLOUR))) { + txtunset(TXT_ATTR_BG_COL_MASK); + txtset(atr & TXT_ATTR_BG_ON_MASK); + set_colour_attribute(atr, COL_SEQ_BG, TSC_RAW); + } + } + break; + case 'k': + txtunset(TXT_ATTR_BG_ON_MASK); + set_colour_attribute(TXTNOBGCOLOUR, COL_SEQ_BG, TSC_RAW); + break; case 'S': txtset(TXTSTANDOUT); tsetcap(TCSTANDOUTBEG, TSC_RAW); diff --git a/Src/prompt.c b/Src/prompt.c index 6943eabc3..d6b378539 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -1045,9 +1045,9 @@ tsetcap(int cap, int flags) if (txtisset(TXTUNDERLINE)) tsetcap(TCUNDERLINEBEG, flags); if (txtisset(TXTFGCOLOUR)) - set_colour_attribute(txtattrmask, COL_SEQ_FG, TSC_PROMPT); + set_colour_attribute(txtattrmask, COL_SEQ_FG, flags); if (txtisset(TXTBGCOLOUR)) - set_colour_attribute(txtattrmask, COL_SEQ_BG, TSC_PROMPT); + set_colour_attribute(txtattrmask, COL_SEQ_BG, flags); } } } @@ -2062,7 +2062,8 @@ set_colour_attribute(zattr atr, int fg_bg, int flags) *bv->bp++ = Outpar; } } else { - tputs(tgoto(tcstr[tc], colour, colour), 1, putshout); + tputs(tgoto(tcstr[tc], colour, colour), 1, + (flags & TSC_RAW) ? putraw : putshout); } /* That worked. */ return; @@ -2121,7 +2122,7 @@ set_colour_attribute(zattr atr, int fg_bg, int flags) *bv->bp++ = Outpar; } } else - tputs(colseq_buf, 1, putshout); + tputs(colseq_buf, 1, (flags & TSC_RAW) ? putraw : putshout); if (do_free) free_colour_buffer(); -- cgit v1.2.3 From 441f594c9f8d3b8afd3b170db54eba0ee9ab0a8b Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 27 Jan 2022 16:46:31 +0000 Subject: unposted: vcs_info quilt docs: Fix misspelled style name --- ChangeLog | 3 +++ Doc/Zsh/contrib.yo | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 7441db2df..11166e6bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2022-01-27 Daniel Shahaf + * unposted: Doc/Zsh/contrib.yo: vcs_info quilt docs: Fix + misspelled style name + * unposted: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: Remove a no-op variable assignment diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 0800fa52b..eb5bbafb2 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1404,7 +1404,7 @@ a directory that holds quilt's patches needs to be found. That directory is configurable via the `tt(QUILT_PATCHES)' environment variable. If that variable exists its value is used, otherwise the value `tt(patches)' is assumed. The value from tt($QUILT_PATCHES) can be overwritten using the -`tt(quilt-patches)' style. (Note: you can use tt(vcs_info) to keep the value +`tt(quilt-patch-dir)' style. (Note: you can use tt(vcs_info) to keep the value of tt($QUILT_PATCHES) correct all the time via the tt(post-quilt) hook). When the directory in question is found, quilt is assumed to be active. To -- cgit v1.2.3 From 8bf0f0cf45606971d1433b36ce21ab45f6226004 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Tue, 18 Jan 2022 23:20:53 +0100 Subject: 49694 + doc: Allow using empty STTY= to freeze tty for a single command Previously, doing this would just run stty with no arguments, which normally causes it to print some terminal settings to stdout. --- ChangeLog | 5 +++++ Doc/Zsh/builtins.yo | 3 ++- Doc/Zsh/params.yo | 5 +++++ Src/exec.c | 6 ++++-- 4 files changed, 16 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 57c26fb38..98dd85274 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-01-30 Mikael Magnusson + + * 49694 + doc: Doc/Zsh/builtins.yo, Doc/Zsh/params.yo, Src/exec.c: + Allow using empty STTY= to freeze tty for a single command + 2022-01-29 Daniel Shahaf * unposted: Functions/VCS_Info/test-repo-git-rebase-apply, diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 733d8f185..c7de50fd6 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -1885,7 +1885,8 @@ unfreezing the tty does not guarantee settings made on the command line are preserved. Strings of commands run between editing the command line will see a consistent tty state. See also the shell variable tt(STTY) for a means of initialising -the tty before running external commands. +the tty before running external commands and/or freezing the tty +around a single command. ) findex(type) item(tt(type) [ tt(-wfpamsS) ] var(name) ...)( diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 6b52d3b1c..6d2d41b7a 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -1570,6 +1570,11 @@ if it is in the environment of the shell but not explicitly assigned to in the input line. This avoids running stty at every external command by accidentally exporting it. Also note that tt(STTY) should not be used for window size specifications; these will not be local to the command. + +If the parameter is set and empty, all of the above applies except +that tt(stty) is not run. This can be useful as a way to freeze the tty +around a single command, blocking its changes to tty settings, +similar to the tt(ttyctl) builtin. ) vindex(TERM) item(tt(TERM) )( diff --git a/Src/exec.c b/Src/exec.c index 1860a10ed..f67074846 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -684,8 +684,10 @@ execute(LinkList args, int flags, int defpath) /* If the parameter STTY is set in the command's environment, * * we first run the stty command with the value of this * - * parameter as it arguments. */ - if ((s = STTYval) && isatty(0) && (GETPGRP() == getpid())) { + * parameter as it arguments. If the parameter is empty, we * + * do nothing, but this causes the terminal settings to be * + * restored later which can be useful. */ + if ((s = STTYval) && *s && isatty(0) && (GETPGRP() == getpid())) { char *t = tricat("stty", " ", s); STTYval = 0; /* this prevents infinite recursion */ -- cgit v1.2.3 From 80389df48067bab3711ad1604bc9554d08fb9994 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 29 Jan 2022 16:15:25 +0000 Subject: 49727 (+ comment): vcs_info quilt: Pass the patches dir path to the gen-applied-string, gen-unapplied-string, and set-patch-format hooks I use that in my gen-applied-string hook. --- ChangeLog | 8 ++++++++ Doc/Zsh/contrib.yo | 15 +++++++++++++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 2 +- Functions/VCS_Info/Backends/VCS_INFO_get_data_hg | 2 +- Functions/VCS_Info/VCS_INFO_quilt | 7 ++++++- Functions/VCS_Info/VCS_INFO_set-patch-format | 8 +++++++- 6 files changed, 38 insertions(+), 4 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 6576ec634..a856cc47f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2022-02-20 Daniel Shahaf + * 49727 (+ comment): Doc/Zsh/contrib.yo, + Functions/VCS_Info/Backends/VCS_INFO_get_data_git, + Functions/VCS_Info/Backends/VCS_INFO_get_data_hg, + Functions/VCS_Info/VCS_INFO_quilt, + Functions/VCS_Info/VCS_INFO_set-patch-format: vcs_info + quilt: Pass the patches dir path to the gen-applied-string, + gen-unapplied-string, and set-patch-format hooks + * unposted: Functions/VCS_Info/Backends/VCS_INFO_get_data_hg: vcs_info hg mg (with get-unapplied set): Stop leaking a variable to global scope diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index eb5bbafb2..0adef7334 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1669,6 +1669,11 @@ available as tt(%p) in the tt(patch-format) and tt(nopatch-format) styles. This hook is, in concert with tt(set-patch-format), responsible for tt(%)-escaping that value for use in the prompt. (See ifzman(the bf(Oddities) section)ifnzman(noderef(vcs_info Oddities)).) + +COMMENT(This paragraph is repeated above/below)\ +The tt(quilt) backend passes to this hook the inputs +tt(${hook_com[quilt-patches-dir]}) and, if it has been +determined, tt(${hook_com[quilt-pc-dir]}). ) item(tt(gen-unapplied-string))( Called in the tt(git) (with tt(stgit) or during rebase), and tt(hg) (with @@ -1687,6 +1692,11 @@ tt(patch-format) and tt(nopatch-format) styles. This hook is, in concert with tt(set-patch-format), responsible for tt(%)-escaping that value for use in the prompt. (See ifzman(the bf(Oddities) section)ifnzman(noderef(vcs_info Oddities)).) + +COMMENT(This paragraph is repeated above/below)\ +The tt(quilt) backend passes to this hook the inputs +tt(${hook_com[quilt-patches-dir]}) and, if it has been +determined, tt(${hook_com[quilt-pc-dir]}). ) item(tt(gen-mqguards-string))( Called in the tt(hg) backend when tt(guards-string) is generated; the @@ -1769,6 +1779,11 @@ This hook is, in concert with the tt(gen-applied-string) or tt(gen-unapplied-string) hooks if they are defined, responsible for tt(%)-escaping the final tt(patch-format) value for use in the prompt. (See ifzman(the bf(Oddities) section)ifnzman(noderef(vcs_info Oddities)).) + +COMMENT(This paragraph is repeated above/below)\ +The tt(quilt) backend passes to this hook the inputs +tt(${hook_com[quilt-patches-dir]}) and, if it has been +determined, tt(${hook_com[quilt-pc-dir]}). ) item(tt(set-message))( Called each time before a `tt(vcs_info_msg_)var(N)tt(_)' message is set. diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index fe084dffb..e45eebc8e 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -132,7 +132,7 @@ VCS_INFO_git_handle_patches () { VCS_INFO_set-patch-format 'git_patches_applied' 'git_applied_s' \ 'git_patches_unapplied' 'git_unapplied_s' \ ":vcs_info:${vcs}:${usercontext}:${rrn}" gitmsg \ - '' '' + '' '' '' gitmisc=$REPLY } diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg index 97086670c..e7123f0bf 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg @@ -225,7 +225,7 @@ if zstyle -T ":vcs_info:${vcs}:${usercontext}:${rrn}" get-mq \ VCS_INFO_set-patch-format 'mqpatches' 'applied_string' \ 'mqunapplied' 'unapplied_string' \ ":vcs_info:${vcs}:${usercontext}:${rrn}" hgmqstring \ - extra_hook_com VCS_INFO_hg_extra_zformats + extra_hook_com VCS_INFO_hg_extra_zformats '' hgmqstring=$REPLY fi diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index ee242f552..ce5b41f24 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -179,10 +179,15 @@ function VCS_INFO_quilt-patch2subject() { done } + typeset -A quilt_extra_info=( + quilt-patches-dir ${patches} + ${pc:+"quilt-pc-dir"} $pc + ) + VCS_INFO_set-patch-format 'applied' 'applied_string' \ 'unapplied' 'unapplied_string' \ ${context} qstring \ - '' '' + quilt_extra_info '' quilt_extra_info qstring=$REPLY case ${mode} in diff --git a/Functions/VCS_Info/VCS_INFO_set-patch-format b/Functions/VCS_Info/VCS_INFO_set-patch-format index c35b695c3..1c774a7f6 100644 --- a/Functions/VCS_Info/VCS_INFO_set-patch-format +++ b/Functions/VCS_Info/VCS_INFO_set-patch-format @@ -15,6 +15,8 @@ # $7 - name of an assoc parameter with extra $hook_com key-value pairs for the # set-patch-format hook invocation, or '' for none # $8 - name of a function that sets $reply to extra arguments for the patch-format zformat call, or '' for none +# $9 - name of an assoc parameter with extra $hook_com key-value pairs for the +# gen-applied-string & gen-unapplied-string hook invocations, or '' for none # # The expanded patch-format string is returned in $REPLY. # @@ -22,8 +24,10 @@ # - $hook_com is overwritten and the keys 'applied', 'applied-n', # 'unapplied', 'unapplied-n', 'all-n' are set. { + hook_com=() + local applied_needs_escaping='unknown' - local unapplied_needs_escaping='unknown' + hook_com+=( ${9:+"${(@kvP)9}"} ) if VCS_INFO_hook 'gen-applied-string' "${(@P)1}"; then if (( ${(P)#1} )); then REPLY=${(P)1[1]} @@ -37,6 +41,8 @@ : ${(P)2::=$REPLY} hook_com=() + local unapplied_needs_escaping='unknown' + hook_com+=( ${9:+"${(@kvP)9}"} ) if VCS_INFO_hook 'gen-unapplied-string' "${(@P)3}"; then REPLY=${(P)#3} unapplied_needs_escaping='yes' -- cgit v1.2.3 From 0684c6a76249f6ec9fb2e79fc26340c2ae42def1 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Sun, 6 Feb 2022 16:12:10 +0100 Subject: 49769: Mention how to show nanosecond precision --- ChangeLog | 5 +++++ Doc/Zsh/mod_stat.yo | 2 ++ 2 files changed, 7 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index a3e6497c6..cebeeb385 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-02-22 Mikael Magnusson + + * 49769: Doc/Zsh/mod_stat.yo: Mention how to show nanosecond + precision + 2022-02-20 Daniel Shahaf * 49728: Functions/VCS_Info/Backends/VCS_INFO_get_data_hg: diff --git a/Doc/Zsh/mod_stat.yo b/Doc/Zsh/mod_stat.yo index 9caed1e45..b591d4003 100644 --- a/Doc/Zsh/mod_stat.yo +++ b/Doc/Zsh/mod_stat.yo @@ -118,6 +118,8 @@ formatting of the time elements. The format string supports all of the zsh extensions described in ifzman(the section EXPANSION OF PROMPT SEQUENCES in zmanref(zshmisc))\ ifnzman(noderef(Prompt Expansion)). +In particular, tt(-F %s.%N) can be used to show timestamps with nanosecond +precision if supported by the system. The tt(-s) option is implied. ) item(tt(-g))( -- cgit v1.2.3 From 865baf7a2513a00996f0eeccf14475670daebe27 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 22 Feb 2022 10:00:14 +0000 Subject: 49672: document "tied" in output from ${(t)...} --- ChangeLog | 5 +++++ Doc/Zsh/expn.yo | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index cebeeb385..401ec9379 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-02-22 Peter Stephenson + + * 49672: Doc/Zsh/expn.yo: document "tied" output in parameter + (t) output. + 2022-02-22 Mikael Magnusson * 49769: Doc/Zsh/mod_stat.yo: Mention how to show nanosecond diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 753e5a008..c53ca645e 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1205,6 +1205,11 @@ for readonly parameters item(tt(tag))( for tagged parameters ) +item(tt(tied))( +for parameters tied to another parameter in the manner of tt(PATH) +(colon-separated list) and tt(path) (array), whether these are +special parameters or user-defined with `tt(typeset -T)' +) item(tt(export))( for exported parameters ) -- cgit v1.2.3 From 45182eb4d447a6fbf5f76538326e1a944880ea52 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Tue, 22 Feb 2022 13:09:33 +0000 Subject: unposted: Fix some typos and markup. --- ChangeLog | 5 +++++ Doc/Zsh/contrib.yo | 4 ++-- Src/Modules/parameter.c | 2 +- Src/string.c | 5 ++++- Src/zsh.h | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 401ec9379..5dc07937f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-02-22 Daniel Shahaf + + * unposted: Doc/Zsh/contrib.yo, Src/Modules/parameter.c, + Src/string.c, Src/zsh.h: Fix some typos and markup. + 2022-02-22 Peter Stephenson * 49672: Doc/Zsh/expn.yo: document "tied" output in parameter diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 0adef7334..0ef59dbc9 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1159,7 +1159,7 @@ This is used by the Perforce backend (tt(p4)) to decide if it should contact the Perforce server to find out if a directory is managed by Perforce. This is the only reliable way of doing this, but runs the risk of a delay if the server name cannot be found. If the -server (more specifically, the tt(host)tt(:)tt(port) pair describing the +server (more specifically, the var(host)tt(:)var(port) pair describing the server) cannot be contacted, its name is put into the associative array tt(vcs_info_p4_dead_servers) and is not contacted again during the session until it is removed by hand. If you do not set this style, the tt(p4) @@ -1318,7 +1318,7 @@ tt(%Q) expando. item(tt(%Q))( Quilt series information. When quilt is used (either in `addon' mode or as a `standalone' backend), -this expando is set to quilt series' tt(patch-format) string. +this expando is set to the quilt series' tt(patch-format) string. The tt(set-patch-format) hook and tt(nopatch-format) style are honoured. See ifzman(tt(Quilt Support))ifnzman(noderef(vcs_info Quilt Support)) below for details. diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index b44555323..c5cb5ce62 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -592,7 +592,7 @@ getpmfunction_source(HashTable ht, const char *name) return getfunction_source(ht, name, 0); } -/* Param table entry for retrieving ds_functions_source element */ +/* Param table entry for retrieving dis_functions_source element */ /**/ static HashNode diff --git a/Src/string.c b/Src/string.c index 9e14ef949..5f439926e 100644 --- a/Src/string.c +++ b/Src/string.c @@ -103,7 +103,10 @@ wcs_ztrdup(const wchar_t *s) #endif /* MULTIBYTE_SUPPORT */ -/* concatenate s1, s2, and s3 in dynamically allocated buffer */ +/* Concatenate s1, s2, and s3 into dynamically allocated buffer. + * + * To concatenate four or more strings, see zjoin(). + */ /**/ mod_export char * diff --git a/Src/zsh.h b/Src/zsh.h index af9b4fb67..641d9c95c 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1448,7 +1448,7 @@ struct builtin { int minargs; /* minimum number of arguments */ int maxargs; /* maximum number of arguments, or -1 for no limit */ int funcid; /* xbins (see above) for overloaded handlerfuncs */ - char *optstr; /* string of legal options */ + char *optstr; /* string of legal options (see execbuiltin()) */ char *defopts; /* options set by default for overloaded handlerfuncs */ }; -- cgit v1.2.3 From 24474bd34a1c19d86ae2adee247f286e2e702815 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 1 Mar 2022 10:47:49 +0000 Subject: users/27536: Improved history list documentation Clarify interaction of matching and numbers. --- ChangeLog | 5 +++++ Doc/Zsh/builtins.yo | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index ca8477dfb..6371cb85d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-03-01 Peter Stephenson + + * users/27536: Doc/Zsh/builtins.yo: Clarify interaction of + history matching and numeric indices. + 2022-02-23 Jun-ichi Takimoto * 49766: Completion/Unix/Command/_less: add quotes to -" and -# diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index c7de50fd6..5649e00d4 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -756,15 +756,16 @@ specifies the most recent event beginning with the given string. All substitutions var(old)tt(=)var(new), if any, are then performed on the text of the events. -In addition to the number range, +The range of events selected by numbers can be narrowed further by the +following flags. startsitem() sitem(tt(-I))(restricts to only internal events (not from tt($HISTFILE))) sitem(tt(-L))(restricts to only local events (not from other shells, see tt(SHARE_HISTORY) in ifzman(zmanref(zshoptions))\ ifnzman(noderef(Description of Options)) -- note that tt($HISTFILE) is considered local when read at startup)) -sitem(tt(-m))(takes the first argument as a pattern (should be quoted) and -only the history events matching this pattern are considered) +sitem(tt(-m))(takes the first argument as a pattern (which should be +quoted) and only the history events matching this pattern are considered) endsitem() If var(first) is not specified, it will be set to -1 (the most recent -- cgit v1.2.3 From 87d276346fcedd29b402eaf3a4d40b2f4e3573f9 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sun, 13 Mar 2022 21:07:14 -0700 Subject: 49844: Fix node reference errors from 49446 and 49448. --- ChangeLog | 5 +++++ Doc/Zsh/expn.yo | 7 +++++++ Doc/Zsh/zle.yo | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index fd2b2bb34..1a2ddb389 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-03-13 Bart Schaefer + + * 49844: Doc/Zsh/expn.yo, Doc/Zsh/zle.yo: Fix node reference + errors from 49446 and 49448. + 2022-03-08 Mikael Magnusson * 49773: Functions/Prompts/promptinit: promptinit: only exclude diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index c53ca645e..00cbbcd27 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1897,6 +1897,13 @@ The tt(PUSHD_MINUS) option exchanges the effects of `tt(~PLUS())' and `tt(~-)' where they are followed by a number. +startmenu() +menu(Dynamic named directories) +menu(Static named directories) +menu(`=' expansion) +menu(Notes) +endmenu() + texinode(Dynamic named directories)(Static named directories)()(Filename Expansion) subsect(Dynamic named directories) cindex(directories, named, dynamic) diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index f0165c7c1..2d033a0a1 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -733,7 +733,7 @@ enditem() enditem() texinode(Zle Widgets)(User-Defined Widgets)(Zle Builtins)(Zsh Line Editor) -sect(Widgets) +sect(Zle Widgets) cindex(widgets) All actions in the editor are performed by `widgets'. A widget's job is simply to perform some small action. The ZLE commands that key sequences @@ -2627,7 +2627,7 @@ argument, multiple words will be selected. ) enditem() -texinode(Character Highlighting)()(Zle Widgets)(Zsh Line Editor) +texinode(Character Highlighting)()(Standard Widgets)(Zsh Line Editor) sect(Character Highlighting) vindex(zle_highlight, setting) -- cgit v1.2.3 From 587793f818be06ad10d31e6692982c1783ed49fd Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 24 Mar 2022 10:35:29 +0000 Subject: 49845: man page clarification on option scope --- ChangeLog | 5 +++++ Doc/Zsh/options.yo | 3 +++ 2 files changed, 8 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index f915fbae5..4f82451e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-03-24 Peter Stephenson + + * 49845: Doc/Zsh/options.yo: clarify that options can be local + in function scope. + 2022-03-18 Matthew Martin * 49852: Completion/BSD/Command/_pfctl, diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index cf4600769..443676b78 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -41,6 +41,9 @@ will be treated just as `tt(-f)', but the string `tt(-f i)' is an error. This is because many systems which implement the `tt(#!)' mechanism for calling scripts do not strip trailing whitespace. +It is possible for options to be set within a function scope. See the +description of the option tt(LOCAL_OPTIONS) below. + texinode(Description of Options)(Option Aliases)(Specifying Options)(Options) sect(Description of Options) cindex(options, description) -- cgit v1.2.3 From 53d6b47d92bccb3e34ebad1becf84b097a3bc525 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Tue, 29 Mar 2022 13:18:49 -0700 Subject: 49917: change sense of "Ignore insecure ..." answer and use "autoload -r" --- ChangeLog | 6 ++++++ Completion/compinit | 18 ++++++++---------- Doc/Zsh/compsys.yo | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 161eb40cc..5053cb36c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2022-03-29 Bart Schaefer + + * 49917: Completion/compinit, Doc/Zsh/compsys.yo: change sense + of "Ignore insecure ..." answer to ignore the files rather than + ignore the problem. Use "autoload -r" for autoload paths. + 2022-03-29 Jun-ichi Takimoto * 49853 + 49882/49883: Src/subst.c, Test/D04parameter.ztst: make diff --git a/Completion/compinit b/Completion/compinit index 1f2e7c634..5cb527fac 100644 --- a/Completion/compinit +++ b/Completion/compinit @@ -329,7 +329,7 @@ compdef() { # and probably do autoloading. func="$1" - [[ -n "$autol" ]] && autoload -Uz "$func" + [[ -n "$autol" ]] && autoload -rUz "$func" shift case "$type" in @@ -451,7 +451,7 @@ typeset _i_wdirs _i_wfiles _i_wdirs=() _i_wfiles=() -autoload -Uz compaudit +autoload -RUz compaudit if [[ -n "$_i_check" ]]; then typeset _i_q if ! eval compaudit; then @@ -467,19 +467,17 @@ Ignore insecure $_i_q and continue [y] or abort compinit [n]? "; then return 1 fi - _i_wfiles=() - _i_wdirs=() - else - (( $#_i_wfiles )) && _i_files=( "${(@)_i_files:#(${(j:|:)_i_wfiles%.zwc})}" ) - (( $#_i_wdirs )) && _i_files=( "${(@)_i_files:#(${(j:|:)_i_wdirs%.zwc})/*}" ) fi + fpath=(${fpath:|_i_wdirs}) + (( $#_i_wfiles )) && _i_files=( "${(@)_i_files:#(${(j:|:)_i_wfiles%.zwc})}" ) + (( $#_i_wdirs )) && _i_files=( "${(@)_i_files:#(${(j:|:)_i_wdirs%.zwc})/*}" ) fi typeset -g _comp_secure=yes fi fi # Make sure compdump is available, even if we aren't going to use it. -autoload -Uz compdump compinstall +autoload -RUz compdump compinstall # If we have a dump file, load it. @@ -538,7 +536,7 @@ if [[ -z "$_i_done" ]]; then fi ;; (\#autoload) - autoload -Uz "$_i_line[@]" ${_i_name} + autoload -rUz "$_i_line[@]" ${_i_name} [[ "$_i_line" != \ # ]] && _compautos[${_i_name}]="$_i_line" ;; esac @@ -570,6 +568,6 @@ if [[ ${_i_line[2]} = expand-or-complete ]] && fi unfunction compinit compaudit -autoload -Uz compinit compaudit +autoload -RUz compinit compaudit return 0 diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index f85293ac7..b968f20dc 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -190,7 +190,7 @@ tt(compinit) will ask if the completion system should really be used. To avoid these tests and make all files found be used without asking, use the option tt(-u), and to make tt(compinit) silently ignore all insecure files and directories use the option tt(-i). This security check is skipped -entirely when the tt(-C) option is given. +entirely when the tt(-C) option is given, provided the dumpfile exists. findex(compaudit) The security check can be retried at any time by running the function -- cgit v1.2.3 From d7b8619396d806d390126c2abd1c3ce099fe7f59 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Tue, 8 Mar 2022 19:34:20 +0100 Subject: 49813: <<<: Document newline behavior and fix optimization The =(<< * 49918: NEWS, README: Update for 49917 and 49911. diff --git a/Doc/Zsh/redirect.yo b/Doc/Zsh/redirect.yo index 2b48974b4..fd40ab5a4 100644 --- a/Doc/Zsh/redirect.yo +++ b/Doc/Zsh/redirect.yo @@ -86,7 +86,8 @@ item(tt(<<<) var(word))( Perform shell expansion on var(word) and pass the result to standard input. This is known as a em(here-string). Compare the use of var(word) in here-documents above, where var(word) -does not undergo shell expansion. +does not undergo shell expansion. The result will have a trailing newline +after it. ) xitem(tt(<&) var(number)) item(tt(>&) var(number))( diff --git a/Src/exec.c b/Src/exec.c index f67074846..70cbfc97f 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4836,8 +4836,10 @@ getoutputfile(char *cmd, char **eptr) singsub(&s); if (errflag) s = NULL; - else + else { untokenize(s); + s = dyncat(s, "\n"); + } } if (!s) /* Unclear why we need to do this before open() */ -- cgit v1.2.3 From 98e46340867028808e71e7f3373881cb7e5b6764 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 30 Mar 2022 09:28:43 +0100 Subject: 49906 (Bart), 49911: Fixes to querying jobs in subshell. Don't attempt to query invalid job off end of table, resulting in crashes from $jobtstates. If background task started in subshell, look at tatsks within subshell instead of main shell. Document and add test. --- ChangeLog | 8 ++++++++ Doc/Zsh/builtins.yo | 18 ++++++++++++++++++ Doc/Zsh/mod_parameter.yo | 6 ++++++ Src/exec.c | 1 + Src/jobs.c | 20 ++++++++++++++++++++ Test/W03jobparameters.ztst | 28 ++++++++++++++++++++++++++++ 6 files changed, 81 insertions(+) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index c52119fa8..e6f73e30e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2022-03-30 Peter Stephenson + + * 49906 (Bart), 49911: Doc/Zsh/builtins.yo, + Doc/Zsh/mod_parameter.yo, Src/exec.c, Src/jobs.c, + Test/W03jobparameters.ztst: Fix querying jobs in subshell. + Don't uery invalid job at end, if background job started in + subshell query jobs in subshell instead of main shell. + 2022-03-30 Mikael Magnusson * 49893: Src/Zle/comp.h, Src/Zle/compcore.c: Fix comments for diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 5649e00d4..1d74f0c17 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -1114,6 +1114,24 @@ The tt(-Z) option replaces the shell's argument and environment space with the given string, truncated if necessary to fit. This will normally be visible in tt(ps) (manref(ps)(1)) listings. This feature is typically used by daemons, to indicate their state. + +Full job control is only available in the top-level interactive shell, +not in commands run in the left hand side of pipelines or within +the tt(LPAR())var(...)tt(RPAR()) construct. However, a snapshot +of the job state at that point is taken, so it is still possible +to use the tt(jobs) builtin, or any parameter providing job information. +This gives information about the state of jobs at the point the subshell +was created. If background processes are created within the subshell, +then instead information about those processes is provided. + +For example, + +example(sleep 10 & # Job in background +LPAR() # Shell forks +jobs # Shows information about "sleep 10 &" +sleep 5 & # Process in background (no job control) +jobs # Shows information about "sleep 5 &" +RPAR()) ) findex(kill) cindex(killing jobs) diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo index 2e3011e44..f3bcd7957 100644 --- a/Doc/Zsh/mod_parameter.yo +++ b/Doc/Zsh/mod_parameter.yo @@ -165,6 +165,8 @@ The keys of the associative arrays are usually valid job numbers, and these are the values output with, for example, tt(${(k)jobdirs}). Non-numeric job references may be used when looking up a value; for example, tt(${jobdirs[%+]}) refers to the current job. + +See the tt(jobs) builtin for how job information is provided in a subshell. ) vindex(jobtexts) item(tt(jobtexts))( @@ -173,6 +175,8 @@ that were used to start the jobs. Handling of the keys of the associative array is as described for tt(jobdirs) above. + +See the tt(jobs) builtin for how job information is provided in a subshell. ) vindex(jobstates) item(tt(jobstates))( @@ -189,6 +193,8 @@ the var(state) describes the state of that process. Handling of the keys of the associative array is as described for tt(jobdirs) above. + +See the tt(jobs) builtin for how job information is provided in a subshell. ) vindex(nameddirs) item(tt(nameddirs))( diff --git a/Src/exec.c b/Src/exec.c index 70cbfc97f..27d49e005 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1689,6 +1689,7 @@ execpline(Estate state, wordcode slcode, int how, int last1) execpline2(state, code, how, opipe[0], ipipe[1], last1); pline_level--; if (how & Z_ASYNC) { + clearoldjobtab(); lastwj = newjob; if (thisjob == list_pipe_job) diff --git a/Src/jobs.c b/Src/jobs.c index 18e43f03c..af0a1233d 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -1718,8 +1718,15 @@ clearjobtab(int monitor) /* Don't report any job we're part of */ if (thisjob != -1 && thisjob < oldmaxjob) memset(oldjobtab+thisjob, 0, sizeof(struct job)); + + /* oldmaxjob is now the size of the table, but outside + * this function, it's used as a job number, which must + * be the largest index available in the table. + */ + --oldmaxjob; } + memset(jobtab, 0, jobtabsize * sizeof(struct job)); /* zero out table */ maxjob = 0; @@ -1733,6 +1740,18 @@ clearjobtab(int monitor) thisjob = initjob(); } +/* In a subshell, decide we want our own job table after all. */ + +/**/ +mod_export void +clearoldjobtab(void) +{ + if (oldjobtab) + free(oldjobtab); + oldjobtab = NULL; + oldmaxjob = 0; +} + static int initnewjob(int i) { jobtab[i].stat = STAT_INUSE; @@ -2449,6 +2468,7 @@ bin_fg(char *name, char **argv, Options ops, int func) case BIN_BG: case BIN_WAIT: if (func == BIN_BG) { + clearoldjobtab(); jobtab[job].stat |= STAT_NOSTTY; jobtab[job].stat &= ~STAT_CURSH; } diff --git a/Test/W03jobparameters.ztst b/Test/W03jobparameters.ztst index af889c6d5..a6f7a09b1 100644 --- a/Test/W03jobparameters.ztst +++ b/Test/W03jobparameters.ztst @@ -48,3 +48,31 @@ *>running:+:*=running *>running:+:*=running *>zsh:*SIGHUPed* + +# $jobstates refers to a job started in the main shell unless +# one has been started in the subshell. In the latter case, +# the subshell has no job control so the job is not marked as current. + zpty_start + zpty_input "MODULE_PATH=${(q)MODULE_PATH}" + zpty_input 'sleep 3 &' + zpty_input '(print main; print $jobstates; sleep 2& print sub; print $jobstates)' + zpty_input 'jobs -s' + zpty_stop +0:$jobstate shows one job started in main shell or one started in subshell +*>\[1] [0-9]## +>main +*>running:+:*=running +>sub +*>running::*=running +*>zsh:*SIGHUPed* + +# output from zpty removes empty lines + zpty_start + zpty_input "MODULE_PATH=${(q)MODULE_PATH}" + zpty_input '(print main; print $jobstates; sleep 2& print sub; print $jobstates)' + zpty_input 'jobs -s' + zpty_stop +0:$jobstate shows no job started in main shell but one started in subshell +>main +>sub +*>running::*=running -- cgit v1.2.3 From 41eb200d66e4bea7bc5798888a1755cdf5daa3b0 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 31 Mar 2022 13:57:56 +0100 Subject: 27639: clarify that ${(#)...} deals with character codes. --- ChangeLog | 5 +++++ Doc/Zsh/expn.yo | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index e6f73e30e..8c0f3e6ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-03-31 Peter Stephenson + + * 27639: Doc/Zsh/expn.yo: clarify that ${(#)...} deals with + character codes. + 2022-03-30 Peter Stephenson * 49906 (Bart), 49911: Doc/Zsh/builtins.yo, diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 00cbbcd27..bbacc6ae4 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -968,9 +968,10 @@ following flags are supported: startitem() item(tt(#))( -Evaluate the resulting words as numeric expressions and output the -characters corresponding to the resulting integer. Note that this form is -entirely distinct from use of the tt(#) without parentheses. +Evaluate the resulting words as numeric expressions and interpret +these as character codes. Output the corresponding characters. Note +that this form is entirely distinct from use of the tt(#) without +parentheses. If the tt(MULTIBYTE) option is set and the number is greater than 127 (i.e. not an ASCII character) it is treated as a Unicode character. -- cgit v1.2.3 From 95749e9e652849215b5d09c5aaf8928056c41688 Mon Sep 17 00:00:00 2001 From: Matthew Martin Date: Thu, 31 Mar 2022 17:40:22 -0500 Subject: 49933: Add nonblock to sysopen --- ChangeLog | 3 +++ Doc/Zsh/mod_system.yo | 3 +++ Src/Modules/system.c | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 7e97c79f0..a4f74a581 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2022-03-31 Matthew Martin + * 49933: Doc/Zsh/mod_system.yo, Src/Modules/system.c: Add + nonblock to sysopen. + * 49932: Completion/Zsh/Context/_brace_parameter: Update _brace_parameter # description. diff --git a/Doc/Zsh/mod_system.yo b/Doc/Zsh/mod_system.yo index 399b6fe03..884c3e753 100644 --- a/Doc/Zsh/mod_system.yo +++ b/Doc/Zsh/mod_system.yo @@ -62,6 +62,9 @@ suppress updating of the file atime item(tt(nofollow))( fail if var(file) is a symbolic link ) +item(tt(nonblock))( +the file is opened in nonblocking mode +) item(tt(sync))( request that writes wait until data has been physically written ) diff --git a/Src/Modules/system.c b/Src/Modules/system.c index ecd4e2546..71745548f 100644 --- a/Src/Modules/system.c +++ b/Src/Modules/system.c @@ -280,7 +280,7 @@ bin_syswrite(char *nam, char **args, Options ops, UNUSED(int func)) } -static struct { char *name; int oflag; } openopts[] = { +static struct { const char *name; int oflag; } openopts[] = { #ifdef O_CLOEXEC { "cloexec", O_CLOEXEC }, #else @@ -296,6 +296,9 @@ static struct { char *name; int oflag; } openopts[] = { #endif #ifdef O_NOATIME { "noatime", O_NOATIME }, +#endif +#ifdef O_NONBLOCK + { "nonblock", O_NONBLOCK}, #endif { "excl", O_EXCL | O_CREAT }, { "creat", O_CREAT }, -- cgit v1.2.3 From 6152200c9b942d204be8740d84f076508e066ac3 Mon Sep 17 00:00:00 2001 From: elig0n <31196036+elig0n@users.noreply.github.com> Date: Thu, 24 Mar 2022 10:28:59 +0200 Subject: github #88: Fix typo --- ChangeLog | 2 ++ Doc/Zsh/func.yo | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index a4f74a581..6afe34962 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2022-03-31 Matthew Martin + * github #88: elig0n: Doc/Zsh/func.yo: Fix typo. + * 49933: Doc/Zsh/mod_system.yo, Src/Modules/system.c: Add nonblock to sysopen. diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo index 7edad7f23..12db3f56a 100644 --- a/Doc/Zsh/func.yo +++ b/Doc/Zsh/func.yo @@ -276,7 +276,7 @@ the history file. In case of a conflict, the first non-zero status value is taken. A hook function may call `tt(fc -p) var(...)' to switch the history -context so that the history is saved in a different file from the +context so that the history is saved in a different file from that in the global tt(HISTFILE) parameter. This is handled specially: the history context is automatically restored after the processing of the history line is finished. -- cgit v1.2.3 From 73265d41e356992664e17bd95e2e5daf22790bf0 Mon Sep 17 00:00:00 2001 From: Matthew Martin Date: Wed, 6 Apr 2022 20:00:55 -0500 Subject: 49960: Sort lists in zshcompsys --- ChangeLog | 4 +++ Doc/Zsh/compsys.yo | 80 +++++++++++++++++++++++++++--------------------------- 2 files changed, 44 insertions(+), 40 deletions(-) (limited to 'Doc') diff --git a/ChangeLog b/ChangeLog index 5b7cb3dc5..e8a1ffc52 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2022-04-06 Matthew Martin + + * 49960: Doc/Zsh/compsys.yo: Sort lists in zshcompsys. + 2022-04-05 Bart Schaefer * 49994: Src/glob.c: Single-byte equivalence of users/22601 and diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index b968f20dc..584ede441 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -322,15 +322,15 @@ item(tt(-array-value-))( The right hand side of an array-assignment (`var(name)tt(=LPAR())var(...)tt(RPAR())') ) -kindex(-brace-parameter-, completion context) -item(tt(-brace-parameter-))( -The name of a parameter expansion within braces (`tt(${)var(...)tt(})') -) kindex(-assign-parameter-, completion context) item(tt(-assign-parameter-))( The name of a parameter in an assignment, i.e. on the left hand side of an `tt(=)' ) +kindex(-brace-parameter-, completion context) +item(tt(-brace-parameter-))( +The name of a parameter expansion within braces (`tt(${)var(...)tt(})') +) kindex(-command-, completion context) item(tt(-command-))( A word in command position @@ -891,14 +891,14 @@ kindex(indexes, completion tag) item(tt(indexes))( for array indexes ) -kindex(jobs, completion tag) -item(tt(jobs))( -for jobs (as listed by the `tt(jobs)' builtin) -) kindex(interfaces, completion tag) item(tt(interfaces))( for network interfaces ) +kindex(jobs, completion tag) +item(tt(jobs))( +for jobs (as listed by the `tt(jobs)' builtin) +) kindex(keymaps, completion tag) item(tt(keymaps))( for names of zsh keymaps @@ -922,14 +922,14 @@ directory when completing arguments of tt(cd) and related builtin commands (compare tt(path-directories)) DASH()- when the tt(cdpath) array is unset, tt(directories) is used instead ) -kindex(manuals, completion tag) -item(tt(manuals))( -for names of manual pages -) kindex(mailboxes, completion tag) item(tt(mailboxes))( for e-mail folders ) +kindex(manuals, completion tag) +item(tt(manuals))( +for names of manual pages +) kindex(maps, completion tag) item(tt(maps))( for map names (e.g. NIS maps) @@ -1389,6 +1389,12 @@ components after the first ambiguous one will also be added. This means that the resulting string is the longest unambiguous string possible. However, menu completion can be used to cycle through all matches. ) +kindex(extra-verbose, completion style) +item(tt(extra-verbose))( +If set, the completion listing is more verbose at the cost of +a probable decrease in completion speed. Completion performance +will suffer if this style is set to `true'. +) kindex(fake, completion style) item(tt(fake))( This style may be set for any completion context. It @@ -1652,6 +1658,15 @@ ifzman(zmanref(zshmodules))\ ifnzman(noderef(The zsh/zutil Module))\ . ) +kindex(gain-privileges, completion style) +item(tt(gain-privileges))( +If set to tt(true), this style enables the use of commands like tt(sudo) +or tt(doas) to gain extra privileges when retrieving information for +completion. This is only done when a command such as tt(sudo) appears on +the command-line. To force the use of, e.g. tt(sudo) or to override any +prefix that might be added due to tt(gain-privileges), the tt(command) +style can be used with a value that begins with a hyphen. +) kindex(glob, completion style) item(tt(glob))( This is used by the tt(_expand) completer. If @@ -1798,12 +1813,6 @@ Excluded values act in a similar fashion to values of the tt(ignored-patterns) style, so they can be restored to consideration by the tt(_ignored) completer. ) -kindex(extra-verbose, completion style) -item(tt(extra-verbose))( -If set, the completion listing is more verbose at the cost of -a probable decrease in completion speed. Completion performance -will suffer if this style is set to `true'. -) kindex(ignored-patterns, completion style) item(tt(ignored-patterns))( A list of patterns; any trial completion matching one of the patterns @@ -1900,15 +1909,6 @@ In the case of the tt(_match) completer, the style may also be set to the string `tt(pattern)'. Then the pattern on the line is left unchanged if it does not match unambiguously. ) -kindex(gain-privileges, completion style) -item(tt(gain-privileges))( -If set to tt(true), this style enables the use of commands like tt(sudo) -or tt(doas) to gain extra privileges when retrieving information for -completion. This is only done when a command such as tt(sudo) appears on -the command-line. To force the use of, e.g. tt(sudo) or to override any -prefix that might be added due to tt(gain-privileges), the tt(command) -style can be used with a value that begins with a hyphen. -) kindex(keep-prefix, completion style) item(tt(keep-prefix))( This style is used by the tt(_expand) completer. If it is `true', the @@ -1924,6 +1924,13 @@ The behaviour of tt(_expand) when this style is `true' is to cause tt(_expand) to give up when a single expansion with the restored prefix is the same as the original; hence any remaining completers may be called. ) +kindex(known-hosts-files) +item(tt(known-hosts-files))( +This style should contain a list of files to search for host names and +(if the tt(use-ip) style is set) IP addresses in a format compatible with +ssh tt(known_hosts) files. If it is not set, the files +tt(/etc/ssh/ssh_known_hosts) and tt(~/.ssh/known_hosts) are used. +) kindex(last-prompt, completion style) item(tt(last-prompt))( This is a more flexible form of the tt(ALWAYS_LAST_PROMPT) option. @@ -1935,13 +1942,6 @@ previous line if this style is `true' for all types of match. Note that unlike the tt(ALWAYS_LAST_PROMPT) option this is independent of the numeric argument. ) -kindex(known-hosts-files) -item(tt(known-hosts-files))( -This style should contain a list of files to search for host names and -(if the tt(use-ip) style is set) IP addresses in a format compatible with -ssh tt(known_hosts) files. If it is not set, the files -tt(/etc/ssh/ssh_known_hosts) and tt(~/.ssh/known_hosts) are used. -) kindex(list, completion style) item(tt(list))( This style is used by the tt(_history_complete_word) bindable command. @@ -2039,6 +2039,12 @@ This style is tested in the same way as the tt(list-packed) style and determines whether matches are to be listed in a rows-first fashion as if the tt(LIST_ROWS_FIRST) option were set. ) +kindex(list-separator, completion style) +item(tt(list-separator))( +The value of this style is used in completion listing to separate the +string to complete from a description when possible (e.g. when +completing options). It defaults to `tt(-)tt(-)' (two hyphens). +) kindex(list-suffixes, completion style) item(tt(list-suffixes))( This style is used by the function that completes filenames. If it is @@ -2046,12 +2052,6 @@ This style is used by the function that completes filenames. If it is typed pathname components, all ambiguous components will be shown. Otherwise, completion stops at the first ambiguous component. ) -kindex(list-separator, completion style) -item(tt(list-separator))( -The value of this style is used in completion listing to separate the -string to complete from a description when possible (e.g. when -completing options). It defaults to `tt(-)tt(-)' (two hyphens). -) kindex(local, completion style) item(tt(local))( This is for use with functions that complete URLs for which the -- cgit v1.2.3