diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Completion/Zsh/Command/_print | 17 | ||||
-rw-r--r-- | Completion/Zsh/Type/_globquals | 3 | ||||
-rw-r--r-- | Doc/Zsh/builtins.yo | 4 | ||||
-rw-r--r-- | Src/builtin.c | 51 | ||||
-rw-r--r-- | Test/B03print.ztst | 6 |
6 files changed, 66 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog index d1ac1cd45..1ebcc3725 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2016-11-04 Oliver Kiddle <opk@zsh.org> + + * 39389: Src/builtin.c, Test/B03print.ztst, Doc/Zsh/builtins.yo, + Completion/Zsh/Type/_globquals, Completion/Zsh/Command/_print: + when printf -v is used with an array use separate elements each + time the format is reused + 2016-11-04 Daniel Shahaf <d.s@daniel.shahaf.name> * users/22080: Doc/Zsh/zle.yo: bracketed-paste: Third time's diff --git a/Completion/Zsh/Command/_print b/Completion/Zsh/Command/_print index 38f17ab8e..8df094107 100644 --- a/Completion/Zsh/Command/_print +++ b/Completion/Zsh/Command/_print @@ -1,15 +1,18 @@ #compdef print printf -local state expl line eflag pflag rest ret=1 +local state expl line eflag pflag rflag rest ret=1 if [[ $service = print ]]; then # -e flag available only after -R eflag="${words[1,CURRENT-1][(r)-*R*]:+-e[enable escapes]}" + rflag='-r[ignore escape conventions of echo]' # -p flag only relevant if we have a coprocess (:>&p) 2>/dev/null && pflag='(-s -u -z)-p[print arguments to input of coprocess]' + [[ -n ${words[(r)-*f]} ]] && rflag='-r[disable reuse of format string]' + if [[ -n ${words[1,CURRENT][(r)-*P*]} ]]; then rest='*: :->prompt' else @@ -17,11 +20,11 @@ if [[ $service = print ]]; then fi _arguments -C -s -A "-*" -S \ - '(-f)-r[ignore escape conventions of echo]' \ + '-r[ignore escape conventions of echo]' \ '(-r -b -f -m -s -l -N -o -O -i -c -u -p -z -D -P)-R[emulate BSD echo (no escapes, -n & -e flags only)]' \ '-b[recognise bindkey escape sequences]' \ - '-m[remove arguments matching specified pattern]' \ - '(-r -n -R -l -N -c)-f+[print arguments as for the printf builtin]:format:->printfformat' \ + '-m[remove arguments not matching specified pattern]:pattern' \ + '(-n -R -l -N -c)-f+[print arguments as for the printf builtin]:format:->printfformat' \ '(-u -p -z)-s[place results in the history list]' \ '(-c -f)-n[do not add a newline to the result]' \ '(-N -c -f)-l[print arguments separated by newlines]' \ @@ -33,11 +36,13 @@ if [[ $service = print ]]; then '(-n -l -N -f -C -s -z)-c[print arguments in columns]' \ '(-n -l -N -f -c -s -z)-C+[print arguments in specified number of columns]:columns' \ '(-s -p -z)-u+[specify file descriptor to print arguments to]:file descriptor:_file_descriptors' \ - '-v[store output in named parameter]:parameter:_parameters' \ + '(-s -z -p -u)-v[store output in named parameter]:parameter:_parameters' \ '(-s -p -u)-z[push arguments onto editing buffer stack]' \ '-D[substitute any arguments which are named directories using ~ notation]' \ '-P[perform prompt expansion]' \ - $pflag $eflag $rest && ret=0 + '(-X -f -a -C -c -z)-x+[expand leading tabs]:tab width' \ + '(-x -f -a -C -c -z)-X+[expand all tabs]:tab width' \ + $pflag $eflag $rflag $rest && ret=0 elif [[ $service = printf ]]; then state=printf fi diff --git a/Completion/Zsh/Type/_globquals b/Completion/Zsh/Type/_globquals index 6eef16877..a904bdf0d 100644 --- a/Completion/Zsh/Type/_globquals +++ b/Completion/Zsh/Type/_globquals @@ -121,8 +121,7 @@ while [[ -n $PREFIX ]]; do tmatch=( s m h d w M ) if zstyle -t ":completion:${curcontext}:time-specifiers" verbose; then zstyle -s ":completion:${curcontext}:time-specifiers" list-separator sep || sep=-- - print -v tdisp -f "%s ${sep//(#m)[%\\]/$MATCH$MATCH} %s\0" ${tmatch:^^tdisp} - tdisp=( ${(0)tdisp} ) + print -v tdisp -f "%s ${sep//(#m)[%\\]/$MATCH$MATCH} %s" ${tmatch:^^tdisp} fi alts+=( "time-specifiers:time specifier:compadd -E 0 -d tdisp -S '' -a tmatch" ) fi diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index dfbbaa034..169a31ea3 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -1289,7 +1289,9 @@ required by the format than have been specified, the behaviour is as if zero or an empty string had been specified as the argument. The tt(-v) option causes the output to be stored as the value of the -parameter var(name), instead of printed. +parameter var(name), instead of printed. If var(name) is an array and +the format string is reused when consuming arguments then one +array element will be used for each use of the format string. ) findex(pushd) pindex(PUSHD_TO_HOME, use of) diff --git a/Src/builtin.c b/Src/builtin.c index 986ace238..083a3aeb3 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -4087,10 +4087,11 @@ bin_print(char *name, char **args, Options ops, int func) { int flen, width, prec, type, argc, n, narg, curlen = 0; int nnl = 0, fmttrunc = 0, ret = 0, maxarg = 0, nc = 0; - int flags[6], *len; + int flags[6], *len, visarr = 0; char *start, *endptr, *c, *d, *flag, *buf = NULL, spec[14], *fmt = NULL; char **first, **argp, *curarg, *flagch = "'0+- #", save = '\0', nullstr = '\0'; size_t rcount = 0, count = 0; + size_t *cursplit, *splits = 0; FILE *fout = stdout; #ifdef HAVE_OPEN_MEMSTREAM size_t mcount; @@ -4122,7 +4123,7 @@ bin_print(char *name, char **args, Options ops, int func) return 1; \ } \ unlink(tmpf); \ - if ((fout = fdopen(tempfd, "w+")) == NULL) { \ + if ((FOUT = fdopen(tempfd, "w+")) == NULL) { \ close(tempfd); \ zwarnnam(name, "can't open temp file: %e", errno); \ return 1; \ @@ -4647,11 +4648,23 @@ bin_print(char *name, char **args, Options ops, int func) * special cases of printing to a ZLE buffer or the history, however. */ + if (OPT_ISSET(ops,'v')) { + struct value vbuf; + char* s = OPT_ARG(ops,'v'); + Value v = getvalue(&vbuf, &s, 0); + visarr = v && PM_TYPE(v->pm->node.flags) == PM_ARRAY; + } /* printf style output */ *spec = '%'; argp = args; do { rcount = count; + if (argp > args && visarr) { /* reusing format string */ + if (!splits) + cursplit = splits = (size_t *)zhalloc(sizeof(size_t) * + (arrlen(args) / (argp - args) + 1)); + *cursplit++ = count; + } if (maxarg) { first += maxarg; argc -= maxarg; @@ -5019,18 +5032,30 @@ bin_print(char *name, char **args, Options ops, int func) if (buf) free(buf); } else { - stringval = metafy(buf, rcount, META_REALLOC); - if (OPT_ISSET(ops,'z')) { - zpushnode(bufstack, stringval); - } else if (OPT_ISSET(ops,'v')) { - setsparam(OPT_ARG(ops, 'v'), stringval); + if (visarr) { + char **arrayval = zshcalloc((cursplit - splits + 2) * sizeof(char *)); + for (;cursplit >= splits; cursplit--) { + int start = cursplit == splits ? 0 : cursplit[-1]; + arrayval[cursplit - splits] = + metafy(buf + start, count - start, META_DUP); + count = start; + } + setaparam(OPT_ARG(ops, 'v'), arrayval); + free(buf); } else { - ent = prepnexthistent(); - ent->node.nam = stringval; - ent->stim = ent->ftim = time(NULL); - ent->node.flags = 0; - ent->words = (short *)NULL; - addhistnode(histtab, ent->node.nam, ent); + stringval = metafy(buf, rcount, META_REALLOC); + if (OPT_ISSET(ops,'z')) { + zpushnode(bufstack, stringval); + } else if (OPT_ISSET(ops,'v')) { + setsparam(OPT_ARG(ops, 'v'), stringval); + } else { + ent = prepnexthistent(); + ent->node.nam = stringval; + ent->stim = ent->ftim = time(NULL); + ent->node.flags = 0; + ent->words = (short *)NULL; + addhistnode(histtab, ent->node.nam, ent); + } } } unqueue_signals(); diff --git a/Test/B03print.ztst b/Test/B03print.ztst index a4431cbc8..6ee2a09c6 100644 --- a/Test/B03print.ztst +++ b/Test/B03print.ztst @@ -310,3 +310,9 @@ 0:print and printf into a variable >typeset -g foo='once more' >typeset -g foo=$'into\C-@the-breach\C-@-' + + typeset -a foo + print -f '%2$d %4s' -v foo one 1 two 2 three 3 + typeset -p foo +0:printf into an array variable +>typeset -a foo=( '1 one' '2 two' '3 three' ) |