From a435ab530f9cf0ebab107f48b4ff7f76d8613126 Mon Sep 17 00:00:00 2001 From: dana Date: Sun, 16 Sep 2018 18:39:55 -0500 Subject: unposted: Fix trivial formatting error in docs --- Doc/Zsh/builtins.yo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Doc/Zsh') diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index f460e48a5..76b593fd2 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -1332,7 +1332,7 @@ If any of `tt(-m)', `tt(-o)' or `tt(-O)' are used in combination with case of `tt(-m)') then nothing is printed. ) findex(printf) -item(tt(printf) [ -v var(name) ] var(format) [ var(arg) ... ])( +item(tt(printf) [ tt(-v) var(name) ] var(format) [ var(arg) ... ])( Print the arguments according to the format specification. Formatting rules are the same as used in C. The same escape sequences as for tt(echo) are recognised in the format. All C conversion specifications ending in -- cgit v1.2.3 From 3f2bcceec86bc11f5e5b1d116e6bd5fe063b076b Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 24 Sep 2018 13:22:07 +0000 Subject: 43528: zshbuiltins(1): Document 'which''s "not found is not an error" behaviour. --- ChangeLog | 5 +++++ Doc/Zsh/builtins.yo | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index 2f37a0359..e7ebc8aeb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-09-25 Daniel Shahaf + + * 43528: Doc/Zsh/builtins.yo: zshbuiltins(1): Document 'which''s + "not found is not an error" behaviour. + 2018-09-25 Oliver Freyermuth * 43554 (tweaked): Completion/X/Command/_zathura: Fix zathura diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 76b593fd2..0141305b4 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -2373,6 +2373,12 @@ item(tt(whence) [ tt(-vcwfpamsS) ] [ tt(-x) var(num) ] var(name) ...)( For each var(name), indicate how it would be interpreted if used as a command name. +If var(name) is not an alias, built-in command, external command, shell +function, hashed command, or a reserved word, the exit status shall be +non-zero, and DASH()- if tt(-v), tt(-c), or tt(-w) was passed DASH()- a message +will be written to standard output. (This is different from other shells that +write that message to standard error.) + tt(whence) is most useful when var(name) is only the last path component of a command, i.e. does not include a `tt(/)'; in particular, pattern matching only succeeds if just the non-directory component of the command is -- cgit v1.2.3 From 15d613a14f989c03ac8e037ceb231f9daff7caee Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 26 Sep 2018 15:11:12 +0000 Subject: 43563: zshzle: Clarify sentence in introduction. --- ChangeLog | 5 +++++ Doc/Zsh/zle.yo | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index 09a7e18e1..241bd917a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-09-27 Daniel Shahaf + + * 43563: Doc/Zsh/zle.yo: zshzle: Clarify sentence in + introduction. + 2018-09-26 Peter Stephenson * 43564: Better output concerning stopped subjob. diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 6ae4863c6..895c5c570 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -47,11 +47,11 @@ by default be entered in emacs mode by holding the alt key and typing a number, or pressing escape before each digit, and in vi command mode by typing the number before entering a command. Generally the numeric argument causes the next command entered to be repeated the specified -number of times, unless otherwise noted below. See also +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) )\ -for some other ways the numeric argument can be modified. The default -bindings mentioned here use the tt(digit-argument) widget. +for some other ways the numeric argument can be modified. startmenu() menu(Keymaps) -- cgit v1.2.3 From 6a5c38626b82d18cad431f69aa21dcc94d1b3181 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Tue, 2 Oct 2018 15:21:31 +0000 Subject: unposted: Fix typo --- ChangeLog | 4 ++++ Doc/Zsh/contrib.yo | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index 205cca392..d078b36cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2018-10-02 Daniel Shahaf + + * unposted: Doc/Zsh/contrib.yo: Fix typo + 2018-09-30 Daniel Shahaf * 43531: Src/Zle/compcore.c: Completion: Fix some false diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 0c2ba484c..9e4e6bc8f 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1668,7 +1668,7 @@ 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 the opposite order, which mean that the first argument is +collected so far in the opposite order, which means that the first argument is the patch next-in-line to be applied and so forth. When setting tt(ret) to non-zero, the string in -- cgit v1.2.3 From f99f7dca7552d21782354f675c0741896c9785f1 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 8 Oct 2018 10:10:42 +0100 Subject: 43616: Various parameter setting and display fixes. Mostly to do with typeset -p and tied variables and their interaction. Some general tied variable fixes. --- ChangeLog | 8 ++ Doc/Zsh/builtins.yo | 30 +++-- Src/Modules/db_gdbm.c | 2 +- Src/Modules/parameter.c | 44 ++++---- Src/builtin.c | 155 +++++++++++++++++++------- Src/hashtable.h | 1 + Src/params.c | 172 +++++++++++++++++----------- Src/subst.c | 4 +- Src/zsh.h | 23 ++-- Test/B02typeset.ztst | 291 ++++++++++++++++++++++++++++++++++++++++++++++-- 10 files changed, 574 insertions(+), 156 deletions(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index af9107e62..ad67dbc23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2018-10-08 Peter Stephenson + + * Stephane: 43616: Doc/Zsh/builtins.yo, Src/Modules/db_gdbm.c, + Src/Modules/parameter.c, Src/builtin.c, Src/hashtable.h, + Src/params.c, Src/subst.c, Src/zsh.h, Test/B02typeset.ztst: + Fixes and improvements to tied variables and interaction + with typeset -p. + 2018-10-07 Daniel Shahaf * 43587: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 0141305b4..4039595df 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -2029,6 +2029,9 @@ scalar version causes a split on all separators (which cannot be quoted). It is possible to apply tt(-T) to two previously tied variables but with a different separator character, in which case the variables remain joined as before but the separator is changed. + +When an existing scalar is tied to a new array, the value of the scalar +is preserved but no attribute other than export will be preserved. ) enditem() @@ -2076,12 +2079,12 @@ flag. ) item(tt(-U))( For arrays (but not for associative arrays), keep only the first -occurrence of each duplicated value. This may also be set for -colon-separated special parameters like tt(PATH) or tt(FIGNORE), etc. -Note the flag takes effect on assignment, and the type of the -variable being assigned to is determinative; for variables with -shared values it is therefore recommended to set the flag for -all interfaces, e.g. `tt(typeset -U PATH path)'. +occurrence of each duplicated value. This may also be set for tied +parameters (see tt(-T)) or colon-separated special parameters like +tt(PATH) or tt(FIGNORE), etc. Note the flag takes effect on assignment, +and the type of the variable being assigned to is determinative; for +variables with shared values it is therefore recommended to set the flag +for all interfaces, e.g. `tt(typeset -U PATH path)'. This flag has a different meaning when used with tt(-f); see below. ) @@ -2174,10 +2177,17 @@ be turned off. If the tt(POSIX_BUILTINS) option is set, the readonly attribute is more restrictive: unset variables can be marked readonly and cannot then be set; furthermore, the readonly attribute cannot be removed from any -variable. Note that in zsh (unlike other shells) it is still possible -to create a local variable of the same name as this is considered a -different variable (though this variable, too, can be marked readonly). -) +variable. + +It is still possible to change other attributes of the variable though, +some of which like tt(-U) or tt(-Z) would affect the value. More generally, +the readonly attribute should not be relied on as a security mechanism. + +Note that in zsh (like in pdksh but unlike most other shells) it is +still possible to create a local variable of the same name as this is +considered a different variable (though this variable, too, can be marked +readonly). Special variables that have been made readonly retain their value +and readonly attribute when made local.) item(tt(-t))( Tags the named parameters. Tags have no special meaning to the shell. This flag has a different meaning when used with tt(-f); see above. diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c index ed702b912..12dd839cf 100644 --- a/Src/Modules/db_gdbm.c +++ b/Src/Modules/db_gdbm.c @@ -809,7 +809,7 @@ myfreeparamnode(HashNode hn) zsfree(pm->node.nam); /* If this variable was tied by the user, ename was ztrdup'd */ - if (pm->node.flags & PM_TIED && pm->ename) { + if (!(pm->node.flags & PM_SPECIAL) && pm->ename) { zsfree(pm->ename); pm->ename = NULL; } diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 783c36df3..76824cf58 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -75,6 +75,8 @@ paramtypestr(Param pm) val = dyncat(val, "-readonly"); if (f & PM_TAGGED) val = dyncat(val, "-tag"); + if (f & PM_TIED) + val = dyncat(val, "-tied"); if (f & PM_EXPORTED) val = dyncat(val, "-export"); if (f & PM_UNIQUE) @@ -2194,67 +2196,67 @@ static const struct gsu_array historywords_gsu = static struct paramdef partab[] = { SPECIALPMDEF("aliases", 0, &pmraliases_gsu, getpmralias, scanpmraliases), - SPECIALPMDEF("builtins", PM_READONLY, NULL, getpmbuiltin, scanpmbuiltins), + SPECIALPMDEF("builtins", PM_READONLY_SPECIAL, NULL, getpmbuiltin, scanpmbuiltins), SPECIALPMDEF("commands", 0, &pmcommands_gsu, getpmcommand, scanpmcommands), SPECIALPMDEF("dirstack", PM_ARRAY, &dirs_gsu, NULL, NULL), SPECIALPMDEF("dis_aliases", 0, &pmdisraliases_gsu, getpmdisralias, scanpmdisraliases), - SPECIALPMDEF("dis_builtins", PM_READONLY, + SPECIALPMDEF("dis_builtins", PM_READONLY_SPECIAL, NULL, getpmdisbuiltin, scanpmdisbuiltins), SPECIALPMDEF("dis_functions", 0, &pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions), - SPECIALPMDEF("dis_functions_source", PM_READONLY, NULL, + SPECIALPMDEF("dis_functions_source", PM_READONLY_SPECIAL, NULL, getpmdisfunction_source, scanpmdisfunction_source), SPECIALPMDEF("dis_galiases", 0, &pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases), - SPECIALPMDEF("dis_patchars", PM_ARRAY|PM_READONLY, + SPECIALPMDEF("dis_patchars", PM_ARRAY|PM_READONLY_SPECIAL, &dispatchars_gsu, NULL, NULL), - SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY, + SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY_SPECIAL, &disreswords_gsu, NULL, NULL), SPECIALPMDEF("dis_saliases", 0, &pmdissaliases_gsu, getpmdissalias, scanpmdissaliases), - SPECIALPMDEF("funcfiletrace", PM_ARRAY|PM_READONLY, + SPECIALPMDEF("funcfiletrace", PM_ARRAY|PM_READONLY_SPECIAL, &funcfiletrace_gsu, NULL, NULL), - SPECIALPMDEF("funcsourcetrace", PM_ARRAY|PM_READONLY, + SPECIALPMDEF("funcsourcetrace", PM_ARRAY|PM_READONLY_SPECIAL, &funcsourcetrace_gsu, NULL, NULL), - SPECIALPMDEF("funcstack", PM_ARRAY|PM_READONLY, + SPECIALPMDEF("funcstack", PM_ARRAY|PM_READONLY_SPECIAL, &funcstack_gsu, NULL, NULL), SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction, scanpmfunctions), - SPECIALPMDEF("functions_source", PM_READONLY, NULL, + SPECIALPMDEF("functions_source", PM_READONLY_SPECIAL, NULL, getpmfunction_source, scanpmfunction_source), - SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY, + SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY_SPECIAL, &functrace_gsu, NULL, NULL), SPECIALPMDEF("galiases", 0, &pmgaliases_gsu, getpmgalias, scanpmgaliases), - SPECIALPMDEF("history", PM_READONLY, + SPECIALPMDEF("history", PM_READONLY_SPECIAL, NULL, getpmhistory, scanpmhistory), - SPECIALPMDEF("historywords", PM_ARRAY|PM_READONLY, + SPECIALPMDEF("historywords", PM_ARRAY|PM_READONLY_SPECIAL, &historywords_gsu, NULL, NULL), - SPECIALPMDEF("jobdirs", PM_READONLY, + SPECIALPMDEF("jobdirs", PM_READONLY_SPECIAL, NULL, getpmjobdir, scanpmjobdirs), - SPECIALPMDEF("jobstates", PM_READONLY, + SPECIALPMDEF("jobstates", PM_READONLY_SPECIAL, NULL, getpmjobstate, scanpmjobstates), - SPECIALPMDEF("jobtexts", PM_READONLY, + SPECIALPMDEF("jobtexts", PM_READONLY_SPECIAL, NULL, getpmjobtext, scanpmjobtexts), - SPECIALPMDEF("modules", PM_READONLY, + SPECIALPMDEF("modules", PM_READONLY_SPECIAL, NULL, getpmmodule, scanpmmodules), SPECIALPMDEF("nameddirs", 0, &pmnameddirs_gsu, getpmnameddir, scanpmnameddirs), SPECIALPMDEF("options", 0, &pmoptions_gsu, getpmoption, scanpmoptions), - SPECIALPMDEF("parameters", PM_READONLY, + SPECIALPMDEF("parameters", PM_READONLY_SPECIAL, NULL, getpmparameter, scanpmparameters), - SPECIALPMDEF("patchars", PM_ARRAY|PM_READONLY, + SPECIALPMDEF("patchars", PM_ARRAY|PM_READONLY_SPECIAL, &patchars_gsu, NULL, NULL), - SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY, + SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY_SPECIAL, &reswords_gsu, NULL, NULL), SPECIALPMDEF("saliases", 0, &pmsaliases_gsu, getpmsalias, scanpmsaliases), - SPECIALPMDEF("userdirs", PM_READONLY, + SPECIALPMDEF("userdirs", PM_READONLY_SPECIAL, NULL, getpmuserdir, scanpmuserdirs), - SPECIALPMDEF("usergroups", PM_READONLY, + SPECIALPMDEF("usergroups", PM_READONLY_SPECIAL, NULL, getpmusergroups, scanpmusergroups) }; diff --git a/Src/builtin.c b/Src/builtin.c index 4abc7da35..c5b319b68 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -64,7 +64,7 @@ static struct builtin builtins[] = BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmprs", NULL), BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL), BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL), - BUILTIN("export", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "E:%F:%HL:%R:%TUZ:%afhi:%lp:%rtu", "xg"), + BUILTIN("export", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, BIN_EXPORT, "E:%F:%HL:%R:%TUZ:%afhi:%lp:%rtu", "xg"), BUILTIN("false", 0, bin_false, 0, -1, 0, NULL, NULL), /* * We used to behave as if the argument to -e was optional. @@ -2258,6 +2258,22 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), } else if (pm->env && !(pm->node.flags & PM_HASHELEM)) delenv(pm); DPUTS(ASG_ARRAYP(asg), "BUG: typeset got array value where scalar expected"); + if (altpm) { + struct tieddata* tdp = (struct tieddata *) pm->u.data; + if (tdp) { + if (tdp->joinchar != joinchar && !asg->value.scalar) { + /* + * Reassign the scalar to itself to do the splitting with + * the new joinchar + */ + tdp->joinchar = joinchar; + if (!(pm = assignsparam(pname, ztrdup(getsparam(pname)), 0))) + return NULL; + } + } + else + DPUTS(!tdp, "BUG: no join character to update"); + } if (asg->value.scalar && !(pm = assignsparam(pname, ztrdup(asg->value.scalar), 0))) return NULL; @@ -2325,6 +2341,9 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), zerrnam(cname, "%s: can only have a single instance", pname); return pm; } + + on |= pm->node.flags & PM_TIED; + /* * For specials, we keep the same struct but zero everything. * Maybe it would be easier to create a new struct but copy @@ -2476,7 +2495,7 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), return NULL; } - if (altpm && PM_TYPE(pm->node.flags) == PM_SCALAR) { + if (altpm && PM_TYPE(pm->node.flags) == PM_SCALAR && !(pm->node.flags & PM_SPECIAL)) { /* * It seems safer to set this here than in createparam(), * to make sure we only ever use the colonarr functions @@ -2646,7 +2665,17 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) /* Given no arguments, list whatever the options specify. */ if (OPT_ISSET(ops,'p')) { - printflags |= PRINT_TYPESET; + + if (isset(POSIXBUILTINS) && SHELL_EMULATION() != EMULATE_KSH) { + if (func == BIN_EXPORT) + printflags |= PRINT_POSIX_EXPORT; + else if (func == BIN_READONLY) + printflags |= PRINT_POSIX_READONLY; + else + printflags |= PRINT_TYPESET; + } else + printflags |= PRINT_TYPESET; + if (OPT_HASARG(ops,'p')) { char *eptr; int pflag = (int)zstrtol(OPT_ARG(ops,'p'), &eptr, 10); @@ -2662,13 +2691,20 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) } hasargs = *argv != NULL || (assigns && firstnode(assigns)); if (!hasargs) { + int exclude = 0; if (!OPT_ISSET(ops,'p')) { if (!(on|roff)) printflags |= PRINT_TYPE; if (roff || OPT_ISSET(ops,'+')) printflags |= PRINT_NAMEONLY; + } else if (printflags & (PRINT_POSIX_EXPORT|PRINT_POSIX_READONLY)) { + /* + * For POSIX export/readonly, exclude non-scalars unless + * explicitly requested. + */ + exclude = (PM_ARRAY|PM_HASHED) & ~(on|roff); } - scanhashtable(paramtab, 1, on|roff, 0, paramtab->printnode, printflags); + scanhashtable(paramtab, 1, on|roff, exclude, paramtab->printnode, printflags); unqueue_signals(); return 0; } @@ -2683,6 +2719,7 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) struct asgment asg0, asg2; char *oldval = NULL, *joinstr; int joinchar, nargs; + int already_tied = 0; if (OPT_ISSET(ops,'m')) { zwarnnam(name, "incompatible options for -T"); @@ -2765,47 +2802,81 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) joinchar = joinstr[1] ^ 32; else joinchar = *joinstr; - /* - * Keep the old value of the scalar. We need to do this - * here as if it is already tied to the same array it - * will be unset when we retie the array. This is all - * so that typeset -T is idempotent. - * - * We also need to remember here whether the damn thing is - * exported and pass that along. Isn't the world complicated? - */ - if ((pm = (Param) paramtab->getnode(paramtab, asg0.name)) - && !(pm->node.flags & PM_UNSET) - && (locallevel == pm->level || !(on & PM_LOCAL))) { - if (pm->node.flags & PM_TIED) { + + pm = (Param) paramtab->getnode(paramtab, asg0.name); + apm = (Param) paramtab->getnode(paramtab, asg->name); + + if (pm && (pm->node.flags & (PM_SPECIAL|PM_TIED)) == (PM_SPECIAL|PM_TIED)) { + /* + * Only allow typeset -T on special tied parameters if the tied + * parameter and join char are the same + */ + if (strcmp(pm->ename, asg->name) || !(apm->node.flags & PM_SPECIAL)) { + zwarnnam(name, "%s special parameter can only be tied to special parameter %s", asg0.name, pm->ename); + unqueue_signals(); + return 1; + } + if (joinchar != ':') { + zwarnnam(name, "cannot change the join character of special tied parameters"); unqueue_signals(); - if (PM_TYPE(pm->node.flags) != PM_SCALAR) { - zwarnnam(name, "already tied as non-scalar: %s", asg0.name); - } else if (!strcmp(asg->name, pm->ename)) { + return 1; + } + already_tied = 1; + } else if (apm && (apm->node.flags & (PM_SPECIAL|PM_TIED)) == (PM_SPECIAL|PM_TIED)) { + /* + * For the array variable, this covers attempts to tie the + * array to a different scalar or to the scalar after it has + * been made non-special + */ + zwarnnam(name, "%s special parameter can only be tied to special parameter %s", asg->name, apm->ename); + unqueue_signals(); + return 1; + } else if (pm) { + if (!(pm->node.flags & PM_UNSET) + && (locallevel == pm->level || !(on & PM_LOCAL))) { + if (pm->node.flags & PM_TIED) { + if (PM_TYPE(pm->node.flags) != PM_SCALAR) { + zwarnnam(name, "already tied as non-scalar: %s", asg0.name); + unqueue_signals(); + return 1; + } else if (!strcmp(asg->name, pm->ename)) { + already_tied = 1; + } else { + zwarnnam(name, "can't tie already tied scalar: %s", + asg0.name); + unqueue_signals(); + return 1; + } + } else { /* - * Already tied in the fashion requested. + * Variable already exists in the current scope but is not tied. + * We're preserving its value and export attribute but no other + * attributes upon converting to "tied". */ - struct tieddata *tdp = (struct tieddata*)pm->u.data; - int flags = (asg->flags & ASG_KEY_VALUE) ? - ASSPM_KEY_VALUE : 0; - /* Update join character */ - tdp->joinchar = joinchar; - if (asg0.value.scalar) - assignsparam(asg0.name, ztrdup(asg0.value.scalar), 0); - else if (asg->value.array) - assignaparam( - asg->name, zlinklist2array(asg->value.array),flags); - return 0; - } else { - zwarnnam(name, "can't tie already tied scalar: %s", - asg0.name); + if (!asg0.value.scalar && !asg->value.array && + !(PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED))) + oldval = ztrdup(getsparam(asg0.name)); + on |= (pm->node.flags & ~roff) & PM_EXPORTED; } - return 1; } - if (!asg0.value.scalar && !asg->value.array && - !(PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED))) - oldval = ztrdup(getsparam(asg0.name)); - on |= (pm->node.flags & PM_EXPORTED); + } + if (already_tied) { + int ret; + /* + * If already tied, we still need to call typeset_single on + * both the array and colonarray, if only to update the attributes + * of both, and of course to set the new value if one is provided + * for either of them. + */ + ret = !(typeset_single(name, asg0.name, pm, + func, on, off, roff, &asg0, apm, + ops, joinchar) && + typeset_single(name, asg->name, apm, + func, (on | PM_ARRAY) & ~PM_EXPORTED, + off & ~PM_ARRAY, roff, asg, NULL, ops, 0) + ); + unqueue_signals(); + return ret; } /* * Create the tied array; this is normal except that @@ -2832,9 +2903,7 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) * Create the tied colonarray. We make it as a normal scalar * and fix up the oddities later. */ - if (!(pm=typeset_single(name, asg0.name, - (Param)paramtab->getnode(paramtab, - asg0.name), + if (!(pm=typeset_single(name, asg0.name, pm, func, on, off, roff, &asg0, apm, ops, joinchar))) { if (oldval) diff --git a/Src/hashtable.h b/Src/hashtable.h index 21398e17c..f6778664e 100644 --- a/Src/hashtable.h +++ b/Src/hashtable.h @@ -63,6 +63,7 @@ #define BIN_UNALIAS 29 #define BIN_UNFUNCTION 30 #define BIN_UNSET 31 +#define BIN_EXPORT 32 /* These currently depend on being 0 and 1. */ #define BIN_SETOPT 0 diff --git a/Src/params.c b/Src/params.c index f7ecff32a..089a958ae 100644 --- a/Src/params.c +++ b/Src/params.c @@ -290,7 +290,7 @@ static initparam special_params[] ={ #define GSU(X) BR((GsuScalar)(void *)(&(X))) #define NULL_GSU BR((GsuScalar)(void *)NULL) #define IPDEF1(A,B,C) {{NULL,A,PM_INTEGER|PM_SPECIAL|C},BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0} -IPDEF1("#", pound_gsu, PM_READONLY), +IPDEF1("#", pound_gsu, PM_READONLY_SPECIAL), IPDEF1("ERRNO", errno_gsu, PM_UNSET), IPDEF1("GID", gid_gsu, PM_DONTIMPORT | PM_RESTRICTED), IPDEF1("EGID", egid_gsu, PM_DONTIMPORT | PM_RESTRICTED), @@ -300,11 +300,11 @@ IPDEF1("SAVEHIST", savehist_gsu, PM_RESTRICTED), IPDEF1("SECONDS", intseconds_gsu, 0), IPDEF1("UID", uid_gsu, PM_DONTIMPORT | PM_RESTRICTED), IPDEF1("EUID", euid_gsu, PM_DONTIMPORT | PM_RESTRICTED), -IPDEF1("TTYIDLE", ttyidle_gsu, PM_READONLY), +IPDEF1("TTYIDLE", ttyidle_gsu, PM_READONLY_SPECIAL), #define IPDEF2(A,B,C) {{NULL,A,PM_SCALAR|PM_SPECIAL|C},BR(NULL),GSU(B),0,0,NULL,NULL,NULL,0} IPDEF2("USERNAME", username_gsu, PM_DONTIMPORT|PM_RESTRICTED), -IPDEF2("-", dash_gsu, PM_READONLY), +IPDEF2("-", dash_gsu, PM_READONLY_SPECIAL), IPDEF2("histchars", histchars_gsu, PM_DONTIMPORT), IPDEF2("HOME", home_gsu, PM_UNSET), IPDEF2("TERM", term_gsu, PM_UNSET), @@ -337,7 +337,7 @@ LCIPDEF("LC_TIME"), # endif #endif /* USE_LOCALE */ -#define IPDEF4(A,B) {{NULL,A,PM_INTEGER|PM_READONLY|PM_SPECIAL},BR((void *)B),GSU(varint_readonly_gsu),10,0,NULL,NULL,NULL,0} +#define IPDEF4(A,B) {{NULL,A,PM_INTEGER|PM_READONLY_SPECIAL},BR((void *)B),GSU(varint_readonly_gsu),10,0,NULL,NULL,NULL,0} IPDEF4("!", &lastpid), IPDEF4("$", &mypid), IPDEF4("?", &lastval), @@ -377,10 +377,9 @@ IPDEF7("PS3", &prompt3), IPDEF7R("PS4", &prompt4), IPDEF7("SPROMPT", &sprompt), -#define IPDEF9F(A,B,C,D) {{NULL,A,D|PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(vararray_gsu),0,0,NULL,C,NULL,0} -#define IPDEF9(A,B,C) IPDEF9F(A,B,C,0) -IPDEF9F("*", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), -IPDEF9F("@", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), +#define IPDEF9(A,B,C,D) {{NULL,A,D|PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(vararray_gsu),0,0,NULL,C,NULL,0} +IPDEF9("*", &pparams, NULL, PM_ARRAY|PM_READONLY_SPECIAL|PM_DONTIMPORT), +IPDEF9("@", &pparams, NULL, PM_ARRAY|PM_READONLY_SPECIAL|PM_DONTIMPORT), /* * This empty row indicates the end of parameters available in @@ -389,17 +388,17 @@ IPDEF9F("@", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), {{NULL,NULL,0},BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0}, #define IPDEF8(A,B,C,D) {{NULL,A,D|PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(colonarr_gsu),0,0,NULL,C,NULL,0} -IPDEF8("CDPATH", &cdpath, "cdpath", 0), -IPDEF8("FIGNORE", &fignore, "fignore", 0), -IPDEF8("FPATH", &fpath, "fpath", 0), -IPDEF8("MAILPATH", &mailpath, "mailpath", 0), -IPDEF8("WATCH", &watch, "watch", 0), -IPDEF8("PATH", &path, "path", PM_RESTRICTED), -IPDEF8("PSVAR", &psvar, "psvar", 0), -IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, "zsh_eval_context", PM_READONLY), +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), /* MODULE_PATH is not imported for security reasons */ -IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED), +IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED|PM_TIED), #define IPDEF10(A,B) {{NULL,A,PM_ARRAY|PM_SPECIAL},BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0} @@ -409,7 +408,7 @@ IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED), */ /* All of these have sh compatible equivalents. */ -IPDEF1("ARGC", argc_gsu, PM_READONLY), +IPDEF1("ARGC", argc_gsu, PM_READONLY_SPECIAL), IPDEF2("HISTCHARS", histchars_gsu, PM_DONTIMPORT), IPDEF4("status", &lastval), IPDEF7("prompt", &prompt), @@ -417,20 +416,20 @@ IPDEF7("PROMPT", &prompt), IPDEF7("PROMPT2", &prompt2), IPDEF7("PROMPT3", &prompt3), IPDEF7("PROMPT4", &prompt4), -IPDEF8("MANPATH", &manpath, "manpath", 0), -IPDEF9("argv", &pparams, NULL), -IPDEF9("fignore", &fignore, "FIGNORE"), -IPDEF9("cdpath", &cdpath, "CDPATH"), -IPDEF9("fpath", &fpath, "FPATH"), -IPDEF9("mailpath", &mailpath, "MAILPATH"), -IPDEF9("manpath", &manpath, "MANPATH"), -IPDEF9("psvar", &psvar, "PSVAR"), -IPDEF9("watch", &watch, "WATCH"), +IPDEF8("MANPATH", &manpath, "manpath", PM_TIED), +IPDEF9("argv", &pparams, NULL, 0), +IPDEF9("fignore", &fignore, "FIGNORE", PM_TIED), +IPDEF9("cdpath", &cdpath, "CDPATH", PM_TIED), +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), -IPDEF9F("zsh_eval_context", &zsh_eval_context, "ZSH_EVAL_CONTEXT", PM_READONLY), +IPDEF9("zsh_eval_context", &zsh_eval_context, "ZSH_EVAL_CONTEXT", PM_TIED|PM_READONLY_SPECIAL), -IPDEF9F("module_path", &module_path, "MODULE_PATH", PM_RESTRICTED), -IPDEF9F("path", &path, "PATH", PM_RESTRICTED), +IPDEF9("module_path", &module_path, "MODULE_PATH", PM_TIED|PM_RESTRICTED), +IPDEF9("path", &path, "PATH", PM_TIED|PM_RESTRICTED), /* These are known to zsh alone. */ @@ -451,7 +450,7 @@ 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), +IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, NULL, PM_READONLY_SPECIAL), /* MODULE_PATH is not imported for security reasons */ IPDEF8("MODULE_PATH", &module_path, NULL, PM_DONTIMPORT|PM_RESTRICTED), @@ -464,7 +463,7 @@ IPDEF8("MODULE_PATH", &module_path, NULL, PM_DONTIMPORT|PM_RESTRICTED), * and $@, this is not readonly. This parameter is not directly * visible in user space. */ -static initparam argvparam_pm = IPDEF9F("", &pparams, NULL, \ +static initparam argvparam_pm = IPDEF9("", &pparams, NULL, \ PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT); #undef BR @@ -5024,10 +5023,10 @@ arrfixenv(char *s, char **t) if (!(pm->node.flags & PM_EXPORTED)) return; - if (pm->node.flags & PM_TIED) - joinchar = STOUC(((struct tieddata *)pm->u.data)->joinchar); - else + if (pm->node.flags & PM_SPECIAL) joinchar = ':'; + else + joinchar = STOUC(((struct tieddata *)pm->u.data)->joinchar); addenv(pm, t ? zjoin(t, joinchar, 1) : ""); } @@ -5650,7 +5649,7 @@ freeparamnode(HashNode hn) pm->gsu.s->unsetfn(pm, 1); zsfree(pm->node.nam); /* If this variable was tied by the user, ename was ztrdup'd */ - if (pm->node.flags & PM_TIED) + if (!(pm->node.flags & PM_SPECIAL)) zsfree(pm->ename); zfree(pm, sizeof(struct param)); } @@ -5685,7 +5684,9 @@ static const struct paramtypes pmtypes[] = { { PM_UPPER, "uppercase", 'u', 0}, { PM_READONLY, "readonly", 'r', 0}, { PM_TAGGED, "tagged", 't', 0}, - { PM_EXPORTED, "exported", 'x', 0} + { PM_EXPORTED, "exported", 'x', 0}, + { PM_UNIQUE, "unique", 'U', 0}, + { PM_TIED, "tied", 'T', 0} }; #define PMTYPES_SIZE ((int)(sizeof(pmtypes)/sizeof(struct paramtypes))) @@ -5774,10 +5775,6 @@ printparamvalue(Param p, int printflags) } break; } - if ((printflags & (PRINT_KV_PAIR|PRINT_LINE)) == PRINT_KV_PAIR) - putchar(' '); - else if (!(printflags & PRINT_KV_PAIR)) - putchar('\n'); } /**/ @@ -5785,36 +5782,41 @@ mod_export void printparamnode(HashNode hn, int printflags) { Param p = (Param) hn; + Param peer = NULL; if (p->node.flags & PM_UNSET) { - if (isset(POSIXBUILTINS) && (p->node.flags & PM_READONLY) && - (printflags & PRINT_TYPESET)) - { + if (printflags & (PRINT_POSIX_READONLY|PRINT_POSIX_EXPORT) && + p->node.flags & (PM_READONLY|PM_EXPORTED)) { /* - * Special POSIX rules: show the parameter as readonly + * Special POSIX rules: show the parameter as readonly/exported * even though it's unset, but with no value. */ printflags |= PRINT_NAMEONLY; } - else if (p->node.flags & PM_EXPORTED) - printflags |= PRINT_NAMEONLY; else return; } if (p->node.flags & PM_AUTOLOAD) printflags |= PRINT_NAMEONLY; - if (printflags & PRINT_TYPESET) { - if ((p->node.flags & (PM_READONLY|PM_SPECIAL)) == - (PM_READONLY|PM_SPECIAL) || - (p->node.flags & PM_AUTOLOAD)) { + if (printflags & (PRINT_TYPESET|PRINT_POSIX_READONLY|PRINT_POSIX_EXPORT)) { + if (p->node.flags & (PM_RO_BY_DESIGN|PM_AUTOLOAD)) { /* * It's not possible to restore the state of * these, so don't output. */ return; } - if (locallevel && p->level >= locallevel) { + /* + * The zsh variants of export -p/readonly -p also report other + * flags to indicate other attributes or scope. The POSIX variants + * don't. + */ + if (printflags & PRINT_POSIX_EXPORT) { + printf("export "); + } else if (printflags & PRINT_POSIX_READONLY) { + printf("readonly "); + } else if (locallevel && p->level >= locallevel) { printf("typeset "); /* printf("local "); */ } else if ((p->node.flags & PM_EXPORTED) && !(p->node.flags & (PM_ARRAY|PM_HASHED))) { @@ -5861,22 +5863,48 @@ printparamnode(HashNode hn, int printflags) } } } - if (p->node.flags & PM_UNIQUE) { - if (!doneminus) { - putchar('-'); - doneminus = 1; - } - putchar('U'); - } if (doneminus) putchar(' '); + + if (p->node.flags & PM_TIED) { + /* + * For scalars tied to arrays,s + * * typeset +m outputs + * array tied SCALAR array + * tied array SCALAR + * * typeset -p outputs: + * typeset -T SCALAR array (for hidden values) + * typeset -T SCALAR array=(values) + * for both scalar and array (flags may be different) + * + * We choose to print the value for the array instead of the scalar + * as scalars can't disambiguate between + * typeset -T SCALAR array=() + * and + * typeset -T SCALAR array=('') + * (same for (a b:c)...) + */ + Param tmp = (Param) paramtab->getnode(paramtab, p->ename); + + /* + * Swap param and tied peer for typeset -p output + */ + if (!(printflags & PRINT_TYPESET) || (p->node.flags & PM_ARRAY)) + peer = tmp; + else { + peer = p; + p = tmp; + } + + quotedzputs(peer->node.nam, stdout); + putchar(' '); + } } if ((printflags & PRINT_NAMEONLY) || - ((p->node.flags & PM_HIDEVAL) && !(printflags & PRINT_INCLUDEVALUE))) { - zputs(p->node.nam, stdout); - putchar('\n'); - } else { + ((p->node.flags & PM_HIDEVAL) && !(printflags & PRINT_INCLUDEVALUE))) + quotedzputs(p->node.nam, stdout); + else { if (printflags & PRINT_KV_PAIR) { if (printflags & PRINT_LINE) printf("\n "); @@ -5888,4 +5916,22 @@ printparamnode(HashNode hn, int printflags) printparamvalue(p, printflags); } + if (peer && (printflags & PRINT_TYPESET) && !(p->node.flags & PM_SPECIAL)) { + /* + * append the join char for tied parameters if different from colon + * for typeset -p output. + */ + unsigned char joinchar = STOUC(((struct tieddata *)peer->u.data)->joinchar); + if (joinchar != ':') { + char buf[2]; + buf[0] = joinchar; + buf[1] = '\0'; + putchar(' '); + quotedzputs(buf, stdout); + } + } + if ((printflags & (PRINT_KV_PAIR|PRINT_LINE)) == PRINT_KV_PAIR) + putchar(' '); + else if (!(printflags & PRINT_KV_PAIR)) + putchar('\n'); } diff --git a/Src/subst.c b/Src/subst.c index c1021fbf3..c706b9688 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2552,8 +2552,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, val = dyncat(val, "-readonly"); if (f & PM_TAGGED) val = dyncat(val, "-tag"); - if (f & PM_TAGGED_LOCAL) - val = dyncat(val, "-tag_local"); + if (f & PM_TIED) + val = dyncat(val, "-tied"); if (f & PM_EXPORTED) val = dyncat(val, "-export"); if (f & PM_UNIQUE) diff --git a/Src/zsh.h b/Src/zsh.h index b81db1527..8d39a0493 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1886,18 +1886,21 @@ struct tieddata { #define PM_ANONYMOUS (1<<20) /* (function) anonymous function */ #define PM_LOCAL (1<<21) /* this parameter will be made local */ #define PM_SPECIAL (1<<22) /* special builtin parameter */ -#define PM_DONTIMPORT (1<<23) /* do not import this variable */ -#define PM_RESTRICTED (1<<24) /* cannot be changed in restricted mode */ -#define PM_UNSET (1<<25) /* has null value */ -#define PM_REMOVABLE (1<<26) /* special can be removed from paramtab */ -#define PM_AUTOLOAD (1<<27) /* autoloaded from module */ -#define PM_NORESTORE (1<<28) /* do not restore value of local special */ -#define PM_AUTOALL (1<<28) /* autoload all features in module +#define PM_RO_BY_DESIGN (1<<23) /* to distinguish from specials that can be + made read-only by the user */ +#define PM_READONLY_SPECIAL (PM_SPECIAL|PM_READONLY|PM_RO_BY_DESIGN) +#define PM_DONTIMPORT (1<<24) /* do not import this variable */ +#define PM_RESTRICTED (1<<25) /* cannot be changed in restricted mode */ +#define PM_UNSET (1<<26) /* has null value */ +#define PM_REMOVABLE (1<<27) /* special can be removed from paramtab */ +#define PM_AUTOLOAD (1<<28) /* autoloaded from module */ +#define PM_NORESTORE (1<<29) /* do not restore value of local special */ +#define PM_AUTOALL (1<<29) /* autoload all features in module * when loading: valid only if PM_AUTOLOAD * is also present. */ -#define PM_HASHELEM (1<<29) /* is a hash-element */ -#define PM_NAMEDDIR (1<<30) /* has a corresponding nameddirtab entry */ +#define PM_HASHELEM (1<<30) /* is a hash-element */ +#define PM_NAMEDDIR (1<<31) /* has a corresponding nameddirtab entry */ /* The option string corresponds to the first of the variables above */ #define TYPESET_OPTSTR "aiEFALRZlurtxUhHTkz" @@ -2138,6 +2141,8 @@ typedef groupset *Groupset; #define PRINT_INCLUDEVALUE (1<<4) #define PRINT_TYPESET (1<<5) #define PRINT_LINE (1<<6) +#define PRINT_POSIX_EXPORT (1<<7) +#define PRINT_POSIX_READONLY (1<<8) /* flags for printing for the whence builtin */ #define PRINT_WHENCE_CSH (1<<7) diff --git a/Test/B02typeset.ztst b/Test/B02typeset.ztst index b53f42f83..ac86e0ad1 100644 --- a/Test/B02typeset.ztst +++ b/Test/B02typeset.ztst @@ -20,6 +20,14 @@ # Not yet tested: # Assorted illegal flag combinations +# For a few tests, we include a +# typeset -p param +# typeset -m param +# typeset +m param +# to test the proper output of typeset for a number of different types +# of variables. Note that we can't use a dedicated function to factorize +# that code, as that would affect the scoping. + %prep ## Do not remove the next line, it's used by V10private.ztst # test_zsh_param_private @@ -37,6 +45,9 @@ typeset -a array array=(l o c a l) print $scalar $array + typeset -p scalar array + typeset -m scalar array + typeset +m scalar array } scope01() { local scalar @@ -44,6 +55,9 @@ local -a array array=(l o c a l) print $scalar $array + typeset -p scalar array + typeset -m scalar array + typeset +m scalar array } scope02() { declare scalar @@ -51,10 +65,16 @@ declare -a array array=(l o c a l) print $scalar $array + typeset -p scalar array + typeset -m scalar array + typeset +m scalar array } scope10() { export outer=outer /bin/sh -fc 'echo $outer' + typeset -p outer + typeset -m outer + typeset +m outer } scope11() { typeset -x outer=outer @@ -68,6 +88,9 @@ local -xT OUTER outer outer=(i n n e r) /bin/sh -fc 'echo $OUTER' + typeset -p OUTER outer + typeset -m OUTER outer + typeset +m OUTER outer } # Bug? `typeset -h' complains that ! # $ * - ? @ are not identifiers. @@ -79,8 +102,14 @@ %test + typeset -p scalar array + typeset -m scalar array typeset +m scalar array -0:Report types of parameters with typeset +m +0:Report types for global variables +>typeset -g scalar=scalar +>typeset -g -a array=( a r r a y ) +>scalar=scalar +>array=( a r r a y ) >scalar >array array @@ -88,18 +117,36 @@ print $scalar $array 0:Simple local declarations >local l o c a l +>typeset scalar=local +>typeset -a array=( l o c a l ) +>scalar=local +>array=( l o c a l ) +>local scalar +>array local array >scalar a r r a y scope01 print $scalar $array 0:Equivalence of local and typeset in functions >local l o c a l +>typeset scalar=local +>typeset -a array=( l o c a l ) +>scalar=local +>array=( l o c a l ) +>local scalar +>array local array >scalar a r r a y scope02 print $scalar $array 0:Basic equivalence of declare and typeset >local l o c a l +>typeset scalar=local +>typeset -a array=( l o c a l ) +>scalar=local +>array=( l o c a l ) +>local scalar +>array local array >scalar a r r a y declare +m scalar @@ -110,6 +157,9 @@ print $outer 0:Global export >outer +>export outer=outer +>outer=outer +>outer >outer scope11 @@ -130,18 +180,30 @@ print $f float -F f print $f + typeset -p f + typeset -m f + typeset +m f 0:Floating point, adding a precision, and fixed point >float local f >3.14e+00 >3.142 +>typeset -F f=3.142 +>f=3.142 +>float local f integer i=3.141 typeset +m i integer -i2 i print $i + typeset -p i + typeset -m i + typeset +m i 0:Integer and changing the base >integer local i >2#11 +>typeset -i2 i=3 +>i=3 +>integer 2 local i float -E3 f=3.141 typeset +m f @@ -174,16 +236,33 @@ typeset -gU array print $array + typeset -p array + typeset -m array + typeset +m array 0:Uniquified arrays and non-local scope >a r y +>typeset -g -aU array=( a r y ) +>array=( a r y ) +>array unique array typeset -T SCALAR=l:o:c:a:l array print $array typeset -U SCALAR print $SCALAR $array + typeset -p SCALAR array + typeset -m SCALAR array + typeset +m SCALAR array + print ${(t)SCALAR} ${(t)array} 0:Tied parameters and uniquified colon-arrays >l o c a l >l:o:c:a l o c a +>typeset -UT SCALAR array=( l o c a ) +>typeset -aT SCALAR array=( l o c a ) +>SCALAR=l:o:c:a +>array=( l o c a ) +>local unique tied array SCALAR +>array local tied SCALAR array +>scalar-local-tied-unique array-local-tied (setopt NO_multibyte cbases LC_ALL=C 2>/dev/null @@ -209,9 +288,18 @@ typeset -T SCALAR=$'l\000o\000c\000a\000l' array $'\000' typeset -U SCALAR print $array + typeset -p SCALAR array + typeset -m SCALAR array + typeset +m SCALAR array [[ $SCALAR == $'l\000o\000c\000a' ]] 0:Tied parameters and uniquified arrays with NUL-character as separator >l o c a +>typeset -UT SCALAR array=( l o c a ) '' +>typeset -aT SCALAR array=( l o c a ) '' +>SCALAR=$'l\C-@o\C-@c\C-@a' +>array=( l o c a ) +>local unique tied array SCALAR +>array local tied SCALAR array typeset -T SCALAR array typeset +T SCALAR @@ -223,15 +311,30 @@ print $OUTER 0:Export of tied parameters >i:n:n:e:r +>typeset -xT OUTER outer=( i n n e r ) +>typeset -aT OUTER outer=( i n n e r ) +>OUTER=i:n:n:e:r +>outer=( i n n e r ) +>local exported tied outer OUTER +>array local tied OUTER outer >outer typeset -TU MORESTUFF=here-we-go-go-again morestuff '-' print -l $morestuff + typeset -p MORESTUFF morestuff + typeset -m MORESTUFF morestuff + typeset +m MORESTUFF morestuff 0:Tied arrays with separator specified >here >we >go >again +>typeset -UT MORESTUFF morestuff=( here we go again ) - +>typeset -aUT MORESTUFF morestuff=( here we go again ) - +>MORESTUFF=here-we-go-again +>morestuff=( here we go again ) +>local unique tied morestuff MORESTUFF +>array local unique tied MORESTUFF morestuff typeset -T THIS will not work 1:Tied array syntax @@ -251,13 +354,25 @@ local b=1 ;: to stomp assoc[1] if assoc[b] is broken typeset assoc[1]=a assoc[b]=2 assoc[3]=c print $assoc[1] $assoc[b] $assoc[3] + typeset -p assoc + typeset -m assoc + typeset +m assoc 0:Legal local associative array element assignment >a 2 c +>typeset -A assoc=( [1]=a [3]=c [b]=2 ) +>assoc=( [1]=a [3]=c [b]=2 ) +>association local assoc local scalar scalar[1]=a scalar[2]=b scalar[3]=c print $scalar + typeset -p scalar + typeset -m scalar + typeset +m scalar 0:Local scalar subscript assignment >abc +>typeset scalar=abc +>scalar=abc +>local scalar typeset -L 10 fools for fools in " once" "twice" " thrice" " oops too long here"; do @@ -273,11 +388,17 @@ for foolf in 1.3 4.6 -2.987 -4.91031; do print "'$foolf'" done + typeset -p foolf + typeset -m foolf + typeset +m foolf 0:Left justification of floating point >'1.300 ' >'4.600 ' >'-2.987 ' >'-4.910 ' +>typeset -FL10 foolf=-4.910 +>foolf=-4.910 +>float local left justified 10 foolf typeset -L 10 -Z foolzs for foolzs in 001.3 04.6 -2.987 -04.91231; do @@ -293,10 +414,16 @@ for foors in short longer even-longer; do print "'$foors'" done + typeset -p foors + typeset -m foors + typeset +m foors 0:Right justification of scalars >' short' >' longer' >'ven-longer' +>typeset -R10 foors=even-longer +>foors=even-longer +>local right justified 10 foors typeset -Z 10 foozs for foozs in 42 -42 " 43" " -43"; do @@ -436,24 +563,36 @@ print $case1 upper="VALUE OF \$UPPER" print ${(P)case1} + typeset -p case1 + typeset -m case1 + typeset +m case1 0:Upper case conversion, does not apply to values used internally >UPPER >VALUE OF $UPPER +>typeset -u case1=upper +>case1=upper +>local uppercase case1 local case2=LOWER typeset -l case2 print $case2 LOWER="value of \$lower" print ${(P)case2} + typeset -p case2 + typeset -m case2 + typeset +m case2 0:Lower case conversion, does not apply to values used internally >lower >value of $lower +>typeset -l case2=LOWER +>case2=LOWER +>local lowercase case2 typeset -a array array=(foo bar) fn() { typeset -p array nonexistent; } fn -1:declare -p shouldn't create scoped values +1:typeset -p shouldn't create scoped values >typeset -g -a array=( foo bar ) ?fn:typeset: no such variable: nonexistent @@ -490,7 +629,7 @@ ?0 ?(eval):5: read-only variable: pbro ?(eval):6: read-only variable: pbro -?typeset -g -r pbro +?readonly pbro ?0 ?(eval):10: read-only variable: pbro @@ -820,7 +959,145 @@ > [three]='' >) - (typeset -a -U foo=(bar bar) - typeset -p foo) -0:typeset -p of typeset -U ->typeset -aU foo=( bar ) + (export PATH MANPATH + path=(/bin) + MANPATH=/ + # read-only special params like zsh_eval_context are not output by typeset -p + specials=(path PATH manpath MANPATH zsh_eval_context ZSH_EVAL_CONTEXT) + typeset -p $specials + typeset -m $specials + typeset +m $specials + for var ($specials) print $var: ${(Pt)var} + ) +0:typeset output for some special tied parameters +>typeset -g -aT PATH path=( /bin ) +>export -T PATH path=( /bin ) +>typeset -g -aT MANPATH manpath=( / ) +>export -T MANPATH manpath=( / ) +>path=( /bin ) +>PATH=/bin +>manpath=( / ) +>MANPATH=/ +>zsh_eval_context=( toplevel shfunc shfunc shfunc eval ) +>ZSH_EVAL_CONTEXT=toplevel:shfunc:shfunc:shfunc:eval +>array tied PATH path +>tied path PATH +>array tied MANPATH manpath +>tied manpath MANPATH +>array readonly tied ZSH_EVAL_CONTEXT zsh_eval_context +>readonly tied zsh_eval_context ZSH_EVAL_CONTEXT +>path: array-tied-special +>PATH: scalar-tied-export-special +>manpath: array-tied-special +>MANPATH: scalar-tied-export-special +>zsh_eval_context: array-readonly-tied-special +>ZSH_EVAL_CONTEXT: scalar-readonly-tied-special + + typeset -T VAR var=(a b a b) + typeset -UuT VAR var + + print $VAR +0:redeclare a tied variable with different attributes +>A+B + + typeset -T VAR=a+b var + typeset -T VAR var + + print $var +0:colonarray re-split when changing the join character +>a b + + readonly -T VAR var=(a b) + readonly -T VAR var + +1:cannot change the join character on a readonly tied variable +?(eval):1: read-only variable: var + + typeset -T FOO manpath +1:Can't tie a special tied array to a different variable +?(eval):typeset:1: manpath special parameter can only be tied to special parameter MANPATH + + typeset -T MANPATH foo +1:Can't tie a special tied scalar to a different variable +?(eval):typeset:1: MANPATH special parameter can only be tied to special parameter manpath + + typeset -T MANPATH manpath + +1:Can't change the join character of a special tied variable +?(eval):typeset:1: cannot change the join character of special tied parameters + + (){ + typeset -h path + typeset -T PATH path=(x) + } + (){ + typeset -h PATH + typeset -T PATH path=(x) + } +1:reject attempt to tie special to downgraded peer +?(anon):typeset:2: PATH special parameter can only be tied to special parameter path +?(anon):typeset:2: path special parameter can only be tied to special parameter PATH + + typeset MANPATH + manpath=(/ /) + typeset -UT MANPATH manpath + print $manpath +0:OK to run typeset -T on tied specials as long as peer and joinchar are unchanged +>/ + + typeset FOO=a:b + export FOO + typeset +x -T FOO foo + typeset -p FOO +0:Make sure +x is honoured when tying a parameter +>typeset -T FOO foo=( a b ) + + $ZTST_testdir/../Src/zsh --emulate sh -f -c ' + PATH=/bin; export PATH; readonly PATH + export -p PATH + typeset -p PATH + readonly -p' +0: readonly/export output for exported+readonly+special when started as sh +>export PATH=/bin +>export -r PATH=/bin +>readonly PATH=/bin + + function { + emulate -L sh + MANPATH=/bin; export MANPATH; readonly MANPATH + export -p MANPATH + typeset -p MANPATH + readonly -p + } +0: readonly/export output for exported+readonly+tied+special after switching to sh emulation +>export MANPATH=/bin +>export -rT MANPATH manpath=( /bin ) +>readonly MANPATH=/bin + + function { + local -rax zsh_exported_readonly_array=(2) + local -rAx zsh_exported_readonly_hash=(3 3) + local -rx zsh_exported_readonly_scalar=1 + print zsh: + export -p | grep zsh_exported_readonly + readonly -p | grep zsh_exported_readonly + print sh: + emulate -L sh + export -p | grep zsh_exported_readonly + readonly -p | grep zsh_exported_readonly + print still asking for arrays: + export -ap | grep zsh_exported_readonly + readonly -ap | grep zsh_exported_readonly + } +0: no array/hash in POSIX export/readonly -p +>zsh: +>typeset -arx zsh_exported_readonly_array=( 2 ) +>typeset -Arx zsh_exported_readonly_hash=( [3]=3 ) +>typeset -rx zsh_exported_readonly_scalar=1 +>typeset -arx zsh_exported_readonly_array=( 2 ) +>typeset -Arx zsh_exported_readonly_hash=( [3]=3 ) +>typeset -rx zsh_exported_readonly_scalar=1 +>sh: +>export zsh_exported_readonly_scalar=1 +>readonly zsh_exported_readonly_scalar=1 +>still asking for arrays: +>export zsh_exported_readonly_array=( 2 ) +>export zsh_exported_readonly_scalar=1 +>readonly zsh_exported_readonly_array=( 2 ) +>readonly zsh_exported_readonly_scalar=1 -- cgit v1.2.3 From c4144bc95b26c41e7c45c5185112f87f9145d94f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 8 Oct 2018 10:17:26 +0100 Subject: unposted: doc tweak for helpfiles --- ChangeLog | 3 +++ Doc/Zsh/builtins.yo | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index ad67dbc23..fa50664fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2018-10-08 Peter Stephenson + * unposted: tweak to Doc/Zsh/builtins.yo to put close + parenthesis on new line for help files script. + * Stephane: 43616: Doc/Zsh/builtins.yo, Src/Modules/db_gdbm.c, Src/Modules/parameter.c, Src/builtin.c, Src/hashtable.h, Src/params.c, Src/subst.c, Src/zsh.h, Test/B02typeset.ztst: diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 4039595df..fd29ca3a5 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -2187,7 +2187,8 @@ Note that in zsh (like in pdksh but unlike most other shells) it is still possible to create a local variable of the same name as this is considered a different variable (though this variable, too, can be marked readonly). Special variables that have been made readonly retain their value -and readonly attribute when made local.) +and readonly attribute when made local. +) item(tt(-t))( Tags the named parameters. Tags have no special meaning to the shell. This flag has a different meaning when used with tt(-f); see above. -- cgit v1.2.3 From e38f15f8ff23651a8c4ef9fc394de7be93eb620f Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 7 Oct 2018 17:46:43 +0000 Subject: 43620 (tweaked): vcs_info git: Reverse the order patches are passed to gen-unapplied-string in. This is an incompatible change; see README for details. Tweaks (relative to posted version): tweaked README, removed scalpel (debug print). --- ChangeLog | 6 ++++++ Doc/Zsh/contrib.yo | 2 +- Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 3 ++- Functions/VCS_Info/VCS_INFO_set-patch-format | 2 ++ README | 16 +++++++++++++++- 5 files changed, 26 insertions(+), 3 deletions(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index cd79613f3..c2f645bcd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2018-10-08 Daniel Shahaf + * 43620 (tweaked): Doc/Zsh/contrib.yo, + Functions/VCS_Info/Backends/VCS_INFO_get_data_git, + Functions/VCS_Info/VCS_INFO_set-patch-format, README: vcs_info + git: Reverse the order patches are passed to gen-unapplied-string + in. + * 43617: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: vcs_info git: During a non-interactive rebase of a detached head, computer the %b expando correctly. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 9e4e6bc8f..d32ba018d 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1668,7 +1668,7 @@ 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 the opposite order, which means that the first argument is +collected so far in order, which means that the first argument is the patch next-in-line to be applied and so forth. When setting tt(ret) to non-zero, the string in diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 8305cf41a..7ae2c0b27 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -123,8 +123,9 @@ VCS_INFO_git_getbranch () { (( ${+functions[VCS_INFO_git_handle_patches]} )) || VCS_INFO_git_handle_patches () { local git_applied_s git_unapplied_s gitmsg + # All callers populate $git_patches_applied and $git_patches_unapplied in + # order, but the hook requires us to reverse $git_patches_applied. git_patches_applied=(${(Oa)git_patches_applied}) - git_patches_unapplied=(${(Oa)git_patches_unapplied}) VCS_INFO_set-patch-format 'git_patches_applied' 'git_applied_s' \ 'git_patches_unapplied' 'git_unapplied_s' \ diff --git a/Functions/VCS_Info/VCS_INFO_set-patch-format b/Functions/VCS_Info/VCS_INFO_set-patch-format index cdf2d303e..917ebf6bf 100644 --- a/Functions/VCS_Info/VCS_INFO_set-patch-format +++ b/Functions/VCS_Info/VCS_INFO_set-patch-format @@ -3,8 +3,10 @@ # # Parameters: # $1 - name of an array parameter to be the argument to gen-applied-string +# (patches in reverse order) # $2 - name of a parameter to store the applied-string in # $3 - name of an array parameter to be the argument to gen-unapplied-string +# (patches in order) # $4 - name of a parameter to store the unapplied-string in # $5 - context argument for use in zstyle getters # $6 - name of a parameter to store a patch-format format string in diff --git a/README b/README index c792d4075..1583002a7 100644 --- a/README +++ b/README @@ -10,7 +10,7 @@ This is version 5.6.2 of the shell. This is a bugfix release, following release. Note in particular the changes highlighted under "Incompatibilities since -5.5.1" below. See NEWS for more information. +5.6.2" below. See NEWS for more information. Installing Zsh -------------- @@ -31,6 +31,20 @@ Zsh is a shell with lots of features. For a list of some of these, see the file FEATURES, and for the latest changes see NEWS. For more details, see the documentation. +Incompatibilities since 5.6.2 +----------------------------- + +1) vcs_info git: The gen-unapplied-string hook receives the patches in order (next +to be applied first). This is consistent with the hg backend and with one of +two contradictory claims in the documentation (the other one has been corrected). +In zsh through 5.6.2, the patches were passed in reverse order, next to be +applied being last in the array. + +The gen-applied-string hook is unaffected; it still receives the patches in +reverse order, from last applied to first applied. + +2) + Incompatibilities since 5.5.1 ----------------------------- -- cgit v1.2.3 From 995a56cf0103b14d9741af40f96f6a741e82b469 Mon Sep 17 00:00:00 2001 From: dana Date: Wed, 10 Oct 2018 18:50:40 -0500 Subject: 43602: Clarify behaviour of `compdef -p` --- ChangeLog | 4 ++++ Doc/Zsh/compsys.yo | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index ddcf717cc..b814a1c14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2018-10-10 dana + + * 43602: Doc/Zsh/compsys.yo: Clarify behaviour of `compdef -p` + 2018-10-10 Peter Stephenson * unposted: Test/C03traps.ztst: Another couple of tests for diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index 65f596752..a5a9e5b5d 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -489,7 +489,11 @@ The parameter tt($_compskip) may be set by any function defined for a pattern context. If it is set to a value containing the substring `tt(patterns)' none of the pattern-functions will be called; if it is set to a value containing the substring `tt(all)', no other function -will be called. +will be called. Setting tt($_compskip) in this manner is of particular +utility when using the tt(-p) option, as otherwise the dispatcher will +move on to additional functions (likely the default one) after calling +the pattern-context one, which can mangle the display of completion +possibilities if not handled properly. The form with tt(-k) defines a widget with the same name as the var(function) that will be called for each of the var(key-sequence)s; this is like the -- cgit v1.2.3 From a8f90de4ffad2c0842bcff5998f50912e132e6d3 Mon Sep 17 00:00:00 2001 From: dana Date: Mon, 15 Oct 2018 22:08:38 -0500 Subject: 43672: Document result of redirecting from a non-existent file --- ChangeLog | 5 +++++ Doc/Zsh/redirect.yo | 1 + 2 files changed, 6 insertions(+) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index 968194be1..619758ffa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-10-15 dana + + * 43672: Doc/Zsh/redirect.yo: Document result of redirecting + from a non-existent file + 2018-10-14 Daniel Shahaf * unposted: Src/utils.c: internals: Document sepjoin(). diff --git a/Doc/Zsh/redirect.yo b/Doc/Zsh/redirect.yo index c793638b7..833241574 100644 --- a/Doc/Zsh/redirect.yo +++ b/Doc/Zsh/redirect.yo @@ -26,6 +26,7 @@ separate filename in turn. startitem() item(tt(<) var(word))( Open file var(word) for reading as standard input. +It is an error to open a file in this fashion if it does not exist. ) item(tt(<>) var(word))( Open file var(word) for reading and writing as standard input. -- cgit v1.2.3 From 079f7f9d48644bfa2b14da69d519b558c5776797 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 17 Oct 2018 17:05:31 +0100 Subject: 43694: More detail on multios. Mention how opening files in multios differs from cat. --- ChangeLog | 5 +++++ Doc/Zsh/redirect.yo | 13 ++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index 7bf8b3485..8dff54fac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-10-17 Peter Stephenson + + * 43694: Doc/Zsh/redirect.yo: More detail on how multio file + opening differs from cat. + 2018-10-17 Oliver Kiddle * 43697: Completion/X/Command/_zathura: match uppercase diff --git a/Doc/Zsh/redirect.yo b/Doc/Zsh/redirect.yo index 833241574..7e38cd0c3 100644 --- a/Doc/Zsh/redirect.yo +++ b/Doc/Zsh/redirect.yo @@ -235,6 +235,9 @@ example(date >foo | cat) writes the date to the file `tt(foo)', and also pipes it to cat. +Note that the shell opens all the files to be used in the multio process +immediately, not at the point they are about to be written. + Note also that redirections are always expanded in order. This happens regardless of the setting of the tt(MULTIOS) option, but with the option in effect there are additional consequences. For example, @@ -269,9 +272,13 @@ example(echo exit 0 >> *.sh) If the user tries to open a file descriptor for reading more than once, the shell opens the file descriptor as a pipe to a process that copies -all the specified inputs to its output in the order -specified, similar to bf(cat), -provided the tt(MULTIOS) option is set. Thus +all the specified inputs to its output in the order specified, provided +the tt(MULTIOS) option is set. It should be noted that each file is +opened immediately, not at the point where it is about to be read: +this behaviour differs from tt(cat), so if strictly standard behaviour +is needed, tt(cat) should be used instead. + +Thus example(sort Date: Mon, 5 Nov 2018 22:24:16 +0100 Subject: 43760: add documentation for true colour changes and nearcolor module --- ChangeLog | 4 ++++ Doc/Makefile.in | 3 ++- Doc/Zsh/mod_nearcolor.yo | 36 ++++++++++++++++++++++++++++++++++++ Doc/Zsh/zle.yo | 14 ++++++++++++-- NEWS | 9 +++++++++ 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 Doc/Zsh/mod_nearcolor.yo (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index cb18c9e71..1af8dfc04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2018-11-05 Oliver Kiddle + * 43760: Doc/Makefile.in, Doc/Zsh/mod_nearcolor.yo, + Doc/Zsh/zle.yo, NEWS: add documentation for true colour + changes and nearcolor module + * 43759: Src/Modules/nearcolor.c, Src/Zle/complist.c, Src/Zle/zle.h, Src/Zle/zle_refresh.c, Src/Zle/zle_tricky.c, Src/prompt.c, Src/zsh.h, Src/zsh_system.h: add support for diff --git a/Doc/Makefile.in b/Doc/Makefile.in index 71ca52195..5a6a705ff 100644 --- a/Doc/Makefile.in +++ b/Doc/Makefile.in @@ -63,7 +63,8 @@ Zsh/mod_compctl.yo Zsh/mod_complete.yo Zsh/mod_complist.yo \ Zsh/mod_computil.yo Zsh/mod_curses.yo \ Zsh/mod_datetime.yo Zsh/mod_db_gdbm.yo Zsh/mod_deltochar.yo \ Zsh/mod_example.yo Zsh/mod_files.yo Zsh/mod_langinfo.yo \ -Zsh/mod_mapfile.yo Zsh/mod_mathfunc.yo Zsh/mod_newuser.yo \ +Zsh/mod_mapfile.yo Zsh/mod_mathfunc.yo \ +Zsh/mod_nearcolor.yo Zsh/mod_newuser.yo \ 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 \ diff --git a/Doc/Zsh/mod_nearcolor.yo b/Doc/Zsh/mod_nearcolor.yo new file mode 100644 index 000000000..df7771397 --- /dev/null +++ b/Doc/Zsh/mod_nearcolor.yo @@ -0,0 +1,36 @@ +COMMENT(!MOD!zsh/nearcolor +Map colours to the nearest colour in the available palette. +!MOD!) +The tt(zsh/nearcolor) module replaces colours specified as hex triplets +with the nearest colour in the 88 or 256 colour palettes that are widely +used by terminal emulators. By default, 24-bit true colour escape codes +are generated when colours are specified using hex triplets. These are +not supported by all terminals. The purpose of this module is to make +it easier to define colour preferences in a form that can work across a +range of terminal emulators. + +Aside from the default colour, the ANSI standard for terminal escape +codes provides for eight colours. The bright attribute brings this to +sixteen. These basic colours are commonly used in terminal applications +due to being widely supported. Expanded 88 and 256 colour palettes are +also common and, while the first sixteen colours vary somewhat between +terminals and configurations, these add a generally consistent and +predictable set of colours. + +In order to use the tt(zsh/nearcolor) module, it only needs to be +loaded. Thereafter, whenever a colour is specified using a hex triplet, +it will be compared against each of the available colours and the +closest will be selected. The first sixteen colours are never matched in +this process due to being unpredictable. + +It isn't possible to reliably detect support for true colour in the +terminal emulator. It is therefore recommended to be selective in +loading the tt(zsh/nearcolor) module. For example, the following +checks the tt(COLORTERM) environment variable: + +example([[ $COLORTERM = *LPAR()24bit|truecolor+RPAR()* ]] || \ + zmodload zsh/nearcolor) + +Note that some terminals accept the true color escape codes but map +them internally to a more limited palette in a similar manner to the +tt(zsh/nearcolor) module. diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 895c5c570..fe4e5bd04 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -2703,8 +2703,9 @@ this to appear with other types of highlighting; it is used to override a default. ) item(tt(fg=)var(colour))( -The foreground colour should be set to var(colour), a decimal integer -or the name of one of the eight most widely-supported colours. +The foreground colour should be set to var(colour), a decimal integer, +the name of one of the eight most widely-supported colours or as a +`tt(#)' followed by an RGB triplet in hexadecimal format. Not all terminals support this and, of those that do, not all provide facilities to test the support, hence the user should decide based on the @@ -2721,6 +2722,15 @@ Co)'; if this succeeds, it indicates a limit on the number of colours which will be enforced by the line editor. The number of colours is in any case limited to 256 (i.e. the range 0 to 255). +Some modern terminal emulators have support for 24-bit true colour (16 +million colours). In this case, the hex triplet format can be used. This +consists of either a three or six digit hexadecimal number describing +the red, green and blue components of the colour. Hex triplets can also +be used with 88 and 256 colour terminals via the tt(zsh/nearcolor) +module (see ifzman(zmanref(zshmodules))\ +ifnzman(noderef(The zsh/nearcolor Module))\ +). + Colour is also known as color. ) item(tt(bg=)var(colour))( diff --git a/NEWS b/NEWS index f3e617b9c..0b0c0e84c 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,15 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH Note also the list of incompatibilities in the README file. +Changes since 5.6.2 +------------------- + +Support for 24-bit true color terminals has been added. Hex triplets +can be used when specifying colours for prompts and line editor +highlighting. On 88 and 256 colour terminals, a new zsh/nearcolor module +allows colours specified with hex triplets to be matched against the +nearest available colour. + Changes from 5.6.1 to 5.6.2 --------------------------- -- cgit v1.2.3 From 6529d52506bb71e0a70970f8a3555eb85b2a5b41 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 7 Nov 2018 12:36:05 +0000 Subject: 43788: clarify zpty -w -n with no string argument --- ChangeLog | 5 +++++ Doc/Zsh/mod_zpty.yo | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index 59ca5a8e9..88a4dac0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-11-07 Peter Stephenson + + * 43788: Doc/Zsh/mod_zpty.yo: make it clear -n option to + zpty -w is irrelevant if no string argument. + 2018-11-07 Jun-ichi Takimoto * 43761: Completion/BSD/Type/_file_flags, diff --git a/Doc/Zsh/mod_zpty.yo b/Doc/Zsh/mod_zpty.yo index 44b375a3c..6f20c4b75 100644 --- a/Doc/Zsh/mod_zpty.yo +++ b/Doc/Zsh/mod_zpty.yo @@ -41,7 +41,8 @@ em(not) given, a newline is added at the end. If no var(string) is provided, the standard input is copied to the pseudo-terminal; this may stop before copying the full input if the -pseudo-terminal is non-blocking. +pseudo-terminal is non-blocking. The exact input is always copied: +the tt(-n) option is not applied. Note that the command under the pseudo-terminal sees this input as if it were typed, so beware when sending special tty driver characters such as -- cgit v1.2.3 From 5ad76492af8931added1ae9600309d915d1427a5 Mon Sep 17 00:00:00 2001 From: dana Date: Tue, 13 Nov 2018 13:01:01 -0600 Subject: 43800: Add nanosecond support to strftime built-in --- ChangeLog | 5 ++++ Doc/Zsh/mod_datetime.yo | 8 +++++-- Src/Modules/datetime.c | 64 +++++++++++++++++++++++++++++++++++-------------- Test/V09datetime.ztst | 29 ++++++++++++++++++++++ 4 files changed, 86 insertions(+), 20 deletions(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index 7e69c5841..4cba03c71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-11-13 dana + + * 43800: Doc/Zsh/mod_datetime.yo, Src/Modules/datetime.c, + Test/V09datetime.ztst: Add nanosecond support to strftime built-in + 2018-11-12 Oliver Kiddle * 43819: Completion/Unix/Command/_adb: expand adb completion to diff --git a/Doc/Zsh/mod_datetime.yo b/Doc/Zsh/mod_datetime.yo index 27bc78157..da65a9bbd 100644 --- a/Doc/Zsh/mod_datetime.yo +++ b/Doc/Zsh/mod_datetime.yo @@ -6,9 +6,13 @@ 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) ) +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) )( -Output the date denoted by var(epochtime) in the var(format) specified. +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 +additionally be used to specify the number of nanoseconds past the second +(otherwise that number is assumed to be 0). See manref(strftime)(3) for details. The zsh extensions described in ifzman(the section EXPANSION OF PROMPT SEQUENCES in zmanref(zshmisc))\ ifnzman(noderef(Prompt Expansion)) are also available. diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c index be378b347..18c7fb58e 100644 --- a/Src/Modules/datetime.c +++ b/Src/Modules/datetime.c @@ -100,8 +100,8 @@ output_strftime(char *nam, char **argv, Options ops, UNUSED(int func)) { int bufsize, x, len; char *endptr = NULL, *scalar = NULL, *buffer; - time_t secs; - struct tm *t; + struct tm *tm; + struct timespec ts; if (OPT_ISSET(ops,'s')) { scalar = OPT_ARG(ops, 's'); @@ -110,30 +110,58 @@ output_strftime(char *nam, char **argv, Options ops, UNUSED(int func)) return 1; } } - if (OPT_ISSET(ops, 'r')) + if (OPT_ISSET(ops, 'r')) { + if (!argv[1]) { + zwarnnam(nam, "timestring expected"); + return 1; + } return reverse_strftime(nam, argv, scalar, OPT_ISSET(ops, 'q')); - - errno = 0; - secs = (time_t)strtoul(argv[1], &endptr, 10); - if (errno != 0) { - zwarnnam(nam, "%s: %e", argv[1], errno); - return 1; - } else if (*endptr != '\0') { - zwarnnam(nam, "%s: invalid decimal number", argv[1]); - return 1; } - t = localtime(&secs); - if (!t) { - zwarnnam(nam, "%s: unable to convert to time", argv[1]); - return 1; + if (!argv[1]) { + zgettime(&ts); + tm = localtime(&ts.tv_sec); + } else { + errno = 0; + + ts.tv_sec = (time_t)strtoul(argv[1], &endptr, 10); + if (errno != 0) { + zwarnnam(nam, "%s: %e", argv[1], errno); + return 1; + } else if (*argv[1] == '\0' || *endptr != '\0') { + zwarnnam(nam, "%s: invalid decimal number", argv[1]); + return 1; + } + + tm = localtime(&ts.tv_sec); + if (!tm) { + zwarnnam(nam, "%s: unable to convert to time", argv[1]); + return 1; + } + + ts.tv_nsec = 0L; + if (argv[2]) { + ts.tv_nsec = (long)zstrtol(argv[2], &endptr, 10); + if (errno != 0) { + zwarnnam(nam, "%s: %e", argv[2], errno); + return 1; + } else if (*argv[2] == '\0' || *endptr != '\0') { + zwarnnam(nam, "%s: invalid decimal number", argv[2]); + return 1; + } else if (ts.tv_nsec < 0) { + zwarnnam(nam, "%s: invalid nanosecond value", argv[2]); + return 1; + } + } } + bufsize = strlen(argv[0]) * 8; buffer = zalloc(bufsize); len = 0; for (x=0; x < 4; x++) { - if ((len = ztrftime(buffer, bufsize, argv[0], t, 0L)) >= 0 || x==3) + if ((len = ztrftime(buffer, bufsize, argv[0], tm, ts.tv_nsec)) >= 0 || + x==3) break; buffer = zrealloc(buffer, bufsize *= 2); } @@ -207,7 +235,7 @@ getcurrenttime(UNUSED(Param pm)) } static struct builtin bintab[] = { - BUILTIN("strftime", 0, bin_strftime, 2, 2, 0, "qrs:", NULL), + BUILTIN("strftime", 0, bin_strftime, 1, 3, 0, "qrs:", NULL), }; static const struct gsu_integer epochseconds_gsu = diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst index ffad96c04..22d560750 100644 --- a/Test/V09datetime.ztst +++ b/Test/V09datetime.ztst @@ -82,3 +82,32 @@ # The result can be '%@' (Linux), '@' (BSDs) or an error (Cygwin). [[ $(strftime '%@' 0 2> /dev/null) == (%|)@ || $? != 0 ]] 0:bad format specifier + +# This test may fail at 23:59:59.xxx on New Year's Eve :/ + [[ "$( strftime '%Y' )" == "$( strftime '%Y' "$EPOCHSECONDS" )" ]] +0:epochtime optional + + strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 + strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 0 + strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 2 + strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 $(( 222 * (10 ** 9) )) +0:optional nanoseconds +>2002-02-02 02:02:02.000 +>2002-02-02 02:02:02.000 +>2002-02-02 02:02:02.000 +>2002-02-02 02:02:02.222 + + strftime '%Y' '' 2> /dev/null +1:empty epochtime not allowed + + strftime '%Y' 1012615322 '' 2> /dev/null +1:empty nanoseconds not allowed + + strftime '%N' 1012615322 ${(l<64><9>):-} 2> /dev/null +1:overflowed nanoseconds not allowed + + strftime '%N' 1012615322 -1 2> /dev/null +1:negative nanoseconds not allowed + + strftime -r '%Y' 2> /dev/null +1:-r timestring not optional -- cgit v1.2.3 From 7292c063e8fe38c9212bfb47880934effc052ae1 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 14 Nov 2018 14:22:10 +0000 Subject: 43620: More care documenting command substitution including $(<...) --- ChangeLog | 5 +++++ Doc/Zsh/expn.yo | 13 ++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index 26068c16d..d07a9dff3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-11-14 Peter Stephenson + + * 43620: Doc/Zsh/expn.yo: more care documenting command + substituion including $(<...). + 2018-11-13 dana * 43809: Completion/Unix/Command/_npm: Suppress npm update checks diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index c79109700..a212d742d 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1683,10 +1683,17 @@ any trailing newlines deleted. If the substitution is not enclosed in double quotes, the output is broken into words using the tt(IFS) parameter. vindex(IFS, use of) + The substitution `tt($LPAR()cat) var(foo)tt(RPAR())' may be replaced -by the equivalent but faster `tt($LPAR()<)var(foo)tt(RPAR())'. -In either case, if the option tt(GLOB_SUBST) is set, -the output is eligible for filename generation. +by the faster `tt($LPAR()<)var(foo)tt(RPAR())'. In this case var(foo) +undergoes single word shell expansions (em(parameter expansion), +em(command substitution) and em(arithmetic expansion)), but not +filename generation. + +If the option tt(GLOB_SUBST) is set, the result of any unquoted command +substitution, including the special form just mentioned, is eligible for +filename generation. + texinode(Arithmetic Expansion)(Brace Expansion)(Command Substitution)(Expansion) sect(Arithmetic Expansion) cindex(arithmetic expansion) -- cgit v1.2.3 From 552ebe6082407b2cd3b9c9434394bad46fc59154 Mon Sep 17 00:00:00 2001 From: Joey Pabalinas Date: Mon, 17 Dec 2018 00:54:24 -1000 Subject: 43904 (plus tweak): zshmisc(1): document term being optional if `in word' is omitted In code such as: > hobbes% () { for arg do print -r $arg; done; } 1 2 3 > 1 > 2 > 3 the implicit positional parameters added when the `in word ...' list is omitted also implicitly append the separator term, making the above code valid, albeit seemingly violating the syntax listed in the documentation. This is related to the various forms of alternative syntax and is the intended behavior of the parsing code, so correct the minor contradiction in the for loop documentation. --- ChangeLog | 5 +++++ Doc/Zsh/grammar.yo | 9 ++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'Doc/Zsh') diff --git a/ChangeLog b/ChangeLog index 976924c04..3c0aabc40 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-12-17 Joey Pabalinas + + * 43904 (plus tweak): Doc/Zsh/grammar.yo: zshmisc(1): document + term being optional if `in word' is omitted + 2018-12-14 dana * unposted: Completion/Unix/Command/_dig: Fix _arguments syntax diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index d2c7cd29c..d30c9d2d7 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -183,12 +183,15 @@ findex(for) cindex(for loops) cindex(loops, for) item(tt(for) var(name) ... [ tt(in) var(word) ... ] var(term) tt(do) var(list) tt(done))( -where var(term) is at least one newline or tt(;). Expand the list of var(word)s, and set the parameter -var(name) to each of them in turn, executing -var(list) each time. If the tt(in) var(word) is omitted, +var(name) to each of them in turn, executing var(list) +each time. If the `tt(in) var(word)' is omitted, use the positional parameters instead of the var(word)s. +The var(term) consists of one or more newline or tt(;) +which terminate the var(word)s, and are optional when the +`tt(in) var(word)' is omitted. + More than one parameter var(name) can appear before the list of var(word)s. If var(N) var(name)s are given, then on each execution of the loop the next var(N) var(word)s are assigned to the corresponding -- cgit v1.2.3