From 560a23033d2d0e029bbbcda0366053d8d87a37d9 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 11 Sep 2015 21:23:21 +0100 Subject: unposted: update internal build string to 5.1.1-dev-0 --- ChangeLog | 3 +++ Config/version.mk | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 83db49234..06427e7a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-09-11 Peter Stephenson + * unposted: Config/version.mk: Update internal build to + 5.1.1-dev-0 + * unposted: Config/version.mk: 5.1.1 * Sebastian Gniazdowski: 36489: Src/Modules/curses.c: fix bug diff --git a/Config/version.mk b/Config/version.mk index 21577997b..7ec276df2 100644 --- a/Config/version.mk +++ b/Config/version.mk @@ -27,5 +27,5 @@ # This must also serve as a shell script, so do not add spaces around the # `=' signs. -VERSION=5.1.1 +VERSION=5.1.1-dev-0 VERSION_DATE='September 11, 2015' -- cgit v1.2.3 From e1c0a947cc845c71dd844db44016d07922cfcefa Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 11 Sep 2015 21:40:45 +0100 Subject: Read full multibyte string early for self-insert --- ChangeLog | 5 +++++ Src/Zle/zle_hist.c | 4 ++-- Src/Zle/zle_keymap.c | 37 +++++++++++++++++++++++++++++-------- Src/Zle/zle_main.c | 10 ++++++++-- Src/Zle/zle_misc.c | 6 ++---- Src/Zle/zle_vi.c | 2 +- 6 files changed, 47 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 06427e7a9..914ee4e47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2015-09-11 Peter Stephenson + * 36496 (plus tweak for key buffer length): Src/Zle/zle_hist.c, + Src/Zle/zle_keymap.c, Src/Zle/zle_main.c, Src/Zle/zle_misc.c, + Src/Zle/zle_vi.c: Read full multibyte string early for + self-insert. + * unposted: Config/version.mk: Update internal build to 5.1.1-dev-0 diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index c61b4ef0e..0cff0391a 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -1643,7 +1643,7 @@ doisearch(char **args, int dir, int pattern) } else if (cmd == Th(z_selfinsert)) { #ifdef MULTIBYTE_SUPPORT if (!lastchar_wide_valid) - if (getrestchar(lastchar) == WEOF) { + if (getrestchar(lastchar, NULL, NULL) == WEOF) { handlefeep(zlenoargs); continue; } @@ -1877,7 +1877,7 @@ getvisrchstr(void) } else { #ifdef MULTIBYTE_SUPPORT if (!lastchar_wide_valid) - if (getrestchar(lastchar) == WEOF) { + if (getrestchar(lastchar, NULL, NULL) == WEOF) { handlefeep(zlenoargs); continue; } diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index 5b4189faa..069580f8a 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -1501,6 +1501,20 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp) * they wait till a key is pressed for the movement anyway */ timeout = !(!virangeflag && !region_active && f && f->widget && f->widget->flags & ZLE_VIOPER); +#ifdef MULTIBYTE_SUPPORT + if ((f == Th(z_selfinsert) || f == Th(z_selfinsertunmeta)) && + !lastchar_wide_valid) { + int len; + VARARR(char, mbc, MB_CUR_MAX); + ZLE_INT_T inchar = getrestchar(lastchar, mbc, &len); + if (inchar != WEOF && len) { + char *ptr = mbc; + while (len--) + addkeybuf(STOUC(*ptr++)); + lastlen = keybuflen; + } + } +#endif } if (!ispfx) break; @@ -1521,6 +1535,20 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp) return keybuf; } +/**/ +static void +addkeybuf(int c) +{ + if(keybuflen + 3 > keybufsz) + keybuf = realloc(keybuf, keybufsz *= 2); + if(imeta(c)) { + keybuf[keybuflen++] = Meta; + keybuf[keybuflen++] = c ^ 32; + } else + keybuf[keybuflen++] = c; + keybuf[keybuflen] = 0; +} + /* * Add a (possibly metafied) byte to the key input so far. * This handles individual bytes of a multibyte string separately; @@ -1542,14 +1570,7 @@ getkeybuf(int w) if(c < 0) return EOF; - if(keybuflen + 3 > keybufsz) - keybuf = realloc(keybuf, keybufsz *= 2); - if(imeta(c)) { - keybuf[keybuflen++] = Meta; - keybuf[keybuflen++] = c ^ 32; - } else - keybuf[keybuflen++] = c; - keybuf[keybuflen] = 0; + addkeybuf(c); return c; } diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index ec3d2c354..992f152df 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -933,7 +933,7 @@ getfullchar(int do_keytmout) int inchar = getbyte((long)do_keytmout, NULL); #ifdef MULTIBYTE_SUPPORT - return getrestchar(inchar); + return getrestchar(inchar, NULL, NULL); #else return inchar; #endif @@ -951,7 +951,7 @@ getfullchar(int do_keytmout) /**/ mod_export ZLE_INT_T -getrestchar(int inchar) +getrestchar(int inchar, char *outstr, int *outcount) { char c = inchar; wchar_t outchar; @@ -965,6 +965,8 @@ getrestchar(int inchar) */ lastchar_wide_valid = 1; + if (outcount) + *outcount = 0; if (inchar == EOF) { /* End of input, so reset the shift state. */ memset(&mbs, 0, sizeof mbs); @@ -1013,6 +1015,10 @@ getrestchar(int inchar) return lastchar_wide = WEOF; } c = inchar; + if (outstr) { + *outstr++ = c; + (*outcount)++; + } } return lastchar_wide = (ZLE_INT_T)outchar; } diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 2d1862813..12143e05f 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -115,9 +115,7 @@ selfinsert(UNUSED(char **args)) ZLE_CHAR_T tmp; #ifdef MULTIBYTE_SUPPORT - if (!lastchar_wide_valid) - if (getrestchar(lastchar) == WEOF) - return 1; + DPUTS(!lastchar_wide_valid, "keybuf did not read full wide character"); #endif tmp = LASTFULLCHAR; doinsert(&tmp, 1); @@ -1431,7 +1429,7 @@ executenamedcommand(char *prmt) else { #ifdef MULTIBYTE_SUPPORT if (!lastchar_wide_valid) - getrestchar(lastchar); + getrestchar(lastchar, NULL, NULL); if (lastchar_wide == WEOF) feep = 1; else diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 42dc46e7e..86840bdd6 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -151,7 +151,7 @@ vigetkey(void) #ifdef MULTIBYTE_SUPPORT if (!lastchar_wide_valid) { - getrestchar(lastchar); + getrestchar(lastchar, NULL, NULL); } #endif return LASTFULLCHAR; -- cgit v1.2.3 From d37b59fe0969a619f049dee081b15af696070009 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 11 Sep 2015 21:47:53 +0000 Subject: 36443: Revert "35834: strip a final newline from pasted text: inserting is hard to tell apart from accepting it" This reverts commit f17eb26a34af69a2238a3d8b46079445e09c096e. Conflicts: ChangeLog Src/Zle/zle_misc.c --- ChangeLog | 5 +++++ Src/Zle/zle_misc.c | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 914ee4e47..a484ad7fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-09-11 Daniel Shahaf + + * 36443: Revert 35834. + 2015-09-11 Peter Stephenson * 36496 (plus tweak for key buffer length): Src/Zle/zle_hist.c, @@ -438,6 +442,7 @@ * 35834 (tweaked): Src/Zle/zle_misc.c: strip a final newline from pasted text: inserting is hard to tell apart from accepting it + [reverted in 36443] 2015-08-12 Mikael Magnusson diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 12143e05f..297dc4ca8 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -785,12 +785,6 @@ bracketedpaste(char **args) zmult = 1; if (region_active) killregion(zlenoargs); - /* Chop a final newline if its insertion would be hard to - * distinguish by the user from the line being accepted. */ - else if (n > 1 && zlecontext != ZLCON_VARED && - (zlecs + (insmode ? 0 : n - 1)) >= zlell && - wpaste[n-1] == ZWC('\n')) - n--; yankcs = yankb = zlecs; doinsert(wpaste, n); yanke = zlecs; -- cgit v1.2.3 From c76f4f96a65c7bfbba2183c422a1fb567069981f Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 7 Sep 2015 15:50:26 +0000 Subject: 36443: Set zle_highlight=(paste:standout) by default. --- ChangeLog | 3 +++ Doc/Zsh/zle.yo | 2 +- Src/Zle/zle_refresh.c | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index a484ad7fc..aedeaed4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-09-11 Daniel Shahaf + * 36443: Doc/Zsh/zle.yo Src/Zle/zle_refresh.c: Set + zle_highlight=(paste:standout) by default. + * 36443: Revert 35834. 2015-09-11 Peter Stephenson diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 2c539c460..71a7af0d7 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -2679,7 +2679,7 @@ If tt(zle_highlight) is not set or no value applies to a particular context, the defaults applied are equivalent to example(zle_highlight=LPAR()region:standout special:standout -suffix:bold isearch:underline+RPAR()) +suffix:bold isearch:underline paste:standout+RPAR()) i.e. both the region and special characters are shown in standout mode. diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index 0c28c0a2d..6facff429 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -372,7 +372,8 @@ zle_set_highlight(void) region_highlights[1].atr = TXTUNDERLINE; if (!suffix_atr_on_set) region_highlights[2].atr = TXTBOLDFACE; - /* paste defaults to 0 */ + if (!paste_atr_on_set) + region_highlights[3].atr = TXTSTANDOUT; allocate_colour_buffer(); } -- cgit v1.2.3 From 8b1676e3b7bca183fea725d38d62350d2688078b Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Sat, 12 Sep 2015 20:35:56 +0900 Subject: 36491: Multibyte support for parameter expansion flags B,E,N --- ChangeLog | 5 +++++ Src/glob.c | 6 +++--- Test/D07multibyte.ztst | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index aedeaed4c..c70396dd4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-12 Jun-ichi Takimoto + + * 36491: Src/glob.c, Test/D07multibyte.ztst: Multibyte + support for the parameter expansion flags B, E and N. + 2015-09-11 Daniel Shahaf * 36443: Doc/Zsh/zle.yo Src/Zle/zle_refresh.c: Set diff --git a/Src/glob.c b/Src/glob.c index dea1bf50e..43d135b99 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2491,17 +2491,17 @@ get_match_ret(char *s, int b, int e, int fl, char *replstr, ll += 1 + (l - (e - b)); if (fl & SUB_BIND) { /* position of start of matched portion */ - sprintf(buf, "%d ", b + 1); + sprintf(buf, "%d ", MB_METASTRLEN2END(s, 0, s+b) + 1); ll += (bl = strlen(buf)); } if (fl & SUB_EIND) { /* position of end of matched portion */ - sprintf(buf + bl, "%d ", e + 1); + sprintf(buf + bl, "%d ", MB_METASTRLEN2END(s, 0, s+e) + 1); ll += (bl = strlen(buf)); } if (fl & SUB_LEN) { /* length of matched portion */ - sprintf(buf + bl, "%d ", e - b); + sprintf(buf + bl, "%d ", MB_METASTRLEN2END(s+b, 0, s+e)); ll += (bl = strlen(buf)); } if (bl) diff --git a/Test/D07multibyte.ztst b/Test/D07multibyte.ztst index ace191f06..5ae9b2c12 100644 --- a/Test/D07multibyte.ztst +++ b/Test/D07multibyte.ztst @@ -293,6 +293,21 @@ >Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ ἦν ὁ λόγος >Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ + a="1ë34ë6" + print ${(BEN)a#*4} + print ${(BEN)a##*ë} + print ${(BEN)a%4*} + print ${(BEN)a%%ë*} + print ${(SBEN)a#ë3} + print ${(SBEN)a%4ë} +0:Flags B, E, N and S in ${...#...} and ${...%...} +>1 5 4 +>1 6 5 +>4 7 3 +>2 7 5 +>2 4 2 +>4 6 2 + foo=(κατέβην χθὲς εἰς Πειραιᾶ) print ${(l.3..¥.r.3..£.)foo} print ${(l.4..¥.r.2..£.)foo} -- cgit v1.2.3 From 6ff0628182ac74bbf22dc02edcc9a148f12767db Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 12 Sep 2015 09:53:39 -0700 Subject: 36509: allocate hash table nodes with zshcalloc() to avoid garbage flag values --- ChangeLog | 5 +++++ Src/Modules/curses.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c70396dd4..3aa4f208a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-12 Barton E. Schaefer + + * 36509: Src/Modules/curses.c: allocate hash table nodes with + zshcalloc() to avoid garbage flag values + 2015-09-12 Jun-ichi Takimoto * 36491: Src/glob.c, Test/D07multibyte.ztst: Multibyte diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c index 0054aef52..64329f643 100644 --- a/Src/Modules/curses.c +++ b/Src/Modules/curses.c @@ -370,7 +370,7 @@ zcurses_colorget(const char *nam, char *colorpair) return NULL; } - cpn = (Colorpairnode)zalloc(sizeof(struct colorpairnode)); + cpn = (Colorpairnode)zshcalloc(sizeof(struct colorpairnode)); if (!cpn) { zsfree(cp); @@ -462,7 +462,7 @@ zccmd_init(const char *nam, char **args) use_default_colors(); #endif /* Initialise the default color pair, always 0 */ - cpn = (Colorpairnode)zalloc(sizeof(struct colorpairnode)); + cpn = (Colorpairnode)zshcalloc(sizeof(struct colorpairnode)); if (cpn) { cpn->colorpair = 0; addhashnode(zcurses_colorpairs, -- cgit v1.2.3 From 8e77fcb050ed09042cc2464f804ac023c0f88b42 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 12 Sep 2015 16:13:01 -0700 Subject: 36522: unmetafy the argument of "zle -U" --- ChangeLog | 2 ++ Src/Zle/zle_thingy.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3aa4f208a..1ce47d7f1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-09-12 Barton E. Schaefer + * 36522: Src/Zle/zle_thingy.c: unmetafy the argument of "zle -U" + * 36509: Src/Modules/curses.c: allocate hash table nodes with zshcalloc() to avoid garbage flag values diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index 7fd3a5941..da3a6d458 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -466,7 +466,7 @@ bin_zle_mesg(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) static int bin_zle_unget(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) { - char *b = *args, *p = b + strlen(b); + char *b = unmeta(*args), *p = b + strlen(b); if (!zleactive) { zwarnnam(name, "can only be called from widget function"); -- cgit v1.2.3 From b957cdd21a8997739aba48c3637fc3b9f88b2168 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 12 Sep 2015 17:16:43 -0700 Subject: unposted: revert 36483 as multibyte is now handled by "zle .read-command"; adapt to new default behavior of zle_highlight for paste --- ChangeLog | 4 ++++ Functions/Zle/bracketed-paste-magic | 18 +++++------------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1ce47d7f1..53772e565 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-09-12 Barton E. Schaefer + * unposted: Functions/Zle/bracketed-paste-magic: revert 36483 as + multibyte is now handled by "zle .read-command"; adapt to new + default behavior of zle_highlight for paste + * 36522: Src/Zle/zle_thingy.c: unmetafy the argument of "zle -U" * 36509: Src/Modules/curses.c: allocate hash table nodes with diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index 464c6b339..cd4a7085b 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -164,25 +164,17 @@ bracketed-paste-magic() { integer bpm_limit=$UNDO_LIMIT_NO bpm_undo=$UNDO_CHANGE_NO UNDO_LIMIT_NO=$UNDO_CHANGE_NO - local mbchar - integer ismb while [[ -n $PASTED ]] && zle .read-command; do - mbchar=$KEYS - ismb=0 - while [[ $mbchar = [[:INCOMPLETE:]]* ]] && zle .read-command; do - mbchar+=$KEYS - ismb=1 - done - PASTED=${PASTED#$mbchar} - if [[ ismb -ne 0 || $mbchar = ${(~j:|:)${(b)bpm_inactive}} ]]; then - LBUFFER+=$mbchar + PASTED=${PASTED#$KEYS} + if [[ $KEYS = ${(~j:|:)${(b)bpm_inactive}} ]]; then + zle .self-insert-unmeta else case $REPLY in (${~bpm_active}) function () { emulate -L $bpm_emulate; set -$bpm_opts zle $REPLY };; - (*) LBUFFER+=$mbchar; + (*) zle .self-insert-unmeta;; esac fi done @@ -221,7 +213,7 @@ bracketed-paste-magic() { zle .split-undo # Arrange to display highlighting if necessary - if [[ -n ${(M)zle_highlight:#paste:*} ]]; then + if [[ -z $zle_highlight || -n ${(M)zle_highlight:#paste:*} ]]; then zle -R zle .read-command && zle -U - $KEYS fi -- cgit v1.2.3 From 9cb8c3f4b5d9918028791d975cf3aa7d745b4b22 Mon Sep 17 00:00:00 2001 From: Axel Beckert Date: Sun, 13 Sep 2015 02:02:59 +0200 Subject: 36523: Completion/…/_gphoto2: Replace --delete-files with --delete-file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog | 5 +++++ Completion/Unix/Command/_gphoto2 | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 53772e565..db594cc5d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-13 Axel Beckert + + * 36523: Thue Janus Kristensen: Completion/Unix/Command/_gphoto2: + Replace --delete-files with --delete-file. + 2015-09-12 Barton E. Schaefer * unposted: Functions/Zle/bracketed-paste-magic: revert 36483 as diff --git a/Completion/Unix/Command/_gphoto2 b/Completion/Unix/Command/_gphoto2 index 95d8a49b7..314d83e3a 100644 --- a/Completion/Unix/Command/_gphoto2 +++ b/Completion/Unix/Command/_gphoto2 @@ -32,7 +32,7 @@ _arguments -s \ '--get-all-raw-data[get all raw data from folder]' \ '--get-audio-data[get audio data given in range]:range' \ '--get-all-audio-data[get all audio data from folder]' \ - '--delete-files[delete files given in range]:range' \ + '--delete-file[delete files given in range]:range' \ '--delete-all-files[delete all files in folder]' \ '(-u --upload-file)'{-u,--upload-file}'[upload a file to camera]:file:_files' \ '--capture-preview[capture a quick preview]' \ -- cgit v1.2.3 From 8a818381cfa843f6bdc25e3517500da31d63c282 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 12 Sep 2015 20:49:13 -0700 Subject: 36525: revert only the selfinsert() bit of 36496 selfinsert() may be called with incomplete wide character processing from places other than getkeymapcmd() --- ChangeLog | 4 ++++ Src/Zle/zle_misc.c | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index db594cc5d..79fb2c779 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,10 @@ 2015-09-12 Barton E. Schaefer + * 36525: Src/Zle/zle_misc.c: revert only the selfinsert() bit of + 36496 because selfinsert() may be called with incomplete wide + character processing from places other than getkeymapcmd() + * unposted: Functions/Zle/bracketed-paste-magic: revert 36483 as multibyte is now handled by "zle .read-command"; adapt to new default behavior of zle_highlight for paste diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 297dc4ca8..0483f758d 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -115,7 +115,10 @@ selfinsert(UNUSED(char **args)) ZLE_CHAR_T tmp; #ifdef MULTIBYTE_SUPPORT - DPUTS(!lastchar_wide_valid, "keybuf did not read full wide character"); + /* may be redundant with getkeymapcmd(), but other widgets call here too */ + if (!lastchar_wide_valid) + if (getrestchar(lastchar, NULL, NULL) == WEOF) + return 1; #endif tmp = LASTFULLCHAR; doinsert(&tmp, 1); -- cgit v1.2.3 From aeb1ac6a9cbbf4c135dc2feedc2322e12bb7e549 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 14 Sep 2015 20:31:43 +0000 Subject: unposted (see 36526): Update changelog for 36443. --- ChangeLog | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 79fb2c779..3445b69cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,8 +25,9 @@ 2015-09-11 Daniel Shahaf - * 36443: Doc/Zsh/zle.yo Src/Zle/zle_refresh.c: Set - zle_highlight=(paste:standout) by default. + * 36443: Doc/Zsh/zle.yo Src/Zle/zle_refresh.c: + Highlight pasted/yanked text as standout by default (i.e., when + $zle_highlight doesn't specify otherwise). * 36443: Revert 35834. -- cgit v1.2.3 From 9955bbdb9faeac388abec68c6b5b976bce27df92 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 14 Sep 2015 20:32:57 +0000 Subject: unposted: docs: Typo fixes --- ChangeLog | 4 ++++ Doc/Zsh/zle.yo | 2 +- README | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3445b69cf..d1143449a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-09-14 Daniel Shahaf + + * unposted: Doc/Zsh/zle.yo README: docs: Typo fixes + 2015-09-13 Axel Beckert * 36523: Thue Janus Kristensen: Completion/Unix/Command/_gphoto2: diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 71a7af0d7..7d95eb377 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -1012,7 +1012,7 @@ xitem(tt(YANK_ACTIVE) (integer)) xitem(tt(YANK_START) (integer)) item(tt(YANK_END) (integer))( These three parameters indicate whether text has just been yanked (pasted) -into the buffer. tt(YANK_START) and tt(YANK_END) are in the same unit sas +into the buffer. tt(YANK_START) and tt(YANK_END) are in the same units as tt(CURSOR), and are only valid when tt(YANK_ACTIVE) is non-zero. All three are read-only. diff --git a/README b/README index 1ebc8cd95..4b840b5c9 100644 --- a/README +++ b/README @@ -10,7 +10,7 @@ a few visible improvements since 5.0.8 as well as many bugfixes. Note in particular the two changes highlighted under "Incompatibilites between 5.0.8 and 5.1" below. See NEWS for more information. -There are mostly bug fixes between 5.1 and 5.1.1; however, a fewer minor +There are mostly bug fixes between 5.1 and 5.1.1; however, a few minor features useful in resolving problems with shell functions were added. Installing Zsh -- cgit v1.2.3 From 18130bed7fa032513261d426b8c3915cf11e20c1 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Thu, 17 Sep 2015 21:44:14 -0700 Subject: 36552 plus test: fix Nularg string in quotestring(QT_DOLLARS) --- ChangeLog | 6 ++++++ Src/utils.c | 6 ++++++ Test/D04parameter.ztst | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index d1143449a..6e02eae27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-09-17 Barton E. Schaefer + + * unposted: Test/D04parameter.ztst: test for 36552 + + * 36552: Src/utils.c: fix Nularg string in quotestring(QT_DOLLARS) + 2015-09-14 Daniel Shahaf * unposted: Doc/Zsh/zle.yo README: docs: Typo fixes diff --git a/Src/utils.c b/Src/utils.c index ca68eae32..d5fd88c00 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -5384,6 +5384,12 @@ quotestring(const char *s, char **e, int instring) "BUG: bad quote type in quotestring"); u = s; if (instring == QT_DOLLARS) { + /* + * The only way to get Nularg here is when + * it is placeholding for the empty string? + */ + if (inull(*u)) + *u++; /* * As we test for printability here we need to be able * to look for multibyte characters. diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index c7d506a51..e380e19b8 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -413,6 +413,10 @@ >$'playing \'stupid\' "games" \\w\\i\\t\\h $quoting.' >'playing '\'stupid\'' "games" \w\i\t\h $quoting.' + print -r ${(qqqq):-""} +0:workers/36551: literal empty string in ${(qqqq)...} +>$'' + x=( a '' '\b' 'c d' '$e' ) print -r ${(q)x} print -r ${(q-)x} -- cgit v1.2.3 From 18d82a6c401758e8bd49fef9478168c68d7d2652 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Fri, 18 Sep 2015 10:10:35 -0700 Subject: cf. users/20586: clean up cross-references to the "Autoloading Functions" doc --- ChangeLog | 5 +++++ Doc/Zsh/builtins.yo | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6e02eae27..ab1b0bbf9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-18 Barton E. Schaefer + + * unposted (cf. users/20586): Doc/Zsh/builtins.yo: clean up + cross-references to the "Autoloading Functions" section. + 2015-09-17 Barton E. Schaefer * unposted: Test/D04parameter.ztst: test for 36552 diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 5bbe7e70b..67e3131cb 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -144,8 +144,12 @@ findex(autoload) cindex(functions, autoloading) cindex(autoloading functions) item(tt(autoload) [ {tt(PLUS())|tt(-)}tt(TUXkmtz) ] [ tt(-w) ] [ var(name) ... ])( +vindex(fpath, searching) Equivalent to tt(functions -u), with the exception of tt(-X)/tt(+X) and -tt(-w). +tt(-w). See the section `Autoloading Functions' in ifzman(zmanref(zshmisc))\ +ifnzman(noderef(Functions)) for full details. The tt(fpath) parameter +will be searched to find the function definition when the function is +first referenced. The flag tt(-X) may be used only inside a shell function, and may not be followed by a var(name). It causes the calling function to be marked for @@ -170,7 +174,8 @@ pattern are loaded. With the tt(-w) flag, the var(name)s are taken as names of files compiled with the tt(zcompile) builtin, and all functions defined in them are -marked for autoloading. +marked for autoloading. Note this does not otherwise change the search +order for The flags tt(-z) and tt(-k) mark the function to be autoloaded using the zsh or ksh style, as if the option tt(KSH_AUTOLOAD) were unset or were @@ -1981,12 +1986,8 @@ for this function; the flag tt(-T) does the same, but turns off tracing on any function called from the present one, unless that function also has the tt(-t) or tt(-T) flag. The tt(-u) and tt(-U) flags cause the function to be marked for autoloading; tt(-U) also causes alias -expansion to be suppressed when the function is loaded. The tt(fpath) -parameter will be searched to find the function definition when the -function is first referenced; see noderef(Functions). The tt(-k) and -tt(-z) flags make the function be loaded using ksh-style or zsh-style -autoloading respectively. If neither is given, the setting of the -tt(KSH_AUTOLOAD) option determines how the function is loaded. +expansion to be suppressed when the function is loaded. See the +description of the `tt(autoload)' builtin for details. Note that the builtin tt(functions) provides the same basic capabilities as tt(typeset -f) but gives access to a few extra options. @@ -2338,6 +2339,7 @@ noderef(Functions) for a description of how autoloaded functions are searched. The extension tt(.zwc) stands for `zsh word code'. +vindex(fpath, with zcompile) If there is at least one var(name) argument, all the named files are compiled into the output var(file) given as the first argument. If var(file) does not end in tt(.zwc), this extension is automatically -- cgit v1.2.3 From 07796811b03f58f2f143cd2860c67c9896c71acb Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 19 Sep 2015 09:34:05 -0700 Subject: cf. 36554: remove unnecessary pointer dereference --- Src/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/utils.c b/Src/utils.c index d5fd88c00..1de3d9578 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -5389,7 +5389,7 @@ quotestring(const char *s, char **e, int instring) * it is placeholding for the empty string? */ if (inull(*u)) - *u++; + u++; /* * As we test for printability here we need to be able * to look for multibyte characters. -- cgit v1.2.3 From cc44b10da1bcc4af87fb7bb0336177a31798608e Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 19 Sep 2015 20:22:19 +0100 Subject: unposted: fix typo in test --- ChangeLog | 4 ++++ Test/D07multibyte.ztst | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ab1b0bbf9..2852b4de9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-09-19 Peter Stephenson + + * unposted: Test/D07multibyte.ztst: fix typo. + 2015-09-18 Barton E. Schaefer * unposted (cf. users/20586): Doc/Zsh/builtins.yo: clean up diff --git a/Test/D07multibyte.ztst b/Test/D07multibyte.ztst index 5ae9b2c12..dff2ec12f 100644 --- a/Test/D07multibyte.ztst +++ b/Test/D07multibyte.ztst @@ -543,6 +543,6 @@ [[ $'\xe3' == [[:INCOMPLETE:]] ]] || print fail 1 [[ $'\xe3\x83' == [[:INCOMPLETE:]][[:INVALID:]] ]] || print fail 2 - [[ $'\xe3\x83\x9b' != [[:INCOMPLETE:][:NVALID:]] ]] || print fail 3 + [[ $'\xe3\x83\x9b' != [[:INCOMPLETE:][:INVALID:]] ]] || print fail 3 [[ $'\xe3\x83\x9b' = ? ]] || print fail 4 0:Testing incomplete and invalid multibyte character components -- cgit v1.2.3 From df0d86b847fbf5bd1ad383531cd52b261dc07717 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 19 Sep 2015 23:08:46 +0100 Subject: 36559: test earlier for overflow in pattern range --- ChangeLog | 3 +++ Src/pattern.c | 23 ++++++++++++++++++----- Src/zsh.h | 7 +++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2852b4de9..bb03894a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-09-19 Peter Stephenson + * 36559: Src/pattern.c: test earlier for overflow in pattern + range. + * unposted: Test/D07multibyte.ztst: fix typo. 2015-09-18 Barton E. Schaefer diff --git a/Src/pattern.c b/Src/pattern.c index 3b55ccf1c..af56bd9cc 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -220,8 +220,10 @@ typedef union upat *Upat; #if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT) typedef zlong zrange_t; #define ZRANGE_T_IS_SIGNED (1) +#define ZRANGE_MAX ZLONG_MAX #else typedef unsigned long zrange_t; +#define ZRANGE_MAX ULONG_MAX #endif #ifdef MULTIBYTE_SUPPORT @@ -2641,19 +2643,30 @@ patmatch(Upat prog) start = compend = patinput; comp = 0; while (patinput < patinend && idigit(*patinput)) { - if (comp) - comp *= 10; - comp += *patinput - '0'; + int out_of_range = 0; + int digit = *patinput - '0'; + if (comp > ZRANGE_MAX / (zlong)10) { + out_of_range = 1; + } else { + zrange_t c10 = comp ? comp * 10 : 0; + if (ZRANGE_MAX - c10 < digit) { + out_of_range = 1; + } else { + comp = c10; + comp += digit; + } + } patinput++; compend++; - if (comp & ((zrange_t)1 << (sizeof(comp)*8 - + if (out_of_range || + (comp & ((zrange_t)1 << (sizeof(comp)*8 - #ifdef ZRANGE_T_IS_SIGNED 2 #else 1 #endif - ))) { + )))) { /* * Out of range (allowing for signedness, which * we need if we are using zlongs). diff --git a/Src/zsh.h b/Src/zsh.h index 4e2cb656e..9c7e5d9dc 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -36,6 +36,12 @@ */ #ifdef ZSH_64_BIT_TYPE typedef ZSH_64_BIT_TYPE zlong; +#if defind(ZLONG_IS_LONG_LONG) && defined(LLONG_MAX) +#define ZLONG_MAX LLONG_MAX +#else +/* umm... */ +#define ZLONG_MAX ((zlong)9223372036854775807) +#endif #ifdef ZSH_64_BIT_UTYPE typedef ZSH_64_BIT_UTYPE zulong; #else @@ -44,6 +50,7 @@ typedef unsigned zlong zulong; #else typedef long zlong; typedef unsigned long zulong; +#define ZLONG_MAX LONG_MAX #endif /* -- cgit v1.2.3 From 4375d7b905dca266c3a14bf603a908eb7c3dfbf2 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 19 Sep 2015 23:03:39 -0700 Subject: 36562: sanitize $PWD on import, per POSIX --- ChangeLog | 4 ++++ Src/utils.c | 20 +++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index bb03894a0..6d99ccd81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-09-19 Barton E. Schaefer + + * 36562: Src/utils.c: sanitize $PWD on import, per POSIX + 2015-09-19 Peter Stephenson * 36559: Src/pattern.c: test earlier for overflow in pattern diff --git a/Src/utils.c b/Src/utils.c index 1de3d9578..ab3b0c274 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -692,9 +692,23 @@ ispwd(char *s) { struct stat sbuf, tbuf; - if (stat(unmeta(s), &sbuf) == 0 && stat(".", &tbuf) == 0) - if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino) - return 1; + /* POSIX: environment PWD must be absolute */ + if (*s != '/') + return 0; + + if (stat((s = unmeta(s)), &sbuf) == 0 && stat(".", &tbuf) == 0) + if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino) { + /* POSIX: No element of $PWD may be "." or ".." */ + while (*s) { + if (s[0] == '.' && + (!s[1] || s[1] == '/' || + (s[1] == '.' && (!s[2] || s[2] == '/')))) + break; + while (*s++ != '/' && *s) + continue; + } + return !*s; + } return 0; } -- cgit v1.2.3 From e61717b6061e77b582313ffc883f40bc5e11ae70 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 19 Sep 2015 23:05:44 -0700 Subject: 36566: check for regular file before lseek() --- ChangeLog | 2 ++ Src/parse.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6d99ccd81..70407ca50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-09-19 Barton E. Schaefer + * 36566: Src/parse.c: check for regular file before lseek() + * 36562: Src/utils.c: sanitize $PWD on import, per POSIX 2015-09-19 Peter Stephenson diff --git a/Src/parse.c b/Src/parse.c index 7c2d20250..a26df6f0a 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -3227,6 +3227,8 @@ build_dump(char *nam, char *dump, char **files, int ali, int map, int flags) noaliases = ali; for (hlen = FD_PRELEN, tlen = 0; *files; files++) { + struct stat st; + if (!strcmp(*files, "-k")) { flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_KSHLOAD; continue; @@ -3235,6 +3237,7 @@ build_dump(char *nam, char *dump, char **files, int ali, int map, int flags) continue; } if ((fd = open(*files, O_RDONLY)) < 0 || + fstat(fd, &st) != 0 || !S_ISREG(st.st_mode) || (flen = lseek(fd, 0, 2)) == -1) { if (fd >= 0) close(fd); -- cgit v1.2.3 From bdcdb562d97f7ed604ead37ccda52792dff9a93f Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 19 Sep 2015 23:06:55 -0700 Subject: cf. users/20606: zcompile prepares scripts for sourcing, not for execution --- ChangeLog | 3 +++ Doc/Zsh/builtins.yo | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 70407ca50..74226a8f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-09-19 Barton E. Schaefer + * unposted: Doc/Zsh/builtins.yo: zcompile prepares scripts for + sourcing, not for execution + * 36566: Src/parse.c: check for regular file before lseek() * 36562: Src/utils.c: sanitize $PWD on import, per POSIX diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 67e3131cb..97c337071 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -2321,7 +2321,7 @@ item(tt(zcompile -t) var(file) [ var(name) ... ])( This builtin command can be used to compile functions or scripts, storing the compiled form in a file, and to examine files containing the compiled form. This allows faster autoloading of functions and -execution of scripts by avoiding parsing of the text when the files +sourcing of scripts by avoiding parsing of the text when the files are read. The first form (without the tt(-c), tt(-a) or tt(-t) options) creates a -- cgit v1.2.3 From 05ec830c943378baf8b9feeb69b97ba6c8eaf257 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Mon, 21 Sep 2015 21:08:29 +0900 Subject: 36574: new completion for the lldb debbuger --- Completion/Unix/Command/_lldb | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Completion/Unix/Command/_lldb diff --git a/Completion/Unix/Command/_lldb b/Completion/Unix/Command/_lldb new file mode 100644 index 000000000..16e346cfb --- /dev/null +++ b/Completion/Unix/Command/_lldb @@ -0,0 +1,55 @@ +#compdef lldb + +local curcontext=$curcontext state state_descr line expl ret=1 +typeset -A opt_args +local -a args + +args=( + '*'{-o+,--one-line=}'[run one-line lldb command after loading executable]:lldb command: ' + '*'{-s+,--source=}'[run lldb commands from a file after loading executable]:file:_files' + '*'{-O+,--one-line-before-file=}'[run one-line lldb command before loading executable]:lldb command' + '*'{-S+,--source-before-file=}'[run lldb commands from a file before loading executable]:file:_files' + '(-k --one-line-on-crash)'{-k+,--one-line-on-crash=}'[run one-line lldb command if target crashes in batch mode]:lldb command' + '(-K --source-on-crash)'{-K+,--source-on-crash=}'[run lldb commands from a file if target crashes in batch mode]:file:_files' + '(-b --batch)'{-b,--batch}'[run commands from -s -S -o -O and quit]' + '(-Q --source-quietly)'{-Q,--source-quietly}'[suppress output from -s, -S, -o or -O]' + '(-e --editor)'{-e,--editor}'[open source files using "external editor" mechanism]' + '(-x --no-lldbinit)'{-x,--no-lldbinit}'[do not automatically parse .lldbinit files]' + '(-X --no-use-colors)'{-X,--no-use-colors}'[do not use colors]' + '(-d --debug)'{-d,--debug}'[print extra information for debugging itself]' + '(-r --repl)'{-r,--repl}'[run lldb in REPL mode]' + '(-l --script-language)'{-l+,--script-language=}'[use the specified scripting language]:language:(Python Perl Ruby Tcl)' + - info + '(-)'{-h,--help}'[print the usage information]' + '(-)'{-v,--version}'[print the current version number]' + '(-)'{-P,--python-path}'[print path to the lldb.py file]' + - file + '(-f --file)'{-f+,--file=}'[specify executable file to debug]:executable:_files -g "*(-*)"' + '(-a --arch)'{-a+,--arch=}'[use the specified architecture]:arch' + '(-c --core)'{-c+,--core=}'[specify core file to open]:core file:_files -g "*core*(-.)"' + '*::executable and arguments:->exe_args' + - name + '(-n --attach-name)'{-n+,--attach-name=}'[attach to the named process]:process name' + '(-w --wait-for)'{-w,--wait-for}'[wait for the specified process to launch]' + - pid + '(-p --attach-pid)'{-p+,--attach-pid=}'[attach to the specified process]:pid:_pids' +) + +_arguments -C -s -S : $args && return 0 + +case $state in + (exe_args) + if [[ -z $opt_args[(I)file-(-f|--file)] ]]; then + if [[ $CURRENT -eq 1 ]]; then + _wanted executables expl 'executable' _files -g '*(-*)' && ret=0 + else + _normal && ret=0 + fi + else + words=( ${(v)opt_args[(i)file-(-f|--file)]} "$words[@]" ) + (( CURRENT++ )) + _normal && ret=0 + fi +esac + +return ret -- cgit v1.2.3 From 6fa5f0612b9866ead0859cd5bbbce9fd8c6488e2 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 21 Sep 2015 13:27:35 +0100 Subject: unposted: typo in 36559 --- ChangeLog | 4 ++++ Src/zsh.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 74226a8f8..f59377031 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-09-21 Peter Stephenson + + * unposted: Src/zsh.h: typo in 36559. + 2015-09-19 Barton E. Schaefer * unposted: Doc/Zsh/builtins.yo: zcompile prepares scripts for diff --git a/Src/zsh.h b/Src/zsh.h index 9c7e5d9dc..b98fc5c43 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -36,7 +36,7 @@ */ #ifdef ZSH_64_BIT_TYPE typedef ZSH_64_BIT_TYPE zlong; -#if defind(ZLONG_IS_LONG_LONG) && defined(LLONG_MAX) +#if defined(ZLONG_IS_LONG_LONG) && defined(LLONG_MAX) #define ZLONG_MAX LLONG_MAX #else /* umm... */ -- cgit v1.2.3 From 9b35a04f98300469ad33b44849920c4c3cb2d986 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Mon, 21 Sep 2015 21:38:41 +0900 Subject: 36556: complete two or more options for zsh --- ChangeLog | 8 ++++++++ Completion/Unix/Command/_sh | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f59377031..b6755caac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2015-09-21 Jun-ichi Takimoto + + * 36574: Completion/Unix/Command/_lldb: new completion for + the lldb debugger + + * 36556: Completion/Unix/Command/_sh: remove unnecessary + helpspec to '_argument --' + 2015-09-21 Peter Stephenson * unposted: Src/zsh.h: typo in 36559. diff --git a/Completion/Unix/Command/_sh b/Completion/Unix/Command/_sh index 21ebfc3b2..1b5112212 100644 --- a/Completion/Unix/Command/_sh +++ b/Completion/Unix/Command/_sh @@ -24,6 +24,6 @@ fi local ret=$? -[[ $service == zsh ]] && _arguments -S -s -- '*:' && ret=0 +[[ $service == zsh ]] && _arguments -S -s -- && ret=0 return ret -- cgit v1.2.3 From d4a640775f8e6aad3a32a2ebcf4d049d728a9e8b Mon Sep 17 00:00:00 2001 From: Frank Terbeck Date: Mon, 21 Sep 2015 14:41:40 +0200 Subject: 36575: _tmux: ‘lock-server’ option is gone in tmux.git MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog | 5 +++++ Completion/Unix/Command/_tmux | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6755caac..29d45e721 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-21 Frank Terbeck + + * 36575: Completion/Unix/Command/_tmux: _tmux: ‘lock-server’ + option is gone in tmux.git + 2015-09-21 Jun-ichi Takimoto * 36574: Completion/Unix/Command/_lldb: new completion for diff --git a/Completion/Unix/Command/_tmux b/Completion/Unix/Command/_tmux index 49c2b63ed..3d4734bcd 100644 --- a/Completion/Unix/Command/_tmux +++ b/Completion/Unix/Command/_tmux @@ -1270,7 +1270,6 @@ function __tmux-option-guard() { 'history-limit:'${int_guard} 'lock-after-time:'${int_guard} 'lock-command:MSG:command string' - 'lock-server:DESC:on off' 'message-command-style:__tmux-style' 'message-style:__tmux-style' 'mouse:DESC:on off' @@ -1394,7 +1393,6 @@ function __tmux-session-options() { 'history-limit:number of copy-mode lines per window' 'lock-after-time:lock sessions after N seconds' 'lock-command:command to run for locking a client' - 'lock-server:make lock-after-time lock the server instead of sessions' 'message-command-style:status line message command style' 'message-style:status line message style' 'mouse:enable mouse support' -- cgit v1.2.3 From 5476e011f16664e601092c1e94e3332efe80720f Mon Sep 17 00:00:00 2001 From: Frank Terbeck Date: Mon, 21 Sep 2015 14:41:41 +0200 Subject: 36576: _tmux: Fix tmux homepage URI --- ChangeLog | 3 +++ Completion/Unix/Command/_tmux | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 29d45e721..221f57fbd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ * 36575: Completion/Unix/Command/_tmux: _tmux: ‘lock-server’ option is gone in tmux.git + * 36576: Completion/Unix/Command/_tmux: _tmux: Fix tmux homepage + URI + 2015-09-21 Jun-ichi Takimoto * 36574: Completion/Unix/Command/_lldb: new completion for diff --git a/Completion/Unix/Command/_tmux b/Completion/Unix/Command/_tmux index 3d4734bcd..6f2cac790 100644 --- a/Completion/Unix/Command/_tmux +++ b/Completion/Unix/Command/_tmux @@ -1,6 +1,6 @@ #compdef tmux -# tmux completion for zsh . +# tmux completion for zsh . # # Configuration: # -- cgit v1.2.3 From 8b84419f45298ee564bd6fa2b531c8991b2a1983 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 21 Sep 2015 14:39:21 +0100 Subject: 36577: supplement 36559 to using LONG_MAX for 64-bit long --- ChangeLog | 3 +++ Src/zsh.h | 4 ++++ configure.ac | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/ChangeLog b/ChangeLog index 221f57fbd..1dd57123c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,9 @@ 2015-09-21 Peter Stephenson + * 36577: configure.ac, Src/zsh.h: supplement 36559 to + use LONG_MAX for 64-bit long. + * unposted: Src/zsh.h: typo in 36559. 2015-09-19 Barton E. Schaefer diff --git a/Src/zsh.h b/Src/zsh.h index b98fc5c43..dd0596116 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -39,9 +39,13 @@ typedef ZSH_64_BIT_TYPE zlong; #if defined(ZLONG_IS_LONG_LONG) && defined(LLONG_MAX) #define ZLONG_MAX LLONG_MAX #else +#ifdef ZLONG_IS_LONG_64 +#define ZLONG_MAX LONG_MAX +#else /* umm... */ #define ZLONG_MAX ((zlong)9223372036854775807) #endif +#endif #ifdef ZSH_64_BIT_UTYPE typedef ZSH_64_BIT_UTYPE zulong; #else diff --git a/configure.ac b/configure.ac index d7db8ba8d..c3bd713c1 100644 --- a/configure.ac +++ b/configure.ac @@ -1079,9 +1079,15 @@ main() { return sizeof(ino_t) < 8; } fi AH_TEMPLATE([ZLONG_IS_LONG_LONG], [Define to 1 if the zlong type uses long long int.]) +AH_TEMPLATE([ZLONG_IS_LONG_64], +[Define to 1 if the zlong type uses 64-bit long int.]) if test "$zsh_cv_64_bit_type" = "long long"; then dnl Remember this so we can get (s)printf output right. AC_DEFINE(ZLONG_IS_LONG_LONG) +else + if test "$zsh_cv_64_bit_type" = "long"; then + AC_DEFINE(ZLONG_IS_LONG_64) + fi fi dnl We'll blithely assume (f)printf supports the same types as sprintf. -- cgit v1.2.3 From 729f6ddfff8a229c404f0ec2b9d83c89395e541d Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 21 Sep 2015 20:33:58 +0100 Subject: 36580: don't copy empty buffer in compmatch. Also check if length is non-zero when buffer is empty. --- ChangeLog | 5 +++++ Src/Zle/compmatch.c | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1dd57123c..4a8c0531a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-21 Peter Stephenson + + * 36580: Src/Zle/compmatch.c: don't copy empty buffer and check + size is consistent. + 2015-09-21 Frank Terbeck * 36575: Completion/Unix/Command/_tmux: _tmux: ‘lock-server’ diff --git a/Src/Zle/compmatch.c b/Src/Zle/compmatch.c index 05ae43ae6..b5728a5fe 100644 --- a/Src/Zle/compmatch.c +++ b/Src/Zle/compmatch.c @@ -338,8 +338,15 @@ add_match_str(Cmatcher m, char *l, char *w, int wl, int sfx) char *buf; buf = (char *) zalloc(blen); - memcpy(buf, matchbuf, matchbuflen); - zfree(matchbuf, matchbuflen); + if (matchbuf) { + memcpy(buf, matchbuf, matchbuflen); + zfree(matchbuf, matchbuflen); + } +#ifdef DEBUG + else { + DPUTS(matchbuflen, "matchbuflen with no matchbuf"); + } +#endif matchbuf = buf; matchbuflen = blen; } -- cgit v1.2.3 From 53fcadc1f8a735ee0194ec83bebe1afd6ff14d1c Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Tue, 22 Sep 2015 11:16:32 +0900 Subject: 36578: option in a set has key "set-opt" in $opt_args --- ChangeLog | 5 +++++ Doc/Zsh/compsys.yo | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4a8c0531a..6523ff8bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-22 Jun-ichi Takimoto + + * 36578: Doc/Zsh/compsys.yo: option in a mutually exclusive set + has key "set-opt" in $opt_args + 2015-09-21 Peter Stephenson * 36580: Src/Zle/compmatch.c: don't copy empty buffer and check diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo index d067795dd..d6b180301 100644 --- a/Doc/Zsh/compsys.yo +++ b/Doc/Zsh/compsys.yo @@ -3982,6 +3982,11 @@ possible completions. When it contains `tt(-d)' or an argument, the option `tt(-c)' will not be considered. However, after `tt(-a)' both sets will still be considered valid. +If an option in a set appears on the command line, it is stored in the +associative array `tt(opt_args)' with 'var(set)tt(-)var(option)' +as a key. In the example above, a key `tt(set1--c)' is used if the option +`tt(-c)' is on the command line. + If the name given for one of the mutually exclusive sets is of the form `tt(LPAR())var(name)tt(RPAR())' then only one value from each set will ever be completed; more formally, all specifications are mutually -- cgit v1.2.3 From d2910fd64f584d57dbf544db8aa36ac909ea212f Mon Sep 17 00:00:00 2001 From: Han Pingtian Date: Tue, 15 Sep 2015 16:23:09 +0800 Subject: 36538: fix description of b and B completion match anchors --- ChangeLog | 5 +++++ Doc/Zsh/compwid.yo | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6523ff8bd..897aa1ad6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-22 Peter Stephenson + + * 36538: Han Pingtian: Doc/Zsh/compwid.yo: tweak code for match + anchors to get correct difference between b and B. + 2015-09-22 Jun-ichi Takimoto * 36578: Doc/Zsh/compsys.yo: option in a mutually exclusive set diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo index 40cabea88..303c19db5 100644 --- a/Doc/Zsh/compwid.yo +++ b/Doc/Zsh/compwid.yo @@ -899,8 +899,8 @@ 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 trial completion -or the word on the command line, respectively. +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)) -- cgit v1.2.3 From acf5bd766a7b5d656cdf1c636c8508492c1aadf4 Mon Sep 17 00:00:00 2001 From: Han Pingtian Date: Tue, 22 Sep 2015 05:55:23 +0800 Subject: 36586: fix completion match right anchor --- ChangeLog | 8 +++++++- Doc/Zsh/compwid.yo | 2 +- Src/Zle/compmatch.c | 6 ++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 897aa1ad6..e5ea4fd30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ 2015-09-22 Peter Stephenson - * 36538: Han Pingtian: Doc/Zsh/compwid.yo: tweak code for match + * 36586: Han Pingtian: Src/Zle/compmatch.c: tweak to completion + matching with right anchor. + + * 36545: Han Pingtian: Doc/Zsh/compwid.yo: tweak doc for match + anchors e and E. + + * 36538: Han Pingtian: Doc/Zsh/compwid.yo: tweak doc for match anchors to get correct difference between b and B. 2015-09-22 Jun-ichi Takimoto diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo index 303c19db5..c01763316 100644 --- a/Doc/Zsh/compwid.yo +++ b/Doc/Zsh/compwid.yo @@ -911,7 +911,7 @@ 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 trial completion or command line string. +match to the end of the command line or trial completion string. ) enditem() diff --git a/Src/Zle/compmatch.c b/Src/Zle/compmatch.c index b5728a5fe..948144006 100644 --- a/Src/Zle/compmatch.c +++ b/Src/Zle/compmatch.c @@ -820,10 +820,12 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, continue; else if (mp->right) t = pattern_match(mp->right, - tl + mp->llen - mp->ralen, + //tl + mp->llen - mp->ralen, + tl + mp->llen, NULL, NULL) && pattern_match(mp->right, - tw + mp->wlen - mp->ralen, + //tw + mp->wlen - mp->ralen, + tw + mp->wlen, NULL, NULL) && (!mp->lalen || pattern_match(mp->left, tw + mp->wlen - -- cgit v1.2.3 From 56ed4df8988249338b0f8f2d999df4217ca533e6 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Tue, 22 Sep 2015 08:52:52 -0700 Subject: 36587: use +LINE:COLUMN to place the cursor when invoking emacs variants, for emacsclient --- ChangeLog | 5 +++++ Functions/Zle/edit-command-line | 9 ++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index e5ea4fd30..6d69e6d61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-22 Barton E. Schaefer + + * 36587: Functions/Zle/edit-command-line: use +LINE:COLUMN to + place the cursor when invoking emacs variants, for emacsclient + 2015-09-22 Peter Stephenson * 36586: Han Pingtian: Src/Zle/compmatch.c: tweak to completion diff --git a/Functions/Zle/edit-command-line b/Functions/Zle/edit-command-line index 2c7f34b8b..103a1c1a5 100644 --- a/Functions/Zle/edit-command-line +++ b/Functions/Zle/edit-command-line @@ -11,13 +11,16 @@ # Compute the cursor's position in bytes, not characters. setopt localoptions nomultibyte - integer byteoffset=$(( $#PREBUFFER + $#LBUFFER + 1 )) # Open the editor, placing the cursor at the right place if we know how. local editor=${${VISUAL:-${EDITOR:-vi}}} case $editor in - (*vim*) ${=editor} -c "normal! ${byteoffset}go" -- $1;; - (*emacs*) ${=editor} $1 -eval "(goto-char ${byteoffset})";; + (*vim*) + integer byteoffset=$(( $#PREBUFFER + $#LBUFFER + 1 )) + ${=editor} -c "normal! ${byteoffset}go" -- $1;; + (*emacs*) + local lines=( ${(f):-"$PREBUFFER$LBUFFER"} ) + ${=editor} +${#lines}:$((${#lines[-1]} + 1)) $1;; (*) ${=editor} $1;; esac -- cgit v1.2.3 From 0f2f34363d24974dcdcb9aecb03df139969b3d18 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Wed, 23 Sep 2015 01:13:26 +0200 Subject: unposted: replace multi-byte curly-quotes with plain quotes in ChangeLog entry --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6d69e6d61..6bad31903 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,7 +26,7 @@ 2015-09-21 Frank Terbeck - * 36575: Completion/Unix/Command/_tmux: _tmux: ‘lock-server’ + * 36575: Completion/Unix/Command/_tmux: _tmux: 'lock-server' option is gone in tmux.git * 36576: Completion/Unix/Command/_tmux: _tmux: Fix tmux homepage -- cgit v1.2.3 From 002d68525c9de1230565d1a1c317996635d39172 Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Sun, 20 Sep 2015 20:36:09 -0400 Subject: 36571: Completion for zsocket and updated losetup's completion --- ChangeLog | 6 ++++++ Completion/Linux/Command/_losetup | 36 +++++++++++++++++++++++++----------- Completion/Zsh/Command/_zsocket | 14 ++++++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 Completion/Zsh/Command/_zsocket diff --git a/ChangeLog b/ChangeLog index 6bad31903..f948328a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-09-23 Mikael Magnusson + + * Eric Cook: 36571: Completion/Linux/Command/_losetup, + Completion/Zsh/Command/_zsocket: Completion for zsocket and + updated losetup's completion + 2015-09-22 Barton E. Schaefer * 36587: Functions/Zle/edit-command-line: use +LINE:COLUMN to diff --git a/Completion/Linux/Command/_losetup b/Completion/Linux/Command/_losetup index ff18681f1..359a9e0ea 100644 --- a/Completion/Linux/Command/_losetup +++ b/Completion/Linux/Command/_losetup @@ -1,14 +1,28 @@ #compdef losetup +# based on util-linux 2.26.2 -local cyphers -cyphers=( /proc/crypto/cipher/*(N:t) ) -cyphers="${cyphers[@]%-*}" - -_arguments -S \ +_arguments -S -A '-*' \ + '(-l --list)'{-l,--list}'[list currently used loop devices]' \ + '(-n --noheadings)'{-n,--noheadings}'[do not print heading for --list output]' \ + '(-d --delete --detach -o --offset -a --all)'{-o,--offset}'+[specify data start is offset]:offset (bytes)' \ + '(-O --output)'{-O,--output}'[specify columns to be printed with --list]:column: _values -s , column name sizelimit offset autoclear ro back-file' \ + '(-P --partscan)'{-P,--partscan}'[scan the partition table of newly created loop devices]' \ + '--raw[raw output format]' \ + '(-r --read-only)'{-r,--read-only}'[set up a read-only loop device]' \ + '(-v --verbose)'{-v,--verbose}'[verbose mode]' \ + '(-V --version)'{-V,--version}'[display version information]' \ + '(-h --help)'{-h,--help}'[display help]' \ + '1:device:_files -g "/dev/loop<->"' \ + '(-d --delete --detach)2:file:_files' \ + - '(set1)' \ + '(-o --offset)'{-a,--all}'[show the status of all loop devices]' \ + - '(set2)' \ + {-c,--set-capacity}'[reread the size of the file associated with the loop device]' \ + - '(set3)' \ '(- 2)'{--delete,--detach,-d}'[detach from specified loop device]' \ - '(-d --delete --detach -e --encryption)'{-e,--encryption}"+[enable encryption]:cypher:( $cyphers )" \ - '(-d --delete --detach -o --offset)'{-o,--offset}'+[specify data start is offset]:offset (bytes)' \ - '(-d --delete --detach -p --pass-fd)'{-p,--pass-fd}'+[read passphrase from specified file descriptor]:file descriptor:_file_descriptors' \ - '(-d --delete --detach -k --keybits)'{-k,--keybits}'+[set the number of bits to use in key]:key size:(64 128 160 192 256)' \ - '1:device:_files -g "loop*(-.)"' \ - '(-d --delete --detach)2:file:_files' + - '(set4)' \ + '(-D --detach-all)'{-D,--detach-all}'[detach all associated loop devices]' \ + - '(set5)' \ + {-f,--find}'[find the first unused loop device]' \ + - '(set6)' \ + {-j,--associated}'[show the status of all loop devices associated with an file]: : _files' diff --git a/Completion/Zsh/Command/_zsocket b/Completion/Zsh/Command/_zsocket new file mode 100644 index 000000000..eeed9f1d8 --- /dev/null +++ b/Completion/Zsh/Command/_zsocket @@ -0,0 +1,14 @@ +#compdef zsocket + +_arguments -s -w -A "-*" \ + '-v[verbose output]' \ + '-d[target file descriptor]:fd:_file_descriptors' \ + - outbound \ + '1: :_files' \ + - listen \ + '-l[open a socket listening]' \ + '1: :_files' \ + - accept \ + '-a[accept an incoming connection]' \ + '-t[return if no incoming connections are pending]' \ + '1:fd:{ (( words[(I)-*a*] )) && _file_descriptors }' -- cgit v1.2.3 From 1b5987cdb11253e2f399bfff72016af22bad9240 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 23 Sep 2015 21:40:34 +0000 Subject: unposted: Followup to 36586: Change C99 comment syntax to the C89 syntax. --- ChangeLog | 5 +++++ Src/Zle/compmatch.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index f948328a7..b92432044 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-23 Daniel Shahaf + + * unposted: Src/Zle/compmatch.c: Followup to 36586: Change C99 + comment syntax to the C89 syntax. + 2015-09-23 Mikael Magnusson * Eric Cook: 36571: Completion/Linux/Command/_losetup, diff --git a/Src/Zle/compmatch.c b/Src/Zle/compmatch.c index 948144006..0e41ac3a5 100644 --- a/Src/Zle/compmatch.c +++ b/Src/Zle/compmatch.c @@ -820,11 +820,11 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, continue; else if (mp->right) t = pattern_match(mp->right, - //tl + mp->llen - mp->ralen, + /* tl + mp->llen - mp->ralen, */ tl + mp->llen, NULL, NULL) && pattern_match(mp->right, - //tw + mp->wlen - mp->ralen, + /* tw + mp->wlen - mp->ralen, */ tw + mp->wlen, NULL, NULL) && (!mp->lalen || -- cgit v1.2.3 From 8d5c0c77609d814de7c0749602a595236f76b487 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 23 Sep 2015 23:16:38 -0700 Subject: 36604: fix getopts+shift calculation --- ChangeLog | 4 ++++ Functions/Misc/zrecompile | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b92432044..e5044931f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-09-23 Barton E. Schaefer + + * 36604: Functions/Misc/zrecompile: fix getopts+shift calculation + 2015-09-23 Daniel Shahaf * unposted: Src/Zle/compmatch.c: Followup to 36586: Change C99 diff --git a/Functions/Misc/zrecompile b/Functions/Misc/zrecompile index 8fe990086..d9fc55020 100644 --- a/Functions/Misc/zrecompile +++ b/Functions/Misc/zrecompile @@ -52,7 +52,7 @@ while getopts ":tqp" opt; do fi esac done -shift OPTIND-${#tmp:-1} +shift OPTIND-${#tmp}-1 if [[ -n $check ]]; then ret=1 -- cgit v1.2.3 From 1aafc028b392ae85f6670a1c0b8cf00da975e304 Mon Sep 17 00:00:00 2001 From: Christoph Mathys Date: Thu, 24 Sep 2015 16:12:27 +0000 Subject: 36613: _hg: extend completion for hg push to support branch and bookmark --- ChangeLog | 5 +++++ Completion/Unix/Command/_hg | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index e5044931f..dcecc8031 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-24 Christoph Mathys + + * 36613: Completion/Unix/Command/_hg: _hg: extend completion + for hg push to support branch and bookmark + 2015-09-23 Barton E. Schaefer * 36604: Functions/Misc/zrecompile: fix getopts+shift calculation diff --git a/Completion/Unix/Command/_hg b/Completion/Unix/Command/_hg index e7c21b9d1..2db5c55a5 100644 --- a/Completion/Unix/Command/_hg +++ b/Completion/Unix/Command/_hg @@ -176,6 +176,13 @@ _hg_bookmarks_internal() { _wanted bookmarks expl 'bookmarks' compadd -a - hgbookmarks } +_hg_branches_internal() { + local expl + typeset -a hgbranches + hgbranches=( ${(f)"$(_hg_cmd branches -q 2>/dev/null)"} ) + _wanted branches expl 'branches' compadd -a - hgbranches +} + _hg_tags() { _alternative \ 'bookmarks:bookmark:_hg_bookmarks_internal' \ @@ -659,6 +666,10 @@ _hg_cmd_push() { _arguments -s -w : $_hg_global_opts $_hg_remote_opts \ '(--force -f)'{-f,--force}'[force push]' \ '(--rev -r)'{-r+,--rev}'[a specific revision you would like to push]:revision:_hg_tags' \ + '*'{-B,--bookmark=}'[bookmark to push]:bookmark:_hg_bookmarks_internal' \ + '*'{-b,--branch=}'[branch to push]:branch:_hg_branches_internal' \ + '--insecure[do not verify server certificate]' \ + '--new-branch[allow pushing a new branch]' \ ':destination:_hg_remote' } -- cgit v1.2.3 From 4c935b9f85d25999a2ff9844274827f7905380f3 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 24 Sep 2015 16:15:15 +0000 Subject: unposted: _hg: Declare $expl as an array --- ChangeLog | 5 +++++ Completion/Unix/Command/_hg | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index dcecc8031..80a7d19c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-24 Daniel Shahaf + + * unposted: Completion/Unix/Command/_hg: _hg: Declare $expl as + an array + 2015-09-24 Christoph Mathys * 36613: Completion/Unix/Command/_hg: _hg: extend completion diff --git a/Completion/Unix/Command/_hg b/Completion/Unix/Command/_hg index 2db5c55a5..9dd023653 100644 --- a/Completion/Unix/Command/_hg +++ b/Completion/Unix/Command/_hg @@ -163,21 +163,21 @@ _hg_revrange() { } _hg_tags_internal() { - local expl + local -a expl typeset -a hgtags hgtags=( ${(f)"$(_hg_cmd tags -q 2>/dev/null)"} ) _wanted tags expl 'tags' compadd -a - hgtags } _hg_bookmarks_internal() { - local expl + local -a expl typeset -a hgbookmarks hgbookmarks=( ${(f)"$(_hg_cmd bookmarks -q 2>/dev/null)"} ) _wanted bookmarks expl 'bookmarks' compadd -a - hgbookmarks } _hg_branches_internal() { - local expl + local -a expl typeset -a hgbranches hgbranches=( ${(f)"$(_hg_cmd branches -q 2>/dev/null)"} ) _wanted branches expl 'branches' compadd -a - hgbranches -- cgit v1.2.3 From bd5806aa0a98d8de6e1b6e7e4b7694b89952f08d Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Thu, 24 Sep 2015 20:51:59 +0200 Subject: 36603: glob: fix dirfd leak during Y shortcut qualifier --- ChangeLog | 11 +++++++---- Src/glob.c | 4 +++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 80a7d19c4..41a56f966 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,15 @@ +2015-09-24 Mikael Magnusson + + * 36603: Src/glob.c: fix dirfd leak during Y shortcut qualifier + 2015-09-24 Daniel Shahaf - * unposted: Completion/Unix/Command/_hg: _hg: Declare $expl as - an array + * unposted: Completion/Unix/Command/_hg: Declare $expl as an array 2015-09-24 Christoph Mathys - * 36613: Completion/Unix/Command/_hg: _hg: extend completion - for hg push to support branch and bookmark + * 36613: Completion/Unix/Command/_hg: extend completion for hg + push to support branch and bookmark 2015-09-23 Barton E. Schaefer diff --git a/Src/glob.c b/Src/glob.c index 43d135b99..fa3ce25f4 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -634,8 +634,10 @@ scanner(Complist q, int shortcircuit) } else { /* if the last filename component, just add it */ insert(fn, 1); - if (shortcircuit && shortcircuit == matchct) + if (shortcircuit && shortcircuit == matchct) { + closedir(lock); return; + } } } } -- cgit v1.2.3 From 377e2400b7b6fc21ff333791461d615538b18cb9 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Thu, 24 Sep 2015 18:46:27 -0700 Subject: 36623: document bracketed-paste-magic and url-quote-magic; add cross-reference to vim text object widgets --- ChangeLog | 5 ++ Doc/Zsh/contrib.yo | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 166 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 41a56f966..ef35827d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-24 Barton E. Schaefer + + * 36623: Doc/Zsh/contrib.yo: document bracketed-paste-magic and + url-quote-magic; add cross-reference to vim text object widgets + 2015-09-24 Mikael Magnusson * 36603: Src/glob.c: fix dirfd leak during Y shortcut qualifier diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 741d4ad07..b966e781c 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1705,7 +1705,10 @@ item(tt(select-word-style), tt(match-word-context), tt(match-words-by-style))( The eight `tt(-match)' functions are drop-in replacements for the builtin widgets without the suffix. By default they behave in a similar way. However, by the use of styles and the function tt(select-word-style), -the way words are matched can be altered. +the way words are matched can be altered. For comparison, the widgets +described in ifzman(zmanref(zshzle) under Text Objects)\ +ifnzman(noderef(Text Objects)) use fixed definitions of words, compatible +with the tt(vim) editor. The simplest way of configuring the functions is to use tt(select-word-style), which can either be called as a normal function with @@ -1895,6 +1898,100 @@ The tt(word-context) style is implemented by the function tt(match-word-context). This should not usually need to be called directly. ) +tindex(bracketed-paste-magic) +item(bracketed-paste-magic)( +The tt(bracketed-paste) widget (see ifzman(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 +widget is replaced in order to accomplish some extra processing. An +example is the contributed tt(url-quote-magic) widget described below. + +The tt(bracketed-paste-magic) widget is meant to replace tt(bracketed-paste) +with a wrapper that re-enables these self-insert actions, and other +actions as selected by zstyles. Therefore this widget is installed with +ifzman() +example(autoload -Uz bracketed-paste-magic +zle -N bracketed-paste bracketed-paste-magic) + +Other than enabling some widget processing, tt(bracketed-paste-magic) +attempts to replicate tt(bracketed-paste) as faithfully as possible. + +The following zstyles may be set to control processing of pasted text. +All are looked up in the context `tt(:bracketed-paste-magic)'. + +startitem() +item(tt(active-widgets))( +A list of patterns matching widget names that should be activated during +the paste. All other key sequences are processed as self-insert-unmeta. +The default is `tt(self-*)' so any user-defined widgets named with that +prefix are active along with the builtin self-insert. + +If this style is not set (explicitly deleted) or set to an empty value, +no widgets are active and the pasted text is inserted literally. If the +value includes `tt(undefined-key)', any unknown sequences are discarded +from the pasted text. +) +item(tt(inactive-keys))( +The inverse of tt(active-widgets), a list of key sequences that always use +tt(self-insert-unmeta) even when bound to an active widget. Note that +this is a list of literal key sequences, not patterns. +) +item(tt(paste-init))( +A list of function names, called in widget context (but not as widgets). +The functions are called in order until one of them returns a non-zero +status. The parameter `tt(PASTED)' contains the initial state of the +pasted text. All other ZLE parameters such as `tt(BUFFER)' have their +normal values and side-effects, and full history is available, so for +example tt(paste-init) functions may move words from tt(BUFFER) into +tt(PASTED) to make those words visible to the tt(active-widgets). + +A non-zero return from a tt(paste-init) function does em(not) prevent the +paste itself from proceeding. + +Loading tt(bracketed-paste-magic) defines tt(backward-extend-paste), a +helper function for use in tt(paste-init). + +example(zstyle :bracketed-paste-magic paste-init \ + backward-extend-paste) + +When a paste would insert into the middle of a word or append text to a +word already on the line, tt(backward-extend-paste) moves the prefix +from tt(LBUFFER) into tt(PASTED) so that the tt(active-widgets) see the +full word so far. This may be useful with tt(url-quote-magic). +) +item(tt(paste-finish))( +Another list of function names called in order until one returns non-zero. +These functions are called em(after) the pasted text has been processed +by the tt(active-widgets), but em(before) it is inserted into `tt(BUFFER)'. +ZLE parameters have their normal values and side-effects. + +A non-zero return from a tt(paste-finish) function does em(not) prevent +the paste itself from proceeding. + +Loading tt(bracketed-paste-magic) also defines tt(quote-paste), a helper +function for use in tt(paste-finish). + +example(zstyle :bracketed-paste-magic paste-finish \ + quote-paste +zstyle :bracketed-paste-magic:finish quote-style \ + qqq) + +When the pasted text is inserted into tt(BUFFER), it is quoted per the +tt(quote-style) value. To forcibly turn off the built-in numeric prefix +quoting of tt(bracketed-paste), use: + +example(zstyle :bracketed-paste-magic:finish quote-style \ + none) +) +enditem() + +em(Important:) During tt(active-widgets) processing of the paste (after +tt(paste-init) and before tt(paste-finish)), tt(BUFFER) starts empty and +history is restricted, so cursor motions, etc., may not pass outside of +the pasted content. Text assigned to tt(BUFFER) by the active widgets +is copied back into tt(PASTED) before tt(paste-finish). +) tindex(copy-earlier-word) item(tt(copy-earlier-word))( This widget works like a combination of tt(insert-last-word) and @@ -2557,6 +2654,69 @@ start of the previous line. Using a numeric argument less than -1 has the effect of moving the line above the cursor up by minus that number of lines. ) +tindex(url-quote-magic) +item(tt(url-quote-magic))( +This widget replaces the built-in tt(self-insert) to make it easier to +type URLs as command line arguments. As you type, the input character is +analyzed and, if it may need quoting, the current word is checked for a +URI scheme. If one is found and the current word is not already in +quotes, a backslash is inserted before the input character. + +Styles to control quoting behavior: + +startitem() +item(tt(url-metas))( +This style is looked up in the context `tt(:url-quote-magic:)var(scheme)' +(where var(scheme) is that of the current URL, e.g. "tt(ftp)"). The value +is a string listing the characters to be treated as globbing +metacharacters when appearing in a URL using that scheme. The default is +to quote all zsh extended globbing characters, excluding 'tt(<)' and +'tt(>)' but including braces (as in brace expansion). See also +tt(url-seps). +) +item(tt(url-seps))( +Like tt(url-metas), but lists characters that should be considered command +separators, redirections, history references, etc. The default is to +quote the standard set of shell separators, excluding those that overlap +with the extended globbing characters, but including 'tt(<)' and +'tt(>)' and the first character of tt($histchars). +) +item(tt(url-globbers))( +This style is looked up in the context `tt(:url-quote-magic)'. The values +form a list of command names that are expected to do their own globbing +on the URL string. This implies that they are aliased to use the +`tt(noglob)' modifier. When the first word on the line matches one of the +values em(and) the URL refers to a local file (see tt(url-local-schema)), +only the tt(url-seps) characters are quoted; the tt(url-metas) are left +alone, allowing them to affect command-line parsing, completion, etc. The +default values are a literal `tt(noglob)' plus (when the tt(zsh/parameter) +module is available) any commands aliased to the helper function +`tt(urlglobber)' or its alias `tt(globurl)'. +) +item(tt(url-local-schema))( +This style is always looked up in the context `tt(:urlglobber)', even +though it is used by both url-quote-magic and urlglobber. The values form +a list of URI schema that should be treated as referring to local files by +their real local path names, as opposed to files which are specified +relative to a web-server-defined document root. The defaults are +"tt(ftp)" and "tt(file)". +) +item(tt(url-other-schema))( +Like tt(url-local-schema), but lists all other URI schema upon which +tt(urlglobber) and tt(url-quote-magic) should act. If the URI on the +command line does not have a scheme appearing either in this list or in +tt(url-local-schema), it is not magically quoted. The default values are +"tt(http)", "tt(https)", and "tt(ftp)". When a scheme appears both here +and in tt(url-local-schema), it is quoted differently depending on whether +the command name appears in tt(url-globbers). +) +enditem() + +Loading tt(url-quote-magic) also defines a helper function `tt(urlglobber)' +and aliases `tt(globurl)' to `tt(noglob urlglobber)'. This function takes +a local URL apart, attempts to pattern-match the local file portion of the +URL path, and then puts the results back into URL format again. +) tindex(which-command) item(tt(which-command))( This function is a drop-in replacement for the builtin widget -- cgit v1.2.3 From 649d06a8cdd9948e3d49fa717f9088d8a87a6262 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 25 Sep 2015 21:30:34 +0100 Subject: 36630: new function zsh_directory_name_generic --- ChangeLog | 5 + Doc/Zsh/contrib.yo | 187 ++++++++++++++++++++++++++++- Doc/Zsh/manual.yo | 1 + Functions/Chpwd/zsh_directory_name_generic | 151 +++++++++++++++++++++++ 4 files changed, 342 insertions(+), 2 deletions(-) create mode 100644 Functions/Chpwd/zsh_directory_name_generic diff --git a/ChangeLog b/ChangeLog index ef35827d2..7055836fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-25 Peter Stephenson + + * 36630: Doc/Zsh/contrib.yo, Doc/Zsh/manual.yo, + Functions/Chpwd/zsh_directory_name_generic: new helper function. + 2015-09-24 Barton E. Schaefer * 36623: Doc/Zsh/contrib.yo: document bracketed-paste-magic and diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index b966e781c..330c6f588 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -12,6 +12,7 @@ such as shell functions, look for comments in the function source files. startmenu() menu(Utilities) menu(Recent Directories) +menu(Other Directory Functions) menu(Version Control Information) menu(Prompt Themes) menu(ZLE Functions) @@ -324,7 +325,7 @@ options tt(-Uz) are appropriate. ) enditem() -texinode(Recent Directories)(Version Control Information)(Utilities)(User Contributions) +texinode(Recent Directories)(Other Directory Functions)(Utilities)(User Contributions) cindex(recent directories, maintaining list of) cindex(directories, maintaining list of recent) findex(cdr) @@ -585,7 +586,189 @@ avoid side effects if the change to the directory is to be invisible at the command line. See the contents of the function tt(chpwd_recent_dirs) for more details. -texinode(Version Control Information)(Prompt Themes)(Recent Directories)(User Contributions) +texinode(Other Directory Functions)(Version Control Information)(Recent Directories)(User Contributions) +cindex(directories, named, dynamic, helper function) +cindex(dynamic directory naming, helper function) +cindex(named directories, dynamic, helper function) +findex(zsh_directory_name_generic) +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))\ +ifnzman(noderef(Filename Expansion)). In this, a reference to +tt(~[)var(...)tt(]) is expanded by a function found by the hooks +mechanism. + +The contributed function tt(zsh_directory_name_generic) provides a +system allowing the user to refer to directories with only a limited +amount of new code. It supports all three of the standard interfaces +for directory naming: converting from a name to a directory, converting +in the reverse direction to find a short name, and completion of names. + +The main feature of this function is a path-like syntax, +combining abbreviations at multiple levels separated by ":". +As an example, ~[g:p:s] might specify: +startitem() +item(tt(g))( +The top level directory for your git area. This first component +has to match, or the function will retrun indicating another +directory name hook function should be tried. +) +item(tt(p))( +The name of a project within your git area. +) +item(tt(s))( +The source area within that project. +) +enditem() +This allows you to collapse references to long hierarchies to a very +compact form, particularly if the hierarchies are similar across different +areas of the disk. + +Name components may be completed: if a description is shown at the top +of the list of completions, it includes the path to which previous +components expand, while the description for an individual completion +shows the path segment it would add. No additional configuration is +needed for this as the completion system is aware of the dynamic +directory name mechanism. + +subsect(Usage) + +To use the function, first define a wrapper function for your specific +case. We'll assume it's to be autoloaded. This can have any name but +we'll refer to it as zdn_mywrapper. This wrapper function will define +various variables and then call this function with the same arguments +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 +add-zsh-hook -U zsh_directory_name zdn_mywrapper) + +subsect(Configuration) + +The wrapper function should define a local associative array zdn_top. +Alternatively, this can be set with a style called tt(mapping). The +context for the style is tt(:zdn:)var(wrapper-name) where +var(wrapper-name) is the function calling zsh_directory_name_generic; +for example: + +example(zstyle :zdn:zdn_mywrapper: mapping zdn_mywrapper_top) + +The keys in this associative array correspond to the first component of +the name. The values are matching directories. They may have an +optional suffix with a slash followed by a colon and the name of a +variable in the same format to give the next component. (The slash +before the colon is to disambiguate the case where a colon is needed in +the path for a drive. There is otherwise no syntax for escaping this, +so path components whose names start with a colon are not supported.) A +special component tt(:default:) specifies a variable in the form +tt(/:)var(var) (the path section is ignored and so is usually empty) +that will be used for the next component if no variable is given for the +path. Variables referred to within tt(zdn_top) have the same format as +tt(zdn_top) itself, but contain relative paths. + +For example, + +example(local -A zdn_top=( + g ~/git + ga ~/alternate/git + gs /scratch/$USER/git/:second2 + :default: /:second1 +)) + +This specifies the behaviour of a directory referred to as tt(~[g:...]) +or tt(~[ga:...]) or tt(~[gs:...]). Later path components are optional; +in that case tt(~[g]) expands to tt(~/git), and so on. tt(gs) expands +to tt(/scratch/$USER/git) and uses the associative array tt(second2) to +match the second component; tt(g) and tt(ga) use the associative array +tt(second1) to match the second component. + +When expanding a name to a directory, if the first component is not tt(g) or +tt(ga) or tt(gs), it is not an error; the function simply returns 1 so that a +later hook function can be tried. However, matching the first component +commits the function, so if a later component does not match, an error +is printed (though this still does not stop later hooks from being +executed). + +For components after the first, a relative path is expected, but note that +multiple levels may still appear. Here is an example of tt(second1): + +example(local -A second1=( + p myproject + s somproject + os otherproject/subproject/:third +)) + +The path as found from tt(zdn_top) is extended with the matching +directory, so tt(~[g:p]) becomes tt(~/git/myproject). The slash between +is added automatically (it's not possible to have a later component +modify the name of a directory already matched). Only tt(os) specifies +a variable for a third component, and there's no tt(:default:), so it's +an error to use a name like tt(~[g:p:x]) or tt(~[ga:s:y]) because +there's nowhere to look up the tt(x) or tt(y). + +The associative arrays need to be visible within this function; the +generic function therefore uses internal variable names beginning +tt(_zdn_) in order to avoid clashes. Note that the variable tt(reply) +needs to be passed back to the shell, so should not be local in the +calling function. + +The function does not test whether directories assembled by component +actually exist; this allows the system to work across automounted +file systems. The error from the command trying to use a non-existent +directory should be sufficient to indicate the problem. + +subsect(Complete example) + +Here is a full fictitious but usable autoloadable definition of the +example function defined by the code above. So tt(~[gs:p:s]) expands +to tt(/scratch/$USER/git/myscratchproject/top/srcdir) (with tt($USER) +also expanded). + +example(local -A zdn_top=( + g ~/git + ga ~/alternate/git + gs /scratch/$USER/git/:second2 + :default: /:second1 +) + +local -A second1=( + p myproject + s somproject + os otherproject/subproject/:third +) + +local -A second2=( + p myscratchproject + s somescratchproject +) + +local -A third=( + s top/srcdir + d top/documentation +) + +# autoload not needed if you did this at initialisation... +autoload -Uz zsh_directory_name_generic +zsh_directory_name_generic "$@) + +It is also possible to use global associative arrays, suitably named, +and set the style for the context of your wrapper function to +refer to this. Then your set up code would contain the following: + +example(typeset -A zdn_mywrapper_top=(...) +# ... and so on for other associative arrays ... +zstyle ':zdn:zdn_mywrapper:' mapping zdn_mywrapper_top +autoload -Uz add-zsh-hook zsh_directory_name_generic zdn_mywrapper +add-zsh-hook -U zsh_directory_name zdn_mywrapper) + +and the function tt(zdn_mywrapper) would contain only the following: + +example(zsh_directory_name_generic "$@") + +texinode(Version Control Information)(Prompt Themes)(Other Directory Functions)(User Contributions) sect(Gathering information from version control systems) cindex(version control utility) diff --git a/Doc/Zsh/manual.yo b/Doc/Zsh/manual.yo index 86c72c0ff..119849e4c 100644 --- a/Doc/Zsh/manual.yo +++ b/Doc/Zsh/manual.yo @@ -164,6 +164,7 @@ User Contributions menu(Utilities) menu(Recent Directories) +menu(Other Directory Functions) menu(Version Control Information) menu(Prompt Themes) menu(ZLE Functions) diff --git a/Functions/Chpwd/zsh_directory_name_generic b/Functions/Chpwd/zsh_directory_name_generic new file mode 100644 index 000000000..9430c95e4 --- /dev/null +++ b/Functions/Chpwd/zsh_directory_name_generic @@ -0,0 +1,151 @@ +## zsh_directory_name_generic +# +# This function is useful as a hook function for the zsh_directory_name +# facility. +# +# See the zsh-contrib manual page for more. + +emulate -L zsh +setopt extendedglob +local -a match mbegin mend + +# The variable containing the top level mapping. +local _zdn_topvar + +zmodload -i zsh/parameter +zstyle -s ":zdn:${funcstack[2]}:" mapping _zdn_topvar || _zdn_topvar=zdn_top + +if (( ! ${(P)#_zdn_topvar} )); then + print -r -- "$0: $_zdn_topver is not set" >&2 + return 1 +fi + +local _zdn_var=$_zdn_topvar +local -A _zdn_assoc + +if [[ $1 = n ]]; then + # Turning a name into a directory. + local _zdn_name=$2 + local -a _zdn_words + local _zdn_dir _zdn_cpt + + _zdn_words=(${(s.:.)_zdn_name}) + while (( ${#_zdn_words} )); do + if [[ -z ${_zdn_var} ]]; then + print -r -- "$0: too many components in directory name \`$_zdn_name'" >&2 + return 1 + fi + + # Subscripting (P)_zdn_var directly seems not to work. + _zdn_assoc=(${(Pkv)_zdn_var}) + _zdn_cpt=${_zdn_assoc[${_zdn_words[1]}]} + shift _zdn_words + + if [[ -z $_zdn_cpt ]]; then + # If top level component, just try another expansion + if [[ $_zdn_var != $_zdn_top ]]; then + # Committed to this expansion, so report failure. + print -r -- "$0: no expansion for directory name \`$_zdn_name'" >&2 + fi + return 1 + fi + if [[ $_zdn_cpt = (#b)(*)/:([[:IDENT:]]##) ]]; then + _zdn_cpt=$match[1] + _zdn_var=$match[2] + else + # may be empty + _zdn_var=${${_zdn_assoc[:default:]}##*/:} + fi + _zdn_dir=${_zdn_dir:+$_zdn_dir/}$_zdn_cpt + done + if (( ${#_zdn_dir} )); then + typeset -ag reply + reply=($_zdn_dir) + return 0 + fi +elif [[ $1 = d ]]; then + # Turning a directory into a name. + local _zdn_dir=$2 + local _zdn_rest=$_zdn_dir + local -a _zdn_cpts + local _zdn_pref _zdn_pref_raw _zdn_matched _zdn_cpt _zdn_name + + while [[ -n $_zdn_var && -n $_zdn_rest ]]; do + _zdn_assoc=(${(Pkv)_zdn_var}) + # Sorting in descending order will ensure prefixes + # come after longer strings with that perfix, so + # we match more specific directory names preferentially. + _zdn_cpts=(${(Ov)_zdn_assoc}) + _zdn_cpt='' + for _zdn_pref_raw in $_zdn_cpts; do + _zdn_pref=${_zdn_pref_raw%/:*} + [[ -z $_zdn_pref ]] && continue + if [[ $_zdn_rest = $_zdn_pref(#b)(/|)(*) ]]; then + _zdn_cpt=${(k)_zdn_assoc[(r)$_zdn_pref_raw]} + # if we matched a /, too, add it... + _zdn_matched+=$_zdn_pref$match[1] + _zdn_rest=$match[2] + break + fi + done + if [[ -n $_zdn_cpt ]]; then + _zdn_name+=${_zdn_name:+${_zdh_name}:}$_zdn_cpt + if [[ ${_zdn_assoc[$_zdn_cpt]} = (#b)*/:([[:IDENT:]]##) ]]; then + _zdn_var=$match[1] + else + _zdn_var=${${_zdn_assoc[:default:]}##*/:} + fi + else + break + fi + done + if [[ -n $_zdn_name ]]; then + # matched something, so report that. + integer _zdn_len=${#_zdn_matched} + [[ $_zdn_matched[-1] = / ]] && (( _zdn_len-- )) + typeset -ag reply + reply=($_zdn_name $_zdn_len) + return 0 + fi + # else let someone else have a go. +elif [[ $1 = c ]]; then + # Completion + + if [[ -n $SUFFIX ]]; then + _message "Can't complete in the middle of a dynamic directory name" + else + local -a _zdn_cpts + local _zdn_word _zdn_cpt _zdn_desc _zdn_sofar expl + + while [[ -n ${_zdn_var} && ${PREFIX} = (#b)([^:]##):* ]]; do + _zdn_word=$match[1] + compset -P '[^:]##:' + _zdn_assoc=(${(Pkv)_zdn_var}) + _zdn_cpt=${_zdn_assoc[$_zdn_word]} + # We only complete at the end so must match here + [[ -z $_zdn_cpt ]] && return 1 + if [[ $_zdn_cpt = (#b)(*)/:([[:IDENT:]]##) ]]; then + _zdn_cpt=$match[1] + _zdn_var=$match[2] + else + _zdn_var=${${_zdn_assoc[:default:]}##*/:} + fi + _zdn_sofar+=${_zdn_sofar:+${_zdn_sofar}/}$_zdn_cpt + done + if [[ -n $_zdn_var ]]; then + _zdn_assoc=(${(Pkv)_zdn_var}) + local -a _zdn_cpts + for _zdn_cpt _zdn_desc in ${(kv)_zdn_assoc}; do + [[ $_zdn_cpt = :* ]] && continue + _zdn_cpts+=(${_zdn_cpt}:${_zdn_desc%/:[[:IDENT:]]##}) + done + _describe -t dirnames "directory name under ${_zdn_sofar%%/}" \ + _zdn_cpts -S: -r ':]' + return + fi + fi +fi + +# Failed +return 1 +## end -- cgit v1.2.3 From 61fa5f66f05c85e290d50df860708e80221011c9 Mon Sep 17 00:00:00 2001 From: Christoph Mathys Date: Fri, 25 Sep 2015 23:19:44 +0000 Subject: 36626: _hg: completion for 'hg bookmarks' --- ChangeLog | 5 +++++ Completion/Unix/Command/_hg | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7055836fa..71788378d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-25 Christoph Mathys + + * 36626: Completion/Unix/Command/_hg: _hg: completion for + 'hg bookmarks' + 2015-09-25 Peter Stephenson * 36630: Doc/Zsh/contrib.yo, Doc/Zsh/manual.yo, diff --git a/Completion/Unix/Command/_hg b/Completion/Unix/Command/_hg index 9dd023653..5d4c9852b 100644 --- a/Completion/Unix/Command/_hg +++ b/Completion/Unix/Command/_hg @@ -460,6 +460,16 @@ _hg_cmd_bisect() { '(--command -c --noupdate -U)'{-U,--noupdate}'[do not update to target]' } +_hg_cmd_bookmarks() { + _arguments -s : $_hg_global_opts \ + '(--force -f)'{-f,--force}'[force]' \ + '(--rev -r)'{-r+,--rev=}'[set bookmark at revision]:revision:_hg_tags' \ + '(--delete -d)'{-d,--delete}'[delete a given bookmark]' \ + '(--rename -m)'{-m+,--rename}'[rename given bookmark]:bookmark:_hg_bookmarks_internal' \ + '(--inactive -i)'{-i,--inactive}'[mark a bookmark inactive]' \ + ':bookmark:_hg_bookmarks_internal' +} + _hg_cmd_branch() { _arguments -s -w : $_hg_global_opts \ '(--force -f)'{-f,--force}'[set branch name even if it shadows an existing branch]' \ -- cgit v1.2.3 From 8165b488cb223ac58629d99f8df1bda930dd29c0 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 25 Sep 2015 23:38:39 +0000 Subject: unposted: zle: Document the C helper function processcmd(). Also, tweak the docstring of zlelineasstring(). --- ChangeLog | 5 +++++ Src/Zle/zle_tricky.c | 3 +++ Src/Zle/zle_utils.c | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 71788378d..fbd7c3a00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-25 Daniel Shahaf + + * unposted: Src/Zle/zle_tricky.c Src/Zle/zle_utils.c: zle: + Document the C helper function processcmd(). + 2015-09-25 Christoph Mathys * 36626: Completion/Unix/Command/_hg: _hg: completion for diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index b1a6f9e7e..e26f66379 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -2952,6 +2952,9 @@ getcurcmd(void) return s; } +/* Run '$WIDGET $commandword' and then restore the command-line using push-line. + */ + /**/ int processcmd(UNUSED(char **args)) diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 9751f7a1f..714d911a6 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -166,13 +166,13 @@ zlecharasstring(ZLE_CHAR_T inchar, char *buf) } /* - * Input a line in internal zle format, possibly using wide characters, + * Input: a line in internal zle format, possibly using wide characters, * possibly not, together with its length and the cursor position. * The length must be accurate and includes all characters (no NULL * termination is expected). The input cursor position is only * significant if outcs is non-NULL. * - * Output an ordinary NULL-terminated string, using multibyte characters + * Output: an ordinary NULL-terminated string, using multibyte characters * instead of wide characters where appropriate and with the contents * metafied. * -- cgit v1.2.3 From 92584634d3d39e9ca64475ae5af8010e2ccebe24 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 26 Sep 2015 00:19:59 +0000 Subject: unposted (see 36633): _hg: Enable --option=value syntax and disable '-xy Xarg Yarg' syntax This simply removes the '-w' argument to _arguments and changes {-x+,--foo} to {-x+,--foo=} throughout the file. --- ChangeLog | 5 + Completion/Unix/Command/_hg | 252 ++++++++++++++++++++++---------------------- 2 files changed, 131 insertions(+), 126 deletions(-) diff --git a/ChangeLog b/ChangeLog index fbd7c3a00..f700ec067 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-26 Daniel Shahaf + + * unposted (see 36633): Completion/Unix/Command/_hg: _hg: + Enable --option=value syntax and disable '-xy Xarg Yarg' syntax + 2015-09-25 Daniel Shahaf * unposted: Src/Zle/zle_tricky.c Src/Zle/zle_utils.c: zle: diff --git a/Completion/Unix/Command/_hg b/Completion/Unix/Command/_hg index 5d4c9852b..8d31cd377 100644 --- a/Completion/Unix/Command/_hg +++ b/Completion/Unix/Command/_hg @@ -359,7 +359,7 @@ _hg_clone_dest() { # Common options _hg_global_opts=( - '(--repository -R)'{-R+,--repository}'[repository root directory]:repository:_files -/' + '(--repository -R)'{-R+,--repository=}'[repository root directory]:repository:_files -/' '--cwd[change working directory]:new working directory:_files -/' '(--noninteractive -y)'{-y,--noninteractive}'[do not prompt, assume yes for any required answers]' '(--verbose -v)'{-v,--verbose}'[enable additional output]' @@ -378,8 +378,8 @@ _hg_global_opts=( ) _hg_pat_opts=( - '*'{-I+,--include}'[include names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/' - '*'{-X+,--exclude}'[exclude names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/') + '*'{-I+,--include=}'[include names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/' + '*'{-X+,--exclude=}'[exclude names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/') _hg_diff_opts=( '(--text -a)'{-a,--text}'[treat all files as text]' @@ -395,11 +395,11 @@ _hg_style_opts=( _hg_commit_opts=( '(-m --message -l --logfile --edit -e)'{-e,--edit}'[edit commit message]' - '(-e --edit -l --logfile --message -m)'{-m+,--message}'[use as commit message]:message:' - '(-e --edit -m --message --logfile -l)'{-l+,--logfile}'[read the commit message from ]:log file:_files') + '(-e --edit -l --logfile --message -m)'{-m+,--message=}'[use as commit message]:message:' + '(-e --edit -m --message --logfile -l)'{-l+,--logfile=}'[read the commit message from ]:log file:_files') _hg_remote_opts=( - '(--ssh -e)'{-e+,--ssh}'[specify ssh command to use]:' + '(--ssh -e)'{-e+,--ssh=}'[specify ssh command to use]:' '--remotecmd[specify hg command to run on the remote side]:') _hg_cmd() { @@ -408,19 +408,19 @@ _hg_cmd() { } _hg_cmd_add() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ '*:unknown files:_hg_unknown' } _hg_cmd_addremove() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ - '(--similarity -s)'{-s+,--similarity}'[guess renamed files by similarity (0<=s<=100)]:' \ + _arguments -s : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ + '(--similarity -s)'{-s+,--similarity=}'[guess renamed files by similarity (0<=s<=100)]:' \ '*:unknown or missing files:_hg_addremove' } _hg_cmd_annotate() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ - '(--rev -r)'{-r+,--rev}'[annotate the specified revision]:revision:_hg_tags' \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ + '(--rev -r)'{-r+,--rev=}'[annotate the specified revision]:revision:_hg_tags' \ '(--follow -f)'{-f,--follow}'[follow file copies and renames]' \ '(--text -a)'{-a,--text}'[treat all files as text]' \ '(--user -u)'{-u,--user}'[list the author]' \ @@ -431,32 +431,32 @@ _hg_cmd_annotate() { } _hg_cmd_archive() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ '--no-decode[do not pass files through decoders]' \ - '(--prefix -p)'{-p+,--prefix}'[directory prefix for files in archive]:' \ - '(--rev -r)'{-r+,--rev}'[revision to distribute]:revision:_hg_tags' \ - '(--type -t)'{-t+,--type}'[type of distribution to create]:archive type:(files tar tbz2 tgz uzip zip)' \ + '(--prefix -p)'{-p+,--prefix=}'[directory prefix for files in archive]:' \ + '(--rev -r)'{-r+,--rev=}'[revision to distribute]:revision:_hg_tags' \ + '(--type -t)'{-t+,--type=}'[type of distribution to create]:archive type:(files tar tbz2 tgz uzip zip)' \ '*:destination:_files' } _hg_cmd_backout() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ '--merge[merge with old dirstate parent after backout]' \ - '(--date -d)'{-d+,--date}'[record datecode as commit date]:date code:' \ + '(--date -d)'{-d+,--date=}'[record datecode as commit date]:date code:' \ '--parent[parent to choose when backing out merge]' \ - '(--user -u)'{-u+,--user}'[record user as commiter]:user:' \ - '(--rev -r)'{-r+,--rev}'[revision]:revision:_hg_tags' \ - '(--message -m)'{-m+,--message}'[specify commit message]:text' \ - '(--logfile -l)'{-l+,--logfile}'[read commit message from specified file]:log file:_files' + '(--user -u)'{-u+,--user=}'[record user as commiter]:user:' \ + '(--rev -r)'{-r+,--rev=}'[revision]:revision:_hg_tags' \ + '(--message -m)'{-m+,--message=}'[specify commit message]:text' \ + '(--logfile -l)'{-l+,--logfile=}'[read commit message from specified file]:log file:_files' } _hg_cmd_bisect() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(-)'{-r,--reset}'[reset bisect state]' \ '(--good -g --bad -b --skip -s --reset -r)'{-g,--good}'[mark changeset good]'::revision:_hg_tags \ '(--good -g --bad -b --skip -s --reset -r)'{-b,--bad}'[mark changeset bad]'::revision:_hg_tags \ '(--good -g --bad -b --skip -s --reset -r)'{-s,--skip}'[skip testing changeset]' \ - '(--command -c --noupdate -U)'{-c+,--command}'[use command to check changeset state]':commands:_command_names \ + '(--command -c --noupdate -U)'{-c+,--command=}'[use command to check changeset state]':commands:_command_names \ '(--command -c --noupdate -U)'{-U,--noupdate}'[do not update to target]' } @@ -465,24 +465,24 @@ _hg_cmd_bookmarks() { '(--force -f)'{-f,--force}'[force]' \ '(--rev -r)'{-r+,--rev=}'[set bookmark at revision]:revision:_hg_tags' \ '(--delete -d)'{-d,--delete}'[delete a given bookmark]' \ - '(--rename -m)'{-m+,--rename}'[rename given bookmark]:bookmark:_hg_bookmarks_internal' \ + '(--rename -m)'{-m+,--rename=}'[rename given bookmark]:bookmark:_hg_bookmarks_internal' \ '(--inactive -i)'{-i,--inactive}'[mark a bookmark inactive]' \ ':bookmark:_hg_bookmarks_internal' } _hg_cmd_branch() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--force -f)'{-f,--force}'[set branch name even if it shadows an existing branch]' \ '(--clean -C)'{-C,--clean}'[reset branch name to parent branch name]' } _hg_cmd_branches() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--active -a)'{-a,--active}'[show only branches that have unmerge heads]' } _hg_cmd_bundle() { - _arguments -s -w : $_hg_global_opts $_hg_remote_opts \ + _arguments -s : $_hg_global_opts $_hg_remote_opts \ '(--force -f)'{-f,--force}'[run even when remote repository is unrelated]' \ '(2)*--base[a base changeset to specify instead of a destination]:revision:_hg_tags' \ ':output file:_files' \ @@ -490,33 +490,33 @@ _hg_cmd_bundle() { } _hg_cmd_cat() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ - '(--output -o)'{-o+,--output}'[print output to file with formatted name]:filespec:' \ - '(--rev -r)'{-r+,--rev}'[revision]:revision:_hg_tags' \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ + '(--output -o)'{-o+,--output=}'[print output to file with formatted name]:filespec:' \ + '(--rev -r)'{-r+,--rev=}'[revision]:revision:_hg_tags' \ '*:file:_hg_files' } _hg_cmd_clone() { - _arguments -s -w : $_hg_global_opts $_hg_remote_opts \ + _arguments -s : $_hg_global_opts $_hg_remote_opts \ '(--noupdate -U)'{-U,--noupdate}'[do not update the new working directory]' \ - '(--rev -r)'{-r+,--rev}'[a changeset you would like to have after cloning]:' \ + '(--rev -r)'{-r+,--rev=}'[a changeset you would like to have after cloning]:' \ '--uncompressed[use uncompressed transfer (fast over LAN)]' \ ':source repository:_hg_remote' \ ':destination:_hg_clone_dest' } _hg_cmd_commit() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ '(--addremove -A)'{-A,--addremove}'[mark new/missing files as added/removed before committing]' \ - '(--message -m)'{-m+,--message}'[specify commit message]:text' \ - '(--logfile -l)'{-l+,--logfile}'[read commit message from specified file]:log file:_files' \ - '(--date -d)'{-d+,--date}'[record datecode as commit date]:date code:' \ - '(--user -u)'{-u+,--user}'[record user as commiter]:user:' \ + '(--message -m)'{-m+,--message=}'[specify commit message]:text' \ + '(--logfile -l)'{-l+,--logfile=}'[read commit message from specified file]:log file:_files' \ + '(--date -d)'{-d+,--date=}'[record datecode as commit date]:date code:' \ + '(--user -u)'{-u+,--user=}'[record user as commiter]:user:' \ '*:file:_hg_committable' } _hg_cmd_copy() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ '(--after -A)'{-A,--after}'[record a copy that has already occurred]' \ '(--force -f)'{-f,--force}'[forcibly copy over an existing managed file]' \ '*:file:_hg_files' @@ -524,8 +524,8 @@ _hg_cmd_copy() { _hg_cmd_diff() { typeset -A opt_args - _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_diff_opts \ - '*'{-r,--rev}'+[revision]:revision:_hg_revrange' \ + _arguments -s : $_hg_global_opts $_hg_pat_opts $_hg_diff_opts \ + '*'{-r+,--rev=}'[revision]:revision:_hg_revrange' \ '(--show-function -p)'{-p,--show-function}'[show which function each change is in]' \ '(--ignore-all-space -w)'{-w,--ignore-all-space}'[ignore white space when comparing lines]' \ '(--ignore-space-change -b)'{-b,--ignore-space-change}'[ignore changes in the amount of white space]' \ @@ -544,99 +544,99 @@ _hg_cmd_diff() { } _hg_cmd_export() { - _arguments -s -w : $_hg_global_opts $_hg_diff_opts \ + _arguments -s : $_hg_global_opts $_hg_diff_opts \ '(--outout -o)'{-o+,--output}'[print output to file with formatted name]:filespec:' \ '--switch-parent[diff against the second parent]' \ '*:revision:_hg_tags' } _hg_cmd_grep() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ '(--print0 -0)'{-0,--print0}'[end filenames with NUL]' \ '--all[print all revisions with matches]' \ '(--follow -f)'{-f,--follow}'[follow changeset or file history]' \ '(--ignore-case -i)'{-i,--ignore-case}'[ignore case when matching]' \ '(--files-with-matches -l)'{-l,--files-with-matches}'[print only filenames and revs that match]' \ '(--line-number -n)'{-n,--line-number}'[print matching line numbers]' \ - '*'{-r+,--rev}'[search in given revision range]:revision:_hg_revrange' \ + '*'{-r+,--rev=}'[search in given revision range]:revision:_hg_revrange' \ '(--user -u)'{-u,--user}'[print user who committed change]' \ '1:search pattern:' \ '*:files:_hg_files' } _hg_cmd_heads() { - _arguments -s -w : $_hg_global_opts $_hg_style_opts \ - '(--rev -r)'{-r+,--rev}'[show only heads which are descendants of rev]:revision:_hg_tags' + _arguments -s : $_hg_global_opts $_hg_style_opts \ + '(--rev -r)'{-r+,--rev=}'[show only heads which are descendants of rev]:revision:_hg_tags' } _hg_cmd_help() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '*:mercurial command:_hg_commands' } _hg_cmd_identify() { - _arguments -s -w : $_hg_global_opts \ - '(--rev -r)'{-r+,--rev}'[identify the specified rev]:revision:_hg_tags' \ - '(--num -n)'{-n+,--num}'[show local revision number]' \ - '(--id -i)'{-i+,--id}'[show global revision id]' \ - '(--branch -b)'{-b+,--branch}'[show branch]' \ - '(--tags -t)'{-t+,--tags}'[show tags]' + _arguments -s : $_hg_global_opts \ + '(--rev -r)'{-r+,--rev=}'[identify the specified rev]:revision:_hg_tags' \ + '(--num -n)'{-n+,--num=}'[show local revision number]' \ + '(--id -i)'{-i+,--id=}'[show global revision id]' \ + '(--branch -b)'{-b+,--branch=}'[show branch]' \ + '(--tags -t)'{-t+,--tags=}'[show tags]' } _hg_cmd_import() { - _arguments -s -w : $_hg_global_opts \ - '(--strip -p)'{-p+,--strip}'[directory strip option for patch (default: 1)]:count:' \ - '(--message -m)'{-m+,--message}'[use as commit message]:text:' \ + _arguments -s : $_hg_global_opts \ + '(--strip -p)'{-p+,--strip=}'[directory strip option for patch (default: 1)]:count:' \ + '(--message -m)'{-m+,--message=}'[use as commit message]:text:' \ '(--force -f)'{-f,--force}'[skip check for outstanding uncommitted changes]' \ '*:patch:_files' } _hg_cmd_incoming() { - _arguments -s -w : $_hg_global_opts $_hg_remote_opts $_hg_style_opts \ + _arguments -s : $_hg_global_opts $_hg_remote_opts $_hg_style_opts \ '(--no-merges -M)'{-M,--no-merges}'[do not show merge revisions]' \ '(--force -f)'{-f,--force}'[run even when the remote repository is unrelated]' \ '(--patch -p)'{-p,--patch}'[show patch]' \ - '(--rev -r)'{-r+,--rev}'[a specific revision up to which you would like to pull]:revision:_hg_tags' \ + '(--rev -r)'{-r+,--rev=}'[a specific revision up to which you would like to pull]:revision:_hg_tags' \ '(--newest-first -n)'{-n,--newest-first}'[show newest record first]' \ '--bundle[file to store the bundles into]:bundle file:_files' \ ':source:_hg_remote' } _hg_cmd_init() { - _arguments -s -w : $_hg_global_opts $_hg_remote_opts \ + _arguments -s : $_hg_global_opts $_hg_remote_opts \ ':dir:_files -/' } _hg_cmd_locate() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ - '(--rev -r)'{-r+,--rev}'[search repository as it stood at revision]:revision:_hg_tags' \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ + '(--rev -r)'{-r+,--rev=}'[search repository as it stood at revision]:revision:_hg_tags' \ '(--print0 -0)'{-0,--print0}'[end filenames with NUL, for use with xargs]' \ '(--fullpath -f)'{-f,--fullpath}'[print complete paths]' \ '*:search pattern:_hg_files' } _hg_cmd_log() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_style_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts $_hg_style_opts \ '(--follow --follow-first -f)'{-f,--follow}'[follow changeset or history]' \ '(-f --follow)--follow-first[only follow the first parent of merge changesets]' \ '(--copies -C)'{-C,--copies}'[show copied files]' \ - '(--keyword -k)'{-k+,--keyword}'[search for a keyword]:' \ - '(--limit -l)'{-l+,--limit}'[limit number of changes displayed]:' \ + '(--keyword -k)'{-k+,--keyword=}'[search for a keyword]:' \ + '(--limit -l)'{-l+,--limit=}'[limit number of changes displayed]:' \ '*'{-r,--rev}'[show the specified revision or range]:revision:_hg_revrange' \ '(--no-merges -M)'{-M,--no-merges}'[do not show merges]' \ '(--only-merges -m)'{-m,--only-merges}'[show only merges]' \ '(--patch -p)'{-p,--patch}'[show patch]' \ - '(--prune -P)'{-P+,--prune}'[do not display revision or any of its ancestors]:revision:_hg_tags' \ + '(--prune -P)'{-P+,--prune=}'[do not display revision or any of its ancestors]:revision:_hg_tags' \ '*:files:_hg_files' } _hg_cmd_manifest() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ ':revision:_hg_tags' } _hg_cmd_merge() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--force -f)'{-f,--force}'[force a merge with outstanding changes]' \ '(--rev -r 1)'{-r,--rev}'[revision to merge]:revision:_hg_mergerevs' \ '(--preview -P)'{-P,--preview}'[review revisions to merge (no merge is performed)]' \ @@ -644,38 +644,38 @@ _hg_cmd_merge() { } _hg_cmd_outgoing() { - _arguments -s -w : $_hg_global_opts $_hg_remote_opts $_hg_style_opts \ + _arguments -s : $_hg_global_opts $_hg_remote_opts $_hg_style_opts \ '(--no-merges -M)'{-M,--no-merges}'[do not show merge revisions]' \ '(--force -f)'{-f,--force}'[run even when the remote repository is unrelated]' \ '(--patch -p)'{-p,--patch}'[show patch]' \ - '(--rev -r)'{-r+,--rev}'[a specific revision you would like to push]' \ + '(--rev -r)'{-r+,--rev=}'[a specific revision you would like to push]' \ '(--newest-first -n)'{-n,--newest-first}'[show newest record first]' \ ':destination:_hg_remote' } _hg_cmd_parents() { - _arguments -s -w : $_hg_global_opts $_hg_style_opts \ - '(--rev -r)'{-r+,--rev}'[show parents of the specified rev]:revision:_hg_tags' \ + _arguments -s : $_hg_global_opts $_hg_style_opts \ + '(--rev -r)'{-r+,--rev=}'[show parents of the specified rev]:revision:_hg_tags' \ ':last modified file:_hg_files' } _hg_cmd_paths() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ ':path:_hg_paths' } _hg_cmd_pull() { - _arguments -s -w : $_hg_global_opts $_hg_remote_opts \ + _arguments -s : $_hg_global_opts $_hg_remote_opts \ '(--force -f)'{-f,--force}'[run even when the remote repository is unrelated]' \ '(--update -u)'{-u,--update}'[update to new tip if changesets were pulled]' \ - '(--rev -r)'{-r+,--rev}'[a specific revision up to which you would like to pull]:revision:' \ + '(--rev -r)'{-r+,--rev=}'[a specific revision up to which you would like to pull]:revision:' \ ':source:_hg_remote' } _hg_cmd_push() { - _arguments -s -w : $_hg_global_opts $_hg_remote_opts \ + _arguments -s : $_hg_global_opts $_hg_remote_opts \ '(--force -f)'{-f,--force}'[force push]' \ - '(--rev -r)'{-r+,--rev}'[a specific revision you would like to push]:revision:_hg_tags' \ + '(--rev -r)'{-r+,--rev=}'[a specific revision you would like to push]:revision:_hg_tags' \ '*'{-B,--bookmark=}'[bookmark to push]:bookmark:_hg_bookmarks_internal' \ '*'{-b,--branch=}'[branch to push]:branch:_hg_branches_internal' \ '--insecure[do not verify server certificate]' \ @@ -684,14 +684,14 @@ _hg_cmd_push() { } _hg_cmd_remove() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ '(--after -A)'{-A,--after}'[record remove that has already occurred]' \ '(--force -f)'{-f,--force}'[remove file even if modified]' \ '*:file:_hg_files' } _hg_cmd_rename() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ '(--after -A)'{-A,--after}'[record a rename that has already occurred]' \ '(--force -f)'{-f,--force}'[forcibly copy over an existing managed file]' \ '*:file:_hg_files' @@ -701,7 +701,7 @@ _hg_cmd_resolve() { local context state line typeset -A opt_args - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--list -l --mark -m --unmark -u)'{-l,--list}'[list state of files needing merge]:*:merged files:->resolve_files' \ '(--mark -m --list -l --unmark -u)'{-m,--mark}'[mark files as resolved]:*:unresolved files:_hg_unresolved' \ '(--unmark -u --list -l --mark -m)'{-u,--unmark}'[unmark files as resolved]:*:resolved files:_hg_resolved' \ @@ -718,9 +718,9 @@ _hg_cmd_revert() { local context state line typeset -A opt_args - _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \ '(--all -a :)'{-a,--all}'[revert all changes when no arguments given]' \ - '(--rev -r)'{-r+,--rev}'[revision to revert to]:revision:_hg_tags' \ + '(--rev -r)'{-r+,--rev=}'[revision to revert to]:revision:_hg_tags' \ '--no-backup[do not save backup copies of files]' \ '*:file:->diff_files' @@ -738,13 +738,13 @@ _hg_cmd_revert() { } _hg_cmd_serve() { - _arguments -s -w : $_hg_global_opts \ - '(--accesslog -A)'{-A+,--accesslog}'[name of access log file]:log file:_files' \ - '(--errorlog -E)'{-E+,--errorlog}'[name of error log file]:log file:_files' \ + _arguments -s : $_hg_global_opts \ + '(--accesslog -A)'{-A+,--accesslog=}'[name of access log file]:log file:_files' \ + '(--errorlog -E)'{-E+,--errorlog=}'[name of error log file]:log file:_files' \ '(--daemon -d)'{-d,--daemon}'[run server in background]' \ - '(--port -p)'{-p+,--port}'[listen port]:listen port:' \ - '(--address -a)'{-a+,--address}'[interface address]:interface address:' \ - '(--name -n)'{-n+,--name}'[name to show in web pages]:repository name:' \ + '(--port -p)'{-p+,--port=}'[listen port]:listen port:' \ + '(--address -a)'{-a+,--address=}'[interface address]:interface address:' \ + '(--name -n)'{-n+,--name=}'[name to show in web pages]:repository name:' \ '(--templates -t)'{-t,--templates}'[web template directory]:template dir:_files -/' \ '--style[web template style]:style' \ '--stdio[for remote clients]' \ @@ -752,13 +752,13 @@ _hg_cmd_serve() { } _hg_cmd_showconfig() { - _arguments -s -w : $_hg_global_opts \ - '(--untrusted -u)'{-u+,--untrusted}'[show untrusted configuration options]' \ + _arguments -s : $_hg_global_opts \ + '(--untrusted -u)'{-u+,--untrusted=}'[show untrusted configuration options]' \ ':config item:_hg_config' } _hg_cmd_status() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ '(--all -A)'{-A,--all}'[show status of all files]' \ '(--modified -m)'{-m,--modified}'[show only modified files]' \ '(--added -a)'{-a,--added}'[show only added files]' \ @@ -775,37 +775,37 @@ _hg_cmd_status() { } _hg_cmd_tag() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--local -l)'{-l,--local}'[make the tag local]' \ - '(--message -m)'{-m+,--message}'[message for tag commit log entry]:message:' \ - '(--date -d)'{-d+,--date}'[record datecode as commit date]:date code:' \ - '(--user -u)'{-u+,--user}'[record user as commiter]:user:' \ - '(--rev -r)'{-r+,--rev}'[revision to tag]:revision:_hg_tags' \ + '(--message -m)'{-m+,--message=}'[message for tag commit log entry]:message:' \ + '(--date -d)'{-d+,--date=}'[record datecode as commit date]:date code:' \ + '(--user -u)'{-u+,--user=}'[record user as commiter]:user:' \ + '(--rev -r)'{-r+,--rev=}'[revision to tag]:revision:_hg_tags' \ ':tag name:' } _hg_cmd_tip() { - _arguments -s -w : $_hg_global_opts $_hg_style_opts \ + _arguments -s : $_hg_global_opts $_hg_style_opts \ '(--patch -p)'{-p,--patch}'[show patch]' } _hg_cmd_unbundle() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--update -u)'{-u,--update}'[update to new tip if changesets were unbundled]' \ ':files:_files' } _hg_cmd_update() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--clean -C)'{-C,--clean}'[overwrite locally modified files]' \ - '(--rev -r)'{-r+,--rev}'[revision]:revision:_hg_tags' \ + '(--rev -r)'{-r+,--rev=}'[revision]:revision:_hg_tags' \ ':revision:_hg_tags' } # HGK _hg_cmd_view() { - _arguments -s -w : $_hg_global_opts \ - '(--limit -l)'{-l+,--limit}'[limit number of changes displayed]:' \ + _arguments -s : $_hg_global_opts \ + '(--limit -l)'{-l+,--limit=}'[limit number of changes displayed]:' \ ':revision range:_hg_tags' } @@ -859,35 +859,35 @@ _hg_qseries_opts=( '(--summary -s)'{-s,--summary}'[print first line of patch header]') _hg_cmd_qapplied() { - _arguments -s -w : $_hg_global_opts $_hg_qseries_opts + _arguments -s : $_hg_global_opts $_hg_qseries_opts } _hg_cmd_qdelete() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--keep -k)'{-k,--keep}'[keep patch file]' \ - '*'{-r+,--rev}'[stop managing a revision]:applied patch:_hg_revrange' \ + '*'{-r+,--rev=}'[stop managing a revision]:applied patch:_hg_revrange' \ '*:unapplied patch:_hg_qdeletable' } _hg_cmd_qdiff() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts \ '*:pattern:_hg_files' } _hg_cmd_qfold() { - _arguments -s -w : $_hg_global_opts $_h_commit_opts \ + _arguments -s : $_hg_global_opts $_h_commit_opts \ '(--keep,-k)'{-k,--keep}'[keep folded patch files]' \ '*:unapplied patch:_hg_qunapplied' } _hg_cmd_qgoto() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--force -f)'{-f,--force}'[overwrite any local changes]' \ ':patch:_hg_qseries' } _hg_cmd_qguard() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--list -l)'{-l,--list}'[list all patches and guards]' \ '(--none -n)'{-n,--none}'[drop all guards]' \ ':patch:_hg_qseries' \ @@ -895,66 +895,66 @@ _hg_cmd_qguard() { } _hg_cmd_qheader() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ ':patch:_hg_qseries' } _hg_cmd_qimport() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--existing -e)'{-e,--existing}'[import file in patch dir]' \ - '(--name -n 2)'{-n+,--name}'[patch file name]:name:' \ + '(--name -n 2)'{-n+,--name=}'[patch file name]:name:' \ '(--force -f)'{-f,--force}'[overwrite existing files]' \ - '*'{-r+,--rev}'[place existing revisions under mq control]:revision:_hg_revrange' \ + '*'{-r+,--rev=}'[place existing revisions under mq control]:revision:_hg_revrange' \ '*:patch:_files' } _hg_cmd_qnew() { - _arguments -s -w : $_hg_global_opts $_hg_commit_opts \ + _arguments -s : $_hg_global_opts $_hg_commit_opts \ '(--force -f)'{-f,--force}'[import uncommitted changes into patch]' \ ':patch:' } _hg_cmd_qnext() { - _arguments -s -w : $_hg_global_opts $_hg_qseries_opts + _arguments -s : $_hg_global_opts $_hg_qseries_opts } _hg_cmd_qpop() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--all -a :)'{-a,--all}'[pop all patches]' \ - '(--name -n)'{-n+,--name}'[queue name to pop]:' \ + '(--name -n)'{-n+,--name=}'[queue name to pop]:' \ '(--force -f)'{-f,--force}'[forget any local changes]' \ ':patch:_hg_qapplied' } _hg_cmd_qprev() { - _arguments -s -w : $_hg_global_opts $_hg_qseries_opts + _arguments -s : $_hg_global_opts $_hg_qseries_opts } _hg_cmd_qpush() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--all -a :)'{-a,--all}'[apply all patches]' \ '(--list -l)'{-l,--list}'[list patch name in commit text]' \ - '(--merge -m)'{-m+,--merge}'[merge from another queue]:' \ - '(--name -n)'{-n+,--name}'[merge queue name]:' \ + '(--merge -m)'{-m+,--merge=}'[merge from another queue]:' \ + '(--name -n)'{-n+,--name=}'[merge queue name]:' \ '(--force -f)'{-f,--force}'[apply if the patch has rejects]' \ ':patch:_hg_qunapplied' } _hg_cmd_qrefresh() { - _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_commit_opts \ + _arguments -s : $_hg_global_opts $_hg_pat_opts $_hg_commit_opts \ '(--git -g)'{-g,--git}'[use git extended diff format]' \ '(--short -s)'{-s,--short}'[short refresh]' \ '*:files:_hg_files' } _hg_cmd_qrename() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ ':patch:_hg_qseries' \ ':destination:' } _hg_cmd_qselect() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--none -n :)'{-n,--none}'[disable all guards]' \ '(--series -s :)'{-s,--series}'[list all guards in series file]' \ '--pop[pop to before first guarded applied patch]' \ @@ -963,20 +963,20 @@ _hg_cmd_qselect() { } _hg_cmd_qseries() { - _arguments -s -w : $_hg_global_opts $_hg_qseries_opts \ + _arguments -s : $_hg_global_opts $_hg_qseries_opts \ '(--missing -m)'{-m,--missing}'[print patches not in series]' } _hg_cmd_qunapplied() { - _arguments -s -w : $_hg_global_opts $_hg_qseries_opts + _arguments -s : $_hg_global_opts $_hg_qseries_opts } _hg_cmd_qtop() { - _arguments -s -w : $_hg_global_opts $_hg_qseries_opts + _arguments -s : $_hg_global_opts $_hg_qseries_opts } _hg_cmd_strip() { - _arguments -s -w : $_hg_global_opts \ + _arguments -s : $_hg_global_opts \ '(--force -f)'{-f,--force}'[force multi-head removal]' \ '(--backup -b)'{-b,--backup}'[bundle unrelated changesets]' \ '(--nobackup -n)'{-n,--nobackup}'[no backups]' \ -- cgit v1.2.3 From 50721a1986a3637e923ccc4531135b8aa39c8e70 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 26 Sep 2015 13:46:20 -0700 Subject: 36641: fix multibyte handling in incremental search during menu selection --- ChangeLog | 5 +++++ Src/Zle/complist.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f700ec067..964e340f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-26 Barton E. Schaefer + + * 36641: Src/Modules/complist.c: fix multibyte handling in + incremental search during menu selection + 2015-09-26 Daniel Shahaf * unposted (see 36633): Completion/Unix/Command/_hg: _hg: diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 01bcb7cf8..433701514 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -3300,7 +3300,7 @@ domenuselect(Hookdef dummy, Chdata dat) int len; memset(&mbs, 0, sizeof(mbs)); - len = wcrtomb(s, lastchar_wide, &mbs); + len = wcrtomb(toins, lastchar_wide, &mbs); if (len < 0) len = 0; insert[len] = '\0'; -- cgit v1.2.3 From 0cfa2dcfc424667f7fc29cf9a13c68883f3ffc28 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Mon, 28 Sep 2015 00:09:03 +0900 Subject: 36631: separate _zsh from _sh Do all the completion for zsh by _arguments --- ChangeLog | 5 +++++ Completion/Unix/Command/_sh | 17 +---------------- Completion/Unix/Command/_zsh | 8 ++++++++ 3 files changed, 14 insertions(+), 16 deletions(-) create mode 100644 Completion/Unix/Command/_zsh diff --git a/ChangeLog b/ChangeLog index 964e340f0..05c163014 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-28 Jun-ichi Takimoto + + * 36631: Completion/Unix/Command/_sh, + Completion/Unix/Command/_zsh: separate _zsh from _sh + 2015-09-26 Barton E. Schaefer * 36641: Src/Modules/complist.c: fix multibyte handling in diff --git a/Completion/Unix/Command/_sh b/Completion/Unix/Command/_sh index 1b5112212..2afb46621 100644 --- a/Completion/Unix/Command/_sh +++ b/Completion/Unix/Command/_sh @@ -1,13 +1,4 @@ -#compdef sh ksh bash zsh csh tcsh rc - -if [[ $service == zsh ]]; then - # try a bit harder - if [[ ${words[CURRENT-1]} == -o ]]; then - _options - # no other possibilities - return - fi -fi +#compdef sh ksh bash csh tcsh rc if (( CURRENT == ${words[(i)-c]} + 1 )); then _cmdstring @@ -21,9 +12,3 @@ else fi _default fi - -local ret=$? - -[[ $service == zsh ]] && _arguments -S -s -- && ret=0 - -return ret diff --git a/Completion/Unix/Command/_zsh b/Completion/Unix/Command/_zsh new file mode 100644 index 000000000..3b6d7ad4f --- /dev/null +++ b/Completion/Unix/Command/_zsh @@ -0,0 +1,8 @@ +#compdef zsh + +_arguments -S -s : \ + '*-o+[set named option]:option:_options' \ + '*+o+[unset named option]:option:_options' \ + '(1 -)-c[run a command]:command:_cmdstring' \ + '(-)1:script file:_files' \ + '*:command arguments' -- -- cgit v1.2.3 From c2254cfe2c9b4bace38035ec95e4bad4ef46c9f5 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 27 Sep 2015 12:43:03 -0700 Subject: 36661: replace obsolete "autobins" setting with "autofeatures" --- ChangeLog | 5 +++++ Src/Modules/curses.mdd | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 05c163014..13a62fdfa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-27 Barton E. Schaefer + + * 36661: Src/Modules/curses.mdd: replace obsolete "autobins" + setting with "autofeatures" + 2015-09-28 Jun-ichi Takimoto * 36631: Completion/Unix/Command/_sh, diff --git a/Src/Modules/curses.mdd b/Src/Modules/curses.mdd index 669c4f5c7..80c8f867b 100644 --- a/Src/Modules/curses.mdd +++ b/Src/Modules/curses.mdd @@ -2,7 +2,7 @@ name=zsh/curses link='if test "x$ac_cv_func_initscr" = xyes && test "x$zsh_cv_path_curses_header" != x; then echo dynamic; else echo no; fi' load=no -autobins="zcurses" +autofeatures="b:zcurses" objects="curses.o" -- cgit v1.2.3 From 7e4784f90105a21af3f5e0a52aa8d2465919e635 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 27 Sep 2015 12:43:25 -0700 Subject: 36663: replace obsolete "autobins" commentary with "autofeatures" --- ChangeLog | 3 +++ Src/mkmakemod.sh | 10 +++------- Src/zsh.mdd | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 13a62fdfa..3562b1379 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-09-27 Barton E. Schaefer + * 36663: Src/mkmakemod.sh, Src/zsh.mdd: replace obsolete + "autobins" commentary with "autofeatures" + * 36661: Src/Modules/curses.mdd: replace obsolete "autobins" setting with "autofeatures" diff --git a/Src/mkmakemod.sh b/Src/mkmakemod.sh index 002160910..3ccf9c5e5 100644 --- a/Src/mkmakemod.sh +++ b/Src/mkmakemod.sh @@ -21,12 +21,8 @@ # moddeps modules on which this module depends (default none) # nozshdep non-empty indicates no dependence on the `zsh/main' pseudo-module # alwayslink if non-empty, always link the module into the executable -# autobins builtins defined by the module, for autoloading -# autoinfixconds infix condition codes defined by the module, for -# autoloading (without the leading `-') -# autoprefixconds like autoinfixconds, but for prefix condition codes -# autoparams parameters defined by the module, for autoloading -# automathfuncs math functions defined by the module, for autoloading +# autofeatures features defined by the module, for autoloading +# autofeatures_emu As autofeatures, but for non-zsh emulation modes # objects .o files making up this module (*must* be defined) # proto .syms files for this module (default generated from $objects) # headers extra headers for this module (default none) @@ -189,7 +185,7 @@ if $first_stage; then for mddname in $here_mddnames; do unset name moddeps nozshdep alwayslink hasexport - unset autobins autoinfixconds autoprefixconds autoparams automathfuncs + unset autofeatures autofeatures_emu unset objects proto headers hdrdeps otherincs . $top_srcdir/$the_subdir/${mddname}.mdd q_name=`echo $name | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'` diff --git a/Src/zsh.mdd b/Src/zsh.mdd index c2e59c910..86dd58866 100644 --- a/Src/zsh.mdd +++ b/Src/zsh.mdd @@ -7,7 +7,7 @@ functions='Functions/Chpwd/* Functions/Exceptions/* Functions/Misc/* Functions/M nozshdep=1 alwayslink=1 -# autobins not specified because of alwayslink +# autofeatures not specified because of alwayslink objects="builtin.o compat.o cond.o context.o \ exec.o glob.o hashtable.o hashnameddir.o \ -- cgit v1.2.3 From 36abe20c0f53015b816d5f3bdd1eeed713614233 Mon Sep 17 00:00:00 2001 From: Matthew Martin Date: Sun, 27 Sep 2015 01:03:16 -0500 Subject: 36653: OpenBSD's usermod has no -a flag --- ChangeLog | 5 +++++ Completion/Unix/Command/_user_admin | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3562b1379..b1fe74da4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-27 Matthew Martin + + * 36653: Completion/Unix/Command/_user_admin: OpenBSD's usermod + has no -a flag + 2015-09-27 Barton E. Schaefer * 36663: Src/mkmakemod.sh, Src/zsh.mdd: replace obsolete diff --git a/Completion/Unix/Command/_user_admin b/Completion/Unix/Command/_user_admin index 31ccbf1c2..3653308a1 100644 --- a/Completion/Unix/Command/_user_admin +++ b/Completion/Unix/Command/_user_admin @@ -44,8 +44,8 @@ if [[ $service = user* ]]; then "(-U -p)-L[lock user's password]" "(-L -p)-U[unlock user's password]" ) + [[ $OSTYPE = openbsd* ]] || args+=('-a[append groups]') args+=( - '-a[append groups]' '-l[specify new user name]:new username' ':username:_users' ) -- cgit v1.2.3 From 2654cb43f63349cff06b3dd26932dd76f53aed4c Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 26 Sep 2015 01:59:48 +0000 Subject: 36651: WARN_CREATE_GLOBAL += math expressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this, '() { (( x=42 )) }' and '() { for (( i=0; … )) }' wouldn't warn about $x and $i, respectively, being created global. --- ChangeLog | 5 +++++ Doc/Zsh/options.yo | 3 ++- Src/exec.c | 3 ++- Src/math.c | 25 +++++++++++++++++++++++++ Test/E01options.ztst | 4 ++++ 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b1fe74da4..2cd07ffa3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-27 Daniel Shahaf + + * 36651: Doc/Zsh/options.yo Src/exec.c Src/math.c + Test/E01options.ztst: WARN_CREATE_GLOBAL += math expressions + 2015-09-27 Matthew Martin * 36653: Completion/Unix/Command/_user_admin: OpenBSD's usermod diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index abd0f8715..fbf65abbc 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -746,7 +746,8 @@ pindex(NOWARNCREATEGLOBAL) cindex(parameters, warning when created globally) item(tt(WARN_CREATE_GLOBAL))( Print a warning message when a global parameter is created in a function -by an assignment. This often indicates that a parameter has not been +by an assignment or in math context. +This often indicates that a parameter has not been declared local when it should have been. Parameters explicitly declared global from within a function using tt(typeset -g) do not cause a warning. Note that there is no warning when a local parameter is assigned to in diff --git a/Src/exec.c b/Src/exec.c index 109a04a26..da808d6f1 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -176,7 +176,8 @@ mod_export int sfcontext; /**/ struct execstack *exstack; -/* Stack with names of functions currently active. */ +/* Stack with names of function calls, 'source' calls, and 'eval' calls + * currently active. */ /**/ mod_export Funcstack funcstack; diff --git a/Src/math.c b/Src/math.c index 977e92345..56565a629 100644 --- a/Src/math.c +++ b/Src/math.c @@ -894,6 +894,24 @@ getcvar(char *s) } +/* If script execution is inside a function call that hasn't returned, + * return the name of that function. Else return NULL. + */ + +/**/ +static const char * +in_function_call(void) +{ + Funcstack i; + for (i = funcstack; i; i = i->prev) + if (i->tp == FS_FUNC) { + DPUTS(!i->name, "funcstack entry with no name"); + return i->name; + } + + return NULL; +} + /**/ static mnumber setmathvar(struct mathvalue *mvp, mnumber v) @@ -929,6 +947,13 @@ setmathvar(struct mathvalue *mvp, mnumber v) if (noeval) return v; untokenize(mvp->lval); + if (isset(WARNCREATEGLOBAL)) { + const char *function_name; + if (!paramtab->getnode(paramtab, mvp->lval) && + (function_name = in_function_call())) + zwarn("math parameter %s created globally in function %s", + mvp->lval, function_name); + } pm = setnparam(mvp->lval, v); if (pm) { /* diff --git a/Test/E01options.ztst b/Test/E01options.ztst index 2b91b21fa..1caee8d24 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -1110,11 +1110,15 @@ foo3=bar6 } foo4=bar7 =true + (( foo5=8 )) + integer foo6=9 + (( foo6=10 )) } fn 0:WARN_CREATE_GLOBAL option ?fn:3: scalar parameter foo1 created globally in function ?fn:5: scalar parameter foo1 created globally in function +?fn:15: math parameter foo5 created globally in function fn # This really just tests if XTRACE is egregiously broken. # To test it properly would need a full set of its own. -- cgit v1.2.3 From d85a1fcd888198d0212d7bec615751e8fe715fdd Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Mon, 28 Sep 2015 02:18:49 +0200 Subject: unposted: Fix broken case condition and "qualifer" typo --- ChangeLog | 15 ++++++++++----- Completion/Zsh/Context/_brace_parameter | 6 +++--- Completion/Zsh/Type/_delimiters | 2 +- Completion/Zsh/Type/_globquals | 2 +- Functions/Calendar/age | 2 +- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2cd07ffa3..7af8a07c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,17 @@ +2015-09-28 Mikael Magnusson + + * unposted: Completion/Zsh/Context/_brace_parameter, + Completion/Zsh/Type/_delimiters, Completion/Zsh/Type/_globquals, + Functions/Calendar/age: Fix broken case condition and "qualifer" + typo + 2015-09-27 Daniel Shahaf - * 36651: Doc/Zsh/options.yo Src/exec.c Src/math.c + * 36651: Doc/Zsh/options.yo, Src/exec.c, Src/math.c, Test/E01options.ztst: WARN_CREATE_GLOBAL += math expressions -2015-09-27 Matthew Martin - - * 36653: Completion/Unix/Command/_user_admin: OpenBSD's usermod - has no -a flag + * Matthew Martin: 36653: Completion/Unix/Command/_user_admin: + OpenBSD's usermod has no -a flag 2015-09-27 Barton E. Schaefer diff --git a/Completion/Zsh/Context/_brace_parameter b/Completion/Zsh/Context/_brace_parameter index 9eb3465ae..e77d4c58b 100644 --- a/Completion/Zsh/Context/_brace_parameter +++ b/Completion/Zsh/Context/_brace_parameter @@ -31,7 +31,7 @@ if [[ $PREFIX = *'${('[^\)]# ]]; then ([gIjsZ_]) # Single delimited argument. if [[ -z $PREFIX ]]; then - _delimiters qualifer-$char + _delimiters qualifier-$char return elif ! _globqual_delims; then # still completing argument @@ -46,7 +46,7 @@ if [[ $PREFIX = *'${('[^\)]# ]]; then _message 'integer expression' ;; - (js) + ([js]) _message "separator" ;; @@ -71,7 +71,7 @@ if [[ $PREFIX = *'${('[^\)]# ]]; then ([lr]) # One compulsory argument, two optional. if [[ -z $PREFIX ]]; then - _delimiters qualifer-$char + _delimiters qualifier-$char return else delim=$PREFIX[1] diff --git a/Completion/Zsh/Type/_delimiters b/Completion/Zsh/Type/_delimiters index bb5bba8d0..d98d5a766 100644 --- a/Completion/Zsh/Type/_delimiters +++ b/Completion/Zsh/Type/_delimiters @@ -1,6 +1,6 @@ #autoload -# Simple function to offer delimiters for modifiers and qualifers. +# Simple function to offer delimiters for modifiers and qualifiers. # Single argument is tag to use. local expl diff --git a/Completion/Zsh/Type/_globquals b/Completion/Zsh/Type/_globquals index 5cdb8f7c4..2523eb333 100644 --- a/Completion/Zsh/Type/_globquals +++ b/Completion/Zsh/Type/_globquals @@ -47,7 +47,7 @@ while [[ -n $PREFIX ]]; do (e) # complete/skip delimited command line if [[ -z $PREFIX ]]; then - _delimiters qualifer-e + _delimiters qualifier-e return elif ! _globqual_delims; then # still completing command to eval diff --git a/Functions/Calendar/age b/Functions/Calendar/age index 17cf4d13e..50755d610 100644 --- a/Functions/Calendar/age +++ b/Functions/Calendar/age @@ -1,4 +1,4 @@ -# Match the age of a file, for use as a glob qualifer. Can +# Match the age of a file, for use as a glob qualifier. Can # take one or two arguments, which can be supplied by one of two # ways (always the same for both arguments): # -- cgit v1.2.3 From 6d6b63c884a7484334a22671d2bd6ca138bb8751 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 28 Sep 2015 01:20:44 +0000 Subject: unposted: Update link to my ChangeLog generator script, on account of patching it to handle commas properly (thanks Mikael). --- ChangeLog | 6 ++++++ Etc/zsh-development-guide | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7af8a07c9..f5b1a073f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-09-28 Daniel Shahaf + + * unposted: Etc/zsh-development-guide: Update link to my + ChangeLog generator script, on account of patching it to handle + commas properly (thanks Mikael). + 2015-09-28 Mikael Magnusson * unposted: Completion/Zsh/Context/_brace_parameter, diff --git a/Etc/zsh-development-guide b/Etc/zsh-development-guide index cbbc798d3..9ca441bd8 100644 --- a/Etc/zsh-development-guide +++ b/Etc/zsh-development-guide @@ -77,7 +77,9 @@ avoided further changes to our workflow. X-Seq: 33835, 33872, 34912 http://www.zsh.org/mla/workers/2014/msg01622.html http://www.zsh.org/mla/workers/2014/msg01659.html + -> https://github.com/ft/zsh-am http://www.zsh.org/mla/workers/2015/msg00836.html + -> https://github.com/danielshahaf/zsh-dev Subject: Re: _git commit object name completion X-Seq: 35414 -- cgit v1.2.3 From 4bed2cf256cf79f8e17093d54a67f75dfa54794a Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 27 Sep 2015 23:56:38 -0700 Subject: 36669: fix ${(z)...} of an an incomplete math expression by restoring "((" at the front of the token --- ChangeLog | 5 +++++ Src/lex.c | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/ChangeLog b/ChangeLog index f5b1a073f..bebc97b53 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-28 Barton E. Schaefer + + * 36669: Src/lex.c: fix ${(z)...} of an an incomplete math + expression by restoring "((" at the front of the token + 2015-09-28 Daniel Shahaf * unposted: Etc/zsh-development-guide: Update link to my diff --git a/Src/lex.c b/Src/lex.c index 70f3d142a..89af96123 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -783,6 +783,15 @@ gettok(void) */ tokstr = NULL; return INPAR; + + case CMD_OR_MATH_ERR: + /* + * LEXFLAGS_ACTIVE means we came from bufferwords(), + * so we treat as an incomplete math expression + */ + if (lexflags & LEXFLAGS_ACTIVE) + tokstr = dyncat("((", tokstr ? tokstr : ""); + /* fall through */ default: return LEXERR; -- cgit v1.2.3 From 45bdc87a1f4058f9a8cd5eaceda704284d4a89a1 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 23 Sep 2015 20:55:40 +0200 Subject: 36601: vcs_info: handle missing .git/rebase-apply/{next,msg-clean} When pressing Ctrl-C after `git am`, only `last` exists in `.git/rebase-apply/`, which is empty. This patch fixes it to fall back to "no patch applied" then. --- ChangeLog | 5 +++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 25 +++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index bebc97b53..5a4db9010 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-28 Daniel Hahler + + * 36601: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: + vcs_info: handle missing .git/rebase-apply/{next,msg-clean} + 2015-09-28 Barton E. Schaefer * 36669: Src/lex.c: fix ${(z)...} of an an incomplete math diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 638ea4572..8ecc7c7f7 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -217,18 +217,21 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then elif [[ -d "${gitdir}/rebase-apply" ]]; then # Fake patch names for all but current patch patchdir="${gitdir}/rebase-apply" - local cur=$(< "${patchdir}/next") - local p subject - for p in $(seq $(($cur - 1))); do - git_patches_applied+=("$(printf "%04d" $p) ?") - done - subject="${$(< "${patchdir}/msg-clean")[(f)1]}" - if [[ -f "${patchdir}/original-commit" ]]; then - git_patches_applied+=("$(< ${patchdir}/original-commit) $subject") - else - git_patches_applied+=("? $subject") + local next="${patchdir}/next" + if [[ -f $next ]]; then + local cur=$(< $next) + local p subject + for p in $(seq $(($cur - 1))); do + git_patches_applied+=("$(printf "%04d" $p) ?") + done + subject="${$(< "${patchdir}/msg-clean")[(f)1]}" + if [[ -f "${patchdir}/original-commit" ]]; then + git_patches_applied+=("$(< ${patchdir}/original-commit) $subject") + else + git_patches_applied+=("? $subject") + fi + git_patches_unapplied=($(seq $cur $(< "${patchdir}/last"))) fi - git_patches_unapplied=($(seq $cur $(< "${patchdir}/last"))) VCS_INFO_git_handle_patches elif [[ -f "${gitdir}/MERGE_HEAD" ]]; then -- cgit v1.2.3 From a5cb918d4018bbd5cdc8751e5c9f4f55f0a211be Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 28 Sep 2015 18:13:49 +0000 Subject: unposted: Test for 36669 --- ChangeLog | 4 ++++ Test/D04parameter.ztst | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5a4db9010..546620d6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-09-28 Daniel Shahaf + + * unposted: Test/D04parameter.ztst: Test for 36669 + 2015-09-28 Daniel Hahler * 36601: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index e380e19b8..f1cc23e7c 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -572,6 +572,12 @@ >echo >three + print -rl - ${(z):-":;(( echo 42 "} +0:${(z)} with incomplete math expressions +>: +>; +>(( echo 42 + psvar=(dog) setopt promptsubst foo='It shouldn'\''t $(happen) to a %1v.' -- cgit v1.2.3 From f9d7651c2554bb5db0373f63185ff358f795ab3c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 28 Sep 2015 20:31:51 +0100 Subject: 36682: expand pattern interface to optimise unmetafication --- ChangeLog | 6 + Src/Zle/complist.c | 5 +- Src/Zle/zle_hist.c | 4 +- Src/glob.c | 56 +++++---- Src/pattern.c | 337 +++++++++++++++++++++++++++++++++++++---------------- Src/zsh.h | 10 ++ 6 files changed, 288 insertions(+), 130 deletions(-) diff --git a/ChangeLog b/ChangeLog index 546620d6b..38e0e4627 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-09-28 Peter Stephenson + + * 36682: Src/glob.c, Src/pattern.c, Src/zsh.h, + Src/Zle/complist,c, Src/Zle/zle_hist.c: expand pattern interface + to allow unmetafying trial string once for reuse. + 2015-09-28 Daniel Shahaf * unposted: Test/D04parameter.ztst: Test for 36669 diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 433701514..986ad31ea 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -868,7 +868,7 @@ putmatchcol(char *group, char *n) nrefs = MAX_POS - 1; if ((!pc->prog || !group || pattry(pc->prog, group)) && - pattryrefs(pc->pat, n, -1, -1, 0, &nrefs, begpos, endpos)) { + pattryrefs(pc->pat, n, -1, -1, NULL, 0, &nrefs, begpos, endpos)) { if (pc->cols[1]) { patcols = pc->cols; @@ -900,7 +900,8 @@ putfilecol(char *group, char *filename, mode_t m, int special) nrefs = MAX_POS - 1; if ((!pc->prog || !group || pattry(pc->prog, group)) && - pattryrefs(pc->pat, filename, -1, -1, 0, &nrefs, begpos, endpos)) { + pattryrefs(pc->pat, filename, -1, -1, NULL, + 0, &nrefs, begpos, endpos)) { if (pc->cols[1]) { patcols = pc->cols; diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index 0cff0391a..95d96c95c 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -1306,8 +1306,8 @@ doisearch(char **args, int dir, int pattern) * this mode. */ if (!skip_pos && - pattryrefs(patprog, zt, -1, -1, 0, NULL, NULL, - &end_pos)) + pattryrefs(patprog, zt, -1, -1, NULL, 0, + NULL, NULL, &end_pos)) t = zt; } else { if (!matchlist && !skip_pos) { diff --git a/Src/glob.c b/Src/glob.c index fa3ce25f4..8bf73520f 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2780,7 +2780,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, p->flags &= ~(PAT_NOTSTART|PAT_NOTEND); if (fl & SUB_ALL) { - int i = matched && pattry(p, s); + int i = matched && pattrylen(p, s, -1, -1, NULL, 0); *sp = get_match_ret(*sp, 0, i ? l : 0, fl, i ? replstr : 0, NULL); if (! **sp && (((fl & SUB_MATCH) && !i) || ((fl & SUB_REST) && i))) return 0; @@ -2809,7 +2809,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, * Largest/smallest possible match at head of string. * First get the longest match... */ - if (pattry(p, s)) { + if (pattrylen(p, s, -1, -1, NULL, 0)) { /* patmatchlen returns metafied length, as we need */ int mlen = patmatchlen(); if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { @@ -2820,7 +2820,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, mb_charinit(); for (t = s, umlen = 0; t < s + mlen; ) { set_pat_end(p, *t); - if (pattrylen(p, s, t - s, umlen, 0)) { + if (pattrylen(p, s, t - s, umlen, NULL, 0)) { mlen = patmatchlen(); break; } @@ -2847,7 +2847,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, tmatch = NULL; for (ioff = 0, t = s, umlen = umltot; t < s + l; ioff++) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, ioff)) + if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) tmatch = t; if (fl & SUB_START) break; @@ -2857,7 +2857,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, *sp = get_match_ret(*sp, tmatch - s, l, fl, replstr, NULL); return 1; } - if (!(fl & SUB_START) && pattrylen(p, s + l, 0, 0, ioff)) { + if (!(fl & SUB_START) && pattrylen(p, s + l, 0, 0, NULL, ioff)) { *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); return 1; } @@ -2870,7 +2870,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, mb_charinit(); for (ioff = 0, t = s, umlen = umltot; t < s + l; ioff++) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, ioff)) { + if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { *sp = get_match_ret(*sp, t-s, l, fl, replstr, NULL); return 1; } @@ -2878,7 +2878,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, break; umlen -= iincchar(&t); } - if (!(fl & SUB_START) && pattrylen(p, s + l, 0, 0, ioff)) { + if (!(fl & SUB_START) && pattrylen(p, s + l, 0, 0, NULL, ioff)) { *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); return 1; } @@ -2887,7 +2887,8 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, case SUB_SUBSTR: /* Smallest at start, but matching substrings. */ set_pat_start(p, l); - if (!(fl & SUB_GLOBAL) && pattry(p, s + l) && !--n) { + if (!(fl & SUB_GLOBAL) && pattrylen(p, s + l, -1, -1, NULL, 0) && + !--n) { *sp = get_match_ret(*sp, 0, 0, fl, replstr, NULL); return 1; } /* fall through */ @@ -2908,7 +2909,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, for (; t < s + l; ioff++) { /* Find the longest match from this position. */ set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, ioff)) { + if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { char *mpos = t + patmatchlen(); if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { char *ptr; @@ -2922,7 +2923,8 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, */ for (ptr = t, umlen2 = 0; ptr < mpos;) { set_pat_end(p, *ptr); - if (pattrylen(p, t, ptr - t, umlen2, ioff)) { + if (pattrylen(p, t, ptr - t, umlen2, + NULL, ioff)) { mpos = t + patmatchlen(); break; } @@ -2970,7 +2972,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, */ set_pat_start(p, l); if ((fl & (SUB_LONG|SUB_GLOBAL)) == SUB_LONG && - pattry(p, s + l) && !--n) { + pattrylen(p, s + l, -1, -1, NULL, 0) && !--n) { *sp = get_match_ret(*sp, 0, 0, fl, replstr, repllist); return 1; } @@ -2981,7 +2983,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, /* Longest/shortest at end, matching substrings. */ if (!(fl & SUB_LONG)) { set_pat_start(p, l); - if (pattrylen(p, s + l, 0, 0, umltot) && !--n) { + if (pattrylen(p, s + l, 0, 0, NULL, umltot) && !--n) { *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); return 1; } @@ -3001,7 +3003,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, mb_charinit(); for (ioff = 0, t = s, umlen = umltot; t < s + l; ioff++) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, ioff)) { + if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { nmatches++; tmatch = t; } @@ -3017,7 +3019,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, mb_charinit(); for (ioff = 0, t = s, umlen = umltot; t < s + l; ioff++) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, ioff) && + if (pattrylen(p, t, s + l - t, umlen, NULL, ioff) && !n--) { tmatch = t; break; @@ -3030,7 +3032,8 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { for (t = tmatch, umlen = 0; t < mpos; ) { set_pat_end(p, *t); - if (pattrylen(p, tmatch, t - tmatch, umlen, ioff)) { + if (pattrylen(p, tmatch, t - tmatch, umlen, + NULL, ioff)) { mpos = tmatch + patmatchlen(); break; } @@ -3042,7 +3045,8 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, return 1; } set_pat_start(p, l); - if ((fl & SUB_LONG) && pattrylen(p, s + l, 0, 0, umltot) && !--n) { + if ((fl & SUB_LONG) && pattrylen(p, s + l, 0, 0, NULL, umltot) && + !--n) { *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); return 1; } @@ -3167,7 +3171,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, */ for (t = s, umlen = 0; t < s + mlen; METAINC(t), umlen++) { set_pat_end(p, *t); - if (pattrylen(p, s, t - s, umlen, 0)) { + if (pattrylen(p, s, t - s, umlen, NULL, 0)) { mlen = patmatchlen(); break; } @@ -3187,7 +3191,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, if (t > s && t[-1] == Meta) t--; set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, ioff)) { + if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { *sp = get_match_ret(*sp, t - s, l, fl, replstr, NULL); return 1; } @@ -3203,7 +3207,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, for (ioff = 0, t = s, umlen = uml; t < s + l; ioff++, METAINC(t), umlen--) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, ioff)) { + if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { *sp = get_match_ret(*sp, t-s, l, fl, replstr, NULL); return 1; } @@ -3235,7 +3239,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, for (; t < s + l; METAINC(t), ioff++, umlen--) { /* Find the longest match from this position. */ set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, ioff)) { + if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { char *mpos = t + patmatchlen(); if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { char *ptr; @@ -3243,7 +3247,8 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, for (ptr = t, umlen2 = 0; ptr < mpos; METAINC(ptr), umlen2++) { set_pat_end(p, *ptr); - if (pattrylen(p, t, ptr - t, umlen2, ioff)) { + if (pattrylen(p, t, ptr - t, umlen2, + NULL, ioff)) { mpos = t + patmatchlen(); break; } @@ -3300,7 +3305,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, /* Longest/shortest at end, matching substrings. */ if (!(fl & SUB_LONG)) { set_pat_start(p, l); - if (pattrylen(p, s + l, 0, 0, uml) && !--n) { + if (pattrylen(p, s + l, 0, 0, NULL, uml) && !--n) { *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); return 1; } @@ -3310,7 +3315,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, if (t > s && t[-1] == Meta) t--; set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, ioff) && !--n) { + if (pattrylen(p, t, s + l - t, umlen, NULL, ioff) && !--n) { /* Found the longest match */ char *mpos = t + patmatchlen(); if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { @@ -3319,7 +3324,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, for (ptr = t, umlen2 = 0; ptr < mpos; METAINC(ptr), umlen2++) { set_pat_end(p, *ptr); - if (pattrylen(p, t, ptr - t, umlen2, ioff)) { + if (pattrylen(p, t, ptr - t, umlen2, NULL, ioff)) { mpos = t + patmatchlen(); break; } @@ -3331,7 +3336,8 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, } } set_pat_start(p, l); - if ((fl & SUB_LONG) && pattrylen(p, s + l, 0, 0, uml) && !--n) { + if ((fl & SUB_LONG) && pattrylen(p, s + l, 0, 0, NULL, uml) && + !--n) { *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); return 1; } diff --git a/Src/pattern.c b/Src/pattern.c index af56bd9cc..03ba37d92 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -2022,6 +2022,131 @@ pattrystart(void) errsfound = 0; } +/* + * Allocate memeory for pattern match. Note this is specific to use + * of pattern *and* trial string. + * + * Unmetafy a trial string for use in pattern matching, if needed. + * + * If it is needed, returns a zalloc()'d string; if not needed, returns + * NULL. + * + * prog is the pattern to be executed. + * string is the metafied trial string. + * stringlen is it's length; it will be calculated if it's negative + * (this is a simple strlen()). + * unmetalen is the unmetafied length of the string, may be -1. + * force is 1 if we always unmetafy: this is useful if we are going + * to try again with different versions of the string. If this is + * called from pattryrefs() we don't force unmetafication as it won't + * be optimal. + * In patstralloc (supplied by caller, must last until last pattry is done) + * unmetalen is the unmetafied length of the string; it will be + * calculated if the input value is negative. + * unmetalenp is the umetafied length of a path segment preceeding + * the trial string needed for file mananagement; it is calculated as + * needed so does not need to be initialised. + * alloced is the memory allocated --- same as return value from + * function. + */ +/**/ +mod_export +char *patallocstr(Patprog prog, char *string, int stringlen, int unmetalen, + int force, Patstralloc patstralloc) +{ + int needfullpath; + + /* + * For a top-level ~-exclusion, we will need the full + * path to exclude, so copy the path so far and append the + * current test string. + */ + needfullpath = (prog->flags & PAT_HAS_EXCLUDP) && pathpos; + + /* Get the length of the full string when unmetafied. */ + if (unmetalen < 0) + patstralloc->unmetalen = ztrsub(string + stringlen, string); + else + patstralloc->unmetalen = unmetalen; + if (needfullpath) { + patstralloc->unmetalenp = ztrsub(pathbuf + pathpos, pathbuf); + if (!patstralloc->unmetalenp) + needfullpath = 0; + } else + patstralloc->unmetalenp = 0; + /* Initialise cache area */ + patstralloc->progstrunmeta = NULL; + patstralloc->progstrunmetalen = 0; + + DPUTS(needfullpath && (prog->flags & (PAT_PURES|PAT_ANY)), + "rum sort of file exclusion"); + /* + * Partly for efficiency, and partly for the convenience of + * globbing, we don't unmetafy pure string patterns, and + * there's no reason to if the pattern is just a *. + */ + if (force || + (!(prog->flags & (PAT_PURES|PAT_ANY)) + && (needfullpath || patstralloc->unmetalen != stringlen))) { + /* + * We need to copy if we need to prepend the path so far + * (in which case we copy both chunks), or if we have + * Meta characters. + */ + char *dst, *ptr; + int i, icopy, ncopy; + + dst = patstralloc->alloced = + zalloc(patstralloc->unmetalen + patstralloc->unmetalenp); + + if (needfullpath) { + /* loop twice, copy path buffer first time */ + ptr = pathbuf; + ncopy = patstralloc->unmetalenp; + } else { + /* just loop once, copy string with unmetafication */ + ptr = string; + ncopy = patstralloc->unmetalen; + } + for (icopy = 0; icopy < 2; icopy++) { + for (i = 0; i < ncopy; i++) { + if (*ptr == Meta) { + ptr++; + *dst++ = *ptr++ ^ 32; + } else { + *dst++ = *ptr++; + } + } + if (!needfullpath) + break; + /* next time append test string to path so far */ + ptr = string; + ncopy = patstralloc->unmetalen; + } + } + else + { + patstralloc->alloced = NULL; + } + + return patstralloc->alloced; +} + + +/* + * Free memory allocated by patallocstr(). + */ + +/**/ +mod_export +void patfreestr(Patstralloc patstralloc) +{ + if (patstralloc->alloced) + zfree(patstralloc->alloced, + patstralloc->unmetalen + patstralloc->unmetalenp); +} + + /* * Test prog against null-terminated, metafied string. */ @@ -2030,7 +2155,7 @@ pattrystart(void) mod_export int pattry(Patprog prog, char *string) { - return pattryrefs(prog, string, -1, -1, 0, NULL, NULL, NULL); + return pattryrefs(prog, string, -1, -1, NULL, 0, NULL, NULL, NULL); } /* @@ -2041,9 +2166,11 @@ pattry(Patprog prog, char *string) /**/ mod_export int -pattrylen(Patprog prog, char *string, int len, int unmetalen, int offset) +pattrylen(Patprog prog, char *string, int len, int unmetalen, + Patstralloc patstralloc, int offset) { - return pattryrefs(prog, string, len, unmetalen, offset, NULL, NULL, NULL); + return pattryrefs(prog, string, len, unmetalen, patstralloc, offset, + NULL, NULL, NULL); } /* @@ -2055,14 +2182,32 @@ pattrylen(Patprog prog, char *string, int len, int unmetalen, int offset) * there may be a severe penalty for this if a lot of matching is done * on one string. * - * offset is the position in the original string (not seen by + * If patstralloc is not NULL it is used to optimise unmetafication + * of a trial string that may be passed (or any substring may be passed) to + * pattryrefs multiple times or the same pattern (N.B. so patstralloc + * depends on both prog *and* the trial string). This should only be + * done if there is no path prefix (pathpos == 0) as otherwise the path + * buffer and unmetafied string may not match. To do this, + * patallocstr() is callled (use force = 1 to ensure it is alway + * unmetafied); paststralloc points to existing storage. When all + * pattern matching is done, patfreestr() is called. + * patstralloc->alloced and patstralloc->unmetalen contain the + * unmetafied string and its length. In that case, the rules for the + * earlier arguments change: + * - string is an unmetafied string + * - stringlen is its unmetafied (i.e. actual) length + * - unmetalenin is not used. + * string and stringlen may refer to arbitrary substrings of + * patstralloc->alloced without any internal modification to patstralloc. + * + * patoffset is the position in the original string (not seen by * the pattern module) at which we are trying to match. * This is added in to the positions recorded in patbeginp and patendp * when we are looking for substrings. Currently this only happens * in the parameter substitution code. * - * Note this is a character offset, i.e. a metafied character - * counts as 1. + * Note this is a character offset, i.e. a single possibly metafied and + * possibly multibyte character counts as 1. * * The last three arguments are used to report the positions for the * backreferences. On entry, *nump should contain the maximum number @@ -2075,14 +2220,15 @@ pattrylen(Patprog prog, char *string, int len, int unmetalen, int offset) /**/ mod_export int -pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, - int patoffset, +pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, + Patstralloc patstralloc, int patoffset, int *nump, int *begp, int *endp) { - int i, maxnpos = 0, ret, needfullpath, unmetalenp; + int i, maxnpos = 0, ret; int origlen; - char **sp, **ep, *tryalloced, *ptr; + char **sp, **ep, *ptr; char *progstr = (char *)prog + prog->startoff; + struct patstralloc patstralloc_struct; if (nump) { maxnpos = *nump; @@ -2091,86 +2237,38 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, /* inherited from domatch, but why, exactly? */ if (*string == Nularg) { string++; - unmetalen--; + if (unmetalenin > 0) + unmetalenin--; + if (stringlen > 0) + stringlen--; } if (stringlen < 0) stringlen = strlen(string); origlen = stringlen; - patflags = prog->flags; - /* - * For a top-level ~-exclusion, we will need the full - * path to exclude, so copy the path so far and append the - * current test string. - */ - needfullpath = (patflags & PAT_HAS_EXCLUDP) && pathpos; - - /* Get the length of the full string when unmetafied. */ - if (unmetalen < 0) - unmetalen = ztrsub(string + stringlen, string); - if (needfullpath) - unmetalenp = ztrsub(pathbuf + pathpos, pathbuf); - else - unmetalenp = 0; - - DPUTS(needfullpath && (patflags & (PAT_PURES|PAT_ANY)), - "rum sort of file exclusion"); - /* - * Partly for efficiency, and partly for the convenience of - * globbing, we don't unmetafy pure string patterns, and - * there's no reason to if the pattern is just a *. - */ - if (!(patflags & (PAT_PURES|PAT_ANY)) - && (needfullpath || unmetalen != stringlen)) { - /* - * We need to copy if we need to prepend the path so far - * (in which case we copy both chunks), or if we have - * Meta characters. - */ - char *dst; - int icopy, ncopy; - - dst = tryalloced = zalloc(unmetalen + unmetalenp); - - if (needfullpath) { - /* loop twice, copy path buffer first time */ - ptr = pathbuf; - ncopy = unmetalenp; - } else { - /* just loop once, copy string with unmetafication */ - ptr = string; - ncopy = unmetalen; - } - for (icopy = 0; icopy < 2; icopy++) { - for (i = 0; i < ncopy; i++) { - if (*ptr == Meta) { - ptr++; - *dst++ = *ptr++ ^ 32; - } else { - *dst++ = *ptr++; - } - } - if (!needfullpath) - break; - /* next time append test string to path so far */ - ptr = string; - ncopy = unmetalen; - } - - if (needfullpath) { - patinstart = tryalloced + unmetalenp; - patinpath = tryalloced; - } else { - patinstart = tryalloced; - patinpath = NULL; - } - stringlen = unmetalen; - } else { + if (patstralloc) { + DPUTS(!patstralloc->alloced, + "External unmetafy didn't actually unmetafy."); + DPUTS(patstralloc->unmetalenp, + "Ooh-err: pathpos with external unmetafy. I have bad vibes."); + patinpath = NULL; patinstart = string; - tryalloced = patinpath = NULL; + /* stringlen is unmetafied length; unmetalenin is ignored */ + } else { + patstralloc = &patstralloc_struct; + if (patallocstr(prog, string, stringlen, unmetalenin, 0, patstralloc)) { + patinstart = patstralloc->alloced + patstralloc->unmetalenp; + stringlen = patstralloc->unmetalen; + } else + patinstart = string; + if (patstralloc->unmetalenp) + patinpath = patstralloc->alloced; + else + patinpath = NULL; } + patflags = prog->flags; patinend = patinstart + stringlen; /* * From now on we do not require NULL termination of @@ -2183,7 +2281,30 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, * Either we are testing against a pure string, * or we can match anything at all. */ - int ret; + int ret, pstrlen; + char *pstr; + if (patstralloc->alloced) + { + /* + * Unmetafied; we need pattern sring that's also unmetafied. + * We'll cache it in the patstralloc structure. + * Note it's on the heap. + */ + if (!patstralloc->progstrunmeta) + { + patstralloc->progstrunmeta = dupstring(progstr); + unmetafy(patstralloc->progstrunmeta, + &patstralloc->progstrunmetalen); + } + pstr = patstralloc->progstrunmeta; + pstrlen = patstralloc->progstrunmetalen; + } + else + { + /* Metafied. */ + pstr = progstr; + pstrlen = (int)prog->patmlen; + } if (prog->flags & PAT_ANY) { /* * Optimisation for a single "*": always matches @@ -2195,11 +2316,11 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, * Testing a pure string. See if initial * components match. */ - int lendiff = stringlen - prog->patmlen; + int lendiff = stringlen - pstrlen; if (lendiff < 0) { /* No, the pattern string is too long. */ ret = 0; - } else if (!memcmp(progstr, patinstart, prog->patmlen)) { + } else if (!memcmp(pstr, patinstart, pstrlen)) { /* * Initial component matches. Matches either * if lengths are the same or we are not anchored @@ -2221,7 +2342,9 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, } else { /* * Remember the length in case used for ${..#..} etc. - * In this case, we didn't unmetafy the string. + * In this case, we didn't unmetafy the pattern string + * In the orignal structure, but it might be unmetafied + * for use with an unmetafied test string. */ patinlen = (int)prog->patmlen; /* if matching files, must update globbing flags */ @@ -2229,16 +2352,26 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, if ((patglobflags & GF_MATCHREF) && !(patflags & PAT_FILE)) { - char *str = ztrduppfx(patinstart, patinlen); + char *str; int mlen; - /* - * Count the characters. We're not using CHARSUB() - * because the string is still metafied. - */ - MB_METACHARINIT(); - mlen = MB_METASTRLEN2END(patinstart, 0, - patinstart + patinlen); + if (patstralloc->alloced) { + /* + * Unmetafied: pstrlen contains unmetafied + * length in bytes. + */ + str = metafy(patinstart, pstrlen, META_ALLOC); + mlen = CHARSUB(patinstart, patinstart + pstrlen); + } else { + str = ztrduppfx(patinstart, patinlen); + /* + * Count the characters. We're not using CHARSUB() + * because the string is still metafied. + */ + MB_METACHARINIT(); + mlen = MB_METASTRLEN2END(patinstart, 0, + patinstart + patinlen); + } setsparam("MATCH", str); setiparam("MBEGIN", @@ -2250,9 +2383,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, } } - if (tryalloced) - zfree(tryalloced, unmetalen + unmetalenp); - + if (patstralloc == &patstralloc_struct) + patfreestr(patstralloc); return ret; } else { int q = queue_signal_level(); @@ -2289,8 +2421,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, } } if (!ret) { - if (tryalloced) - zfree(tryalloced, unmetalen + unmetalenp); + if (patstralloc == &patstralloc_struct) + patfreestr(patstralloc); return 0; } @@ -2322,8 +2454,11 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, /* * Optimization: if we didn't find any Meta characters * to begin with, we don't need to look for them now. + * Only do this if we did the unmetfication internally, + * since otherwise it's too hard to work out. */ - if (unmetalen != origlen) { + if (patstralloc == &patstralloc_struct && + patstralloc->unmetalen != origlen) { for (ptr = patinstart; ptr < patinput; ptr++) if (imeta(*ptr)) patinlen++; @@ -2444,8 +2579,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen, restore_queue_signals(q); - if (tryalloced) - zfree(tryalloced, unmetalen + unmetalenp); + if (patstralloc == &patstralloc_struct) + patfreestr(patstralloc); return ret; } diff --git a/Src/zsh.h b/Src/zsh.h index dd0596116..32f2e0cb2 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -491,6 +491,7 @@ typedef struct options *Options; typedef struct optname *Optname; typedef struct param *Param; typedef struct paramdef *Paramdef; +typedef struct patstralloc *Patstralloc; typedef struct patprog *Patprog; typedef struct prepromptfn *Prepromptfn; typedef struct process *Process; @@ -1470,6 +1471,15 @@ struct patprog { char patstartch; }; +struct patstralloc { + int unmetalen; /* Unmetafied length of trial string */ + int unmetalenp; /* Unmetafied length of path prefix. + If 0, no path prefix. */ + char *alloced; /* Allocated string, may be NULL */ + char *progstrunmeta; /* Unmetafied pure string in pattern, cached */ + int progstrunmetalen; /* Length of the foregoing */ +}; + /* Flags used in pattern matchers (Patprog) and passed down to patcompile */ #define PAT_FILE 0x0001 /* Pattern is a file name */ -- cgit v1.2.3 From d07783628e935daab518509db123141ceb535a28 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 29 Sep 2015 19:06:43 +0100 Subject: 36700: unmetafy early for parameter match --- Src/glob.c | 436 ++++++++++++++++++++++++++++++++++------------------------ Src/pattern.c | 20 ++- Src/zsh.h | 26 ++++ 3 files changed, 294 insertions(+), 188 deletions(-) diff --git a/Src/glob.c b/Src/glob.c index 8bf73520f..0594f0a82 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2450,29 +2450,46 @@ matchpat(char *a, char *b) /* please do not laugh at this code. */ /* Having found a match in getmatch, decide what part of string - * to return. The matched part starts b characters into string s - * and finishes e characters in: 0 <= b <= e <= strlen(s) + * to return. The matched part starts b characters into string imd->ustr + * and finishes e characters in: 0 <= b <= e <= imd->ulen on input * (yes, empty matches should work). - * fl is a set of the SUB_* matches defined in zsh.h from SUB_MATCH onwards; - * the lower parts are ignored. - * replstr is the replacement string for a substitution + * + * imd->flags is a set of the SUB_* matches defined in zsh.h from + * SUB_MATCH onwards; the lower parts are ignored. + * + * imd->replstr is the replacement string for a substitution + * + * imd->replstr is metafied and the values put in imd->repllist are metafied. */ /**/ static char * -get_match_ret(char *s, int b, int e, int fl, char *replstr, - LinkList repllist) +get_match_ret(Imatchdata imd, int b, int e) { - char buf[80], *r, *p, *rr; - int ll = 0, l = strlen(s), bl = 0, t = 0, i; - + char buf[80], *r, *p, *rr, *replstr = imd->replstr; + int ll = 0, bl = 0, t = 0, add = 0, fl = imd->flags, i; + + /* Account for b and e referring to unmetafied string */ + for (p = imd->ustr; p < imd->ustr + b; p++) + if (imeta(*p)) + add++; + b += add; + for (; p < imd->ustr + e; p++) + if (imeta(*p)) + add++; + e += add; + for (; p < imd->ustr + imd->ulen; p++) + if (imeta(*p)) + add++; + + /* Everything now refers to meatfied lengths. */ if (replstr || (fl & SUB_LIST)) { if (fl & SUB_DOSUBST) { replstr = dupstring(replstr); singsub(&replstr); untokenize(replstr); } - if ((fl & (SUB_GLOBAL|SUB_LIST)) && repllist) { + if ((fl & (SUB_GLOBAL|SUB_LIST)) && imd->repllist) { /* We are replacing the chunk, just add this to the list */ Repldata rd = (Repldata) ((fl & SUB_LIST) ? zalloc(sizeof(*rd)) : zhalloc(sizeof(*rd))); @@ -2480,30 +2497,32 @@ get_match_ret(char *s, int b, int e, int fl, char *replstr, rd->e = e; rd->replstr = replstr; if (fl & SUB_LIST) - zaddlinknode(repllist, rd); + zaddlinknode(imd->repllist, rd); else - addlinknode(repllist, rd); - return s; + addlinknode(imd->repllist, rd); + return imd->mstr; } ll += strlen(replstr); } if (fl & SUB_MATCH) /* matched portion */ ll += 1 + (e - b); if (fl & SUB_REST) /* unmatched portion */ - ll += 1 + (l - (e - b)); + ll += 1 + (imd->mlen - (e - b)); if (fl & SUB_BIND) { /* position of start of matched portion */ - sprintf(buf, "%d ", MB_METASTRLEN2END(s, 0, s+b) + 1); + sprintf(buf, "%d ", MB_METASTRLEN2END(imd->mstr, 0, imd->mstr+b) + 1); ll += (bl = strlen(buf)); } if (fl & SUB_EIND) { /* position of end of matched portion */ - sprintf(buf + bl, "%d ", MB_METASTRLEN2END(s, 0, s+e) + 1); + sprintf(buf + bl, "%d ", + MB_METASTRLEN2END(imd->mstr, 0, imd->mstr+e) + 1); ll += (bl = strlen(buf)); } if (fl & SUB_LEN) { /* length of matched portion */ - sprintf(buf + bl, "%d ", MB_METASTRLEN2END(s+b, 0, s+e)); + sprintf(buf + bl, "%d ", MB_METASTRLEN2END(imd->mstr+b, 0, + imd->mstr+e)); ll += (bl = strlen(buf)); } if (bl) @@ -2513,7 +2532,7 @@ get_match_ret(char *s, int b, int e, int fl, char *replstr, if (fl & SUB_MATCH) { /* copy matched portion to new buffer */ - for (i = b, p = s + b; i < e; i++) + for (i = b, p = imd->mstr + b; i < e; i++) *rr++ = *p++; t = 1; } @@ -2523,12 +2542,12 @@ get_match_ret(char *s, int b, int e, int fl, char *replstr, if (t) *rr++ = ' '; /* there may be unmatched bits at both beginning and end of string */ - for (i = 0, p = s; i < b; i++) + for (i = 0, p = imd->mstr; i < b; i++) *rr++ = *p++; if (replstr) for (p = replstr; *p; ) *rr++ = *p++; - for (i = e, p = s + e; i < l; i++) + for (i = e, p = imd->mstr + e; i < imd->mlen; i++) *rr++ = *p++; t = 1; } @@ -2710,26 +2729,18 @@ set_pat_end(Patprog p, char null_me) /* * Increment *tp over character which may be multibyte. - * Return number of bytes that remain in the character after unmetafication. + * Return number of bytes. + * All unmetafied here. */ /**/ -static int iincchar(char **tp) +static int iincchar(char **tp, int left) { char *t = *tp; - int mbclen = mb_metacharlenconv(t, NULL); - int umlen = 0; - - while (mbclen--) { - umlen++; - if (*t++ == Meta) { - t++; - mbclen--; - } - } - *tp = t; + int mbclen = mb_charlenconv(t, left, NULL); + *tp = t + mbclen; - return umlen; + return mbclen; } /**/ @@ -2737,7 +2748,7 @@ static int igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, LinkList *repllistp) { - char *s = *sp, *t, *tmatch; + char *s = *sp, *t, *tmatch, *send; /* * Note that ioff counts (possibly multibyte) characters in the * character set (Meta's are not included), while l counts characters in @@ -2752,36 +2763,52 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, */ int ioff, l = strlen(*sp), matched = 1, umltot = ztrlen(*sp); int umlen, nmatches; - /* - * List of bits of matches to concatenate with replacement string. - * The data is a struct repldata. It is not used in cases like - * ${...//#foo/bar} even though SUB_GLOBAL is set, since the match - * is anchored. It goes on the heap. - */ - LinkList repllist = NULL; + struct patstralloc patstralloc; + struct imatchdata imd; + + (void)patallocstr(p, s, l, umltot, 1, &patstralloc); + s = patstralloc.alloced; + DPUTS(!s, "forced patallocstr failed"); + send = s + umltot; + + imd.mstr = *sp; + imd.mlen = l; + imd.ustr = s; + imd.ulen = umltot; + imd.flags = fl; + imd.replstr = replstr; + imd.repllist = NULL; /* perform must-match test for complex closures */ if (p->mustoff) { - /* - * Yuk. Probably we should rewrite this whole function to - * use an unmetafied test string. - * - * Use META_HEAPDUP because we need a terminating NULL. - */ - char *muststr = metafy((char *)p + p->mustoff, - p->patmlen, META_HEAPDUP); + char *muststr = (char *)p + p->mustoff; - if (!strstr(s, muststr)) - matched = 0; + matched = 0; + if (p->patmlen <= umltot) + { + for (t = s; t <= send - p->patmlen; t++) + { + if (!memcmp(muststr, t, p->patmlen)) { + matched = 1; + break; + } + } + } } /* in case we used the prog before... */ p->flags &= ~(PAT_NOTSTART|PAT_NOTEND); if (fl & SUB_ALL) { - int i = matched && pattrylen(p, s, -1, -1, NULL, 0); - *sp = get_match_ret(*sp, 0, i ? l : 0, fl, i ? replstr : 0, NULL); + int i = matched && pattrylen(p, s, umltot, 0, &patstralloc, 0); + if (!i) { + /* Perform under no-match conditions */ + umltot = 0; + imd.replstr = NULL; + } + *sp = get_match_ret(&imd, 0, umltot); + patfreestr(&patstralloc); if (! **sp && (((fl & SUB_MATCH) && !i) || ((fl & SUB_REST) && i))) return 0; return 1; @@ -2809,25 +2836,27 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, * Largest/smallest possible match at head of string. * First get the longest match... */ - if (pattrylen(p, s, -1, -1, NULL, 0)) { - /* patmatchlen returns metafied length, as we need */ + if (pattrylen(p, s, umltot, 0, &patstralloc, 0)) { + /* patmatchlen returns unmetafied length in this case */ int mlen = patmatchlen(); if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { + send = s + mlen; /* * ... now we know whether it's worth looking for the * shortest, which we do by brute force. */ mb_charinit(); - for (t = s, umlen = 0; t < s + mlen; ) { + for (t = s, umlen = 0; t < send; ) { set_pat_end(p, *t); - if (pattrylen(p, s, t - s, umlen, NULL, 0)) { + if (pattrylen(p, s, umlen, 0, &patstralloc, 0)) { mlen = patmatchlen(); break; } - umlen += iincchar(&t); + umlen += iincchar(&t, send - t); } } - *sp = get_match_ret(*sp, 0, mlen, fl, replstr, NULL); + *sp = get_match_ret(&imd, 0, mlen); + patfreestr(&patstralloc); return 1; } break; @@ -2845,20 +2874,23 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, */ mb_charinit(); tmatch = NULL; - for (ioff = 0, t = s, umlen = umltot; t < s + l; ioff++) { + for (ioff = 0, t = s, umlen = umltot; t < send; ioff++) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) + if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) tmatch = t; if (fl & SUB_START) break; - umlen -= iincchar(&t); + umlen -= iincchar(&t, send - t); } if (tmatch) { - *sp = get_match_ret(*sp, tmatch - s, l, fl, replstr, NULL); + *sp = get_match_ret(&imd, tmatch - s, umltot); + patfreestr(&patstralloc); return 1; } - if (!(fl & SUB_START) && pattrylen(p, s + l, 0, 0, NULL, ioff)) { - *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); + if (!(fl & SUB_START) && pattrylen(p, s + umltot, 0, 0, + &patstralloc, ioff)) { + *sp = get_match_ret(&imd, umltot, umltot); + patfreestr(&patstralloc); return 1; } break; @@ -2868,18 +2900,21 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, * move forward along string until we get a match. * * Again there's no optimisation. */ mb_charinit(); - for (ioff = 0, t = s, umlen = umltot; t < s + l; ioff++) { + for (ioff = 0, t = s, umlen = umltot; t < send ; ioff++) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { - *sp = get_match_ret(*sp, t-s, l, fl, replstr, NULL); + if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) { + *sp = get_match_ret(&imd, t-s, umltot); + patfreestr(&patstralloc); return 1; } if (fl & SUB_START) break; - umlen -= iincchar(&t); + umlen -= iincchar(&t, send - t); } - if (!(fl & SUB_START) && pattrylen(p, s + l, 0, 0, NULL, ioff)) { - *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); + if (!(fl & SUB_START) && pattrylen(p, send, 0, 0, + &patstralloc, ioff)) { + *sp = get_match_ret(&imd, umltot, umltot); + patfreestr(&patstralloc); return 1; } break; @@ -2887,18 +2922,20 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, case SUB_SUBSTR: /* Smallest at start, but matching substrings. */ set_pat_start(p, l); - if (!(fl & SUB_GLOBAL) && pattrylen(p, s + l, -1, -1, NULL, 0) && + if (!(fl & SUB_GLOBAL) && + pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) { - *sp = get_match_ret(*sp, 0, 0, fl, replstr, NULL); + *sp = get_match_ret(&imd, 0, 0); + patfreestr(&patstralloc); return 1; } /* fall through */ case (SUB_SUBSTR|SUB_LONG): /* longest or smallest at start with substrings */ t = s; if (fl & SUB_GLOBAL) { - repllist = (fl & SUB_LIST) ? znewlinklist() : newlinklist(); + imd.repllist = (fl & SUB_LIST) ? znewlinklist() : newlinklist(); if (repllistp) - *repllistp = repllist; + *repllistp = imd.repllist; } ioff = 0; /* offset into string */ umlen = umltot; @@ -2906,10 +2943,10 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, do { /* loop over all matches for global substitution */ matched = 0; - for (; t < s + l; ioff++) { + for (; t < send; ioff++) { /* Find the longest match from this position. */ set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { + if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) { char *mpos = t + patmatchlen(); if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { char *ptr; @@ -2923,19 +2960,18 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, */ for (ptr = t, umlen2 = 0; ptr < mpos;) { set_pat_end(p, *ptr); - if (pattrylen(p, t, ptr - t, umlen2, - NULL, ioff)) { + if (pattrylen(p, t, umlen2, 0, + &patstralloc, ioff)) { mpos = t + patmatchlen(); break; } - umlen2 += iincchar(&ptr); + umlen2 += iincchar(&ptr, mpos - ptr); } } if (!--n || (n <= 0 && (fl & SUB_GLOBAL))) { - *sp = get_match_ret(*sp, t-s, mpos-s, fl, - replstr, repllist); + *sp = get_match_ret(&imd, t-s, mpos-s); if (mpos == t) - mpos += mb_metacharlenconv(mpos, NULL); + mpos += mb_charlenconv(mpos, send - mpos, NULL); } if (!(fl & SUB_GLOBAL)) { if (n) { @@ -2945,9 +2981,10 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, * the next character, even if it overlaps * with what we just found. */ - umlen -= iincchar(&t); + umlen -= iincchar(&t, send - t); continue; } else { + patfreestr(&patstralloc); return 1; } } @@ -2958,11 +2995,11 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, matched = 1; while (t < mpos) { ioff++; - umlen -= iincchar(&t); + umlen -= iincchar(&t, send - t); } break; } - umlen -= iincchar(&t); + umlen -= iincchar(&t, send - t); } } while (matched); /* @@ -2972,8 +3009,9 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, */ set_pat_start(p, l); if ((fl & (SUB_LONG|SUB_GLOBAL)) == SUB_LONG && - pattrylen(p, s + l, -1, -1, NULL, 0) && !--n) { - *sp = get_match_ret(*sp, 0, 0, fl, replstr, repllist); + pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) { + *sp = get_match_ret(&imd, 0, 0); + patfreestr(&patstralloc); return 1; } break; @@ -2983,8 +3021,10 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, /* Longest/shortest at end, matching substrings. */ if (!(fl & SUB_LONG)) { set_pat_start(p, l); - if (pattrylen(p, s + l, 0, 0, NULL, umltot) && !--n) { - *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); + if (pattrylen(p, send, 0, 0, &patstralloc, umltot) && + !--n) { + *sp = get_match_ret(&imd, umltot, umltot); + patfreestr(&patstralloc); return 1; } } @@ -3001,13 +3041,13 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, nmatches = 0; tmatch = NULL; mb_charinit(); - for (ioff = 0, t = s, umlen = umltot; t < s + l; ioff++) { + for (ioff = 0, t = s, umlen = umltot; t < send; ioff++) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { + if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) { nmatches++; tmatch = t; } - umlen -= iincchar(&t); + umlen -= iincchar(&t, send - t); } if (nmatches) { char *mpos; @@ -3017,14 +3057,14 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, */ n = nmatches - n; mb_charinit(); - for (ioff = 0, t = s, umlen = umltot; t < s + l; ioff++) { + for (ioff = 0, t = s, umlen = umltot; t < send; ioff++) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, NULL, ioff) && + if (pattrylen(p, t, umlen, 0, &patstralloc, ioff) && !n--) { tmatch = t; break; } - umlen -= iincchar(&t); + umlen -= iincchar(&t, send - t); } } mpos = tmatch + patmatchlen(); @@ -3032,29 +3072,31 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { for (t = tmatch, umlen = 0; t < mpos; ) { set_pat_end(p, *t); - if (pattrylen(p, tmatch, t - tmatch, umlen, - NULL, ioff)) { + if (pattrylen(p, tmatch, umlen, 0, + &patstralloc, ioff)) { mpos = tmatch + patmatchlen(); break; } - umlen += iincchar(&t); + umlen += iincchar(&t, mpos - t); } } - *sp = get_match_ret(*sp, tmatch-s, mpos-s, fl, - replstr, NULL); + *sp = get_match_ret(&imd, tmatch-s, mpos-s); + patfreestr(&patstralloc); return 1; } set_pat_start(p, l); - if ((fl & SUB_LONG) && pattrylen(p, s + l, 0, 0, NULL, umltot) && + if ((fl & SUB_LONG) && pattrylen(p, send, 0, 0, + &patstralloc, umltot) && !--n) { - *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); + *sp = get_match_ret(&imd, umltot, umltot); + patfreestr(&patstralloc); return 1; } break; } } - if (repllist && nonempty(repllist)) { + if (imd.repllist && nonempty(imd.repllist)) { /* Put all the bits of a global search and replace together. */ LinkNode nd; Repldata rd; @@ -3062,10 +3104,15 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, char *ptr, *start; int i; + /* + * Use metafied string again. + * Results from get_match_ret in repllist are all metafied. + */ + s = *sp; if (!(fl & SUB_LIST)) { lleft = 0; /* size of returned string */ - i = 0; /* start of last chunk we got from *sp */ - for (nd = firstnode(repllist); nd; incnode(nd)) { + i = 0; /* start of last chunk we got from *sp */ + for (nd = firstnode(imd.repllist); nd; incnode(nd)) { rd = (Repldata) getdata(nd); lleft += rd->b - i; /* previous chunk of *sp */ lleft += strlen(rd->replstr); /* the replaced bit */ @@ -3074,7 +3121,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, lleft += l - i; /* final chunk from *sp */ start = t = zhalloc(lleft+1); i = 0; - for (nd = firstnode(repllist); nd; incnode(nd)) { + for (nd = firstnode(imd.repllist); nd; incnode(nd)) { rd = (Repldata) getdata(nd); memcpy(t, s + i, rd->b - i); t += rd->b - i; @@ -3087,13 +3134,19 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, start[lleft] = '\0'; *sp = (char *)start; } + patfreestr(&patstralloc); return 1; } - if (fl & SUB_LIST) /* safety: don't think this can happen */ + if (fl & SUB_LIST) { /* safety: don't think this can happen */ + patfreestr(&patstralloc); return 0; + } /* munge the whole string: no match, so no replstr */ - *sp = get_match_ret(*sp, 0, 0, fl, 0, 0); + imd.replstr = NULL; + imd.repllist = NULL; + *sp = get_match_ret(&imd, 0, 0); + patfreestr(&patstralloc); return (fl & SUB_RETFAIL) ? 0 : 1; } @@ -3111,7 +3164,7 @@ static int igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, LinkList *repllistp) { - char *s = *sp, *t; + char *s = *sp, *t, *send; /* * Note that ioff and uml count characters in the character * set (Meta's are not included), while l counts characters in the @@ -3119,36 +3172,48 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, * lengths. */ int ioff, l = strlen(*sp), uml = ztrlen(*sp), matched = 1, umlen; - /* - * List of bits of matches to concatenate with replacement string. - * The data is a struct repldata. It is not used in cases like - * ${...//#foo/bar} even though SUB_GLOBAL is set, since the match - * is anchored. It goes on the heap. - */ - LinkList repllist = NULL; + struct patstralloc patstralloc; + struct imatchdata imd; + + (void)patallocstr(p, s, l, uml, 1, &patstralloc); + s = patstralloc.alloced; + DPUTS(!s, "forced patallocstr failed"); + send = s + uml; + + imd.mstr = *sp; + imd.mlen = l; + imd.ustr = s; + imd.ulen = uml; + imd.flags = fl; + imd.replstr = replstr; + imd.repllist = NULL; /* perform must-match test for complex closures */ if (p->mustoff) { - /* - * Yuk. Probably we should rewrite this whole function to - * use an unmetafied test string. - * - * Use META_HEAPDUP because we need a terminating NULL. - */ - char *muststr = metafy((char *)p + p->mustoff, - p->patmlen, META_HEAPDUP); + char *muststr = (char *)p + p->mustoff; - if (!strstr(s, muststr)) - matched = 0; + matched = 0; + if (p->patmlen <= uml) + { + for (t = s; t <= send - p->patmlen; t++) + { + if (!memcmp(muststr, t, p->patmlen)) { + matched = 1; + break; + } + } + } } /* in case we used the prog before... */ p->flags &= ~(PAT_NOTSTART|PAT_NOTEND); if (fl & SUB_ALL) { - int i = matched && pattry(p, s); - *sp = get_match_ret(*sp, 0, i ? l : 0, fl, i ? replstr : 0, NULL); + int i = matched && pattrylen(p, s, uml, 0, &patstralloc, 0); + if (!i) + imd.replstr = NULL; + *sp = get_match_ret(&imd, 0, i ? l : 0); if (! **sp && (((fl & SUB_MATCH) && !i) || ((fl & SUB_REST) && i))) return 0; return 1; @@ -3161,23 +3226,25 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, * Largest/smallest possible match at head of string. * First get the longest match... */ - if (pattry(p, s)) { + if (pattrylen(p, s, uml, 0, &patstralloc, 0)) { /* patmatchlen returns metafied length, as we need */ int mlen = patmatchlen(); if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { + send = s + mlen; /* * ... now we know whether it's worth looking for the * shortest, which we do by brute force. */ for (t = s, umlen = 0; t < s + mlen; METAINC(t), umlen++) { set_pat_end(p, *t); - if (pattrylen(p, s, t - s, umlen, NULL, 0)) { + if (pattrylen(p, s, umlen, 0, &patstralloc, 0)) { mlen = patmatchlen(); break; } } } - *sp = get_match_ret(*sp, 0, mlen, fl, replstr, NULL); + *sp = get_match_ret(&imd, 0, mlen); + patfreestr(&patstralloc); return 1; } break; @@ -3186,17 +3253,13 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, /* Smallest possible match at tail of string: * * move back down string until we get a match. * * There's no optimization here. */ - for (ioff = uml, t = s + l, umlen = 0; t >= s; + for (ioff = uml, t = send, umlen = 0; t >= s; t--, ioff--, umlen++) { - if (t > s && t[-1] == Meta) - t--; set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { - *sp = get_match_ret(*sp, t - s, l, fl, replstr, NULL); + if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) { + *sp = get_match_ret(&imd, t - s, uml); return 1; } - if (t > s+1 && t[-2] == Meta) - t--; } break; @@ -3204,61 +3267,59 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, /* Largest possible match at tail of string: * * move forward along string until we get a match. * * Again there's no optimisation. */ - for (ioff = 0, t = s, umlen = uml; t < s + l; - ioff++, METAINC(t), umlen--) { + for (ioff = 0, t = s, umlen = uml; t < send; + ioff++, t++, umlen--) { set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { - *sp = get_match_ret(*sp, t-s, l, fl, replstr, NULL); + if (pattrylen(p, t, send - t, umlen, &patstralloc, ioff)) { + *sp = get_match_ret(&imd, t-s, uml); return 1; } - if (*t == Meta) - t++; } break; case SUB_SUBSTR: /* Smallest at start, but matching substrings. */ set_pat_start(p, l); - if (!(fl & SUB_GLOBAL) && pattry(p, s + l) && !--n) { - *sp = get_match_ret(*sp, 0, 0, fl, replstr, NULL); + if (!(fl & SUB_GLOBAL) && + pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) { + *sp = get_match_ret(&imd, 0, 0); return 1; } /* fall through */ case (SUB_SUBSTR|SUB_LONG): /* longest or smallest at start with substrings */ t = s; if (fl & SUB_GLOBAL) { - repllist = newlinklist(); + imd.repllist = newlinklist(); if (repllistp) - *repllistp = repllist; + *repllistp = imd.repllist; } ioff = 0; /* offset into string */ umlen = uml; do { /* loop over all matches for global substitution */ matched = 0; - for (; t < s + l; METAINC(t), ioff++, umlen--) { + for (; t < send; t++, ioff++, umlen--) { /* Find the longest match from this position. */ set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, NULL, ioff)) { + if (pattrylen(p, t, send - t, umlen, &patstralloc, ioff)) { char *mpos = t + patmatchlen(); if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { char *ptr; int umlen2; for (ptr = t, umlen2 = 0; ptr < mpos; - METAINC(ptr), umlen2++) { + ptr++, umlen2++) { set_pat_end(p, *ptr); if (pattrylen(p, t, ptr - t, umlen2, - NULL, ioff)) { + &patstralloc, ioff)) { mpos = t + patmatchlen(); break; } } } if (!--n || (n <= 0 && (fl & SUB_GLOBAL))) { - *sp = get_match_ret(*sp, t-s, mpos-s, fl, - replstr, repllist); + *sp = get_match_ret(&imd, t-s, mpos-s); if (mpos == t) - METAINC(mpos); + mpos++; } if (!(fl & SUB_GLOBAL)) { if (n) { @@ -3278,13 +3339,13 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, * which is already marked for replacement. */ matched = 1; - for ( ; t < mpos; t++, ioff++, umlen--) - if (*t == Meta) - t++; + while (t < mpos) { + ioff++; + umlen--; + t++; + } break; } - if (*t == Meta) - t++; } } while (matched); /* @@ -3294,8 +3355,9 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, */ set_pat_start(p, l); if ((fl & (SUB_LONG|SUB_GLOBAL)) == SUB_LONG && - pattry(p, s + l) && !--n) { - *sp = get_match_ret(*sp, 0, 0, fl, replstr, repllist); + pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) { + *sp = get_match_ret(&imd, 0, 0); + patfreestr(&patstralloc); return 1; } break; @@ -3305,47 +3367,50 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, /* Longest/shortest at end, matching substrings. */ if (!(fl & SUB_LONG)) { set_pat_start(p, l); - if (pattrylen(p, s + l, 0, 0, NULL, uml) && !--n) { - *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); + if (pattrylen(p, send, 0, 0, &patstralloc, uml) && !--n) { + *sp = get_match_ret(&imd, uml, uml); + patfreestr(&patstralloc); return 1; } } - for (ioff = uml - 1, t = s + l - 1, umlen = 1; t >= s; + for (ioff = uml - 1, t = send - 1, umlen = 1; t >= s; t--, ioff--, umlen++) { - if (t > s && t[-1] == Meta) - t--; set_pat_start(p, t-s); - if (pattrylen(p, t, s + l - t, umlen, NULL, ioff) && !--n) { + if (pattrylen(p, t, send - t, umlen, &patstralloc, ioff) && + !--n) { /* Found the longest match */ char *mpos = t + patmatchlen(); if (!(fl & SUB_LONG) && !(p->flags & PAT_PURES)) { char *ptr; int umlen2; for (ptr = t, umlen2 = 0; ptr < mpos; - METAINC(ptr), umlen2++) { + ptr++, umlen2++) { set_pat_end(p, *ptr); - if (pattrylen(p, t, ptr - t, umlen2, NULL, ioff)) { + if (pattrylen(p, t, umlen2, 0, &patstralloc, + ioff)) { mpos = t + patmatchlen(); break; } } } - *sp = get_match_ret(*sp, t-s, mpos-s, fl, - replstr, NULL); + *sp = get_match_ret(&imd, t-s, mpos-s); + patfreestr(&patstralloc); return 1; } } set_pat_start(p, l); - if ((fl & SUB_LONG) && pattrylen(p, s + l, 0, 0, NULL, uml) && + if ((fl & SUB_LONG) && pattrylen(p, send, 0, 0, + &patstralloc, uml) && !--n) { - *sp = get_match_ret(*sp, l, l, fl, replstr, NULL); + *sp = get_match_ret(&imd, uml, uml); + patfreestr(&patstralloc); return 1; } break; } } - if (repllist && nonempty(repllist)) { + if (imd.repllist && nonempty(imd.repllist)) { /* Put all the bits of a global search and replace together. */ LinkNode nd; Repldata rd; @@ -3353,8 +3418,13 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, char *ptr, *start; int i; + /* + * Use metafied string again. + * Results from get_match_ret in repllist are all metafied. + */ + s = *sp; i = 0; /* start of last chunk we got from *sp */ - for (nd = firstnode(repllist); nd; incnode(nd)) { + for (nd = firstnode(imd.repllist); nd; incnode(nd)) { rd = (Repldata) getdata(nd); lleft += rd->b - i; /* previous chunk of *sp */ lleft += strlen(rd->replstr); /* the replaced bit */ @@ -3363,7 +3433,7 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, lleft += l - i; /* final chunk from *sp */ start = t = zhalloc(lleft+1); i = 0; - for (nd = firstnode(repllist); nd; incnode(nd)) { + for (nd = firstnode(imd.repllist); nd; incnode(nd)) { rd = (Repldata) getdata(nd); memcpy(t, s + i, rd->b - i); t += rd->b - i; @@ -3375,11 +3445,15 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, memcpy(t, s + i, l - i); start[lleft] = '\0'; *sp = (char *)start; + patfreestr(&patstralloc); return 1; } /* munge the whole string: no match, so no replstr */ - *sp = get_match_ret(*sp, 0, 0, fl, 0, 0); + imd.replstr = NULL; + imd.repllist = NULL; + *sp = get_match_ret(&imd, 0, 0); + patfreestr(&patstralloc); return 1; } diff --git a/Src/pattern.c b/Src/pattern.c index 03ba37d92..8de372c9e 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -2204,7 +2204,10 @@ pattrylen(Patprog prog, char *string, int len, int unmetalen, * the pattern module) at which we are trying to match. * This is added in to the positions recorded in patbeginp and patendp * when we are looking for substrings. Currently this only happens - * in the parameter substitution code. + * in the parameter substitution code. It refers to a real character + * offset, i.e. is already in the form ready for presentation to the + * general public --- this is necessary as we don't have the + * information to convert it down here. * * Note this is a character offset, i.e. a single possibly metafied and * possibly multibyte character counts as 1. @@ -2292,7 +2295,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, */ if (!patstralloc->progstrunmeta) { - patstralloc->progstrunmeta = dupstring(progstr); + patstralloc->progstrunmeta = + dupstrpfx(progstr, (int)prog->patmlen); unmetafy(patstralloc->progstrunmeta, &patstralloc->progstrunmetalen); } @@ -2346,7 +2350,7 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, * In the orignal structure, but it might be unmetafied * for use with an unmetafied test string. */ - patinlen = (int)prog->patmlen; + patinlen = pstrlen; /* if matching files, must update globbing flags */ patglobflags = prog->globend; @@ -2360,7 +2364,7 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, * Unmetafied: pstrlen contains unmetafied * length in bytes. */ - str = metafy(patinstart, pstrlen, META_ALLOC); + str = metafy(patinstart, pstrlen, META_DUP); mlen = CHARSUB(patinstart, patinstart + pstrlen); } else { str = ztrduppfx(patinstart, patinlen); @@ -2454,8 +2458,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, /* * Optimization: if we didn't find any Meta characters * to begin with, we don't need to look for them now. - * Only do this if we did the unmetfication internally, - * since otherwise it's too hard to work out. + * + * For patstralloc pased in, we want the unmetafied length. */ if (patstralloc == &patstralloc_struct && patstralloc->unmetalen != origlen) { @@ -2588,7 +2592,9 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, /* * Return length of previous succesful match. This is - * in metafied bytes, i.e. includes a count of Meta characters. + * in metafied bytes, i.e. includes a count of Meta characters, + * unless the match was done on an unmetafied string using + * a patstralloc stuct, in which case it, too is unmetafed. * Unusual and futile attempt at modular encapsulation. */ diff --git a/Src/zsh.h b/Src/zsh.h index 32f2e0cb2..15fa5e417 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -480,6 +480,7 @@ typedef struct heap *Heap; typedef struct heapstack *Heapstack; typedef struct histent *Histent; typedef struct hookdef *Hookdef; +typedef struct imatchdata *Imatchdata; typedef struct jobfile *Jobfile; typedef struct job *Job; typedef struct linkedmod *Linkedmod; @@ -1593,6 +1594,31 @@ typedef struct zpc_disables_save *Zpc_disables_save; /* Range: token followed by the (possibly multibyte) start and end */ #define PP_RANGE 21 +/* + * Argument to get_match_ret() in glob.c + */ +struct imatchdata { + /* Metafied trial string */ + char *mstr; + /* Its length */ + int mlen; + /* Unmetafied string */ + char *ustr; + /* Its length */ + int ulen; + /* Flags (SUB_*) */ + int flags; + /* Replacement string (metafied) */ + char *replstr; + /* + * List of bits of matches to concatenate with replacement string. + * The data is a struct repldata. It is not used in cases like + * ${...//#foo/bar} even though SUB_GLOBAL is set, since the match + * is anchored. It goes on the heap. + */ + LinkList repllist; +}; + /* Globbing flags: lower 8 bits gives approx count */ #define GF_LCMATCHUC 0x0100 #define GF_IGNCASE 0x0200 -- cgit v1.2.3 From a5a6c58ff883edc202bd0103af1e09848c9b8fe7 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Tue, 29 Sep 2015 13:36:43 -0700 Subject: unposted: fix typo in comment. --- Src/glob.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/glob.c b/Src/glob.c index 0594f0a82..d9986634a 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2482,7 +2482,7 @@ get_match_ret(Imatchdata imd, int b, int e) if (imeta(*p)) add++; - /* Everything now refers to meatfied lengths. */ + /* Everything now refers to metafied lengths. */ if (replstr || (fl & SUB_LIST)) { if (fl & SUB_DOSUBST) { replstr = dupstring(replstr); -- cgit v1.2.3 From 533658730745ae6261f9552aba01dc5346405d30 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 30 Sep 2015 10:19:16 +0100 Subject: 36711: Allocate unmetafied pattern trial string on the heap --- ChangeLog | 5 +++++ Src/glob.c | 25 ------------------------- Src/pattern.c | 34 +++++++--------------------------- 3 files changed, 12 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index 38e0e4627..56e725cf0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-30 Peter Stephenson + + * 36711: Src/glob.c, Src/pattern.c: Memory for early unmetafied + pattern trial string is on the heap. + 2015-09-28 Peter Stephenson * 36682: Src/glob.c, Src/pattern.c, Src/zsh.h, diff --git a/Src/glob.c b/Src/glob.c index d9986634a..24e60d0c5 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2478,9 +2478,6 @@ get_match_ret(Imatchdata imd, int b, int e) if (imeta(*p)) add++; e += add; - for (; p < imd->ustr + imd->ulen; p++) - if (imeta(*p)) - add++; /* Everything now refers to metafied lengths. */ if (replstr || (fl & SUB_LIST)) { @@ -2808,7 +2805,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, imd.replstr = NULL; } *sp = get_match_ret(&imd, 0, umltot); - patfreestr(&patstralloc); if (! **sp && (((fl & SUB_MATCH) && !i) || ((fl & SUB_REST) && i))) return 0; return 1; @@ -2856,7 +2852,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, } } *sp = get_match_ret(&imd, 0, mlen); - patfreestr(&patstralloc); return 1; } break; @@ -2884,13 +2879,11 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, } if (tmatch) { *sp = get_match_ret(&imd, tmatch - s, umltot); - patfreestr(&patstralloc); return 1; } if (!(fl & SUB_START) && pattrylen(p, s + umltot, 0, 0, &patstralloc, ioff)) { *sp = get_match_ret(&imd, umltot, umltot); - patfreestr(&patstralloc); return 1; } break; @@ -2904,7 +2897,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, set_pat_start(p, t-s); if (pattrylen(p, t, umlen, 0, &patstralloc, ioff)) { *sp = get_match_ret(&imd, t-s, umltot); - patfreestr(&patstralloc); return 1; } if (fl & SUB_START) @@ -2914,7 +2906,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, if (!(fl & SUB_START) && pattrylen(p, send, 0, 0, &patstralloc, ioff)) { *sp = get_match_ret(&imd, umltot, umltot); - patfreestr(&patstralloc); return 1; } break; @@ -2926,7 +2917,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) { *sp = get_match_ret(&imd, 0, 0); - patfreestr(&patstralloc); return 1; } /* fall through */ case (SUB_SUBSTR|SUB_LONG): @@ -2984,7 +2974,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, umlen -= iincchar(&t, send - t); continue; } else { - patfreestr(&patstralloc); return 1; } } @@ -3011,7 +3000,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, if ((fl & (SUB_LONG|SUB_GLOBAL)) == SUB_LONG && pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) { *sp = get_match_ret(&imd, 0, 0); - patfreestr(&patstralloc); return 1; } break; @@ -3024,7 +3012,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, if (pattrylen(p, send, 0, 0, &patstralloc, umltot) && !--n) { *sp = get_match_ret(&imd, umltot, umltot); - patfreestr(&patstralloc); return 1; } } @@ -3081,7 +3068,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, } } *sp = get_match_ret(&imd, tmatch-s, mpos-s); - patfreestr(&patstralloc); return 1; } set_pat_start(p, l); @@ -3089,7 +3075,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, &patstralloc, umltot) && !--n) { *sp = get_match_ret(&imd, umltot, umltot); - patfreestr(&patstralloc); return 1; } break; @@ -3134,11 +3119,9 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, start[lleft] = '\0'; *sp = (char *)start; } - patfreestr(&patstralloc); return 1; } if (fl & SUB_LIST) { /* safety: don't think this can happen */ - patfreestr(&patstralloc); return 0; } @@ -3146,7 +3129,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, imd.replstr = NULL; imd.repllist = NULL; *sp = get_match_ret(&imd, 0, 0); - patfreestr(&patstralloc); return (fl & SUB_RETFAIL) ? 0 : 1; } @@ -3244,7 +3226,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, } } *sp = get_match_ret(&imd, 0, mlen); - patfreestr(&patstralloc); return 1; } break; @@ -3357,7 +3338,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, if ((fl & (SUB_LONG|SUB_GLOBAL)) == SUB_LONG && pattrylen(p, send, 0, 0, &patstralloc, 0) && !--n) { *sp = get_match_ret(&imd, 0, 0); - patfreestr(&patstralloc); return 1; } break; @@ -3369,7 +3349,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, set_pat_start(p, l); if (pattrylen(p, send, 0, 0, &patstralloc, uml) && !--n) { *sp = get_match_ret(&imd, uml, uml); - patfreestr(&patstralloc); return 1; } } @@ -3394,7 +3373,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, } } *sp = get_match_ret(&imd, t-s, mpos-s); - patfreestr(&patstralloc); return 1; } } @@ -3403,7 +3381,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, &patstralloc, uml) && !--n) { *sp = get_match_ret(&imd, uml, uml); - patfreestr(&patstralloc); return 1; } break; @@ -3445,7 +3422,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, memcpy(t, s + i, l - i); start[lleft] = '\0'; *sp = (char *)start; - patfreestr(&patstralloc); return 1; } @@ -3453,7 +3429,6 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr, imd.replstr = NULL; imd.repllist = NULL; *sp = get_match_ret(&imd, 0, 0); - patfreestr(&patstralloc); return 1; } diff --git a/Src/pattern.c b/Src/pattern.c index 8de372c9e..68a340919 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -2028,8 +2028,8 @@ pattrystart(void) * * Unmetafy a trial string for use in pattern matching, if needed. * - * If it is needed, returns a zalloc()'d string; if not needed, returns - * NULL. + * If it is needed, returns a heap allocated string; if not needed, + * returns NULL. * * prog is the pattern to be executed. * string is the metafied trial string. @@ -2046,7 +2046,7 @@ pattrystart(void) * unmetalenp is the umetafied length of a path segment preceeding * the trial string needed for file mananagement; it is calculated as * needed so does not need to be initialised. - * alloced is the memory allocated --- same as return value from + * alloced is the memory allocated on the heap --- same as return value from * function. */ /**/ @@ -2097,7 +2097,7 @@ char *patallocstr(Patprog prog, char *string, int stringlen, int unmetalen, int i, icopy, ncopy; dst = patstralloc->alloced = - zalloc(patstralloc->unmetalen + patstralloc->unmetalenp); + zhalloc(patstralloc->unmetalen + patstralloc->unmetalenp); if (needfullpath) { /* loop twice, copy path buffer first time */ @@ -2133,20 +2133,6 @@ char *patallocstr(Patprog prog, char *string, int stringlen, int unmetalen, } -/* - * Free memory allocated by patallocstr(). - */ - -/**/ -mod_export -void patfreestr(Patstralloc patstralloc) -{ - if (patstralloc->alloced) - zfree(patstralloc->alloced, - patstralloc->unmetalen + patstralloc->unmetalenp); -} - - /* * Test prog against null-terminated, metafied string. */ @@ -2189,8 +2175,9 @@ pattrylen(Patprog prog, char *string, int len, int unmetalen, * done if there is no path prefix (pathpos == 0) as otherwise the path * buffer and unmetafied string may not match. To do this, * patallocstr() is callled (use force = 1 to ensure it is alway - * unmetafied); paststralloc points to existing storage. When all - * pattern matching is done, patfreestr() is called. + * unmetafied); paststralloc points to existing storage. Memory is + * on the heap. + * * patstralloc->alloced and patstralloc->unmetalen contain the * unmetafied string and its length. In that case, the rules for the * earlier arguments change: @@ -2387,8 +2374,6 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, } } - if (patstralloc == &patstralloc_struct) - patfreestr(patstralloc); return ret; } else { int q = queue_signal_level(); @@ -2425,8 +2410,6 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, } } if (!ret) { - if (patstralloc == &patstralloc_struct) - patfreestr(patstralloc); return 0; } @@ -2583,9 +2566,6 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, restore_queue_signals(q); - if (patstralloc == &patstralloc_struct) - patfreestr(patstralloc); - return ret; } } -- cgit v1.2.3 From 007f249a8e190306a9ef6bca2317e79004ace871 Mon Sep 17 00:00:00 2001 From: Matthew Martin Date: Tue, 29 Sep 2015 00:06:39 -0500 Subject: 36693: arithmetic rounds towards zero, document --- ChangeLog | 3 +++ Doc/Zsh/arith.yo | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 56e725cf0..ea7bd2e98 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-09-30 Peter Stephenson + * Matthew Martin: 36693: Doc/Zsh/arith.yo: arithmetic rounds + towards zero. + * 36711: Src/glob.c, Src/pattern.c: Memory for early unmetafied pattern trial string is on the heap. diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo index 1dcd18cad..c152bf48d 100644 --- a/Doc/Zsh/arith.yo +++ b/Doc/Zsh/arith.yo @@ -215,7 +215,7 @@ findex(integer, use of) Arithmetic evaluation is performed on the value of each assignment to a named parameter declared integer in this manner. Assigning a floating point number to an integer results in -rounding down to the next integer. +rounding towards zero. cindex(parameters, floating point) cindex(floating point parameters) @@ -230,16 +230,16 @@ format. Promotion of integer to floating point values is performed where necessary. In addition, if any operator which requires an integer -(`tt(~)', `tt(&)', `tt(|)', `tt(^)', `tt(%)', `tt(<<)', `tt(>>)' and their -equivalents with assignment) is given a floating point argument, it will be -silently rounded down to the next integer. +(`tt(&)', `tt(|)', `tt(^)', `tt(<<)', `tt(>>)' and their equivalents with +assignment) is given a floating point argument, it will be silently rounded +towards zero except for `tt(~)' which rounds down. Users should beware that, in common with many other programming languages but not software designed for calculation, the evaluation of an expression in zsh is taken a term at a time and promotion of integers to floating point does not occur in terms only containing integers. A typical result of this is that a division such as tt(6/8) is truncated, -in this being rounded down to 0. The tt(FORCE_FLOAT) shell option can +in this being rounded towards 0. The tt(FORCE_FLOAT) shell option can be used in scripts or functions where floating point evaluation is required throughout. -- cgit v1.2.3 From 756526eef3e064c3ffb023ae5e5e6df42e6e9162 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Wed, 30 Sep 2015 23:56:14 +0900 Subject: 36697: handle options of _arguments correctly --- ChangeLog | 5 +++++ Completion/Base/Utility/_arguments | 45 +++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 56e725cf0..498ad7c87 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-09-30 Jun-ichi Takimoto + + * 36697: Completion/Base/Utility/_arguments: handle options + of _arguments correctly + 2015-09-30 Peter Stephenson * 36711: Src/glob.c, Src/pattern.c: Memory for early unmetafied diff --git a/Completion/Base/Utility/_arguments b/Completion/Base/Utility/_arguments index 1f35e8d43..87fb20e6b 100644 --- a/Completion/Base/Utility/_arguments +++ b/Completion/Base/Utility/_arguments @@ -8,15 +8,33 @@ local oldcontext="$curcontext" hasopts rawret optarg singopt alwopt local setnormarg start rest local -a match mbegin mend +subopts=() +singopt=() +while [[ "$1" = -([AMO]*|[CRSWnsw]) ]]; do + case "$1" in + -C) usecc=yes; shift ;; + -O) subopts=( "${(@P)2}" ); shift 2 ;; + -O*) subopts=( "${(@P)${1[3,-1]}}" ); shift ;; + -R) rawret=yes; shift;; + -n) setnormarg=yes; NORMARG=-1; shift;; + -w) optarg=yes; shift;; + -W) alwopt=arg; shift;; + -[Ss]) singopt+=( $1 ); shift;; + -[AM]) singopt+=( $1 $2 ); shift 2 ;; + -[AM]*) singopt+=( $1 ); shift ;; + esac +done + +[[ $1 = ':' ]] && shift +singopt+=( ':' ) # always end with ':' to indicate the end of options + +[[ "$PREFIX" = [-+] ]] && alwopt=arg + long=$argv[(I)--] if (( long )); then local name tmp tmpargv - if [[ long -eq 1 ]]; then - tmpargv=() - else - tmpargv=( "${(@)argv[1,long-1]}" ) - fi + tmpargv=( "${(@)argv[1,long-1]}" ) # optspec's before --, if any name=${~words[1]} [[ "$name" = [^/]*/* ]] && name="$PWD/$name" @@ -290,23 +308,6 @@ if (( long )); then set -- "$tmpargv[@]" "${(@P)name}" fi -subopts=() -singopt=() -while [[ "$1" = -(O*|[CRWnsw]) ]]; do - case "$1" in - -C) usecc=yes; shift ;; - -O) subopts=( "${(@P)2}" ); shift 2 ;; - -O*) subopts=( "${(@P)${1[3,-1]}}" ); shift ;; - -R) rawret=yes; shift;; - -n) setnormarg=yes; NORMARG=-1; shift;; - -w) optarg=yes; shift;; - -s) singopt=(-s); shift;; - -W) alwopt=arg; shift;; - esac -done - -[[ "$PREFIX" = [-+] ]] && alwopt=arg - zstyle -s ":completion:${curcontext}:options" auto-description autod if (( $# )) && comparguments -i "$autod" "$singopt[@]" "$@"; then -- cgit v1.2.3 From 7ac34a3055d87b88d8b1b28ddfe68982f6550a08 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 30 Sep 2015 14:21:59 +0000 Subject: 36725: vcs_info git: Compute %b correctly when merging to detached heads. The %b expando should be the hash prior to the merge. The hash of the merge result is available as the %i expando and via the gen-applied-string hook. --- ChangeLog | 6 ++++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 498ad7c87..9a755434a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-09-30 Daniel Shahaf + + * 36725: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: + vcs_info git: Compute %b correctly when merging to detached + heads. + 2015-09-30 Jun-ichi Takimoto * 36697: Completion/Base/Utility/_arguments: handle options diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 8ecc7c7f7..312f17c33 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -90,7 +90,7 @@ VCS_INFO_git_getbranch () { elif [[ -f "${gitdir}/MERGE_HEAD" ]] ; then gitbranch="$(${(z)gitsymref} 2> /dev/null)" - [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/MERGE_HEAD)" + [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/ORIG_HEAD)" elif [[ -d "${gitdir}/rebase-merge" ]] ; then gitbranch="$(< ${gitdir}/rebase-merge/head-name)" -- cgit v1.2.3 From cd1cda9d57ff9f44d285bcd867721c4024500837 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 30 Sep 2015 14:21:59 +0000 Subject: 36725: vcs_info git: Compute %b correctly when rebasing detached heads. This sets the %b expando to the hash of the before-the-merge HEAD, rather than to the literal string "detached HEAD". That hash is already available via the gen-applied-string hook. --- ChangeLog | 3 +++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9a755434a..f45b414c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-09-30 Daniel Shahaf + * 36725: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: + vcs_info git: Compute %b correctly when rebasing detached heads. + * 36725: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: vcs_info git: Compute %b correctly when merging to detached heads. diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 312f17c33..0a2a8bc37 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -94,6 +94,10 @@ VCS_INFO_git_getbranch () { elif [[ -d "${gitdir}/rebase-merge" ]] ; then gitbranch="$(< ${gitdir}/rebase-merge/head-name)" + if [[ $gitbranch == 'detached HEAD' ]]; then + # get a sha1 + gitbranch="$(< ${gitdir}/rebase-merge/orig-head)" + fi elif [[ -d "${gitdir}/.dotest-merge" ]] ; then gitbranch="$(< ${gitdir}/.dotest-merge/head-name)" -- cgit v1.2.3 From a90cf551efc92184ab25da25b837296d1c4edc8a Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 30 Sep 2015 14:21:59 +0000 Subject: 36725: vcs_info git: Compute %b correctly when "git am"-ing onto detached heads. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this patch, $gitbranch would be set to empty, which caused VCS_INFO_get_data_git to early out with a failure status¹, consequently $vcs_info_msg_0_ would be empty. ¹ via the 'if [[ -z ]]' block around line 170. --- ChangeLog | 4 ++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index f45b414c0..20860a1f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-09-30 Daniel Shahaf + * 36725: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: + vcs_info git: Compute %b correctly when "git am"-ing onto + detached heads. + * 36725: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: vcs_info git: Compute %b correctly when rebasing detached heads. diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 0a2a8bc37..8664d510e 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -87,6 +87,7 @@ VCS_INFO_git_getbranch () { gitbranch="$(${(z)gitsymref} 2> /dev/null)" [[ -z ${gitbranch} ]] && [[ -r ${actiondir}/head-name ]] \ && gitbranch="$(< ${actiondir}/head-name)" + [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/ORIG_HEAD)" elif [[ -f "${gitdir}/MERGE_HEAD" ]] ; then gitbranch="$(${(z)gitsymref} 2> /dev/null)" -- cgit v1.2.3 From a855d7bd246ef44d5393c3088aae8214d41d2b85 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Tue, 29 Sep 2015 06:11:24 +0200 Subject: 36709: zle -f from inside widget to set flags and make yank start/end zle params writable --- ChangeLog | 7 +++++++ Doc/Zsh/zle.yo | 29 ++++++++++++++++++++++++----- Src/Zle/zle_main.c | 5 +++-- Src/Zle/zle_params.c | 24 +++++++++++++++++++----- Src/Zle/zle_thingy.c | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 20860a1f6..eaa565870 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2015-10-01 Mikael Magnusson + + * 36709: Doc/Zsh/zle.yo, Functions/Zle/bracketed-paste-url-magic, + Src/Zle/zle_main.c, Src/Zle/zle_params.c, Src/Zle/zle_thingy.c: + zle -f from inside widget to set flags and make yank start/end + zle params writable. + 2015-09-30 Daniel Shahaf * 36725: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 7d95eb377..05bb14829 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -404,6 +404,7 @@ xitem(tt(zle) tt(-l) [ tt(-L) | tt(-a) ] [ var(string) ... ]) xitem(tt(zle) tt(-D) var(widget) ...) xitem(tt(zle) tt(-A) var(old-widget) var(new-widget)) xitem(tt(zle) tt(-N) var(widget) [ var(function) ]) +xitem(tt(zle) tt(-f) var(flag) [ var(flag)... ]) xitem(tt(zle) tt(-C) var(widget) var(completion-widget) var(function)) xitem(tt(zle) tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ]) xitem(tt(zle) tt(-M) var(string)) @@ -464,6 +465,21 @@ ifzman(the section `Widgets' below)\ ifnzman(noderef(Zle Widgets))\ . ) +item(tt(-f) var(flag) [ var(flag)... ])( +Set various flags on the running widget. Possible values for var(flag) are: + +tt(yank) for indicating that the widget has yanked text into the buffer. +If the widget is wrapping an existing internal widget, no further +action is necessary, but if it has inserted the text manually, then it +should also take care to set tt(YANK_START) and tt(YANK_END) correctly. +tt(yankbefore) does the same but is used when the yanked text appears +after the cursor. + +tt(kill) for indicating that text has been killed into the cutbuffer. +When repeatedly invoking a kill widget, text is appended to the cutbuffer +instead of replacing it, but when wrapping such widgets, it is necessary +to call `tt(zle -f kill)' to retain this effect. +) cindex(completion widgets, creating) item(tt(-C) var(widget) var(completion-widget) var(function))( Create a user-defined completion widget named var(widget). The @@ -1011,11 +1027,14 @@ vindex(YANK_END) xitem(tt(YANK_ACTIVE) (integer)) xitem(tt(YANK_START) (integer)) item(tt(YANK_END) (integer))( -These three parameters indicate whether text has just been yanked (pasted) -into the buffer. tt(YANK_START) and tt(YANK_END) are in the same units as -tt(CURSOR), and are only valid when tt(YANK_ACTIVE) is non-zero. - -All three are read-only. +tt(YANK_ACTIVE) indicates whether text has just been yanked (pasted) +into the buffer. tt(YANK_START) and tt(YANK_END) give the location of +the pasted text and are in the same units as tt(CURSOR). They are only +valid for reading when tt(YANK_ACTIVE) is non-zero. They can also be +assigned by widgets that insert text in a yank-like fashion, for example +wrappers of tt(bracketed-paste). See also tt(zle -f). + +tt(YANK_ACTIVE) is read-only. ) vindex(ZLE_STATE) item(tt(ZLE_STATE) (scalar))( diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 992f152df..593d636cc 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -1402,7 +1402,8 @@ execzlefunc(Thingy func, char **args, int set_bindk) opts[XTRACE] = oxt; sfcontext = osc; endparamscope(); - lastcmd = 0; + lastcmd = w->flags; + w->flags = 0; r = 1; redup(osi, 0); } @@ -1981,7 +1982,7 @@ zle_main_entry(int cmd, va_list ap) static struct builtin bintab[] = { BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaM:ldDANmrsLRp", NULL), BUILTIN("vared", 0, bin_vared, 1, 1, 0, "aAcef:hi:M:m:p:r:t:", NULL), - BUILTIN("zle", 0, bin_zle, 0, -1, 0, "aAcCDFgGIKlLmMNrRTUw", NULL), + BUILTIN("zle", 0, bin_zle, 0, -1, 0, "aAcCDfFgGIKlLmMNrRTUw", NULL), }; /* The order of the entries in this table has to match the *HOOK diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index 000bc388c..b5bb288f1 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -98,9 +98,9 @@ static const struct gsu_integer undo_change_no_gsu = static const struct gsu_integer undo_limit_no_gsu = { get_undo_limit_change, set_undo_limit_change, zleunsetfn }; static const struct gsu_integer yankstart_gsu = -{ get_yankstart, NULL, zleunsetfn }; +{ get_yankstart, set_yankstart, zleunsetfn }; static const struct gsu_integer yankend_gsu = -{ get_yankend, NULL, zleunsetfn }; +{ get_yankend, set_yankend, zleunsetfn }; static const struct gsu_integer yankactive_gsu = { get_yankactive, NULL, zleunsetfn }; @@ -149,8 +149,8 @@ static struct zleparam { { "WIDGET", PM_SCALAR | PM_READONLY, GSU(widget_gsu), NULL }, { "WIDGETFUNC", PM_SCALAR | PM_READONLY, GSU(widgetfunc_gsu), NULL }, { "WIDGETSTYLE", PM_SCALAR | PM_READONLY, GSU(widgetstyle_gsu), NULL }, - { "YANK_START", PM_INTEGER | PM_READONLY, GSU(yankstart_gsu), NULL }, - { "YANK_END", PM_INTEGER | PM_READONLY, GSU(yankend_gsu), NULL }, + { "YANK_START", PM_INTEGER, GSU(yankstart_gsu), NULL }, + { "YANK_END", PM_INTEGER, GSU(yankend_gsu), NULL }, { "YANK_ACTIVE", PM_INTEGER | PM_READONLY, GSU(yankactive_gsu), NULL }, { "ZLE_STATE", PM_SCALAR | PM_READONLY, GSU(zle_state_gsu), NULL }, { NULL, 0, NULL, NULL } @@ -503,7 +503,21 @@ get_yankend(UNUSED(Param pm)) static zlong get_yankactive(UNUSED(Param pm)) { - return lastcmd & ZLE_YANK; + return !!(lastcmd & ZLE_YANK) + !!(lastcmd & ZLE_YANKAFTER); +} + +/**/ +static void +set_yankstart(UNUSED(Param pm), zlong i) +{ + yankb = i; +} + +/**/ +static void +set_yankend(UNUSED(Param pm), zlong i) +{ + yanke = i; } /**/ diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index da3a6d458..3963d7eaf 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -352,6 +352,7 @@ bin_zle(char *name, char **args, Options ops, UNUSED(int func)) { 'U', bin_zle_unget, 1, 1 }, { 'K', bin_zle_keymap, 1, 1 }, { 'I', bin_zle_invalidate, 0, 0 }, + { 'f', bin_zle_flags, 1, -1 }, { 'F', bin_zle_fd, 0, 2 }, { 'T', bin_zle_transform, 0, 2}, { 0, bin_zle_call, 0, -1 }, @@ -623,6 +624,44 @@ bin_zle_complete(char *name, char **args, UNUSED(Options ops), UNUSED(char func) return 0; } +/**/ +static int +bin_zle_flags(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) +{ + char **flag; + + if (!zle_usable()) { + zwarnnam(name, "can only set flags from a widget"); + return 1; + } + + if (bindk) { + Widget w = bindk->widget; + if (w) { + for (flag = args; *flag; flag++) { + if (!strcmp(*flag, "yank")) { + w->flags |= ZLE_YANKAFTER; + } else if (!strcmp(*flag, "yankbefore")) + w->flags |= ZLE_YANKBEFORE; + else if (!strcmp(*flag, "kill")) + w->flags |= ZLE_KILL; + /* + * These won't do anything yet, because of how execzlefunc + * handles user widgets + } else if (!strcmp(*flag, "menucmp")) + w->flags |= ZLE_MENUCMP; + else if (!strcmp(*flag, "linemove")) + w->flags |= ZLE_LINEMOVE; + else if (!strcmp(*flag, "keepsuffix")) + w->flags |= ZLE_KEEPSUFFIX; + */ + else + zwarnnam(name, "invalid flag `%s' given to zle -f", *flag); + } + } + } +} + /**/ static int zle_usable() -- cgit v1.2.3 From 76da752fd75955cd6240c1daa026cc34dea1e010 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Thu, 1 Oct 2015 03:52:16 +0200 Subject: 36692: bracketed-paste-url-magic: simpler alternative for handling pasted urls --- ChangeLog | 3 +++ Functions/Zle/bracketed-paste-url-magic | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 Functions/Zle/bracketed-paste-url-magic diff --git a/ChangeLog b/ChangeLog index eaa565870..b003b9a71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,9 @@ zle -f from inside widget to set flags and make yank start/end zle params writable. + * 36692: Functions/Zle/bracketed-paste-url-magic: simpler + alternative for handling pasted urls + 2015-09-30 Daniel Shahaf * 36725: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: diff --git a/Functions/Zle/bracketed-paste-url-magic b/Functions/Zle/bracketed-paste-url-magic new file mode 100644 index 000000000..e1bea60d6 --- /dev/null +++ b/Functions/Zle/bracketed-paste-url-magic @@ -0,0 +1,42 @@ +# bracketed-paste-url-magic quotes pasted urls automatically, if the +# paste exactly starts with a url, eg no spaces or other characters precede it +# +# If the numeric argument is provided (eg, pressing alt-0 or alt-1 in emacs mode, +# or just the number by itself in vi command mode), then override the url detection +# and if it was 0, never quote, and if it was 1, always quote. +# +# To use this widget, put this in your startup files (eg, .zshrc) +# +# autoload -Uz bracketed-paste-url-magic +# zle -N bracketed-paste bracketed-paste-url-magic +# +# You can customize which schemas are to be quoted by using +# +# zstyle :bracketed-paste-url-magic schema http https ftp +# +# The default can be seen just below. + +local -a schema +zstyle -a :bracketed-paste-url-magic schema schema || schema=(http https ftp ftps file ssh sftp) + +local wantquote=${NUMERIC:-0} +local content +local start=$#LBUFFER + +zle .$WIDGET -N content + +if ! (( $wantquote )); then + if [[ $content = (${(~j:|:)schema})://* ]]; then + wantquote=1 + fi +fi + +if (( $wantquote )); then + content=${(q-)content} +fi + +LBUFFER+=$content + +YANK_START=$start +YANK_END=$#LBUFFER +zle -f yank -- cgit v1.2.3 From d1a810b000296bac43b114af526b0787068ae3ba Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 30 Sep 2015 19:58:43 -0700 Subject: remove sentence fragment --- ChangeLog | 4 ++++ Doc/Zsh/builtins.yo | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b003b9a71..018585611 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,10 @@ * 36692: Functions/Zle/bracketed-paste-url-magic: simpler alternative for handling pasted urls +2015-09-30 Barton E. Schaefer + + * cf. 36690: Doc/Zsh/builtins.yo: remove sentence fragment + 2015-09-30 Daniel Shahaf * 36725: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 97c337071..85d1742f0 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -174,8 +174,7 @@ pattern are loaded. With the tt(-w) flag, the var(name)s are taken as names of files compiled with the tt(zcompile) builtin, and all functions defined in them are -marked for autoloading. Note this does not otherwise change the search -order for +marked for autoloading. The flags tt(-z) and tt(-k) mark the function to be autoloaded using the zsh or ksh style, as if the option tt(KSH_AUTOLOAD) were unset or were -- cgit v1.2.3 From 2bf4f667fb41a8aba139e3ef93b1ebcd9f3e016d Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 30 Sep 2015 20:01:13 -0700 Subject: 36707: distinguish ERR_RETURN value of retflag so that execif() can ignore it in the test sublist --- ChangeLog | 3 +++ Src/exec.c | 2 +- Src/loop.c | 8 ++++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 018585611..3f54075f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,9 @@ 2015-09-30 Barton E. Schaefer + * 36707: Src/exec.c, Src/loop.c: distinguish ERR_RETURN value + of retflag so that execif() can ignore it in the test sublist + * cf. 36690: Doc/Zsh/builtins.yo: remove sentence fragment 2015-09-30 Daniel Shahaf diff --git a/Src/exec.c b/Src/exec.c index da808d6f1..154bbb8db 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1408,7 +1408,7 @@ sublist_done: exit(lastval); } if (errreturn) { - retflag = 1; + retflag = 2; breaks = loops; } } diff --git a/Src/loop.c b/Src/loop.c index 4def9b652..7d1528efe 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -552,8 +552,12 @@ execif(Estate state, int do_exec) run = 1; break; } - if (retflag) - break; + if (retflag) { + if (retflag == 2) + retflag = 0; /* Never ERR_RETURN here */ + else + break; + } s = 1; state->pc = next; } -- cgit v1.2.3 From bc2e73ba4c27a220a6f122cb7b9b5c6fa9996941 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 30 Sep 2015 20:02:53 -0700 Subject: users/20672: missing "do" in gettext2() for "select" --- ChangeLog | 2 ++ Src/text.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3f54075f8..bb7717692 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,8 @@ 2015-09-30 Barton E. Schaefer + * users/20672: Src/text.c: missing "do" in gettext2() for "select" + * 36707: Src/exec.c, Src/loop.c: distinguish ERR_RETURN value of retflag so that execif() can ignore it in the test sublist diff --git a/Src/text.c b/Src/text.c index 7e65f43a4..9421d70ce 100644 --- a/Src/text.c +++ b/Src/text.c @@ -632,8 +632,10 @@ gettext2(Estate state) taddstr(" in "); taddlist(state, *state->pc++); } - tindent++; taddnl(0); + taddstr("do"); + taddnl(0); + tindent++; tpush(code, 1); } else { dec_tindent(); -- cgit v1.2.3 From 9064483b6c73286cd892acd5d30366db14a77371 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 1 Oct 2015 09:47:15 +0100 Subject: 36722: allow git range to complete after ^. Take account of backslash quoting. --- ChangeLog | 5 +++++ Completion/Unix/Command/_git | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b3a0a649f..80edc8fdf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-01 Peter Stephenson + + * 36722: Completion/Unix/Command/_git: allow range to complete + after ^, taking acoount of backslash quoting. + 2015-10-01 Mikael Magnusson * 36709: Doc/Zsh/zle.yo, Functions/Zle/bracketed-paste-url-magic, diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 40a9fb63b..1fcde9015 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5753,7 +5753,14 @@ __git_commit_ranges () { if compset -P '*..(.|)'; then expl=( $* ) else - compset -S '..*' || suf=( -S .. -r '.@~ ^:\t\n\-' ) + if ! compset -S '..*'; then + local match mbegin mend + if [[ ${PREFIX} = (#b)((\\|)\^)* ]]; then + compset -p ${#match[1]} + else + suf=( -S .. -r '.@~ ^:\t\n\-' ) + fi + fi expl=( $* $suf ) fi -- cgit v1.2.3 From 8bf72dd65b00ffd223d0705c8fde952ff129eafa Mon Sep 17 00:00:00 2001 From: Andrew Janke Date: Wed, 30 Sep 2015 21:14:05 -0400 Subject: 36729: fix some typos in distro docs --- ChangeLog | 2 ++ MACHINES | 4 ++-- NEWS | 6 +++--- README | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 80edc8fdf..4a9d1cebc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-10-01 Peter Stephenson + * Andrew Janke: 36729: MACHINES, NEWS, README: fix some typos. + * 36722: Completion/Unix/Command/_git: allow range to complete after ^, taking acoount of backslash quoting. diff --git a/MACHINES b/MACHINES index ddbf69ac6..73f80c7d1 100644 --- a/MACHINES +++ b/MACHINES @@ -162,8 +162,8 @@ Other machines Zsh has previously been compiled on the following machines, but the developers do not have direct access to them and the reports may be out -of date. Some of these OS's are now very long in the tooth. We would -be glad to receive any reports of success or failure on these OS's --- +of date. Some of these OSes are now very long in the tooth. We would +be glad to receive any reports of success or failure on these OSes --- and, of course, any others not mentioned in this file. Apple/NeXT OpenStep 4.2 for i386. diff --git a/NEWS b/NEWS index 7b2994b6b..bc14a8beb 100644 --- a/NEWS +++ b/NEWS @@ -47,7 +47,7 @@ and an array "array" containing the words "several" - Improved (though still not perfect) POSIX compatibility for getopts builtin when POSIX_BUILTINS is set. -- New setopt APPEND_CREATE for POSIX-compatible NO_CLOBBER behavior. +- New setopt APPEND_CREATE for POSIX-compatible NO_CLOBBER behaviour. - Completion of date values now displays in a calendar format when the complist module is available. Controllable by zstyle. @@ -929,7 +929,7 @@ Parameter and expansion changes: - expansion of ~ and other globbing flags via ${~param} do not depend upon EXTENDED_GLOB (bug fix). - nested parameter substitutions require braces (this was always the - documented behavior, but previous parsers didn't enforce it). + documented behaviour, but previous parsers didn't enforce it). - quote only nested expansion, e.g. ${(f)"$( Date: Thu, 1 Oct 2015 15:55:01 +0100 Subject: 36735: add ~/.zcalcrc handling to zcalc --- ChangeLog | 2 ++ Doc/Zsh/contrib.yo | 8 ++++++++ Functions/Misc/zcalc | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4a9d1cebc..a51dc4795 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-10-01 Peter Stephenson + * 36735: Doc/Zsh/contrib.yo, Functions/Misc/zcalc: ~/.zcalcrc. + * Andrew Janke: 36729: MACHINES, NEWS, README: fix some typos. * 36722: Completion/Unix/Command/_git: allow range to complete diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 330c6f588..635f9b010 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -3657,6 +3657,14 @@ integer arithmetic, which is not how an ordinary desk calculator operates. To force floating point operation, pass the option tt(-f); see further notes below. +If the file tt(~/.zcalcrc) exists it will be sourced inside the function +once it is set up and about to process the command line. This +can be used, for example, to set shell options; tt(emulate -L zsh) +and tt(setopt extendedglob) are in effect at this point. Any +failure to source the file if it exists is treated as fatal. +As with other initialisation files, the directory tt($ZDOTDIR) is used +instead of tt($HOME) if it is set. + The mathematical library tt(zsh/mathfunc) will be loaded if it is available; see ifzman(the section `The zsh/mathfunc Module' in zmanref(zshmodules))\ diff --git a/Functions/Misc/zcalc b/Functions/Misc/zcalc index 63f67adb0..17700e48b 100644 --- a/Functions/Misc/zcalc +++ b/Functions/Misc/zcalc @@ -120,6 +120,10 @@ autoload -Uz zmathfuncdef float PI E (( PI = 4 * atan(1), E = exp(1) )) +if [[ -f "${ZDOTDIR:-$HOME}/.zcalcrc" ]]; then + . "${ZDOTDIR:-$HOME}/.zcalcrc" || return 1 +fi + # Process command line while [[ -n $1 && $1 = -(|[#-]*|f|e) ]]; do optlist=${1[2,-1]} -- cgit v1.2.3 From 807a8338a3be8127dd23c69971668b7b0c6b79a2 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 1 Oct 2015 16:21:18 +0100 Subject: 36737: Ensure we don't dreference unterminated zero-length string --- ChangeLog | 3 +++ Src/pattern.c | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a51dc4795..14749d9ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-01 Peter Stephenson + * 36737: Src/pattern.c: Ensure we are not dereferencing + zero-length unterminated string. + * 36735: Doc/Zsh/contrib.yo, Functions/Misc/zcalc: ~/.zcalcrc. * Andrew Janke: 36729: MACHINES, NEWS, README: fix some typos. diff --git a/Src/pattern.c b/Src/pattern.c index 68a340919..04d3e3dfb 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -2224,8 +2224,10 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, maxnpos = *nump; *nump = 0; } - /* inherited from domatch, but why, exactly? */ - if (*string == Nularg) { + /* + * Special signalling of empty tokenised string. + */ + if ((!patstralloc || stringlen > 0) && *string == Nularg) { string++; if (unmetalenin > 0) unmetalenin--; @@ -2233,8 +2235,10 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, stringlen--; } - if (stringlen < 0) + if (stringlen < 0) { + DPUTS(patstralloc != NULL, "length needed with patstralloc"); stringlen = strlen(string); + } origlen = stringlen; if (patstralloc) { -- cgit v1.2.3 From 99aff5bb0cad712b0e24e76ff2ba1ea3d2214769 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Thu, 1 Oct 2015 20:14:55 +0200 Subject: unposted: bracketed-paste-url-magic: actually do what the comment says --- Functions/Zle/bracketed-paste-url-magic | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Functions/Zle/bracketed-paste-url-magic b/Functions/Zle/bracketed-paste-url-magic index e1bea60d6..06dee2657 100644 --- a/Functions/Zle/bracketed-paste-url-magic +++ b/Functions/Zle/bracketed-paste-url-magic @@ -2,8 +2,10 @@ # paste exactly starts with a url, eg no spaces or other characters precede it # # If the numeric argument is provided (eg, pressing alt-0 or alt-1 in emacs mode, -# or just the number by itself in vi command mode), then override the url detection -# and if it was 0, never quote, and if it was 1, always quote. +# or just the number by itself in vi command mode), then +# 0 is the default and means auto detect urls +# 1 means always quote +# any other value means never quote # # To use this widget, put this in your startup files (eg, .zshrc) # @@ -25,13 +27,13 @@ local start=$#LBUFFER zle .$WIDGET -N content -if ! (( $wantquote )); then +if (( $wantquote == 0 )); then if [[ $content = (${(~j:|:)schema})://* ]]; then wantquote=1 fi fi -if (( $wantquote )); then +if (( $wantquote == 1 )); then content=${(q-)content} fi -- cgit v1.2.3 From fa72e547120581cdbff1b1695a47c2c19fed3487 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Thu, 1 Oct 2015 20:24:09 +0200 Subject: unposted: zle_thingy: return a value in bin_zle_flags --- Src/Zle/zle_thingy.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index 3963d7eaf..ba89e00a8 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -628,6 +628,7 @@ bin_zle_complete(char *name, char **args, UNUSED(Options ops), UNUSED(char func) static int bin_zle_flags(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) { + int ret = 0; char **flag; if (!zle_usable()) { @@ -655,11 +656,14 @@ bin_zle_flags(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) else if (!strcmp(*flag, "keepsuffix")) w->flags |= ZLE_KEEPSUFFIX; */ - else + else { zwarnnam(name, "invalid flag `%s' given to zle -f", *flag); + ret = 1; + } } } } + return ret; } /**/ -- cgit v1.2.3 From e3bc9aa22843cb55912b909e00f54972eab5b2c5 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Fri, 2 Oct 2015 22:11:43 +0900 Subject: 36732: _zsh now complets script args; also support -s, -b --- ChangeLog | 5 +++++ Completion/Unix/Command/_zsh | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 14749d9ff..87a2ce490 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-02 Jun-ichi Takimoto + + * 36732: Completion/Unix/Command/_zsh: support -s and -b, + and complete script arguments + 2015-10-01 Peter Stephenson * 36737: Src/pattern.c: Ensure we are not dereferencing diff --git a/Completion/Unix/Command/_zsh b/Completion/Unix/Command/_zsh index 3b6d7ad4f..a5414670b 100644 --- a/Completion/Unix/Command/_zsh +++ b/Completion/Unix/Command/_zsh @@ -1,8 +1,23 @@ #compdef zsh +local curcontext=$curcontext state state_descr line expl +typeset -A opt_args + _arguments -S -s : \ '*-o+[set named option]:option:_options' \ '*+o+[unset named option]:option:_options' \ + '(1 -s --shinstdin)'{-s,--shinstdin}'[read commands from standard input]' \ + '(-)-b[end of option processing, like --]' \ '(1 -)-c[run a command]:command:_cmdstring' \ '(-)1:script file:_files' \ - '*:command arguments' -- + '*::script arguments:->args' -- && return 0 + +case $state in + (args) + if [[ -n ${opt_args[(I)-c|-s|--shinstdin]} ]]; then + _files + else + _normal + fi + ;; +esac -- cgit v1.2.3 From 0626be9e3c02ca9171cd4e0975c208e0c3d6ec2b Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Fri, 2 Oct 2015 20:41:49 +0200 Subject: unposted: define zle_usable before using it (reported in 36741) --- Src/Zle/zle_thingy.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index ba89e00a8..c6ef8e6a0 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -624,6 +624,23 @@ bin_zle_complete(char *name, char **args, UNUSED(Options ops), UNUSED(char func) return 0; } +/**/ +static int +zle_usable() +{ + return zleactive && !incompctlfunc && !incompfunc +#if 0 + /* + * PWS experiment: commenting this out allows zle widgets + * in signals, hooks etc. I'm not sure if this has a down side; + * it ought to be that zleactive is good enough to test whether + * widgets are callable. + */ + && sfcontext == SFC_WIDGET +#endif + ; +} + /**/ static int bin_zle_flags(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) @@ -666,23 +683,6 @@ bin_zle_flags(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) return ret; } -/**/ -static int -zle_usable() -{ - return zleactive && !incompctlfunc && !incompfunc -#if 0 - /* - * PWS experiment: commenting this out allows zle widgets - * in signals, hooks etc. I'm not sure if this has a down side; - * it ought to be that zleactive is good enough to test whether - * widgets are callable. - */ - && sfcontext == SFC_WIDGET -#endif - ; -} - /**/ static int bin_zle_call(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) -- cgit v1.2.3 From 64061e504fe9145c34911622a9fec6ec43869cea Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Sat, 3 Oct 2015 00:04:09 +0200 Subject: 36754: Functions/TCP: Tweak some usage output in the tcp_* functions --- ChangeLog | 6 ++++++ Functions/TCP/tcp_open | 2 +- Functions/TCP/tcp_read | 2 +- Functions/TCP/tcp_send | 2 +- Functions/TCP/tcp_shoot | 4 ++-- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 87a2ce490..1061d1d94 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-10-03 Mikael Magnusson + + * 36754: Functions/TCP/tcp_open, Functions/TCP/tcp_read, + Functions/TCP/tcp_send, Functions/TCP/tcp_shoot: Tweak some + usage output in the tcp_* functions + 2015-10-02 Jun-ichi Takimoto * 36732: Completion/Unix/Command/_zsh: support -s and -b, diff --git a/Functions/TCP/tcp_open b/Functions/TCP/tcp_open index 091217788..a04403c76 100644 --- a/Functions/TCP/tcp_open +++ b/Functions/TCP/tcp_open @@ -152,7 +152,7 @@ fi if (( $# )); then print "Usage: $0 [-z] [-a fd | -f fd | host port [ session ] ] - $0 [-z] [ -s session | -l sesslist ] ..." >&2 + $0 [-z] [ -s session | -l sesslist ] ..." >&2 return 1 fi diff --git a/Functions/TCP/tcp_read b/Functions/TCP/tcp_read index f880395dd..ba9185ed5 100644 --- a/Functions/TCP/tcp_read +++ b/Functions/TCP/tcp_read @@ -116,7 +116,7 @@ while getopts "abdl:qs:t:T:u:" opt; do read_fds[$((read_fd))]=1 done ;; - (*) [[ $opt != \? ]] && print Unhandled option, complain: $opt >&2 + (*) [[ $opt != \? ]] && print "Unhandled option, complain: $opt" >&2 return 1 ;; esac diff --git a/Functions/TCP/tcp_send b/Functions/TCP/tcp_send index c976a2fb7..86dda6403 100644 --- a/Functions/TCP/tcp_send +++ b/Functions/TCP/tcp_send @@ -29,7 +29,7 @@ while getopts "acl:nqs:" opt; do fi sessions+=($OPTARG) ;; - (*) [[ $opt != '?' ]] && print Unhandled option, complain: $opt >&2 + (*) [[ $opt != '?' ]] && print "Unhandled option, complain: $opt" >&2 return 1 ;; esac diff --git a/Functions/TCP/tcp_shoot b/Functions/TCP/tcp_shoot index 8ff9866ba..c485c140a 100644 --- a/Functions/TCP/tcp_shoot +++ b/Functions/TCP/tcp_shoot @@ -4,8 +4,8 @@ setopt extendedglob local REPLY tfd if [[ $# -ne 2 ]]; then - print "Usage: tcp_dump host port -Connect to the given host and port; send standard input.">&2 + print "Usage: $0 host port +Connect to the given host and port; send standard input." >&2 return 1 fi -- cgit v1.2.3 From faeb9555d3c853b019aa30ee1ca62bec3971ce9f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 3 Oct 2015 20:25:57 +0100 Subject: 36760: more care with already unmetafied pattern trial strings --- ChangeLog | 5 +++++ Src/pattern.c | 55 ++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1061d1d94..e45273e68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-03 Peter Stephenson + + * 36760: Src/pattern.c: ensure we don't do anything untoward + with an already metafied pattern trial match. + 2015-10-03 Mikael Magnusson * 36754: Functions/TCP/tcp_open, Functions/TCP/tcp_read, diff --git a/Src/pattern.c b/Src/pattern.c index 04d3e3dfb..8b07cca92 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -2022,6 +2022,39 @@ pattrystart(void) errsfound = 0; } +/* + * Fix up string length stuff. + * + * If we call patallocstr() with "force" to set things up early, it's + * done there, else it's done in pattryrefs(). The reason for the + * difference is in the latter case we may not be relying on + * patallocstr() having an effect. + */ + +/**/ +static void +patmungestring(char **string, int *stringlen, int *unmetalenin) +{ + /* + * Special signalling of empty tokenised string. + */ + if (*stringlen > 0 && **string == Nularg) { + (*string)++; + /* + * If we don't have an unmetafied length + * and need it (we may not) we'll get it later. + */ + if (*unmetalenin > 0) + (*unmetalenin)--; + if (*stringlen > 0) + (*stringlen)--; + } + + /* Ensure we have a metafied length */ + if (*stringlen < 0) + *stringlen = strlen(*string); +} + /* * Allocate memeory for pattern match. Note this is specific to use * of pattern *and* trial string. @@ -2039,7 +2072,8 @@ pattrystart(void) * force is 1 if we always unmetafy: this is useful if we are going * to try again with different versions of the string. If this is * called from pattryrefs() we don't force unmetafication as it won't - * be optimal. + * be optimal. This option should be used if the resulting + * patstralloc is going to be passed to pattrylen() / pattryrefs(). * In patstralloc (supplied by caller, must last until last pattry is done) * unmetalen is the unmetafied length of the string; it will be * calculated if the input value is negative. @@ -2056,6 +2090,9 @@ char *patallocstr(Patprog prog, char *string, int stringlen, int unmetalen, { int needfullpath; + if (force) + patmungestring(&string, &stringlen, &unmetalen); + /* * For a top-level ~-exclusion, we will need the full * path to exclude, so copy the path so far and append the @@ -2224,21 +2261,9 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalenin, maxnpos = *nump; *nump = 0; } - /* - * Special signalling of empty tokenised string. - */ - if ((!patstralloc || stringlen > 0) && *string == Nularg) { - string++; - if (unmetalenin > 0) - unmetalenin--; - if (stringlen > 0) - stringlen--; - } - if (stringlen < 0) { - DPUTS(patstralloc != NULL, "length needed with patstralloc"); - stringlen = strlen(string); - } + if (!patstralloc) + patmungestring(&string, &stringlen, &unmetalenin); origlen = stringlen; if (patstralloc) { -- cgit v1.2.3 From b581c3fece76c87ed86ae9fc704d0fcf208a79d3 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 3 Oct 2015 19:40:14 -0700 Subject: 36766: fix incorrect reset of noerrexit during "if" conditions --- ChangeLog | 5 +++++ Src/exec.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e45273e68..a5a235389 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-03 Barton E. Schaefer + + * 36766: Src/exec.c: fix incorrect reset of noerrexit during + "if" conditions + 2015-10-03 Peter Stephenson * 36760: Src/pattern.c: ensure we don't do anything untoward diff --git a/Src/exec.c b/Src/exec.c index 154bbb8db..235faf3ba 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1364,7 +1364,8 @@ sublist_done: * we hit execcmd on the way down. We're now * on the way back up, so don't restore it. */ - noerrexit = (oldnoerrexit == 2) ? 0 : oldnoerrexit; + if (oldnoerrexit != 2) + noerrexit = oldnoerrexit; if (sigtrapped[SIGDEBUG] && !isset(DEBUGBEFORECMD) && !donedebug) { /* -- cgit v1.2.3 From cb26e11c70f95c72e300e1f4f16b33e4e5f54d21 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 3 Oct 2015 22:11:09 -0700 Subject: unposted: back out 36707, add test case for 36766 --- ChangeLog | 4 ++++ Src/exec.c | 2 +- Src/loop.c | 8 ++------ Test/C03traps.ztst | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index a5a235389..aa2253522 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-10-03 Barton E. Schaefer + * unposted (cf. 36696): Test/C03traps.ztst: test case for 36766 + + * unposted: Src/exec.c, Src/loop.c: back out 36707, fixed by 36766 + * 36766: Src/exec.c: fix incorrect reset of noerrexit during "if" conditions diff --git a/Src/exec.c b/Src/exec.c index 235faf3ba..bcc8065a2 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1409,7 +1409,7 @@ sublist_done: exit(lastval); } if (errreturn) { - retflag = 2; + retflag = 1; breaks = loops; } } diff --git a/Src/loop.c b/Src/loop.c index 7d1528efe..4def9b652 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -552,12 +552,8 @@ execif(Estate state, int do_exec) run = 1; break; } - if (retflag) { - if (retflag == 2) - retflag = 0; /* Never ERR_RETURN here */ - else - break; - } + if (retflag) + break; s = 1; state->pc = next; } diff --git a/Test/C03traps.ztst b/Test/C03traps.ztst index d179dc46d..4b2843a47 100644 --- a/Test/C03traps.ztst +++ b/Test/C03traps.ztst @@ -450,6 +450,20 @@ fn 1:ERRRETURN in "else" branch (regression test) + $ZTST_testdir/../Src/zsh -f =(<<<" + if false; then + : + else + if [[ -n '' ]]; then + a=2 + fi + print Yes + fi + ") +0:ERRRETURN when false "if" is the first statement in an "else" (regression) +>Yes +F:Must be tested with a top-level script rather than source or function + %clean rm -f TRAPEXIT -- cgit v1.2.3 From 3f9606333578384221948e285ed896738071b253 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 4 Oct 2015 14:01:08 -0700 Subject: 36773: limit CORRECT / CORRECT_ALL to directory names in cases where it is obvious that a directory is expected --- ChangeLog | 5 +++++ Src/utils.c | 49 ++++++++++++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index aa2253522..e1f58c9ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-04 Barton E. Schaefer + + * 36773: Src/utils.c: limit CORRECT / CORRECT_ALL to directory + names in cases where it is obvious that a directory is expected + 2015-10-03 Barton E. Schaefer * unposted (cf. 36696): Test/C03traps.ztst: test case for 36766 diff --git a/Src/utils.c b/Src/utils.c index ab3b0c274..61cbe84aa 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -2812,7 +2812,7 @@ spckword(char **s, int hist, int cmd, int ask) * as used in spscan(), so that an autocd is chosen * * only when it is better than anything so far, and * * so we prefer directories earlier in the cdpath. */ - if ((thisdist = mindist(*pp, *s, bestcd)) < d) { + if ((thisdist = mindist(*pp, *s, bestcd, 1)) < d) { best = dupstring(bestcd); d = thisdist; } @@ -4057,7 +4057,8 @@ spname(char *oldname) thresh = 3; else if (thresh > 100) thresh = 100; - if ((thisdist = mindist(newname, spnameguess, spnamebest)) >= thresh) { + thisdist = mindist(newname, spnameguess, spnamebest, *old == '/'); + if (thisdist >= thresh) { /* The next test is always true, except for the first path * * component. We could initialize bestdist to some large * * constant instead, and then compare to that constant here, * @@ -4082,42 +4083,52 @@ spname(char *oldname) /**/ static int -mindist(char *dir, char *mindistguess, char *mindistbest) +mindist(char *dir, char *mindistguess, char *mindistbest, int wantdir) { int mindistd, nd; DIR *dd; char *fn; char *buf; + struct stat st; + size_t dirlen; if (dir[0] == '\0') dir = "."; mindistd = 100; - buf = zalloc(strlen(dir) + strlen(mindistguess) + 2); + if (!(buf = zalloc((dirlen = strlen(dir)) + strlen(mindistguess) + 2))) + return 0; sprintf(buf, "%s/%s", dir, mindistguess); - if (access(unmeta(buf), F_OK) == 0) { + if (stat(unmeta(buf), &st) == 0 && (!wantdir || S_ISDIR(st.st_mode))) { strcpy(mindistbest, mindistguess); free(buf); return 0; } - free(buf); - if (!(dd = opendir(unmeta(dir)))) - return mindistd; - while ((fn = zreaddir(dd, 0))) { - if (spnamepat && pattry(spnamepat, fn)) - continue; - nd = spdist(fn, mindistguess, - (int)strlen(mindistguess) / 4 + 1); - if (nd <= mindistd) { - strcpy(mindistbest, fn); - mindistd = nd; - if (mindistd == 0) - break; + if ((dd = opendir(unmeta(dir)))) { + while ((fn = zreaddir(dd, 0))) { + if (spnamepat && pattry(spnamepat, fn)) + continue; + nd = spdist(fn, mindistguess, + (int)strlen(mindistguess) / 4 + 1); + if (nd <= mindistd) { + if (wantdir) { + if (!(buf = zrealloc(buf, dirlen + strlen(fn) + 2))) + continue; + sprintf(buf, "%s/%s", dir, fn); + if (stat(unmeta(buf), &st) != 0 || !S_ISDIR(st.st_mode)) + continue; + } + strcpy(mindistbest, fn); + mindistd = nd; + if (mindistd == 0) + break; + } } + closedir(dd); } - closedir(dd); + free(buf); return mindistd; } -- cgit v1.2.3 From 83a175795a444e8169fcb592a110d4d15a09b907 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 6 Oct 2015 09:28:07 +0100 Subject: 36780: Fix crash in ksh mode with -n and $HOME. If home variable is NULL ensure HOME is unset. --- ChangeLog | 5 +++++ Src/params.c | 13 +++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index e1f58c9ae..6369cf6e9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-06 Peter Stephenson + + * 36780: Src/params.c: ensure HOME parameter is unset if + corresponding internal variable is null. + 2015-10-04 Barton E. Schaefer * 36773: Src/utils.c: limit CORRECT / CORRECT_ALL to directory diff --git a/Src/params.c b/Src/params.c index de151a4cd..a8abb289e 100644 --- a/Src/params.c +++ b/Src/params.c @@ -775,17 +775,18 @@ createparamtable(void) #endif opts[ALLEXPORT] = oae; + /* + * For native emulation we always set the variable home + * (see setupvals()). + */ + pm = (Param) paramtab->getnode(paramtab, "HOME"); if (EMULATION(EMULATE_ZSH)) { - /* - * For native emulation we always set the variable home - * (see setupvals()). - */ - pm = (Param) paramtab->getnode(paramtab, "HOME"); pm->node.flags &= ~PM_UNSET; if (!(pm->node.flags & PM_EXPORTED)) addenv(pm, home); - } + } else if (!home) + pm->node.flags |= PM_UNSET; pm = (Param) paramtab->getnode(paramtab, "LOGNAME"); if (!(pm->node.flags & PM_EXPORTED)) addenv(pm, pm->u.str); -- cgit v1.2.3 From 7a1678767f44f200295d88dfea94902718275266 Mon Sep 17 00:00:00 2001 From: Frank Terbeck Date: Sun, 11 Oct 2015 11:54:06 +0200 Subject: 36830: vcs_info: Silence an error message with new git versions Mikael informs me on IRC, that in new versions of git (he used 2.6.1) where the "am" subcommand is now a builtin, a file that is used by the git backend of vcs_info (namely .git/rebase-apply/msg-clean) is not available anymore, leading to an annoying error message: VCS_INFO_get_data_git:232: no such file or directory: .git/rebase-apply/msg-clean This patch checks for the availabiliy of the file before using it, and adjusts the value of the dependant values accordingly. --- ChangeLog | 5 ++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 34 +++++++++++++++-------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6369cf6e9..c8cad2adb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-11 Frank Terbeck + + * 36830: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: + vcs_info: Silence an error message with new git versions + 2015-10-06 Peter Stephenson * 36780: Src/params.c: ensure HOME parameter is unset if diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 8664d510e..7fc213916 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -224,18 +224,28 @@ elif [[ -d "${gitdir}/rebase-apply" ]]; then patchdir="${gitdir}/rebase-apply" local next="${patchdir}/next" if [[ -f $next ]]; then - local cur=$(< $next) - local p subject - for p in $(seq $(($cur - 1))); do - git_patches_applied+=("$(printf "%04d" $p) ?") - done - subject="${$(< "${patchdir}/msg-clean")[(f)1]}" - if [[ -f "${patchdir}/original-commit" ]]; then - git_patches_applied+=("$(< ${patchdir}/original-commit) $subject") - else - git_patches_applied+=("? $subject") - fi - git_patches_unapplied=($(seq $cur $(< "${patchdir}/last"))) + local cur=$(< $next) + local p subject + for p in $(seq $(($cur - 1))); do + git_patches_applied+=("$(printf "%04d" $p) ?") + done + if [[ -f "${patchdir}/msg-clean" ]]; then + subject="${$(< "${patchdir}/msg-clean")[(f)1]}" + fi + if [[ -f "${patchdir}/original-commit" ]]; then + if [[ -n $subject ]]; then + git_patches_applied+=("$(< ${patchdir}/original-commit) $subject") + else + git_patches_applied+=("$(< ${patchdir}/original-commit)") + fi + else + if [[ -n $subject ]]; then + git_patches_applied+=("? $subject") + else + git_patches_applied+=("?") + fi + fi + git_patches_unapplied=($(seq $cur $(< "${patchdir}/last"))) fi VCS_INFO_git_handle_patches -- cgit v1.2.3 From e245dd71936d1c22fce39f02c203ed2cdb43a548 Mon Sep 17 00:00:00 2001 From: Frank Terbeck Date: Sun, 11 Oct 2015 12:39:56 +0200 Subject: 36832: vcs_info: Remove dependency on "seq" The "seq" utility is usually available on GNU systems only. This exchanges calls to seq with pure zsh features. Also: Less forks are good. --- ChangeLog | 3 +++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c8cad2adb..be49cf526 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ * 36830: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: vcs_info: Silence an error message with new git versions + * 36832: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: + vcs_info: Remove dependency on "seq" + 2015-10-06 Peter Stephenson * 36780: Src/params.c: ensure HOME parameter is unset if diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 7fc213916..fcee47c13 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -226,7 +226,7 @@ elif [[ -d "${gitdir}/rebase-apply" ]]; then if [[ -f $next ]]; then local cur=$(< $next) local p subject - for p in $(seq $(($cur - 1))); do + for ((p = 1; p < cur; p++)); do git_patches_applied+=("$(printf "%04d" $p) ?") done if [[ -f "${patchdir}/msg-clean" ]]; then @@ -245,7 +245,8 @@ elif [[ -d "${gitdir}/rebase-apply" ]]; then git_patches_applied+=("?") fi fi - git_patches_unapplied=($(seq $cur $(< "${patchdir}/last"))) + local last="$(< "${patchdir}/last")" + git_patches_unapplied=( {$cur..$last} ) fi VCS_INFO_git_handle_patches -- cgit v1.2.3 From 9f8e3e82dd2c2bb98f72b6e026b72d9c47d5ad62 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 11 Oct 2015 21:11:10 -0700 Subject: 36834: freeheap preserves last allocated heap This is the first of two optimizations to improve heap performance when there are a large number of mostly-filled heap arenas. --- ChangeLog | 4 ++++ Src/mem.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index be49cf526..3adb1f159 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-10-11 Barton E. Schaefer + + * 36834: Src/mem.c: freeheap preserves last allocated heap + 2015-10-11 Frank Terbeck * 36830: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: diff --git a/Src/mem.c b/Src/mem.c index b9569ea0c..d49f685fe 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -294,7 +294,7 @@ pushheap(void) #endif for (h = heaps; h; h = h->next) { - DPUTS(!h->used, "BUG: empty heap"); + DPUTS(!h->used && h->next, "BUG: empty heap"); hs = (Heapstack) zalloc(sizeof(*hs)); hs->next = h->sp; h->sp = hs; @@ -334,17 +334,15 @@ freeheap(void) * * Whenever fheap is NULL here, the loop below sweeps back over the * entire heap list again, resetting the free space in every arena to - * the amount stashed by pushheap() and finding the first arena with + * the amount stashed by pushheap() and finding the arena with the most * free space to optimize zhalloc()'s next search. When there's a lot * of stuff already on the heap, this is an enormous amount of work, * and performance goes to hell. * - * However, if the arena to which fheap points is unused, we want to - * free it, so we have no choice but to do the sweep for a new fheap. - */ - if (fheap && !fheap->sp) - fheap = NULL; /* We used to do this unconditionally */ - /* + * Therefore, we defer freeing the most recently allocated arena until + * we reach popheap(). This may fail to reclaim some space in earlier + * arenas. + * * In other cases, either fheap is already correct, or it has never * been set and this loop will do it, or it'll be reset from scratch * on the next popheap(). So all that's needed here is to pick up @@ -361,7 +359,11 @@ freeheap(void) memset(arena(h) + h->sp->used, 0xff, h->used - h->sp->used); #endif h->used = h->sp->used; - if (!fheap && h->used < ARENA_SIZEOF(h)) + if (!fheap) { + if (h->used < ARENA_SIZEOF(h)) + fheap = h; + } else if (ARENA_SIZEOF(h) - h->used > + ARENA_SIZEOF(fheap) - fheap->used) fheap = h; hl = h; #ifdef ZSH_HEAP_DEBUG @@ -384,6 +386,26 @@ freeheap(void) VALGRIND_MEMPOOL_TRIM((char *)h, (char *)arena(h), h->used); #endif } else { + if (h->next) { + /* We want to cut this out of the arena list if we can */ + if (h == heaps) + hl = heaps = h->next; + else if (hl && hl->next == h) + hl->next = h->next; + else { + DPUTS(hl, "hl->next != h when freeing"); + hl = h; + continue; + } + h->next = NULL; + } else { + /* Leave an empty arena at the end until popped */ + h->used = 0; + fheap = hl = h; + break; + } + if (fheap == h) + fheap = NULL; #ifdef USE_MMAP munmap((void *) h, h->size); #else @@ -441,12 +463,29 @@ popheap(void) #ifdef ZSH_VALGRIND VALGRIND_MEMPOOL_TRIM((char *)h, (char *)arena(h), h->used); #endif - if (!fheap && h->used < ARENA_SIZEOF(h)) + if (!fheap) { + if (h->used < ARENA_SIZEOF(h)) + fheap = h; + } else if (ARENA_SIZEOF(h) - h->used > + ARENA_SIZEOF(fheap) - fheap->used) fheap = h; zfree(hs, sizeof(*hs)); hl = h; } else { + if (h->next) { + /* We want to cut this out of the arena list if we can */ + if (h == heaps) + hl = heaps = h->next; + else if (hl && hl->next == h) + hl->next = h->next; + else { + DPUTS(hl, "hl->next != h when popping"); + hl = h; + continue; + } + h->next = NULL; + } #ifdef USE_MMAP munmap((void *) h, h->size); #else @@ -524,7 +563,7 @@ zheapptr(void *p) mod_export void * zhalloc(size_t size) { - Heap h; + Heap h, hp = NULL; size_t n; #ifdef ZSH_VALGRIND size_t req_size = size; @@ -546,6 +585,7 @@ zhalloc(size_t size) for (h = ((fheap && ARENA_SIZEOF(fheap) >= (size + fheap->used)) ? fheap : heaps); h; h = h->next) { + hp = h; if (ARENA_SIZEOF(h) >= (n = size + h->used)) { void *ret; @@ -566,7 +606,6 @@ zhalloc(size_t size) } } { - Heap hp; /* not found, allocate new heap */ #if defined(ZSH_MEM) && !defined(USE_MMAP) static int called = 0; @@ -575,7 +614,6 @@ zhalloc(size_t size) #endif n = HEAP_ARENA_SIZE > size ? HEAPSIZE : size + sizeof(*h); - for (hp = NULL, h = heaps; h; hp = h, h = h->next); #ifdef USE_MMAP h = mmap_heap_alloc(&n); @@ -607,6 +645,7 @@ zhalloc(size_t size) VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)arena(h), req_size); #endif + DPUTS(hp && hp->next, "failed to find end of chain in zhalloc"); if (hp) hp->next = h; else -- cgit v1.2.3 From d77bf2ba88c289e28139ce36ac767447113ab95d Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 11 Oct 2015 21:16:58 -0700 Subject: 36836: zhalloc() avoids re-scanning all heaps when the last known heap with free space does not have enough space This is the second of two performance optimizations for situations where all heap arenas in the list are mostly full. --- ChangeLog | 5 ++++- Src/mem.c | 12 ++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3adb1f159..421da2f6f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ 2015-10-11 Barton E. Schaefer - * 36834: Src/mem.c: freeheap preserves last allocated heap + * 36836: Src/mem.c: zhalloc() avoids re-scanning all heaps when + the last known heap with free space does not have enough space + + * 36834: Src/mem.c: freeheap() preserves last allocated heap 2015-10-11 Frank Terbeck diff --git a/Src/mem.c b/Src/mem.c index d49f685fe..191428323 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -582,10 +582,14 @@ zhalloc(size_t size) /* find a heap with enough free space */ - for (h = ((fheap && ARENA_SIZEOF(fheap) >= (size + fheap->used)) - ? fheap : heaps); - h; h = h->next) { - hp = h; + /* + * This previously assigned: + * h = ((fheap && ARENA_SIZEOF(fheap) >= (size + fheap->used)) + * ? fheap : heaps); + * but we think that nothing upstream of fheap has more free space, + * so why start over at heaps just because fheap has too little? + */ + for (h = (fheap ? fheap : heaps); h; h = h->next) { if (ARENA_SIZEOF(h) >= (n = size + h->used)) { void *ret; -- cgit v1.2.3 From ce929eb37e0a79d847dbfcaf1436c1a46bca55b2 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 11 Oct 2015 21:23:38 -0700 Subject: 36841: factor out and update the patterns that filter "uninteresting" functions out of the $funcstack display --- ChangeLog | 5 +++++ Completion/Base/Widget/_complete_help | 9 ++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 421da2f6f..ae61df68d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2015-10-11 Barton E. Schaefer + * 36841: Completion/Base/Widget/_complete_help: factor out and + update the patterns that filter "uninteresting" functions out + of the $funcstack list when generating the call trace to show + where a tag is active. + * 36836: Src/mem.c: zhalloc() avoids re-scanning all heaps when the last known heap with free space does not have enough space diff --git a/Completion/Base/Widget/_complete_help b/Completion/Base/Widget/_complete_help index 0563c618f..09637ecb9 100644 --- a/Completion/Base/Widget/_complete_help +++ b/Completion/Base/Widget/_complete_help @@ -6,12 +6,15 @@ _complete_help() { local _sort_tags=_help_sort_tags text i j k tmp typeset -A help_funcs help_tags help_sfuncs help_styles + local -H _help_scan_funcstack="main_complete|complete|approximate|normal" + local -H _help_filter_funcstack="alternative|call_function|describe|dispatch|wanted|requested|all_labels|next_label" + { compadd() { return 1 } zstyle() { - local _f="${${(@)${(@)funcstack[2,(i)_(main_complete|complete|approximate|normal)]}:#_(dispatch|wanted|requested|all_labels|next_label)}% *}" + local _f="${${(@)${(@)funcstack[2,(i)_($~_help_scan_funcstack)]}:#(_($~_help_filter_funcstack)|\((eval|anon)\))}% *}" - [[ -z "$_f" ]] && _f="${${(@)funcstack[2,(i)_(main_complete|complete|approximate|normal)]}:#_(dispatch|wanted|requested|all_labels|next_label)}" + [[ -z "$_f" ]] && _f="${${(@)funcstack[2,(i)_($~_help_scan_funcstack)]}:#(_($~_help_filter_funcstack)|\((eval|anon)\))}" if [[ "$help_sfuncs[$2]" != *${_f}* || "$help_styles[${2}${_f}]" != *${3}* ]]; then @@ -73,7 +76,7 @@ _complete_help() { } _help_sort_tags() { - local f="${${(@)${(@)funcstack[3,(i)_(main_complete|complete|approximate|normal)]}:#(_(dispatch|wanted|requested|all_labels|next_label)|\(eval\))}% *}" + local f="${${(@)${(@)funcstack[3,(i)_($~_help_scan_funcstack)]}:#(_($~_help_filter_funcstack)|\((eval|anon)\))}% *}" if [[ "$help_funcs[$curcontext]" != *${f}* || "$help_tags[${curcontext}${f}]" != *(${(j:|:)~argv})* ]]; then -- cgit v1.2.3 From 643aca932aa30083246312eeddd2e0d6befa5861 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 11 Oct 2015 21:48:10 -0700 Subject: One crucial assignment accidentally lost from 36834 when merging 36836. --- Src/mem.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Src/mem.c b/Src/mem.c index 191428323..68bd76740 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -386,6 +386,8 @@ freeheap(void) VALGRIND_MEMPOOL_TRIM((char *)h, (char *)arena(h), h->used); #endif } else { + if (fheap == h) + fheap = NULL; if (h->next) { /* We want to cut this out of the arena list if we can */ if (h == heaps) @@ -404,8 +406,6 @@ freeheap(void) fheap = hl = h; break; } - if (fheap == h) - fheap = NULL; #ifdef USE_MMAP munmap((void *) h, h->size); #else @@ -590,6 +590,7 @@ zhalloc(size_t size) * so why start over at heaps just because fheap has too little? */ for (h = (fheap ? fheap : heaps); h; h = h->next) { + hp = h; if (ARENA_SIZEOF(h) >= (n = size + h->used)) { void *ret; -- cgit v1.2.3 From bab1fc50436f23402696cd5236c0689c4d4dbd59 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 14 Oct 2015 14:23:16 +0100 Subject: 36856: cdr -p/-P to prune directory list --- ChangeLog | 5 +++++ Doc/Zsh/contrib.yo | 12 ++++++++++++ Functions/Chpwd/cdr | 37 +++++++++++++++++++++++++++++++------ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index ae61df68d..2e31d243b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-14 Peter Stephenson + + * 36856: Doc/Zsh/contrib.yo, Functions/Chpwd/cdr: add -p and -P + options to cdr for pruning the directory list. + 2015-10-11 Barton E. Schaefer * 36841: Completion/Base/Widget/_complete_help: factor out and diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 635f9b010..d367d8b0f 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -415,6 +415,18 @@ 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(/). Usually the first entry should be left as the current directory. ) +item(tt(-p ')var(pattern)tt('))( +Prunes any items in the directory list that match the given extended glob +pattern; the pattern needs to be quoted from immediate expansion on the +command line. The pattern is matched against each completely expanded +file name in the list; the full string must match, so wildcards at the +end (e.g. tt('*removeme*')) are needed to remove entries with a given +substring. + +If output is to a terminal, then the function will print the new list +after pruning and prompt for confirmation by the user. This output and +confirmation step can be skipped by using tt(-P) instead of tt(-p). +) enditem() subsect(Configuration) diff --git a/Functions/Chpwd/cdr b/Functions/Chpwd/cdr index 4f399106b..4bed88b13 100644 --- a/Functions/Chpwd/cdr +++ b/Functions/Chpwd/cdr @@ -51,6 +51,13 @@ # (and only /). Usually the first entry should be left as the current # directory. # +# "cdr -p 'pattern'" prunes anything matching the given extended glob +# pattern from the directory list. The match is against the fully +# expanded directory path and the full string must match (use wildcards +# at the ends if needed). If output is going to a terminal, the +# function will print the new list for the user to confrim; this can be +# skipped by giving -P instead of -p. +# # Details of directory handling # ============================= # @@ -217,11 +224,11 @@ setopt extendedglob autoload -Uz chpwd_recent_filehandler chpwd_recent_add -integer list set_reply i bad edit -local opt dir +integer list set_reply i bad edit force_prune +local opt dir prune local -aU dirs -while getopts "elr" opt; do +while getopts "elp:P:r" opt; do case $opt in (e) edit=1 @@ -231,6 +238,12 @@ while getopts "elr" opt; do list=1 ;; + ([pP]) + prune=$OPTARG + edit=1 + [[ $opt = P ]] && force_prune=1 + ;; + (r) set_reply=1 ;; @@ -278,10 +291,22 @@ if [[ $PWD != $reply[1] ]]; then fi if (( edit )); then - local compcontext='directories:directory:_path_files -/' -IFS=' + if [[ -n $prune ]]; then + reply=(${reply:#$~prune}) + if [[ force_prune -eq 0 && -t 1 ]]; then + print -nrl "New list:" $reply 'Accept? ' + if ! read -q; then + print + return 1 + fi + print + fi + else + local compcontext='directories:directory:_path_files -/' + IFS=' ' vared reply || return 1 -chpwd_recent_filehandler $reply + fi + chpwd_recent_filehandler $reply fi # Skip current directory if present (may have been pruned). -- cgit v1.2.3 From 827d36077641ca87d1796b9c5cb05e7c44b01919 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 14 Oct 2015 21:46:26 -0700 Subject: 36853: replace pushheap/popheap by NEWHEAPS/OLDHEAPS in doshfunc() to optimize memory management Includes re-indentation that was not done in the posted patch. --- ChangeLog | 5 + Src/exec.c | 402 ++++++++++++++++++++++++++++++------------------------------- 2 files changed, 206 insertions(+), 201 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2e31d243b..f0c88c979 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-14 Barton E. Schaefer + + * 36853: Src/exec.c: replace pushheap/popheap by NEWHEAPS/OLDHEAPS + in doshfunc() to optimize memory management + 2015-10-14 Peter Stephenson * 36856: Doc/Zsh/contrib.yo, Functions/Chpwd/cdr: add -p and -P diff --git a/Src/exec.c b/Src/exec.c index bcc8065a2..f0d1d2f70 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -5067,230 +5067,230 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) #ifdef MAX_FUNCTION_DEPTH static int funcdepth; #endif + Heap funcheap; queue_signals(); /* Lots of memory and global state changes coming */ - pushheap(); + NEWHEAPS(funcheap) { + oargv0 = NULL; + obreaks = breaks; + ocontflag = contflag; + oloops = loops; + if (trap_state == TRAP_STATE_PRIMED) + trap_return--; + oldlastval = lastval; + oldnumpipestats = numpipestats; + if (noreturnval) { + /* + * Easiest to use the heap here since we're bracketed + * immediately by a pushheap/popheap pair. + */ + size_t bytes = sizeof(int)*numpipestats; + oldpipestats = (int *)zhalloc(bytes); + memcpy(oldpipestats, pipestats, bytes); + } - oargv0 = NULL; - obreaks = breaks; - ocontflag = contflag; - oloops = loops; - if (trap_state == TRAP_STATE_PRIMED) - trap_return--; - oldlastval = lastval; - oldnumpipestats = numpipestats; - if (noreturnval) { - /* - * Easiest to use the heap here since we're bracketed - * immediately by a pushheap/popheap pair. - */ - size_t bytes = sizeof(int)*numpipestats; - oldpipestats = (int *)zhalloc(bytes); - memcpy(oldpipestats, pipestats, bytes); - } + starttrapscope(); + startpatternscope(); + + pptab = pparams; + if (!(flags & PM_UNDEFINED)) + scriptname = dupstring(name); + oldzoptind = zoptind; + oldoptcind = optcind; + if (!isset(POSIXBUILTINS)) { + zoptind = 1; + optcind = 0; + } - starttrapscope(); - startpatternscope(); - - pptab = pparams; - if (!(flags & PM_UNDEFINED)) - scriptname = dupstring(name); - oldzoptind = zoptind; - oldoptcind = optcind; - if (!isset(POSIXBUILTINS)) { - zoptind = 1; - optcind = 0; - } + /* We need to save the current options even if LOCALOPTIONS is * + * not currently set. That's because if it gets set in the * + * function we need to restore the original options on exit. */ + memcpy(saveopts, opts, sizeof(opts)); + saveemulation = emulation; + save_sticky = sticky; - /* We need to save the current options even if LOCALOPTIONS is * - * not currently set. That's because if it gets set in the * - * function we need to restore the original options on exit. */ - memcpy(saveopts, opts, sizeof(opts)); - saveemulation = emulation; - save_sticky = sticky; + if (sticky_emulation_differs(shfunc->sticky)) { + /* + * Function is marked for sticky emulation. + * Enable it now. + * + * We deliberately do not do this if the sticky emulation + * in effect is the same as that requested. This enables + * option setting naturally within emulation environments. + * Note that a difference in EMULATE_FULLY (emulate with + * or without -R) counts as a different environment. + * + * This propagates the sticky emulation to subfunctions. + */ + sticky = sticky_emulation_dup(shfunc->sticky, 1); + emulation = sticky->emulation; + restore_sticky = 1; + installemulation(emulation, opts); + if (sticky->n_on_opts) { + OptIndex *onptr; + for (onptr = sticky->on_opts; + onptr < sticky->on_opts + sticky->n_on_opts; + onptr++) + opts[*onptr] = 1; + } + if (sticky->n_off_opts) { + OptIndex *offptr; + for (offptr = sticky->off_opts; + offptr < sticky->off_opts + sticky->n_off_opts; + offptr++) + opts[*offptr] = 0; + } + /* All emulations start with pattern disables clear */ + clearpatterndisables(); + } else + restore_sticky = 0; - if (sticky_emulation_differs(shfunc->sticky)) { + if (flags & (PM_TAGGED|PM_TAGGED_LOCAL)) + opts[XTRACE] = 1; + else if (oflags & PM_TAGGED_LOCAL) + opts[XTRACE] = 0; + ooflags = oflags; /* - * Function is marked for sticky emulation. - * Enable it now. - * - * We deliberately do not do this if the sticky emulation - * in effect is the same as that requested. This enables - * option setting naturally within emulation environments. - * Note that a difference in EMULATE_FULLY (emulate with - * or without -R) counts as a different environment. - * - * This propagates the sticky emulation to subfunctions. + * oflags is static, because we compare it on the next recursive + * call. Hence also we maintain ooflags for restoring the previous + * value of oflags after the call. */ - sticky = sticky_emulation_dup(shfunc->sticky, 1); - emulation = sticky->emulation; - restore_sticky = 1; - installemulation(emulation, opts); - if (sticky->n_on_opts) { - OptIndex *onptr; - for (onptr = sticky->on_opts; - onptr < sticky->on_opts + sticky->n_on_opts; - onptr++) - opts[*onptr] = 1; - } - if (sticky->n_off_opts) { - OptIndex *offptr; - for (offptr = sticky->off_opts; - offptr < sticky->off_opts + sticky->n_off_opts; - offptr++) - opts[*offptr] = 0; - } - /* All emulations start with pattern disables clear */ - clearpatterndisables(); - } else - restore_sticky = 0; - - if (flags & (PM_TAGGED|PM_TAGGED_LOCAL)) - opts[XTRACE] = 1; - else if (oflags & PM_TAGGED_LOCAL) - opts[XTRACE] = 0; - ooflags = oflags; - /* - * oflags is static, because we compare it on the next recursive - * call. Hence also we maintain ooflags for restoring the previous - * value of oflags after the call. - */ - oflags = flags; - opts[PRINTEXITVALUE] = 0; - if (doshargs) { - LinkNode node; - - node = firstnode(doshargs); - pparams = x = (char **) zshcalloc(((sizeof *x) * - (1 + countlinknodes(doshargs)))); - if (isset(FUNCTIONARGZERO)) { - oargv0 = argzero; - argzero = ztrdup(getdata(node)); - } - /* first node contains name regardless of option */ - node = node->next; - for (; node; node = node->next, x++) - *x = ztrdup(getdata(node)); - } else { - pparams = (char **) zshcalloc(sizeof *pparams); - if (isset(FUNCTIONARGZERO)) { - oargv0 = argzero; - argzero = ztrdup(argzero); + oflags = flags; + opts[PRINTEXITVALUE] = 0; + if (doshargs) { + LinkNode node; + + node = firstnode(doshargs); + pparams = x = (char **) zshcalloc(((sizeof *x) * + (1 + countlinknodes(doshargs)))); + if (isset(FUNCTIONARGZERO)) { + oargv0 = argzero; + argzero = ztrdup(getdata(node)); + } + /* first node contains name regardless of option */ + node = node->next; + for (; node; node = node->next, x++) + *x = ztrdup(getdata(node)); + } else { + pparams = (char **) zshcalloc(sizeof *pparams); + if (isset(FUNCTIONARGZERO)) { + oargv0 = argzero; + argzero = ztrdup(argzero); + } } - } #ifdef MAX_FUNCTION_DEPTH - if(++funcdepth > MAX_FUNCTION_DEPTH) - { - zerr("maximum nested function level reached"); - goto undoshfunc; - } + if(++funcdepth > MAX_FUNCTION_DEPTH) + { + zerr("maximum nested function level reached"); + goto undoshfunc; + } #endif - fstack.name = dupstring(name); - /* - * The caller is whatever is immediately before on the stack, - * unless we're at the top, in which case it's the script - * or interactive shell name. - */ - fstack.caller = funcstack ? funcstack->name : - dupstring(oargv0 ? oargv0 : argzero); - fstack.lineno = lineno; - fstack.prev = funcstack; - fstack.tp = FS_FUNC; - funcstack = &fstack; - - fstack.flineno = shfunc->lineno; - fstack.filename = dupstring(shfunc->filename); - - prog = shfunc->funcdef; - if (prog->flags & EF_RUN) { - Shfunc shf; + fstack.name = dupstring(name); + /* + * The caller is whatever is immediately before on the stack, + * unless we're at the top, in which case it's the script + * or interactive shell name. + */ + fstack.caller = funcstack ? funcstack->name : + dupstring(oargv0 ? oargv0 : argzero); + fstack.lineno = lineno; + fstack.prev = funcstack; + fstack.tp = FS_FUNC; + funcstack = &fstack; - prog->flags &= ~EF_RUN; + fstack.flineno = shfunc->lineno; + fstack.filename = dupstring(shfunc->filename); - runshfunc(prog, NULL, fstack.name); + prog = shfunc->funcdef; + if (prog->flags & EF_RUN) { + Shfunc shf; - if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, - (name = fname)))) { - zwarn("%s: function not defined by file", name); - if (noreturnval) - errflag |= ERRFLAG_ERROR; - else - lastval = 1; - goto doneshfunc; + prog->flags &= ~EF_RUN; + + runshfunc(prog, NULL, fstack.name); + + if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, + (name = fname)))) { + zwarn("%s: function not defined by file", name); + if (noreturnval) + errflag |= ERRFLAG_ERROR; + else + lastval = 1; + goto doneshfunc; + } + prog = shf->funcdef; } - prog = shf->funcdef; - } - runshfunc(prog, wrappers, fstack.name); - doneshfunc: - funcstack = fstack.prev; + runshfunc(prog, wrappers, fstack.name); + doneshfunc: + funcstack = fstack.prev; #ifdef MAX_FUNCTION_DEPTH - undoshfunc: - --funcdepth; + undoshfunc: + --funcdepth; #endif - if (retflag) { - retflag = 0; - breaks = obreaks; - } - freearray(pparams); - if (oargv0) { - zsfree(argzero); - argzero = oargv0; - } - pparams = pptab; - if (!isset(POSIXBUILTINS)) { - zoptind = oldzoptind; - optcind = oldoptcind; - } - scriptname = oldscriptname; - oflags = ooflags; + if (retflag) { + retflag = 0; + breaks = obreaks; + } + freearray(pparams); + if (oargv0) { + zsfree(argzero); + argzero = oargv0; + } + pparams = pptab; + if (!isset(POSIXBUILTINS)) { + zoptind = oldzoptind; + optcind = oldoptcind; + } + scriptname = oldscriptname; + oflags = ooflags; - endpatternscope(); /* before restoring old LOCALPATTERNS */ + endpatternscope(); /* before restoring old LOCALPATTERNS */ - if (restore_sticky) { - /* - * If we switched to an emulation environment just for - * this function, we interpret the option and emulation - * switch as being a firewall between environments. - */ - memcpy(opts, saveopts, sizeof(opts)); - emulation = saveemulation; - sticky = save_sticky; - } else if (isset(LOCALOPTIONS)) { - /* restore all shell options except PRIVILEGED and RESTRICTED */ - saveopts[PRIVILEGED] = opts[PRIVILEGED]; - saveopts[RESTRICTED] = opts[RESTRICTED]; - memcpy(opts, saveopts, sizeof(opts)); - emulation = saveemulation; - } else { - /* just restore a couple. */ - opts[XTRACE] = saveopts[XTRACE]; - opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE]; - opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS]; - opts[LOCALLOOPS] = saveopts[LOCALLOOPS]; - } + if (restore_sticky) { + /* + * If we switched to an emulation environment just for + * this function, we interpret the option and emulation + * switch as being a firewall between environments. + */ + memcpy(opts, saveopts, sizeof(opts)); + emulation = saveemulation; + sticky = save_sticky; + } else if (isset(LOCALOPTIONS)) { + /* restore all shell options except PRIVILEGED and RESTRICTED */ + saveopts[PRIVILEGED] = opts[PRIVILEGED]; + saveopts[RESTRICTED] = opts[RESTRICTED]; + memcpy(opts, saveopts, sizeof(opts)); + emulation = saveemulation; + } else { + /* just restore a couple. */ + opts[XTRACE] = saveopts[XTRACE]; + opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE]; + opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS]; + opts[LOCALLOOPS] = saveopts[LOCALLOOPS]; + } - if (opts[LOCALLOOPS]) { - if (contflag) - zwarn("`continue' active at end of function scope"); - if (breaks) - zwarn("`break' active at end of function scope"); - breaks = obreaks; - contflag = ocontflag; - loops = oloops; - } + if (opts[LOCALLOOPS]) { + if (contflag) + zwarn("`continue' active at end of function scope"); + if (breaks) + zwarn("`break' active at end of function scope"); + breaks = obreaks; + contflag = ocontflag; + loops = oloops; + } - endtrapscope(); + endtrapscope(); - if (trap_state == TRAP_STATE_PRIMED) - trap_return++; - ret = lastval; - if (noreturnval) { - lastval = oldlastval; - numpipestats = oldnumpipestats; - memcpy(pipestats, oldpipestats, sizeof(int)*numpipestats); - } - popheap(); + if (trap_state == TRAP_STATE_PRIMED) + trap_return++; + ret = lastval; + if (noreturnval) { + lastval = oldlastval; + numpipestats = oldnumpipestats; + memcpy(pipestats, oldpipestats, sizeof(int)*numpipestats); + } + } OLDHEAPS; unqueue_signals(); -- cgit v1.2.3 From 21b6852b15c563c434ae053b71d109e4c6010479 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 15 Oct 2015 11:24:21 +0100 Subject: 36864: new objdump completion and tweak to nm completion --- ChangeLog | 6 ++++++ Completion/Unix/Command/_nm | 2 +- Completion/Unix/Command/_objdump | 8 ++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 Completion/Unix/Command/_objdump diff --git a/ChangeLog b/ChangeLog index f0c88c979..c84b643b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-10-15 Peter Stephenson + + * 36864: Completion/Unix/Command/_nm, + Completion/Unix/Command/_objdump: new objdump completion plus + tweak to _nm. + 2015-10-14 Barton E. Schaefer * 36853: Src/exec.c: replace pushheap/popheap by NEWHEAPS/OLDHEAPS diff --git a/Completion/Unix/Command/_nm b/Completion/Unix/Command/_nm index 80136329d..d171ef5a3 100644 --- a/Completion/Unix/Command/_nm +++ b/Completion/Unix/Command/_nm @@ -6,7 +6,7 @@ _nm_object_file() { [[ -x $REPLY || $REPLY = *.([ao]|so|elf) ]] } -files="*:object file:_files -g '*(-.e:_nm_object_file:)'" +files="*:object file:_files -g '*(-.e,_nm_object_file,)'" args=( '(-A -o --print-file-name)'{-A,-o,--print-file-name}'[print name of input file on each line]' '(--demangle)-C[decode symbol names]' diff --git a/Completion/Unix/Command/_objdump b/Completion/Unix/Command/_objdump new file mode 100644 index 000000000..607719a19 --- /dev/null +++ b/Completion/Unix/Command/_objdump @@ -0,0 +1,8 @@ +#compdef objdump + +# borrowed from _nm_object_file +_objdump_object_file() { + [[ -x $REPLY || $REPLY = *.([ao]|so|elf) ]] +} + +_arguments -- '*:object file:_files -g "*(-.e,_objdump_object_file,)"' -- cgit v1.2.3 From 2e600b432a1a0167304ba5b57738b9f5c0af1cc3 Mon Sep 17 00:00:00 2001 From: Frank Terbeck Date: Sun, 18 Oct 2015 20:27:55 +0200 Subject: 36888: vcs_info: Prevent warn_create_global warning with '-preinit-' state This is related to 33405. Turns out that not all other calls to VCS_INFO_set are okay: With recent zsh versions the early call to that function with the '-preinit-' argument causes a warning like this: VCS_INFO_set:9: math parameter maxexports created globally in function VCS_INFO_set This fixes it. --- ChangeLog | 5 +++++ Functions/VCS_Info/vcs_info | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index c84b643b4..70a8d2e2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-18 Frank Terbeck + + * 36888: Functions/VCS_Info/vcs_info: vcs_info: Prevent + warn_create_global warning with '-preinit-' state + 2015-10-15 Peter Stephenson * 36864: Completion/Unix/Command/_nm, diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index 350b189e9..628dde9b1 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -11,6 +11,7 @@ setopt localoptions noksharrays extendedglob NO_shwordsplit local file func sys local -a static_functions +local -i maxexports static_functions=( VCS_INFO_adjust @@ -38,6 +39,7 @@ for func in ${static_functions} ; do done [[ -n ${(Mk)parameters:#vcs_info_msg_<->_} ]] && unset ${parameters[(I)vcs_info_msg_<->_]} +VCS_INFO_maxexports VCS_INFO_set --nvcs '-preinit-' vcs_info_setsys -- cgit v1.2.3 From 509c822b626c01e0787aac2baef5af80d15da529 Mon Sep 17 00:00:00 2001 From: Matthew Martin Date: Mon, 19 Oct 2015 11:23:57 +0200 Subject: 36869: use permissions to limit files completed for ssh identity files --- ChangeLog | 5 +++++ Completion/Unix/Command/_ssh | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 70a8d2e2e..ea86f62cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-19 Oliver Kiddle + + * 36869: Matthew Martin: Completion/Unix/Command/_ssh: use + permissions to limit files completed for ssh identity files + 2015-10-18 Frank Terbeck * 36888: Functions/VCS_Info/vcs_info: vcs_info: Prevent diff --git a/Completion/Unix/Command/_ssh b/Completion/Unix/Command/_ssh index a66702a65..c6ede9efe 100644 --- a/Completion/Unix/Command/_ssh +++ b/Completion/Unix/Command/_ssh @@ -18,7 +18,7 @@ _ssh () { # for protocol version 2, this can be a comma-separated list '-c+[select encryption cipher]:encryption cipher:(idea des 3des blowfish arcfour tss none)' '-F+[specify alternate config file]:config file:_files' - '*-i+[select identity file]:SSH identity file:_files' + '*-i+[select identity file]:SSH identity file:_files -g "*(-.^AR)"' '*-o+[specify extra options]:option string:->option' ) common_transfer=( -- cgit v1.2.3 From d8f8d3e5340e4f61e70aef68d20a41db4445a66f Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Mon, 19 Oct 2015 11:33:17 +0200 Subject: 36889: completion of system specific sockstat options --- ChangeLog | 3 +++ Completion/BSD/Command/_sockstat | 50 +++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index ea86f62cf..f7369b89a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-19 Oliver Kiddle + * 36889: Eric Cook: Completion/BSD/Command/_sockstat: + completion of system specific sockstat options + * 36869: Matthew Martin: Completion/Unix/Command/_ssh: use permissions to limit files completed for ssh identity files diff --git a/Completion/BSD/Command/_sockstat b/Completion/BSD/Command/_sockstat index e61854622..1b11ba473 100644 --- a/Completion/BSD/Command/_sockstat +++ b/Completion/BSD/Command/_sockstat @@ -1,23 +1,35 @@ #compdef sockstat +local -a args -local tmp_proto protocols proto +case $OSTYPE in + *bsd*) + args=( + '-4[show AF_INET (IPv4) sockets]' + '-6[show AF_INET6 (IPv6) sockets]' + '-c[show connected sockets]' + '-l[show listening sockets]' + '*-p[specify port number]:port numbers (comma delimited)' + '-u[show AF_LOCAL (UNIX) sockets]' + ) + ;| + freebsd*) + args+=( + '*-j[show sockets belonging to JID]: : _jails -0 -o jid' + '-L[exclude loopback]' + '*-P[specify protocol]: :_sequence -s , _ports' + ) + ;; + netbsd*) + args+=( + '*-f[only show specified address family]:address family:(inet inet6 local unix)' + '-n[no symbolic names for addresses/ports]' + ) + ;; +esac -tmp_proto=(${${(M)${(f)"$( Date: Mon, 19 Oct 2015 16:05:01 +0200 Subject: 36646: handle solaris/openzfs differences; only use -t share on solaris --- ChangeLog | 4 ++++ Completion/Unix/Command/_zfs | 4 +++- Completion/Unix/Command/_zpool | 4 +++- Completion/Unix/Type/_zfs_dataset | 6 ++++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index f7369b89a..83aef6f64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-10-19 Oliver Kiddle + * 36646: Eric Cook: Completion/Unix/Type/_zfs_dataset, + Completion/Unix/Command/_zpool, Completion/Unix/Command/_zfs: + solaris/openzfs differences; only use -t share solaris + * 36889: Eric Cook: Completion/BSD/Command/_sockstat: completion of system specific sockstat options diff --git a/Completion/Unix/Command/_zfs b/Completion/Unix/Command/_zfs index cd5ad3edc..04a92e685 100644 --- a/Completion/Unix/Command/_zfs +++ b/Completion/Unix/Command/_zfs @@ -2,7 +2,7 @@ # Synced with the S11U1 man page _zfs() { - local context state line expl + local context state line expl implementation typeset -A opt_args local -a subcmds rw_properties rw_propnames ro_properties create_properties local -a share_nfs_ro_properties share_nfs_rw_properties @@ -10,6 +10,8 @@ _zfs() { local -a share_ro_properties share_rw_properties local -a difffields delegatable_perms + _pick_variant -r implementation -c 'zpool upgrade -v' openzfs='This system supports ZFS pool feature flags' solaris + subcmds=( "create" "destroy" "clone" "promote" "rename" "snapshot" "rollback" "list" "set" "get" "inherit" "mount" "unmount" diff --git a/Completion/Unix/Command/_zpool b/Completion/Unix/Command/_zpool index f2116dc2e..53022db8a 100644 --- a/Completion/Unix/Command/_zpool +++ b/Completion/Unix/Command/_zpool @@ -2,9 +2,11 @@ # Synced with the S11U1 man page _zpool() { - local context state line expl + local context state line expl implementation local -a subcmds fields ro_props rw_props versions create_properties_dataset + _pick_variant -r implementation -c 'zpool upgrade -v' openzfs='This system supports ZFS pool feature flags' solaris + subcmds=( create destroy add remove list iostat status online offline clear attach detach replace scrub import export diff --git a/Completion/Unix/Type/_zfs_dataset b/Completion/Unix/Type/_zfs_dataset index 64e343f3a..5fa3e9e50 100644 --- a/Completion/Unix/Type/_zfs_dataset +++ b/Completion/Unix/Type/_zfs_dataset @@ -34,6 +34,8 @@ if [[ ${#rsrc} -gt 0 ]]; then typearg=( -t snapshot ) elif [[ -n $words[(r)-p] ]]; then typearg=( -t filesystem,volume ) + elif [[ $implementation == openzfs ]]; then + typearg=( -t filesystem,snapshot,volume ) else typearg=( -t filesystem,share,snapshot,volume ) fi @@ -50,13 +52,13 @@ if [[ ${#rdst} -gt 0 ]]; then else # The parent dataset must be a filesystem, and can't rename # a dataset into another pool. Plus we hardcode the expl. - typearg=( -t fs -r ${${words[CURRENT - 1]}%%/*} ) + typearg=( -t filesystem -r ${${words[CURRENT - 1]}%%/*} ) expl_type_arr=( -e "parent dataset" ) fi fi if [[ -n $type[(r)clone] ]]; then - datasetlist=( ${="$(zfs list -H -o name,origin -t fs | awk "\$2 != \"-\" {print \$1}")":#no cloned filesystems available} ) + datasetlist=( ${="$(zfs list -H -o name,origin -t filesystem | awk "\$2 != \"-\" {print \$1}")":#no cloned filesystems available} ) else datasetlist=( ${="$(zfs list -H -o name $typearg)":#no datasets available} ) fi -- cgit v1.2.3 From c6028f7387ad496ade9daaf76ac1683c3002bbf7 Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Mon, 19 Oct 2015 16:00:21 +0200 Subject: 36642: complete jail/unjail zfs subcommands on freebsd --- ChangeLog | 3 +++ Completion/Unix/Command/_zfs | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index 83aef6f64..4d8b15c69 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-19 Oliver Kiddle + * 36642: Eric Cook: Completion/Unix/Command/_zfs: + complete jail/unjail subcommands on freebsd + * 36646: Eric Cook: Completion/Unix/Type/_zfs_dataset, Completion/Unix/Command/_zpool, Completion/Unix/Command/_zfs: solaris/openzfs differences; only use -t share solaris diff --git a/Completion/Unix/Command/_zfs b/Completion/Unix/Command/_zfs index 04a92e685..f3869da43 100644 --- a/Completion/Unix/Command/_zfs +++ b/Completion/Unix/Command/_zfs @@ -20,6 +20,8 @@ _zfs() { "diff" "key" "help" ) + [[ $OSTYPE == freebsd<7->.* ]] && subcmds+=(jail unjail) + share_nfs_ro_properties=( "share.nfs.all" ) @@ -533,6 +535,12 @@ _zfs() { ':filesystem or volume:_zfs_dataset -t fs -t vol' ;; + ("jail"|"unjail") + _arguments \ + '1: : _jails' \ + '2:filesystem:_zfs_dataset -t fs' + ;; + ("help") _arguments -A "-*" \ - set1 \ -- cgit v1.2.3 From 98875bcb05d552cc59b300e33fe9000d295b1ffe Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Tue, 20 Oct 2015 14:22:25 +0000 Subject: 36900: _git: stash names completion: Display log messages The "$@" argument to compadd is removed because (I think) it contains a -J, which conflicts with the -V. Joint with Daniel Hahler. --- ChangeLog | 5 +++++ Completion/Unix/Command/_git | 13 +++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4d8b15c69..04883a152 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-20 Daniel Shahaf + + * 36900: Completion/Unix/Command/_git: _git: stash names + completion: Display log messages + 2015-10-19 Oliver Kiddle * 36642: Eric Cook: Completion/Unix/Command/_zfs: diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 1fcde9015..719d717d7 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5487,12 +5487,21 @@ __git_signoff_file () { (( $+functions[__git_stashes] )) || __git_stashes () { local expl + declare -a interleaved declare -a stashes + declare -a descriptions - stashes=(${(f)"$(_call_program stashes git stash list --pretty=format:%gd 2>/dev/null)"}) + interleaved=(${(ps:\0:)"$(_call_program stashes git stash list -z --pretty='format:%gd%x00%s%x00\(%cr\)' 2>/dev/null)"}) __git_command_successful $pipestatus || return 1 + () { + local i j k + for i j k in $interleaved; do + stashes+=($i) + descriptions+=("$i: $j $k") + done + } - _wanted stashes expl stash compadd "$@" -a - stashes + _wanted stashes expl 'stash' compadd -Vx -d descriptions -a - stashes } (( $+functions[__git_svn_revisions] )) || -- cgit v1.2.3 From b947789d7c7a9e01880512dff1f27198f4707e50 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 21 Oct 2015 14:47:41 -0700 Subject: 36871: move initial call to "zle .bracketed-paste-magic" to occur earlier in the function Just in case any later initialization might have side-effects. --- ChangeLog | 5 +++++ Functions/Zle/bracketed-paste-magic | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 04883a152..22e4b9478 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-21 Barton E. Schaefer + + * 36871: Functions/Zle/bracketed-paste-magic: move initial call + to "zle .bracketed-paste-magic" to occur earlier in the function + 2015-10-20 Daniel Shahaf * 36900: Completion/Unix/Command/_git: _git: stash names diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index cd4a7085b..2368bc315 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -116,10 +116,14 @@ quote-paste() { # Now the actual function bracketed-paste-magic() { - # Fast exit in the vi-mode cut-buffer context if [[ "$LASTWIDGET" = *vi-set-buffer ]]; then + # Fast exit in the vi-mode cut-buffer context zle .bracketed-paste return + else + # Capture the pasted text in $PASTED + local PASTED + zle .bracketed-paste PASTED fi # Really necessary to go to this much effort? @@ -127,10 +131,9 @@ bracketed-paste-magic() { emulate -L zsh local -a bpm_hooks bpm_inactive - local PASTED bpm_func bpm_active bpm_keymap=$KEYMAP + local bpm_func bpm_active bpm_keymap=$KEYMAP - # Set PASTED and run the paste-init functions - zle .bracketed-paste PASTED + # Run the paste-init functions if zstyle -a :bracketed-paste-magic paste-init bpm_hooks; then for bpm_func in $bpm_hooks; do if (( $+functions[$bpm_func] )); then -- cgit v1.2.3 From 5cb75f0d4114f83a7cf072ff8201445ae721f8c6 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 21 Oct 2015 15:13:17 -0700 Subject: 36909: in getargs(), sanity-check the offsets for start and end of the requested words, in case of overflow --- ChangeLog | 3 +++ Src/hist.c | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 22e4b9478..e40242eb8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-21 Barton E. Schaefer + * 36909: Src/hist.c: in getargs(), sanity-check the offsets for + start and end of the requested words, in case of overflow + * 36871: Functions/Zle/bracketed-paste-magic: move initial call to "zle .bracketed-paste-magic" to occur earlier in the function diff --git a/Src/hist.c b/Src/hist.c index 9c42d85c9..007366a49 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -2254,7 +2254,7 @@ static char * getargs(Histent elist, int arg1, int arg2) { short *words = elist->words; - int pos1, nwords = elist->nwords; + int pos1, pos2, nwords = elist->nwords; if (arg2 < arg1 || arg1 >= nwords || arg2 >= nwords) { /* remember, argN is indexed from 0, nwords is total no. of words */ @@ -2263,8 +2263,22 @@ getargs(Histent elist, int arg1, int arg2) return NULL; } + /* optimization for accessing entire history event */ + if (arg1 == 0 && arg2 == nwords - 1) + return dupstring(elist->node.nam); + pos1 = words[2*arg1]; - return dupstrpfx(elist->node.nam + pos1, words[2*arg2+1] - pos1); + pos2 = words[2*arg2+1]; + + /* a word has to be at least one character long, so if the position + * of a word is less than its index, we've overflowed our signed + * short integer word range and the recorded position is garbage. */ + if (pos1 < 0 || pos1 < arg1 || pos2 < 0 || pos2 < arg2) { + herrflush(); + zerr("history event too long, can't index requested words"); + return NULL; + } + return dupstrpfx(elist->node.nam + pos1, pos2 - pos1); } /**/ -- cgit v1.2.3 From b970ef6ef50dc4e21a053ae673fe89fff5a3c52f Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 21 Oct 2015 15:13:45 -0700 Subject: unposted: strdup should be ztrdup --- ChangeLog | 2 ++ Src/math.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e40242eb8..e383ab9b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-10-21 Barton E. Schaefer + * unposted: Src/math.c: strdup should be ztrdup + * 36909: Src/hist.c: in getargs(), sanity-check the offsets for start and end of the requested words, in case of overflow diff --git a/Src/math.c b/Src/math.c index 56565a629..eee21e146 100644 --- a/Src/math.c +++ b/Src/math.c @@ -535,7 +535,7 @@ lexconstant(void) for (ptr2 = ptr; ptr2 < nptr; ptr2++) { if (*ptr2 == '_') { int len = nptr - ptr; - ptr = strdup(ptr); + ptr = ztrdup(ptr); for (ptr2 = ptr; len; len--) { if (*ptr2 == '_') chuck(ptr2); -- cgit v1.2.3 From 8e9a68ad14655c1949b1a04d5715a5caa8c344ee Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 22 Oct 2015 12:29:39 +0000 Subject: unposted: vcs_info docs: Typo fix. --- ChangeLog | 4 ++++ Doc/Zsh/contrib.yo | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e383ab9b6..84f1b9856 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-10-22 Daniel Shahaf + + * unposted: Doc/Zsh/contrib.yo: vcs_info docs: Typo fix. + 2015-10-21 Barton E. Schaefer * unposted: Src/math.c: strdup should be ztrdup diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index d367d8b0f..cb68952a4 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1332,7 +1332,7 @@ otherwise would be something like `svn' or `cvs') will be set to identifier is the second element. tt(vcs_info) will have filled in a proper value for the "repository's" root directory and the string containing the information about quilt's state will be available as the `misc' replacement -(and tt(%Q) for compatibility with `addon' mode. +(and tt(%Q) for compatibility with `addon' mode). What is left to discuss is how `standalone' mode is detected. The detection itself is a series of searches for directories. You can have this detection -- cgit v1.2.3 From 1f6dcf9bcdade41886e36826196e79502a9afa26 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 24 Oct 2015 20:24:35 +0100 Subject: 36941: Mark file descripors in ztcp as used. Allow such file descriptors to be either internal and closed on exec or external and so managed explicitly by module. --- ChangeLog | 6 ++++++ Src/Modules/tcp.c | 7 ++++++- Src/utils.c | 26 ++++++++++++++++++++++++++ Src/zsh.h | 15 +++++++++++---- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 84f1b9856..356e92319 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-10-24 Peter Stephenson + + * 36941: Src/utils.c, Src/zsh.h, Src/Modules/tcp.c: ensure shell + knows about file descriptiors used by ztcp and allow such file + descriptors to be marked as internal if needed (not yet used). + 2015-10-22 Daniel Shahaf * unposted: Doc/Zsh/contrib.yo: vcs_info docs: Typo fix. diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c index bc1765da1..274f01ffc 100644 --- a/Src/Modules/tcp.c +++ b/Src/Modules/tcp.c @@ -236,6 +236,8 @@ tcp_socket(int domain, int type, int protocol, int ztflags) if (!sess) return NULL; sess->fd = socket(domain, type, protocol); + /* We'll check failure and tidy up in caller */ + addmodulefd(sess->fd, FALSE); return sess; } @@ -298,7 +300,7 @@ tcp_close(Tcp_session sess) { if (sess->fd != -1) { - err = close(sess->fd); + err = zclose(sess->fd); if (err) zwarn("connection close failed: %e", errno); } @@ -546,6 +548,9 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } + /* redup expects fd is already registered */ + addmodulefd(rfd, FALSE); + if (targetfd) { sess->fd = redup(rfd, targetfd); if (sess->fd < 0) { diff --git a/Src/utils.c b/Src/utils.c index 61cbe84aa..4c69d75a1 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1891,6 +1891,32 @@ redup(int x, int y) return ret; } +/* + * Add an fd opened ithin a module. + * + * If is_internal is FALSE, the fd can be used within the shell for + * normal I/O but it will not be closed automatically or by normal shell + * syntax; it can only be closed by the module (which should included + * zclose() as part of the sequence). + * + * If is_internal is TRUE the fd is treated like others created by the + * shell for internall use; it can be closed and will be closed by the + * shell if it exec's or performs an exec with a fork optimised out. + *. + * Safe if fd is -1 to indicate failure. + */ +/**/ +mod_export void +addmodulefd(int fd, bool is_internal) +{ + if (fd >= 0) { + check_fd_table(fd); + fdtable[fd] = is_internal ? FDT_INTERNAL : FDT_MODULE; + } +} + +/**/ + /* * Indicate that an fd has a file lock; if cloexec is 1 it will be closed * on exec. diff --git a/Src/zsh.h b/Src/zsh.h index 15fa5e417..f819249c3 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -405,26 +405,33 @@ enum { * the {varid}> file syntax. */ #define FDT_EXTERNAL 2 +/* + * Entry visible to other processes but controlled by a module. + * The difference from FDT_EXTERNAL is that closing this using + * standard fd syntax will fail as there is some tidying up that + * needs to be done by the module's own mechanism. + */ +#define FDT_MODULE 3 /* * Entry used by output from the XTRACE option. */ -#define FDT_XTRACE 3 +#define FDT_XTRACE 4 /* * Entry used for file locking. */ -#define FDT_FLOCK 4 +#define FDT_FLOCK 5 /* * As above, but the fd is not marked for closing on exec, * so the shell can still exec the last process. */ -#define FDT_FLOCK_EXEC 5 +#define FDT_FLOCK_EXEC 6 #ifdef PATH_DEV_FD /* * Entry used by a process substition. * This marker is not tested internally as we associated the file * descriptor with a job for closing. */ -#define FDT_PROC_SUBST 6 +#define FDT_PROC_SUBST 7 #endif /* Flags for input stack */ -- cgit v1.2.3 From 15490398d7553605c422d8ab0e59e69e25111df4 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 24 Oct 2015 20:48:47 +0100 Subject: 36944: extend fd management to zsocket --- ChangeLog | 4 ++++ Doc/Zsh/mod_socket.yo | 5 +++++ Src/Modules/socket.c | 17 +++++++++++++++-- Src/Modules/tcp.c | 4 ++-- Src/utils.c | 25 +++++++++++++++---------- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 356e92319..71f15bb0d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-10-24 Peter Stephenson + * 36944: Src/utils.c, Src/Modules/tcp.c, Src/Modules/socket.c: + extend the previous to zsocket, although this needs to allow the + fd to be closed explicitly. + * 36941: Src/utils.c, Src/zsh.h, Src/Modules/tcp.c: ensure shell knows about file descriptiors used by ztcp and allow such file descriptors to be marked as internal if needed (not yet used). diff --git a/Doc/Zsh/mod_socket.yo b/Doc/Zsh/mod_socket.yo index 332c551fe..867f6081f 100644 --- a/Doc/Zsh/mod_socket.yo +++ b/Doc/Zsh/mod_socket.yo @@ -28,6 +28,11 @@ will be taken as the target file descriptor for the connection. In order to elicit more verbose output, use tt(-v). + +File descriptors can be closed with normal shell syntax when no longer +needed, for example: + +example(exec {REPLY}>&-) ) enditem() diff --git a/Src/Modules/socket.c b/Src/Modules/socket.c index 65b87d7dd..f683496df 100644 --- a/Src/Modules/socket.c +++ b/Src/Modules/socket.c @@ -115,6 +115,8 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } + addmodulefd(sfd, FDT_EXTERNAL); + if (targetfd) { sfd = redup(sfd, targetfd); } @@ -127,6 +129,9 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } + /* allow to be closed explicitly */ + fdtable[sfd] = FDT_EXTERNAL; + setiparam("REPLY", sfd); if (verbose) @@ -200,12 +205,16 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } + addmodulefd(rfd, FDT_EXTERNAL); + if (targetfd) { sfd = redup(rfd, targetfd); if (sfd < 0) { zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno); + zclose(rfd); return 1; } + fdtable[sfd] = FDT_EXTERNAL; } else { sfd = rfd; @@ -240,12 +249,16 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func)) } else { + addmodulefd(sfd, FDT_EXTERNAL); + if (targetfd) { - sfd = redup(sfd, targetfd); - if (sfd < 0) { + if (redup(sfd, targetfd) < 0) { zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno); + zclose(sfd); return 1; } + sfd = targetfd; + fdtable[sfd] = FDT_EXTERNAL; } setiparam("REPLY", sfd); diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c index 274f01ffc..7b0dcc74a 100644 --- a/Src/Modules/tcp.c +++ b/Src/Modules/tcp.c @@ -237,7 +237,7 @@ tcp_socket(int domain, int type, int protocol, int ztflags) sess->fd = socket(domain, type, protocol); /* We'll check failure and tidy up in caller */ - addmodulefd(sess->fd, FALSE); + addmodulefd(sess->fd, FDT_MODULE); return sess; } @@ -549,7 +549,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) } /* redup expects fd is already registered */ - addmodulefd(rfd, FALSE); + addmodulefd(rfd, FDT_MODULE); if (targetfd) { sess->fd = redup(rfd, targetfd); diff --git a/Src/utils.c b/Src/utils.c index 4c69d75a1..37a02c593 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1894,24 +1894,29 @@ redup(int x, int y) /* * Add an fd opened ithin a module. * - * If is_internal is FALSE, the fd can be used within the shell for - * normal I/O but it will not be closed automatically or by normal shell - * syntax; it can only be closed by the module (which should included - * zclose() as part of the sequence). + * fdt is the type of the fd; see the FDT_ definitions in zsh.h. + * The most likely falures are: + * + * FDT_EXTERNAL: the fd can be used within the shell for normal I/O but + * it will not be closed automatically or by normal shell syntax. + * + * FDT_MODULE: as FDT_EXTERNAL, but it can only be closed by the module + * (which should included zclose() as part of the sequence, not by + * the standard shell syntax for closing file descriptors. + * + * FDT_INTERNAL: fd is treated like others created by the shell for + * internall use; it can be closed and will be closed by the shell if it + * exec's or performs an exec with a fork optimised out. * - * If is_internal is TRUE the fd is treated like others created by the - * shell for internall use; it can be closed and will be closed by the - * shell if it exec's or performs an exec with a fork optimised out. - *. * Safe if fd is -1 to indicate failure. */ /**/ mod_export void -addmodulefd(int fd, bool is_internal) +addmodulefd(int fd, int fdt) { if (fd >= 0) { check_fd_table(fd); - fdtable[fd] = is_internal ? FDT_INTERNAL : FDT_MODULE; + fdtable[fd] = fdt; } } -- cgit v1.2.3 From c8c42d6ed55c23f83a4a94eaae7e42a70c5d55c7 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 24 Oct 2015 20:59:48 +0100 Subject: unposted: small typo --- ChangeLog | 2 ++ Src/utils.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 71f15bb0d..ef5cbe1f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-10-24 Peter Stephenson + * unposted: Src/utils.c: small typo. + * 36944: Src/utils.c, Src/Modules/tcp.c, Src/Modules/socket.c: extend the previous to zsocket, although this needs to allow the fd to be closed explicitly. diff --git a/Src/utils.c b/Src/utils.c index 37a02c593..b72addaff 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1905,7 +1905,7 @@ redup(int x, int y) * the standard shell syntax for closing file descriptors. * * FDT_INTERNAL: fd is treated like others created by the shell for - * internall use; it can be closed and will be closed by the shell if it + * internal use; it can be closed and will be closed by the shell if it * exec's or performs an exec with a fork optimised out. * * Safe if fd is -1 to indicate failure. -- cgit v1.2.3 From 272119b774a5227e8778e5f86b4a519db89ab0fa Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 24 Oct 2015 21:00:30 +0100 Subject: unposted: small typo again --- Src/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/utils.c b/Src/utils.c index b72addaff..0afa8c908 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1901,7 +1901,7 @@ redup(int x, int y) * it will not be closed automatically or by normal shell syntax. * * FDT_MODULE: as FDT_EXTERNAL, but it can only be closed by the module - * (which should included zclose() as part of the sequence, not by + * (which should included zclose() as part of the sequence), not by * the standard shell syntax for closing file descriptors. * * FDT_INTERNAL: fd is treated like others created by the shell for -- cgit v1.2.3 From c62db9e7dc2f59337aec1df55663383c524886cb Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 22 Oct 2015 12:30:24 +0000 Subject: 36912: vcs_info quilt: Tolerate being in child of .pc's parent Without this, gen-applied-string would only be set when .pc is a child of cwd, not when it is a child of an ancestor of cwd. --- ChangeLog | 5 +++++ Functions/VCS_Info/VCS_INFO_quilt | 1 + 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index ef5cbe1f0..fe93bc724 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-24 Daniel Shahaf + + * 36912: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: + Tolerate being in child of .pc's parent + 2015-10-24 Peter Stephenson * unposted: Src/utils.c: small typo. diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index bc71cfb7d..29603a27a 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -119,6 +119,7 @@ function VCS_INFO_quilt() { applied=() fi patches=$(<$pc/.quilt_patches) + patches=`builtin cd -q "${pc:h}" && print -r - ${patches:A}` fi if zstyle -t "${context}" get-unapplied; then # This zstyle call needs to be moved further up if `quilt' needs -- cgit v1.2.3 From 779b3112f85d01d297ab04e6c1b68a0b33d76a55 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 21 Oct 2015 05:11:59 +0000 Subject: 36913 + 36945: vcs_info quilt: Pass patch subject lines to gen-applied-string The format used is '${patchname} ${subject}', which is analogous to the git backend. --- ChangeLog | 3 +++ Functions/VCS_Info/VCS_INFO_quilt | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/ChangeLog b/ChangeLog index fe93bc724..dffd3b35a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-24 Daniel Shahaf + * 36913 + 36945: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: + Pass patch subject lines to gen-applied-string + * 36912: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: Tolerate being in child of .pc's parent diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index 29603a27a..c3c3d864d 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -145,6 +145,36 @@ function VCS_INFO_quilt() { unapplied=() fi + if [[ -n $patches ]]; then + () { + local i line + for ((i=1; i<=$#applied; i++)); do + if [[ -f "$patches/$applied[$i]" ]] && + read -r line < "$patches/$applied[$i]" && + [[ $line != (#b)(---|Index:)* ]] && + true + ; + then + applied[$i]+=" $line" + else + applied[$i]+=" ?" + fi + done + for ((i=1; i<=$#unapplied; i++)); do + if [[ -f "$patches/$unapplied[$i]" ]] && + read -r line < "$patches/$unapplied[$i]" && + [[ $line != (#b)(---|Index:)* ]] && + true + ; + then + unapplied[$i]+=" $line" + else + unapplied[$i]+=" ?" + fi + done + } + fi + all=( ${(Oa)applied} ${unapplied} ) if VCS_INFO_hook 'gen-applied-string' "${applied[@]}"; then -- cgit v1.2.3 From e3c68450d77e679499a93fa87d964907213e15c3 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 24 Oct 2015 20:31:01 +0000 Subject: unposted: _beep completion: Actually hook it for the 'beep' command. --- ChangeLog | 3 +++ Completion/Unix/Command/_beep | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index dffd3b35a..44830070e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-24 Daniel Shahaf + * unposted: Completion/Unix/Command/_beep: _beep completion: + Actually hook it for the 'beep' command. + * 36913 + 36945: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: Pass patch subject lines to gen-applied-string diff --git a/Completion/Unix/Command/_beep b/Completion/Unix/Command/_beep index c49c09726..d393bc91e 100644 --- a/Completion/Unix/Command/_beep +++ b/Completion/Unix/Command/_beep @@ -1,4 +1,4 @@ -#compdef _beep +#compdef beep # beep [--verbose | --debug] [-e device | --device device] [-f N] [-l N] # [-r N] [-d N] [-D N] [-s] [-c] -- cgit v1.2.3 From 506d5923802a930f24dd264588a8d33c05ed085b Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 24 Oct 2015 13:43:21 -0700 Subject: 36943: restore scan for reclaimable blocks in freeheap() That scan had been removed by 36834, but testing showed memory usage climbing too high in cases where a new arena was always added at the end of the heap list. --- ChangeLog | 5 +++++ Src/mem.c | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index ef5cbe1f0..31fc78366 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-24 Barton E. Schaefer + + * 36943 (with updated comment): Src/mem.c: restore scan for + reclaimable blocks in freeheap() [had been removed by 36834] + 2015-10-24 Peter Stephenson * unposted: Src/utils.c: small typo. diff --git a/Src/mem.c b/Src/mem.c index 68bd76740..158ad9641 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -340,9 +340,15 @@ freeheap(void) * and performance goes to hell. * * Therefore, we defer freeing the most recently allocated arena until - * we reach popheap(). This may fail to reclaim some space in earlier - * arenas. + * we reach popheap(). * + * However, if the arena to which fheap points is unused, we want to + * reclaim space in earlier arenas, so we have no choice but to do the + * sweep for a new fheap. + */ + if (fheap && !fheap->sp) + fheap = NULL; /* We used to do this unconditionally */ + /* * In other cases, either fheap is already correct, or it has never * been set and this loop will do it, or it'll be reset from scratch * on the next popheap(). So all that's needed here is to pick up -- cgit v1.2.3 From a40417929cb6f94ccd8fb5af78aa47ff69a785c0 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Sun, 25 Oct 2015 23:42:03 +0900 Subject: 36911: '-optarg' should not match optspec '-opt=' Remove the requirement that -xy= should come before -x= in the list of optspecs passed to _arguments. --- ChangeLog | 5 +++++ Src/Zle/computil.c | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e6edaa8c0..8bf01dc3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-25 Jun-ichi Takimoto + + * 36911: Src/Zle/computil.c: '-optarg' should not match + optspec '-opt=' + 2015-10-24 Barton E. Schaefer * 36943 (with updated comment): Src/mem.c: restore scan for diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index e5db0867b..db8db88a6 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -1693,10 +1693,13 @@ ca_get_opt(Cadef d, char *line, int full, char **end) for (p = d->opts; p; p = p->next) if (p->active && ((!p->args || p->type == CAO_NEXT) ? !strcmp(p->name, line) : strpfx(p->name, line))) { + int l = strlen(p->name); + if ((p->type == CAO_OEQUAL || p->type == CAO_EQUAL) && + line[l] && line[l] != '=') + continue; + if (end) { /* Return a pointer to the end of the option. */ - int l = strlen(p->name); - if ((p->type == CAO_OEQUAL || p->type == CAO_EQUAL) && line[l] == '=') l++; -- cgit v1.2.3 From f8b2c13c97228c9a1a0319f07d1ae7c1268e12db Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 25 Oct 2015 18:39:31 +0000 Subject: unposted: _git: Fix 'commit object name' completion messages. Offer the "this alternative is still valid, but I don't know to offer completions for it" for hash completion but not for recent object completion; the former is protected by a _guard and the latter incorrectly appeared also in cases such as 'git log a/b' which were not the start of a gitrevisions(7) expression. --- ChangeLog | 5 +++++ Completion/Unix/Command/_git | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8bf01dc3f..812ef3540 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-25 Daniel Shahaf + + * unposted: Completion/Unix/Command/_git: _git: Fix 'commit + object name' completion messages. + 2015-10-25 Jun-ichi Takimoto * 36911: Src/Zle/computil.c: '-optarg' should not match diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 719d717d7..e38b1c6e7 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5640,7 +5640,7 @@ __git_commit_objects () { commits=(${(f)"$(_call_program commits git --no-pager log -1000 --all --reflog --format='%h:\[%h\]\ %s\ \(%cr\)')"}) __git_command_successful $pipestatus || return 1 - _describe -V -t commits 'commit object name' commits + _describe -Vx -t commits 'commit object name' commits } (( $+functions[__git_recent_commits] )) || @@ -5704,7 +5704,7 @@ __git_recent_commits () { expl=() _wanted heads expl 'head' compadd "$@" -a - heads && ret=0 expl=() - _describe -Vx -t commits 'recent commit object name' descr && ret=0 + _describe -V -t commits 'recent commit object name' descr && ret=0 return $ret } -- cgit v1.2.3 From 17af119089379ec1b65b327c72eee3aac93fada7 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 25 Oct 2015 18:34:08 +0000 Subject: 36958: _git: Fix recent commit completion descriptions. The uniquifiers 'HEAD~$n' were incorrect when a recent commit was the second parent of a merge commit. Detect that case and print something correct instead. --- ChangeLog | 3 +++ Completion/Unix/Command/_git | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 812ef3540..234f26f11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-25 Daniel Shahaf + * 36958: Completion/Unix/Command/_git: _git: Fix recent commit + completion descriptions. + * unposted: Completion/Unix/Command/_git: _git: Fix 'commit object name' completion messages. diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index e38b1c6e7..279331b00 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5650,6 +5650,8 @@ __git_recent_commits () { local i j k ret integer distance_from_head local label + local parents + local next_first_parent_ancestral_line_commit zparseopts -D -E O:=argument_array_names # Turn (-O foo:bar) to (foo bar) @@ -5659,10 +5661,10 @@ __git_recent_commits () { # Careful: most %d will expand to the empty string. Quote properly! # NOTE: we could use %D directly, but it's not available in git 1.9.1 at least. - commits=("${(f)"$(_call_program commits git --no-pager log $commit_opts -20 --format='%h%n%d%n%s\ \(%cr\)')"}") + commits=("${(f)"$(_call_program commits git --no-pager log $commit_opts -20 --format='%h%n%d%n%s\ \(%cr\)%n%p')"}") __git_command_successful $pipestatus || return 1 - for i j k in "$commits[@]" ; do + for i j k parents in "$commits[@]" ; do # Note: the after-the-colon part must be unique across the entire array; # see workers/34768 if (( $#commit_opts )); then @@ -5671,20 +5673,35 @@ __git_recent_commits () { # description unique (due to workers/34768), which we do by including the # hash. Git always prints enough hash digits to make the output unique.) label="[$i]" - elif (( distance_from_head == 0 )); then - label="[HEAD] " - elif (( distance_from_head == 1 )); then - label="[HEAD^] " - elif (( distance_from_head == 2 )); then - label="[HEAD^^] " - elif (( distance_from_head < 10 )); then - label="[HEAD~$distance_from_head] " + elif (( distance_from_head )) && [[ $i != $next_first_parent_ancestral_line_commit ]]; then + # The first commit (HEAD), and its ancestors along the first-parent line, + # get HEAD~$n labels. + # + # For other commits, we just print the hash. (${parents} does provide enough + # information to compute HEAD~3^2~4 -style labels, though, if somebody cared + # enough to implement that.) + label="[$i]" else - label="[HEAD~$distance_from_head]" + # Compute a first-parent-ancestry commit's label. + if false ; then + elif (( distance_from_head == 0 )); then + label="[HEAD] " + elif (( distance_from_head == 1 )); then + label="[HEAD^] " + elif (( distance_from_head == 2 )); then + label="[HEAD^^] " + elif (( distance_from_head < 10 )); then + label="[HEAD~$distance_from_head] " + else + label="[HEAD~$distance_from_head]" + fi + + # Prepare for the next first-parent-ancestry commit. + (( ++distance_from_head )) + next_first_parent_ancestral_line_commit=${parents%% *} fi # label is now 9 bytes, so the descriptions ($k) will be aligned. descr+=($i:"${label} $k") - (( ++distance_from_head )) j=${${j# \(}%\)} # strip leading ' (' and trailing ')' j=${j/ ->/,} # Convert " -> master, origin/master". -- cgit v1.2.3 From f890d442e22fccb94997c400710a88f8415388cf Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 25 Oct 2015 18:34:58 +0000 Subject: 36959: _git: Offer @~$n as completion of recent commits. Suggested-by: Oliver Kiddle (users/20705) --- ChangeLog | 3 +++ Completion/Unix/Command/_git | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 234f26f11..67129de6e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-25 Daniel Shahaf + * 36959: Completion/Unix/Command/_git: _git: Offer @~$n as + completion of recent commits. + * 36958: Completion/Unix/Command/_git: _git: Fix recent commit completion descriptions. diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 279331b00..740aec4cd 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5695,13 +5695,14 @@ __git_recent_commits () { else label="[HEAD~$distance_from_head]" fi + descr+=("@~${distance_from_head}":"${label} $k") # CROSSREF: use the same label as below # Prepare for the next first-parent-ancestry commit. (( ++distance_from_head )) next_first_parent_ancestral_line_commit=${parents%% *} fi # label is now 9 bytes, so the descriptions ($k) will be aligned. - descr+=($i:"${label} $k") + descr+=($i:"${label} $k") # CROSSREF: use the same label as above j=${${j# \(}%\)} # strip leading ' (' and trailing ')' j=${j/ ->/,} # Convert " -> master, origin/master". -- cgit v1.2.3 From b4f7482e44ec59bfe99c8d0f23503570eda0ca1b Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 25 Oct 2015 18:35:20 +0000 Subject: 36960: _git: Enable slash matcher for more branch and tag completions, include 'git branch ' and 'git tag '. --- ChangeLog | 4 ++++ Completion/Unix/Command/_git | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 67129de6e..c77e0a525 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-10-25 Daniel Shahaf + * 36960: Completion/Unix/Command/_git: _git: Enable slash matcher + for more branch and tag completions, include 'git branch ' + and 'git tag '. + * 36959: Completion/Unix/Command/_git: _git: Offer @~$n as completion of recent commits. diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 740aec4cd..e5005f1c3 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5540,7 +5540,7 @@ __git_branch_names () { branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}) __git_command_successful $pipestatus || return 1 - _wanted branch-names expl branch-name compadd "$@" -a - branch_names + _wanted branch-names expl branch-name compadd -M 'r:|/=**' "$@" -a - branch_names } (( $+functions[__git_remote_branch_names] )) || @@ -5848,7 +5848,7 @@ __git_tags () { tags=(${${(f)"$(_call_program tagrefs git for-each-ref --format='"%(refname)"' refs/tags 2>/dev/null)"}#refs/tags/}) __git_command_successful $pipestatus || return 1 - _wanted tags expl tag compadd "$@" -a - tags + _wanted tags expl tag compadd -M 'r:|/=**' "$@" -a - tags } (( $+functions[__git_commit_tags] )) || @@ -5871,7 +5871,7 @@ __git_tags_of_type () { tags=(${${(M)${(f)"$(_call_program $type-tag-refs "git for-each-ref --format='%(*objecttype)%(objecttype) %(refname)' refs/tags 2>/dev/null")"}:#$type(tag|) *}#$type(tag|) refs/tags/}) __git_command_successful $pipestatus || return 1 - _wanted $type-tags expl "$type tag" compadd "$@" -a - tags + _wanted $type-tags expl "$type tag" compadd -M 'r:|/=**' "$@" -a - tags } # Reference Argument Types -- cgit v1.2.3 From cc19bb96b91904cc650512297df63b834aa42d28 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 25 Oct 2015 18:35:38 +0000 Subject: 36964: _git: Complete remotes branch names with slashes correctly. For example, 'git push remote HEAD:foo/bar' creates such branches. --- ChangeLog | 3 +++ Completion/Unix/Command/_git | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index c77e0a525..2e5b99cd3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-25 Daniel Shahaf + * 36964: Completion/Unix/Command/_git: _git: Complete remotes + branch names with slashes correctly. + * 36960: Completion/Unix/Command/_git: _git: Enable slash matcher for more branch and tag completions, include 'git branch ' and 'git tag '. diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index e5005f1c3..f22cddb3e 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5559,7 +5559,7 @@ __git_remote_branch_names_noprefix () { local expl declare -a heads - branch_names=(${${${(f)"$(_call_program remote-branch-refs-noprefix git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}##*/}:#HEAD}) + branch_names=(${${${${(f)"$(_call_program remote-branch-refs-noprefix git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}#refs/remotes/}#*/}:#HEAD}) __git_command_successful $pipestatus || return 1 _wanted remote-branch-names-noprefix expl 'remote branch name' compadd -M 'r:|/=**' "$@" -a - branch_names -- cgit v1.2.3 From 8b5158424637834f242bb1e2114dee4ac7cca328 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 25 Oct 2015 18:35:50 +0000 Subject: 36962: _git: Fix completion of RHS of refspecs. Before this patch, 'git push $remote :' completed branch names (as though by `git branch -a`), instead of completing remote branch names sans the ${remote}/ prefix. --- ChangeLog | 3 +++ Completion/Unix/Command/_git | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2e5b99cd3..e26e62e5f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-25 Daniel Shahaf + * 36962: Completion/Unix/Command/_git: _git: Fix completion of + RHS of refspecs. + * 36964: Completion/Unix/Command/_git: _git: Complete remotes branch names with slashes correctly. diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index f22cddb3e..320bfa712 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5313,7 +5313,8 @@ __git_remotes () { __git_ref_specs () { # TODO: This needs to deal with a lot more types of things. if compset -P '*:'; then - __git_heads + # TODO: have the caller supply the correct remote name, restrict to refs/remotes/${that_remote}/* only + __git_remote_branch_names_noprefix else compset -P '+' if compset -S ':*'; then -- cgit v1.2.3 From 11ca38c6d99192856d33254c504114d4ba8cd258 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 26 Oct 2015 10:00:54 +0000 Subject: users/20825: fix crash when complex completion hooks. get_undo_current_change() needs protecting against execution in completion environment. --- ChangeLog | 6 ++++++ Src/Zle/zle_utils.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/ChangeLog b/ChangeLog index e26e62e5f..b2291f5b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-10-26 Peter Stephenson + + * users/20825: Src/Zle/zle_utils.c: get_undo_current_change() + needs same protection as mkundoent() for execution within + completion. + 2015-10-25 Daniel Shahaf * 36962: Completion/Unix/Command/_git: _git: Fix completion of diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 714d911a6..ffff8fd1c 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -1739,9 +1739,26 @@ zlecallhook(char *name, char *arg) zlong get_undo_current_change(UNUSED(Param pm)) { + int remetafy; + + /* + * Yuk: we call this from within the completion system, + * so we need to convert back to the form which can be + * copied into undo entries. + */ + if (zlemetaline != NULL) { + unmetafy_line(); + remetafy = 1; + } else + remetafy = 0; + /* add entry for any pending changes */ mkundoent(); setlastline(); + + if (remetafy) + metafy_line(); + return undo_changeno; } -- cgit v1.2.3 From 8934007f25600150cee7e6eda2816c9110a9dc69 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Mon, 26 Oct 2015 07:19:01 -0700 Subject: 36956: revert 34451, mmap() is too slow on MacOS --- ChangeLog | 4 ++++ Src/mem.c | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index b2291f5b1..a55439df4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-10-26 Barton E. Schaefer + + * 36956: Src/mem.c: revert 34451, mmap() is too slow on MacOS + 2015-10-26 Peter Stephenson * users/20825: Src/Zle/zle_utils.c: get_undo_current_change() diff --git a/Src/mem.c b/Src/mem.c index 158ad9641..3138bb1d5 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -79,9 +79,16 @@ #include +#if 0 +/* + * This change was designed to enable use of memory mapping on MacOS. + * However, performance tests indicate that MacOS mapped regions are + * significantly slower to allocate than memory from malloc(). + */ #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) #define MAP_ANONYMOUS MAP_ANON #endif +#endif /* 0 */ #if defined(MAP_ANONYMOUS) && defined(MAP_PRIVATE) -- cgit v1.2.3 From 609273875d3fb911c20806aeb7c4d558e698a7f2 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Mon, 26 Oct 2015 07:25:51 -0700 Subject: 36968: use addmodulefd() to tell the shell about the descriptor of the dbm file --- ChangeLog | 3 +++ Src/Modules/db_gdbm.c | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index a55439df4..df70cbd45 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-26 Barton E. Schaefer + * 36968: Src/Modules/db_gdbm.c: use addmodulefd() to tell the + shell about the descriptor of the dbm file + * 36956: Src/mem.c: revert 34451, mmap() is too slow on MacOS 2015-10-26 Peter Stephenson diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c index 76d4751bf..032963262 100644 --- a/Src/Modules/db_gdbm.c +++ b/Src/Modules/db_gdbm.c @@ -106,7 +106,9 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func)) } dbf = gdbm_open(resource_name, 0, read_write, 0666, 0); - if(!dbf) { + if(dbf) + addmodulefd(gdbm_fdesc(dbf), FDT_INTERNAL); + else { zwarnnam(nam, "error opening database file %s", resource_name); return 1; } @@ -114,6 +116,7 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func)) if (!(tied_param = createspecialhash(pmname, &getgdbmnode, &scangdbmkeys, pmflags))) { zwarnnam(nam, "cannot create the requested parameter %s", pmname); + fdtable[gdbm_fdesc(dbf)] = FDT_UNUSED; gdbm_close(dbf); return 1; } @@ -319,8 +322,10 @@ gdbmuntie(Param pm) GDBM_FILE dbf = (GDBM_FILE)(pm->u.hash->tmpdata); HashTable ht = pm->u.hash; - if (dbf) /* paranoia */ + if (dbf) { /* paranoia */ + fdtable[gdbm_fdesc(dbf)] = FDT_UNUSED; gdbm_close(dbf); + } ht->tmpdata = NULL; -- cgit v1.2.3 From 81fa9fd25a57ebaf7e242bc678a6fd179bbdb718 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Mon, 26 Oct 2015 14:27:26 -0700 Subject: 36906: quite_signals() in ZSH_MEM realloc() --- ChangeLog | 3 +++ Src/mem.c | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index df70cbd45..bdd27871d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-26 Barton E. Schaefer + * 36906: Kamil Dudka : Src/mem.c: + quite_signals() in ZSH_MEM realloc() + * 36968: Src/Modules/db_gdbm.c: use addmodulefd() to tell the shell about the descriptor of the dbm file diff --git a/Src/mem.c b/Src/mem.c index 3138bb1d5..62d18d0cd 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -1668,8 +1668,13 @@ realloc(MALLOC_RET_T p, MALLOC_ARG_T size) int i, l = 0; /* some system..., see above */ - if (!p && size) - return (MALLOC_RET_T) malloc(size); + if (!p && size) { + queue_signals(); + r = malloc(size); + unqueue_signals(); + return (MALLOC_RET_T) r; + } + /* and some systems even do this... */ if (!p || !size) return (MALLOC_RET_T) p; -- cgit v1.2.3 From d45a68c5463224f43721371fb7bd4cbc24e62874 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 27 Oct 2015 09:28:36 +0000 Subject: 36974: fix some functions with empty argument lists --- ChangeLog | 6 ++++++ Src/Modules/zftp.c | 8 ++++---- Src/Zle/complist.c | 6 +++--- Src/Zle/computil.c | 4 ++-- Src/Zle/zle_thingy.c | 2 +- Src/parse.c | 2 +- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index bdd27871d..846b57ef7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-10-27 Peter Stephenson + + * 36974: Src/Modules/zftp.c, Src/Zle/complist.c, + Src/Zle/computil.c, Src/Zle/zle_thingy.c, Src/parse.c: fix empty + argument lists. + 2015-10-26 Barton E. Schaefer * 36906: Kamil Dudka : Src/mem.c: diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index bd51512f9..b4081df5f 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -409,7 +409,7 @@ zfalarm(int tmout) /**/ static void -zfpipe() +zfpipe(void) { /* Just ignore SIGPIPE and rely on getting EPIPE from the write. */ signal(SIGPIPE, SIG_IGN); @@ -450,7 +450,7 @@ zfunalarm(void) /**/ static void -zfunpipe() +zfunpipe(void) { if (sigtrapped[SIGPIPE]) { if (siglists[SIGPIPE] || (sigtrapped[SIGPIPE] & ZSIG_FUNC)) @@ -1298,7 +1298,7 @@ zfstarttrans(char *nam, int recv, off_t sz) /**/ static void -zfendtrans() +zfendtrans(void) { zfunsetparam("ZFTP_SIZE"); zfunsetparam("ZFTP_FILE"); @@ -2834,7 +2834,7 @@ newsession(char *nm) /* Save the existing session: this just means saving the parameters. */ static void -savesession() +savesession(void) { char **ps, **pd, *val; diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 986ad31ea..29aaee82a 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -499,7 +499,7 @@ filecol(char *col) */ static void -getcols() +getcols(void) { char *s; int i, l; @@ -602,7 +602,7 @@ zcoff(void) static void -initiscol() +initiscol(void) { int i; @@ -1909,7 +1909,7 @@ singlecalc(int *cp, int l, int *lcp) } static void -singledraw() +singledraw(void) { Cmgroup g; int mc1, mc2, ml1, ml2, md1, md2, mcc1, mcc2, lc1, lc2, t1, t2; diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index db8db88a6..60fb096be 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -185,7 +185,7 @@ cd_group(int maxg) * descriptions. */ static void -cd_calc() +cd_calc(void) { Cdset set; Cdstr str; @@ -236,7 +236,7 @@ cd_sort(const void *a, const void *b) } static int -cd_prep() +cd_prep(void) { Cdrun run, *runp; Cdset set; diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index c6ef8e6a0..271fd8efc 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -626,7 +626,7 @@ bin_zle_complete(char *name, char **args, UNUSED(Options ops), UNUSED(char func) /**/ static int -zle_usable() +zle_usable(void) { return zleactive && !incompctlfunc && !incompfunc #if 0 diff --git a/Src/parse.c b/Src/parse.c index a26df6f0a..83ba396b0 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -530,7 +530,7 @@ empty_eprog(Eprog p) } static void -clear_hdocs() +clear_hdocs(void) { struct heredocs *p, *n; -- cgit v1.2.3 From 63fd71f171e9d282985ba24e5f3ee2507bce6f47 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 27 Oct 2015 10:58:39 +0000 Subject: 36977: note about difficulties of pattern repetitions --- ChangeLog | 3 +++ Doc/Zsh/expn.yo | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/ChangeLog b/ChangeLog index 846b57ef7..b64f785f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-27 Peter Stephenson + * 36977: Doc/Zsh/expn.yo: note about complications of pattern + repetitions (#cN). + * 36974: Src/Modules/zftp.c, Src/Zle/complist.c, Src/Zle/computil.c, Src/Zle/zle_thingy.c, Src/parse.c: fix empty argument lists. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 5ea8610f2..49a0f0d53 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -2192,6 +2192,16 @@ inclusive. The form tt(LPAR()#c)var(N)tt(RPAR()) requires exactly tt(N) matches; tt(LPAR()#c,)var(M)tt(RPAR()) is equivalent to specifying var(N) as 0; tt(LPAR()#c)var(N)tt(,RPAR()) specifies that there is no maximum limit on the number of matches. + +Note that if the previous group of characters contains wildcards, +results can be unpredictable to the point of being logically incorrect. +It is recommended that the pattern be trimmed to match the minimum +possible. For example, to match a string of the form `tt(1_2_3_)', use +a pattern of the form `tt(LPAR()[[:digit:]]##_+RPAR()LPAR()#c3+RPAR())', not +`tt(LPAR()*_+RPAR()LPAR()#c3+RPAR())'. This arises from the +complicated interaction between attempts to match a number of +repetitions of the whole pattern and attempts to match the wildcard +`tt(*)'. ) vindex(MATCH) vindex(MBEGIN) -- cgit v1.2.3 From b498bd7ce5b8f126f420f8f9fd4946912f8334da Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 27 Oct 2015 11:54:19 +0000 Subject: 36982: Fix bug with (#cN) patterns and remove redundant description. We need to restore the current count of matches when returning to match at the point where we previously matched. --- ChangeLog | 4 ++++ Doc/Zsh/expn.yo | 10 ---------- Src/pattern.c | 1 + Test/D02glob.ztst | 8 ++++++++ Test/D04parameter.ztst | 9 +++++++++ 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index b64f785f7..cd8359281 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-10-27 Peter Stephenson + * 36982: Doc/Zsh/expn.yo, Src/pattern.c, Test/D02glob.ztst, + Test/D04parameter.ztst: fix actual bug with (#cN) and back off + previous change. + * 36977: Doc/Zsh/expn.yo: note about complications of pattern repetitions (#cN). diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 49a0f0d53..5ea8610f2 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -2192,16 +2192,6 @@ inclusive. The form tt(LPAR()#c)var(N)tt(RPAR()) requires exactly tt(N) matches; tt(LPAR()#c,)var(M)tt(RPAR()) is equivalent to specifying var(N) as 0; tt(LPAR()#c)var(N)tt(,RPAR()) specifies that there is no maximum limit on the number of matches. - -Note that if the previous group of characters contains wildcards, -results can be unpredictable to the point of being logically incorrect. -It is recommended that the pattern be trimmed to match the minimum -possible. For example, to match a string of the form `tt(1_2_3_)', use -a pattern of the form `tt(LPAR()[[:digit:]]##_+RPAR()LPAR()#c3+RPAR())', not -`tt(LPAR()*_+RPAR()LPAR()#c3+RPAR())'. This arises from the -complicated interaction between attempts to match a number of -repetitions of the whole pattern and attempts to match the wildcard -`tt(*)'. ) vindex(MATCH) vindex(MBEGIN) diff --git a/Src/pattern.c b/Src/pattern.c index 8b07cca92..9e8a80ae1 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -3376,6 +3376,7 @@ patmatch(Upat prog) scan[P_CT_CURRENT].l = cur + 1; if (patmatch(scan + P_CT_OPERAND)) return 1; + scan[P_CT_CURRENT].l = cur; patinput = patinput_thistime; } if (cur < min) diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst index 3e2095a0c..f944a4fbd 100644 --- a/Test/D02glob.ztst +++ b/Test/D02glob.ztst @@ -574,3 +574,11 @@ 0:Optimisation to squeeze multiple *'s used as ordinary glob wildcards. >glob.tmp/ra=1.0_et=3.5 >glob.tmp/ra=1.0_et=3.5 + + [[ 1_2_ = (*_)(#c1) ]] && print 1 OK # because * matches 1_2 + [[ 1_2_ = (*_)(#c2) ]] && print 2 OK + [[ 1_2_ = (*_)(#c3) ]] || print 3 OK +0:Some more complicated backtracking with match counts. +>1 OK +>2 OK +>3 OK diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index f1cc23e7c..cb7079c98 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1735,3 +1735,12 @@ 0:History modifier works the same for scalar and array substitution >ddd bdb cdc >ddd bdb cdc + + a=1_2_3_4_5_6 + print ${a#(*_)(#c2)} + print ${a#(*_)(#c5)} + print ${a#(*_)(#c7)} +0:Complicated backtracking with match counts +>3_4_5_6 +>6 +>1_2_3_4_5_6 -- cgit v1.2.3 From 0920bc6881af979ec538c8ab635c07f52601de4b Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Tue, 27 Oct 2015 08:48:47 -0700 Subject: unposted: fix typo quite -> queue --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index cd8359281..b10cf06ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,7 +14,7 @@ 2015-10-26 Barton E. Schaefer * 36906: Kamil Dudka : Src/mem.c: - quite_signals() in ZSH_MEM realloc() + queue_signals() in ZSH_MEM realloc() * 36968: Src/Modules/db_gdbm.c: use addmodulefd() to tell the shell about the descriptor of the dbm file -- cgit v1.2.3 From aba7c00698fdd459d2f17f84ed371413458afae5 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Tue, 27 Oct 2015 20:29:07 -0700 Subject: 36994: declare local REPLY for use with "zle .read-command"; use .self-insert instead of .self-insert-unmeta --- ChangeLog | 6 ++++++ Functions/Zle/bracketed-paste-magic | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index b10cf06ab..b5da1df4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-10-27 Barton E. Schaefer + + * 36994: Functions/Zle/bracketed-paste-magic: declare local REPLY + for use with "zle .read-command"; use .self-insert instead of + .self-insert-unmeta + 2015-10-27 Peter Stephenson * 36982: Doc/Zsh/expn.yo, Src/pattern.c, Test/D02glob.ztst, diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index 2368bc315..2b2bc630d 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -122,7 +122,7 @@ bracketed-paste-magic() { return else # Capture the pasted text in $PASTED - local PASTED + local PASTED REPLY zle .bracketed-paste PASTED fi @@ -170,14 +170,14 @@ bracketed-paste-magic() { while [[ -n $PASTED ]] && zle .read-command; do PASTED=${PASTED#$KEYS} if [[ $KEYS = ${(~j:|:)${(b)bpm_inactive}} ]]; then - zle .self-insert-unmeta + zle .self-insert else case $REPLY in (${~bpm_active}) function () { emulate -L $bpm_emulate; set -$bpm_opts zle $REPLY };; - (*) zle .self-insert-unmeta;; + (*) zle .self-insert;; esac fi done -- cgit v1.2.3 From 9640e9f497e8d78bf0bfa9defc4cfdeba1e7bfae Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Thu, 29 Oct 2015 01:03:18 +0900 Subject: 36983 + 36990: new completions for head and tail --- ChangeLog | 5 ++++ Completion/Unix/Command/_head | 45 ++++++++++++++++++++++++++++++ Completion/Unix/Command/_tail | 65 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 Completion/Unix/Command/_head create mode 100644 Completion/Unix/Command/_tail diff --git a/ChangeLog b/ChangeLog index b5da1df4e..0c38b2697 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-29 Jun-ichi Takimoto + + * 36983 (with fix from 36990): Completion/Unix/Command/_head, + Completion/Unix/Command/_tail: new completions for head and tail + 2015-10-27 Barton E. Schaefer * 36994: Functions/Zle/bracketed-paste-magic: declare local REPLY diff --git a/Completion/Unix/Command/_head b/Completion/Unix/Command/_head new file mode 100644 index 000000000..4f956acdc --- /dev/null +++ b/Completion/Unix/Command/_head @@ -0,0 +1,45 @@ +#compdef head + +local curcontext=$curcontext state state_descr line expl opts args ret=1 +typeset -A opt_args + +if _pick_variant gnu=GNU unix --version; then + args=( + '(-n --lines -c --bytes)'{-c+,--bytes=}'[print the first (or with -, all but the last) specified bytes]:number of bytes:->number' + '(-n --lines -c --bytes)'{-n+,--lines=}'[print the first (or with -, all but the last) specified lines]:number of lines:->number' + '(-q --quiet --silent -v --verbose)'{-q,--quiet,--silent}'[never print headers giving file names]' + '(-q --quiet --silent -v --verbose)'{-v,--verbose}'[always print headers giving file names]' + '(- *)--help[display help and exit]' + '(- *)--version[output version information and exit]' + ) +else + opts=(-A '-*') + args=( '(-c)-n+[display the first specified lines]:number of lines' ) + case $OSTYPE in + (freebsd*|darwin*|dragonfly*|netbsd*) + args+=( '(-n)-c+[display the first specified bytes]:number of bytes' ) + ;; + esac +fi + +_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 + ;; +esac + +return ret diff --git a/Completion/Unix/Command/_tail b/Completion/Unix/Command/_tail new file mode 100644 index 000000000..6e1445328 --- /dev/null +++ b/Completion/Unix/Command/_tail @@ -0,0 +1,65 @@ +#compdef tail + +local curcontext=$curcontext state state_descr line expl opts args ret=1 +typeset -A opt_args + +if _pick_variant gnu=GNU unix --version; then + args=( + '(-n --lines -c --bytes)'{-c+,--bytes=}'[print the last specified bytes; with +, start at the specified byte]:number of bytes:->number' + '(-n --lines -c --bytes)'{-n+,--lines=}'[print the last specified lines; with +, start at the specified line]:number of lines:->number' + '(-F -f)--follow=-[output appended data as the file grows]::how:(name descriptor)' + '(-F --follow)-f[same as --follow=descriptor]' + '(-f --follow --retry)-F[same as --follow=name --retry]' + '--max-unchanged-stats=[with --follow=name, check file rename after the specified number of iterations]:number of iterations' + '(-s --sleep-interval)'{-s+,--sleep-interval=}'[with -f, sleep the specfied seconds between iterations]:seconds' + '--pid=[with -f, terminate after the specified process dies]:pid:_pids' + '(-q --quiet --silent -v --verbose)'{-q,--quiet,--silent}'[never output headers giving file names]' + '(-q --quiet --silent -v --verbose)'{-v,--verbose}'[always output headers giving file names]' + '--retry[keep trying to open a file even when it becomes inaccessible]' + '(- *)--help[display help and exit]' + '(- *)--version[output version information and exit]' + ) +else + opts=(-A '-*') + args=( + '(-b -n)-c+[start at the specified byte]:bytes relative to the end (with +, beginning) of file' + '(-b -c)-n+[start at the specified line]:lines relative to the end (with +, beginning) of file' + '(-F -r)-f[wait for new data to be appended to the file]' + ) + case $OSTYPE in + (freebsd*|darwin*|dragonfly*|netbsd*|openbsd*) + args+=( + '(-f -F)-r[display the file in reverse order]' + '(-c -n)-b+[start at the specified block (512-byte)]:blocks relative to the end (with +, beginning) of file' + ) + ;| + (freebsd*|darwin*|dragonfly*|netbsd*) + args+=( '(-f -r)-F[implies -f, but also detect file rename]' ) + ;| + (freebsd*|darwin*|dragonfly*) + args+=( '-q[suppress the headers when displaying multiple files]' ) + ;; + esac +fi + +_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:((+\:"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 + ;; +esac + +return ret -- cgit v1.2.3 From 0628802baf5c9245138db82dd058cad023a7d0ae Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 29 Oct 2015 15:01:07 +0000 Subject: 37014: Improved internal parameter setting. Enhance WARNCREATEGLOBAL to work in many more cases. Don't create REPLY as an integer if it didn't previously exist as one, even if the value to be set is integral, as this is likely to mess up later uses of REPLY. --- ChangeLog | 11 +++++++++ Functions/MIME/zsh-mime-setup | 2 +- Functions/Misc/add-zsh-hook | 2 ++ Src/Modules/socket.c | 6 ++--- Src/Modules/tcp.c | 6 ++--- Src/Modules/zpty.c | 2 +- Src/builtin.c | 38 ++++++++++++++++++------------- Src/params.c | 53 +++++++++++++++++++++++++++++++++++++++++-- Src/zsh.h | 3 --- 9 files changed, 94 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0c38b2697..9454013cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2015-10-29 Peter Stephenson + + * 37014: Functions/MIME/zsh-mime-setup, + Functions/Misc/add-zsh-hook, Src/Modules/socket.c, + Src/Modules/tcp.c, Src/Modules/zpty.c, Src/builtin.c, + Src/params.c,Src/zsh.h: improved internal parameter setting. + Enhance WARNCREATEGLOBAL to work in many more cases. Don't + create REPLY as an integer if it didn't previously exist as one, + even if the value to be set is integral, as this is likely to + mess up later uses of REPLY. + 2015-10-29 Jun-ichi Takimoto * 36983 (with fix from 36990): Completion/Unix/Command/_head, diff --git a/Functions/MIME/zsh-mime-setup b/Functions/MIME/zsh-mime-setup index 23e44fdc0..35f6e6b6b 100644 --- a/Functions/MIME/zsh-mime-setup +++ b/Functions/MIME/zsh-mime-setup @@ -1,7 +1,7 @@ emulate -L zsh setopt extendedglob cbases -local opt o_verbose o_list +local opt o_verbose o_list i autoload -Uz zsh-mime-handler diff --git a/Functions/Misc/add-zsh-hook b/Functions/Misc/add-zsh-hook index ee37d674d..fc39659ae 100644 --- a/Functions/Misc/add-zsh-hook +++ b/Functions/Misc/add-zsh-hook @@ -82,9 +82,11 @@ if (( del )); then else if (( ${(P)+hook} )); then if (( ${${(P)hook}[(I)$fn]} == 0 )); then + typeset -ga $hook set -A $hook ${(P)hook} $fn fi else + typeset -ga $hook set -A $hook $fn fi autoload $autoopts -- $fn diff --git a/Src/Modules/socket.c b/Src/Modules/socket.c index f683496df..7c3fb5ebe 100644 --- a/Src/Modules/socket.c +++ b/Src/Modules/socket.c @@ -132,7 +132,7 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func)) /* allow to be closed explicitly */ fdtable[sfd] = FDT_EXTERNAL; - setiparam("REPLY", sfd); + setiparam_no_convert("REPLY", (zlong)sfd); if (verbose) printf("%s listener is on fd %d\n", soun.sun_path, sfd); @@ -220,7 +220,7 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func)) sfd = rfd; } - setiparam("REPLY", sfd); + setiparam_no_convert("REPLY", (zlong)sfd); if (verbose) printf("new connection from %s is on fd %d\n", soun.sun_path, sfd); @@ -261,7 +261,7 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func)) fdtable[sfd] = FDT_EXTERNAL; } - setiparam("REPLY", sfd); + setiparam_no_convert("REPLY", (zlong)sfd); if (verbose) printf("%s is now on fd %d\n", soun.sun_path, sfd); diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c index 7b0dcc74a..9fc1b29a2 100644 --- a/Src/Modules/tcp.c +++ b/Src/Modules/tcp.c @@ -461,7 +461,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) return 1; } - setiparam("REPLY", sess->fd); + setiparam_no_convert("REPLY", (zlong)sess->fd); if (verbose) printf("%d listener is on fd %d\n", ntohs(sess->sock.in.sin_port), sess->fd); @@ -562,7 +562,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) sess->fd = rfd; } - setiparam("REPLY", sess->fd); + setiparam_no_convert("REPLY", (zlong)sess->fd); if (verbose) printf("%d is on fd %d\n", ntohs(sess->peer.in.sin_port), sess->fd); @@ -681,7 +681,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func)) } } - setiparam("REPLY", sess->fd); + setiparam_no_convert("REPLY", (zlong)sess->fd); if (verbose) printf("%s:%d is now on fd %d\n", diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c index 9741ee287..3b8366076 100644 --- a/Src/Modules/zpty.c +++ b/Src/Modules/zpty.c @@ -464,7 +464,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock) #endif errno == EINTR)); - setiparam("REPLY", master); + setiparam_no_convert("REPLY", (zlong)master); return 0; } diff --git a/Src/builtin.c b/Src/builtin.c index 97022addf..8045bc8f7 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -2090,7 +2090,9 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), tc = 0; /* but don't do a normal conversion */ } } else if (!setsecondstype(pm, on, off)) { - if (asg->value.scalar && !(pm = setsparam(pname, ztrdup(asg->value.scalar)))) + if (asg->value.scalar && + !(pm = assignsparam( + pname, ztrdup(asg->value.scalar), 0))) return NULL; usepm = 1; err = 0; @@ -2202,12 +2204,13 @@ 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 (asg->value.scalar && !(pm = setsparam(pname, ztrdup(asg->value.scalar)))) + if (asg->value.scalar && + !(pm = assignsparam(pname, ztrdup(asg->value.scalar), 0))) return NULL; } else if (asg->is_array) { - if (!(pm = setaparam(pname, asg->value.array ? + if (!(pm = assignaparam(pname, asg->value.array ? zlinklist2array(asg->value.array) : - mkarray(NULL)))) + mkarray(NULL), 0))) return NULL; } pm->node.flags |= (on & PM_READONLY); @@ -2347,16 +2350,18 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), * creating a stray parameter along the way via createparam(), * now called below in the isident() branch. */ - if (!(pm = setsparam(pname, ztrdup(asg->value.scalar ? asg->value.scalar : "")))) + if (!(pm = assignsparam( + pname, + ztrdup(asg->value.scalar ? asg->value.scalar : ""), 0))) return NULL; dont_set = 1; asg->is_array = 0; keeplocal = 0; on = pm->node.flags; } else if (PM_TYPE(on) == PM_ARRAY && ASG_ARRAYP(asg)) { - if (!(pm = setaparam(pname, asg->value.array ? - zlinklist2array(asg->value.array) : - mkarray(NULL)))) + if (!(pm = assignaparam(pname, asg->value.array ? + zlinklist2array(asg->value.array) : + mkarray(NULL), 0))) return NULL; dont_set = 1; keeplocal = 0; @@ -2433,13 +2438,13 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), Param ipm = pm; if (pm->node.flags & (PM_ARRAY|PM_HASHED)) { DPUTS(!ASG_ARRAYP(asg), "BUG: inconsistent scalar value for array"); - if (!(pm=setaparam(pname, asg->value.array ? - zlinklist2array(asg->value.array) : - mkarray(NULL)))) + if (!(pm=assignaparam(pname, asg->value.array ? + zlinklist2array(asg->value.array) : + mkarray(NULL), 0))) return NULL; } else { DPUTS(ASG_ARRAYP(asg), "BUG: inconsistent array value for scalar"); - if (!(pm = setsparam(pname, ztrdup(asg->value.scalar)))) + if (!(pm = assignsparam(pname, ztrdup(asg->value.scalar), 0))) return NULL; } if (pm != ipm) { @@ -2687,9 +2692,10 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) /* Update join character */ tdp->joinchar = joinchar; if (asg0.value.scalar) - setsparam(asg0.name, ztrdup(asg0.value.scalar)); + assignsparam(asg0.name, ztrdup(asg0.value.scalar), 0); else if (asg->value.array) - setaparam(asg->name, zlinklist2array(asg->value.array)); + assignaparam( + asg->name, zlinklist2array(asg->value.array), 0); return 0; } else { zwarnnam(name, "can't tie already tied scalar: %s", @@ -2750,9 +2756,9 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) zsfree(apm->ename); apm->ename = ztrdup(asg0.name); if (asg->value.array) - setaparam(asg->name, zlinklist2array(asg->value.array)); + assignaparam(asg->name, zlinklist2array(asg->value.array), 0); else if (oldval) - setsparam(asg0.name, oldval); + assignsparam(asg0.name, oldval, 0); unqueue_signals(); return 0; diff --git a/Src/params.c b/Src/params.c index a8abb289e..4d33660fb 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2826,6 +2826,15 @@ assignsparam(char *s, char *val, int flags) return v->pm; } +/**/ +mod_export Param +setsparam(char *s, char *val) +{ + return assignsparam( + s, val, isset(WARNCREATEGLOBAL) && locallevel > 0 ? + ASSPM_WARN_CREATE : 0); +} + /**/ mod_export Param assignaparam(char *s, char **val, int flags) @@ -2914,6 +2923,16 @@ assignaparam(char *s, char **val, int flags) return v->pm; } + +/**/ +mod_export Param +setaparam(char *s, char **aval) +{ + return assignaparam( + s, aval, isset(WARNCREATEGLOBAL) && locallevel >0 ? + ASSPM_WARN_CREATE : 0); +} + /**/ mod_export Param sethparam(char *s, char **val) @@ -2937,11 +2956,15 @@ sethparam(char *s, char **val) if (unset(EXECOPT)) return NULL; queue_signals(); - if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING))) + if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING))) { createparam(t, PM_HASHED); - else if (!(PM_TYPE(v->pm->node.flags) & PM_HASHED) && + if (isset(WARNCREATEGLOBAL) && locallevel > 0 && v->pm->level == 0) + zwarn("associative array parameter %s created globally in function", + v->pm->node.nam); + } else if (!(PM_TYPE(v->pm->node.flags) & PM_HASHED) && !(v->pm->node.flags & PM_SPECIAL)) { unsetparam(t); + /* no WARNCREATEGLOBAL check here as parameter already existed */ createparam(t, PM_HASHED); v = NULL; } @@ -2968,6 +2991,7 @@ setnparam(char *s, mnumber val) Value v; char *t = s, *ss; Param pm; + int was_unset = 0; if (!isident(s)) { zerr("not an identifier: %s", s); @@ -2987,6 +3011,7 @@ setnparam(char *s, mnumber val) */ unset(KSHARRAYS) && !ss) { unsetparam_pm(v->pm, 0, 1); + was_unset = 1; s = t; v = NULL; } @@ -3007,6 +3032,10 @@ setnparam(char *s, mnumber val) } v = getvalue(&vbuf, &t, 1); DPUTS(!v, "BUG: value not found for new parameter"); + if (!was_unset && isset(WARNCREATEGLOBAL) && locallevel > 0 && + v->pm->level == 0) + zwarn("numeric parameter %s created globally in function", + v->pm->node.nam); } setnumvalue(v, val); unqueue_signals(); @@ -3025,6 +3054,26 @@ setiparam(char *s, zlong val) return setnparam(s, mnval); } +/* + * Set an integer parameter without forcing creation of an integer type. + * This is useful if the integer is going to be set to a parmaeter which + * would usually be scalar but may not exist. + */ + +/**/ +mod_export Param +setiparam_no_convert(char *s, zlong val) +{ + /* + * If the target is already an integer, thisgets converted + * back. Low technology rules. + */ + char buf[BDIGBUFSIZE]; + convbase(buf, val, 10); + return assignsparam( + s, ztrdup(buf), + isset(WARNCREATEGLOBAL) && locallevel > 0 ? ASSPM_WARN_CREATE : 0); +} /* Unset a parameter */ diff --git a/Src/zsh.h b/Src/zsh.h index f819249c3..d03d171e4 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1939,9 +1939,6 @@ struct paramdef { { name, flags | PM_SPECIAL | PM_HIDE | PM_HIDEVAL, \ NULL, gsufn, getfn, scanfn, NULL } -#define setsparam(S,V) assignsparam(S,V,0) -#define setaparam(S,V) assignaparam(S,V,0) - /* * Flags for assignsparam and assignaparam. */ -- cgit v1.2.3 From 053f01ee485cc0a07397c7b1484dbca00467b400 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 29 Oct 2015 15:01:53 +0000 Subject: unposted: ignore .orig files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 08f90a29e..c0b7964ad 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ tags TAGS *.o *.o.c +*.orig *.a *.so *.dll -- cgit v1.2.3 From 300a58f5935631cad660ed238315e68bb86fca8c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 29 Oct 2015 16:52:21 +0000 Subject: missed ChangeLog entry --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9454013cb..b45d5b59e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-10-29 Peter Stephenson + * unposted: .giignore: ignore .orig files. + * 37014: Functions/MIME/zsh-mime-setup, Functions/Misc/add-zsh-hook, Src/Modules/socket.c, Src/Modules/tcp.c, Src/Modules/zpty.c, Src/builtin.c, -- cgit v1.2.3 From de9effbce601db7ad7f7f0d0969b70b920b4e371 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 29 Oct 2015 17:06:27 +0000 Subject: 37018: Make WARNCREATEGLOBAL more consistent. Wd don't need separate math handling any more, and can make it output the function name in all cases. --- ChangeLog | 3 +++ Src/math.c | 26 -------------------------- Src/params.c | 52 +++++++++++++++++++++++++++++++++++++++------------- Test/E01options.ztst | 6 +++--- 4 files changed, 45 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index b45d5b59e..ba9113487 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-10-29 Peter Stephenson + * 37018: Src/math.c, Src/params.c, Test/E01options.ztst: make + WARNCREATEGLOBAL consistent in all cases, outputting file name. + * unposted: .giignore: ignore .orig files. * 37014: Functions/MIME/zsh-mime-setup, diff --git a/Src/math.c b/Src/math.c index eee21e146..37981cf22 100644 --- a/Src/math.c +++ b/Src/math.c @@ -893,25 +893,6 @@ getcvar(char *s) return mn; } - -/* If script execution is inside a function call that hasn't returned, - * return the name of that function. Else return NULL. - */ - -/**/ -static const char * -in_function_call(void) -{ - Funcstack i; - for (i = funcstack; i; i = i->prev) - if (i->tp == FS_FUNC) { - DPUTS(!i->name, "funcstack entry with no name"); - return i->name; - } - - return NULL; -} - /**/ static mnumber setmathvar(struct mathvalue *mvp, mnumber v) @@ -947,13 +928,6 @@ setmathvar(struct mathvalue *mvp, mnumber v) if (noeval) return v; untokenize(mvp->lval); - if (isset(WARNCREATEGLOBAL)) { - const char *function_name; - if (!paramtab->getnode(paramtab, mvp->lval) && - (function_name = in_function_call())) - zwarn("math parameter %s created globally in function %s", - mvp->lval, function_name); - } pm = setnparam(mvp->lval, v); if (pm) { /* diff --git a/Src/params.c b/Src/params.c index 4d33660fb..5058695bb 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2694,6 +2694,37 @@ gethkparam(char *s) return NULL; } +/**/ +static void +check_warn_create(Param pm, const char *pmtype) +{ + Funcstack i; + const char *name; + + if (pm->level != 0) + return; + + name = NULL; + for (i = funcstack; i; i = i->prev) { + if (i->tp == FS_FUNC) { + DPUTS(!i->name, "funcstack entry with no name"); + name = i->name; + break; + } + } + + if (name) + { + zwarn("%s parameter %s created globally in function %s", + pmtype, pm->node.nam, name); + } + else + { + zwarn("%s parameter %s created globally in function", + pmtype, pm->node.nam); + } +} + /**/ mod_export Param assignsparam(char *s, char *val, int flags) @@ -2747,9 +2778,8 @@ assignsparam(char *s, char *val, int flags) zsfree(val); return NULL; } - if ((flags & ASSPM_WARN_CREATE) && v->pm->level == 0) - zwarn("scalar parameter %s created globally in function", - v->pm->node.nam); + if (flags & ASSPM_WARN_CREATE) + check_warn_create(v->pm, "scalar"); if (flags & ASSPM_AUGMENT) { if (v->start == 0 && v->end == -1) { switch (PM_TYPE(v->pm->node.flags)) { @@ -2898,9 +2928,8 @@ assignaparam(char *s, char **val, int flags) return NULL; } - if ((flags & ASSPM_WARN_CREATE) && v->pm->level == 0) - zwarn("array parameter %s created globally in function", - v->pm->node.nam); + if (flags & ASSPM_WARN_CREATE) + check_warn_create(v->pm, "array"); if (flags & ASSPM_AUGMENT) { if (v->start == 0 && v->end == -1) { if (PM_TYPE(v->pm->node.flags) & PM_ARRAY) { @@ -2958,9 +2987,8 @@ sethparam(char *s, char **val) queue_signals(); if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING))) { createparam(t, PM_HASHED); - if (isset(WARNCREATEGLOBAL) && locallevel > 0 && v->pm->level == 0) - zwarn("associative array parameter %s created globally in function", - v->pm->node.nam); + if (isset(WARNCREATEGLOBAL) && locallevel > 0) + check_warn_create(v->pm, "associative array"); } else if (!(PM_TYPE(v->pm->node.flags) & PM_HASHED) && !(v->pm->node.flags & PM_SPECIAL)) { unsetparam(t); @@ -3032,10 +3060,8 @@ setnparam(char *s, mnumber val) } v = getvalue(&vbuf, &t, 1); DPUTS(!v, "BUG: value not found for new parameter"); - if (!was_unset && isset(WARNCREATEGLOBAL) && locallevel > 0 && - v->pm->level == 0) - zwarn("numeric parameter %s created globally in function", - v->pm->node.nam); + if (!was_unset && isset(WARNCREATEGLOBAL) && locallevel > 0) + check_warn_create(v->pm, "numeric parameter"); } setnumvalue(v, val); unqueue_signals(); diff --git a/Test/E01options.ztst b/Test/E01options.ztst index 1caee8d24..15468e888 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -1116,9 +1116,9 @@ } fn 0:WARN_CREATE_GLOBAL option -?fn:3: scalar parameter foo1 created globally in function -?fn:5: scalar parameter foo1 created globally in function -?fn:15: math parameter foo5 created globally in function fn +?fn:3: scalar parameter foo1 created globally in function fn +?fn:5: scalar parameter foo1 created globally in function fn +?fn:15: numeric parameter parameter foo5 created globally in function fn # This really just tests if XTRACE is egregiously broken. # To test it properly would need a full set of its own. -- cgit v1.2.3 From 58f4cccb1fbd66b7645178af971cb317cf1a2d7a Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 30 Oct 2015 12:28:07 +0000 Subject: 37022: add GLOB_STAR_SHORT option to abbreviate ** and *** --- ChangeLog | 6 ++++++ Doc/Zsh/expn.yo | 12 ++++++++++++ Doc/Zsh/options.yo | 15 +++++++++++++++ Src/glob.c | 43 +++++++++++++++++++++++++------------------ Src/options.c | 1 + Src/zsh.h | 1 + 6 files changed, 60 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index ba9113487..0ef6fe6ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-10-30 Peter Stephenson + + * 37022: Doc/Zsh/expn.yo, Doc/Zsh/options.yo, Src/glob.c, + Src/options.c, Src/zsh.h: add GLOB_STAR_SHORT option to + allow shorthand ** for **/* and *** for ***/*. + 2015-10-29 Peter Stephenson * 37018: Src/math.c, Src/params.c, Test/E01options.ztst: make diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 5ea8610f2..20e0c8d35 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -2381,6 +2381,18 @@ follow symbolic links; the alternative form `tt(***/)' does, but is otherwise identical. Neither of these can be combined with other forms of globbing within the same path segment; in that case, the `tt(*)' operators revert to their usual effect. + +Even shorter forms are available when the option tt(GLOB_STAR_SHORT) is +set. In that case if no tt(/) immediately follows a tt(**) or tt(***) +they are treated as if both a tt(/) plus a further tt(*) are present. +Hence: + +example(setopt GLOBSTARSHORT +ls **.c) + +is equivalent to + +example(ls **/*.c) subsect(Glob Qualifiers) cindex(globbing, qualifiers) cindex(qualifiers, globbing) diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index fbf65abbc..60379cabc 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -534,6 +534,21 @@ cindex(globbing, of . files) item(tt(GLOB_DOTS) (tt(-4)))( Do not require a leading `tt(.)' in a filename to be matched explicitly. ) +pindex(GLOB_STAR_SHORT) +pindex(NO_GLOB_STAR_SHORT) +pindex(GLOBSTARSHORT) +pindex(NOGLOBSTARSHORT) +cindex(globbing, short forms) +cindex(globbing, ** special) +item(tt(GLOB_STAR_SHORT))( +When this option is set and the default zsh-style globbing is in +effect, the pattern `tt(**/*)' can be abbreviated to `tt(**)' and the +pattern `tt(***/*)' can be abbreviated to tt(***). Hence `tt(**.c)' +finds a file ending in tt(.c) in any subdirectory, and `tt(***.c)' does +the same while also following symbolic links. A tt(/) immediately +after the `tt(**)' or `tt(***)' forces the pattern to be treated as the +unabbreviated form. +) pindex(GLOB_SUBST) pindex(NO_GLOB_SUBST) pindex(GLOBSUBST) diff --git a/Src/glob.c b/Src/glob.c index 24e60d0c5..51ffeb5d5 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -682,25 +682,32 @@ parsecomplist(char *instr) char *str; int compflags = gf_noglobdots ? (PAT_FILE|PAT_NOGLD) : PAT_FILE; - if (instr[0] == Star && instr[1] == Star && - (instr[2] == '/' || (instr[2] == Star && instr[3] == '/'))) { - /* Match any number of directories. */ - int follow; - - /* with three stars, follow symbolic links */ - follow = (instr[2] == Star); - instr += (3 + follow); - - /* Now get the next path component if there is one. */ - l1 = (Complist) zhalloc(sizeof *l1); - if ((l1->next = parsecomplist(instr)) == NULL) { - errflag |= ERRFLAG_ERROR; - return NULL; + if (instr[0] == Star && instr[1] == Star) { + int shortglob = 0; + if (instr[2] == '/' || (instr[2] == Star && instr[3] == '/') + || (shortglob = isset(GLOBSTARSHORT))) { + /* Match any number of directories. */ + int follow; + + /* with three stars, follow symbolic links */ + follow = (instr[2] == Star); + /* + * With GLOBSTARSHORT, leave a star in place for the + * pattern inside the directory. + */ + instr += ((shortglob ? 1 : 3) + follow); + + /* Now get the next path component if there is one. */ + l1 = (Complist) zhalloc(sizeof *l1); + if ((l1->next = parsecomplist(instr)) == NULL) { + errflag |= ERRFLAG_ERROR; + return NULL; + } + l1->pat = patcompile(NULL, compflags | PAT_ANY, NULL); + l1->closure = 1; /* ...zero or more times. */ + l1->follow = follow; + return l1; } - l1->pat = patcompile(NULL, compflags | PAT_ANY, NULL); - l1->closure = 1; /* ...zero or more times. */ - l1->follow = follow; - return l1; } /* Parse repeated directories such as (dir/)# and (dir/)## */ diff --git a/Src/options.c b/Src/options.c index 1fb102f1d..3bf9f39a4 100644 --- a/Src/options.c +++ b/Src/options.c @@ -140,6 +140,7 @@ static struct optname optns[] = { {{NULL, "globassign", OPT_EMULATE|OPT_CSH}, GLOBASSIGN}, {{NULL, "globcomplete", 0}, GLOBCOMPLETE}, {{NULL, "globdots", OPT_EMULATE}, GLOBDOTS}, +{{NULL, "globstarshort", OPT_EMULATE}, GLOBSTARSHORT}, {{NULL, "globsubst", OPT_EMULATE|OPT_NONZSH}, GLOBSUBST}, {{NULL, "hashcmds", OPT_ALL}, HASHCMDS}, {{NULL, "hashdirs", OPT_ALL}, HASHDIRS}, diff --git a/Src/zsh.h b/Src/zsh.h index d03d171e4..a6f039741 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2215,6 +2215,7 @@ enum { GLOBASSIGN, GLOBCOMPLETE, GLOBDOTS, + GLOBSTARSHORT, GLOBSUBST, HASHCMDS, HASHDIRS, -- cgit v1.2.3 From 51d50218fb04229ead75d5f472bc86c26936afe4 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 30 Oct 2015 15:02:22 +0000 Subject: unposted (after 37018): Fix typo in error message. --- ChangeLog | 5 +++++ Src/params.c | 2 +- Test/E01options.ztst | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0ef6fe6ee..4c9b8dca6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-30 Daniel Shahaf + + * unposted (after 37018): Src/params.c, Test/E01options.ztst: Fix + typo in error message. + 2015-10-30 Peter Stephenson * 37022: Doc/Zsh/expn.yo, Doc/Zsh/options.yo, Src/glob.c, diff --git a/Src/params.c b/Src/params.c index 5058695bb..de456c144 100644 --- a/Src/params.c +++ b/Src/params.c @@ -3061,7 +3061,7 @@ setnparam(char *s, mnumber val) v = getvalue(&vbuf, &t, 1); DPUTS(!v, "BUG: value not found for new parameter"); if (!was_unset && isset(WARNCREATEGLOBAL) && locallevel > 0) - check_warn_create(v->pm, "numeric parameter"); + check_warn_create(v->pm, "numeric"); } setnumvalue(v, val); unqueue_signals(); diff --git a/Test/E01options.ztst b/Test/E01options.ztst index 15468e888..c9427c755 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -1118,7 +1118,7 @@ 0:WARN_CREATE_GLOBAL option ?fn:3: scalar parameter foo1 created globally in function fn ?fn:5: scalar parameter foo1 created globally in function fn -?fn:15: numeric parameter parameter foo5 created globally in function fn +?fn:15: numeric parameter foo5 created globally in function fn # This really just tests if XTRACE is egregiously broken. # To test it properly would need a full set of its own. -- cgit v1.2.3 From 26614ad0e05d99e974742276b710a4afff79e8b2 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 30 Oct 2015 15:03:51 +0000 Subject: unposted: Typo in ChangeLog --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4c9b8dca6..d29e1e4c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,7 +14,7 @@ * 37018: Src/math.c, Src/params.c, Test/E01options.ztst: make WARNCREATEGLOBAL consistent in all cases, outputting file name. - * unposted: .giignore: ignore .orig files. + * unposted: .gitignore: ignore .orig files. * 37014: Functions/MIME/zsh-mime-setup, Functions/Misc/add-zsh-hook, Src/Modules/socket.c, -- cgit v1.2.3 From 1eef57b3d15af235430ad2b5e2940ded375e69d2 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 30 Oct 2015 16:59:04 +0000 Subject: 37027: allow subword context to discriminate between words --- ChangeLog | 3 +++ Doc/Zsh/contrib.yo | 7 ++++--- Functions/Zle/match-word-context | 9 +++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index d29e1e4c0..ed5cd5e6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,9 @@ 2015-10-30 Peter Stephenson + * 37027: Doc/Zsh/contrib.yo, Functions/Zle/match-word-context: + add editing word context to allow detecting being between words. + * 37022: Doc/Zsh/expn.yo, Doc/Zsh/options.yo, Src/glob.c, Src/options.c, Src/zsh.h: add GLOB_STAR_SHORT option to allow shorthand ** for **/* and *** for ***/*. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index cb68952a4..f74f7d709 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2016,9 +2016,10 @@ matched against each var(pattern) in turn until one matches; if it does, the context is extended by a colon and the corresponding var(subcontext). Note that the test is made against the original word on the line, with no stripping of quotes. Special handling is done between words: the current -context is examined and if it contains the string tt(back), the word before -the cursor is considered, else the word after cursor is considered. Some -examples are given below. +context is examined and if it contains the string tt(between) the word +is set to a single space; else if it is contains the string tt(back), +the word before the cursor is considered, else the word after cursor is +considered. Some examples are given below. The style tt(skip-whitespace-first) is only used with the tt(forward-word) widget. If it is set to true, then tt(forward-word) diff --git a/Functions/Zle/match-word-context b/Functions/Zle/match-word-context index 7f1154498..8793483f4 100644 --- a/Functions/Zle/match-word-context +++ b/Functions/Zle/match-word-context @@ -7,7 +7,7 @@ setopt extendedglob local -a worcon bufwords local pat tag lastword word backword forword -integer iword +integer iword between zstyle -a $curcontext word-context worcon || return 0 @@ -25,13 +25,18 @@ if [[ $lastword = ${bufwords[iword]} ]]; then # If the word immediately left of the cursor is complete, # we're not on it for forward operations. forword=${bufwords[iword+1]} + # If, furthermore, we're on whitespace, then we're between words. + # It can't be significant whitespace because the previous word is complete. + [[ $RBUFFER[1] = [[:space:]] ]] && between=1 else # We're on a word. forword=${bufwords[iword]} fi backword=${bufwords[iword]} -if [[ $curcontext = *back* ]]; then +if [[ between -ne 0 && $curcontext = *between* ]]; then + word=' ' +elif [[ $curcontext = *back* ]]; then word=$backword else word=$forword -- cgit v1.2.3 From 0e510f0c3522c9b18e9320388dd232a84fa79351 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 31 Oct 2015 12:54:56 +0000 Subject: 37032: Temporarily revert 36959. --- ChangeLog | 4 ++++ Completion/Unix/Command/_git | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ed5cd5e6b..499c871e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-10-31 Daniel Shahaf + + * 37032: Completion/Unix/Command/_git: Temporarily revert 36959. + 2015-10-30 Daniel Shahaf * unposted (after 37018): Src/params.c, Test/E01options.ztst: Fix diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 320bfa712..df7a7d900 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5696,7 +5696,10 @@ __git_recent_commits () { else label="[HEAD~$distance_from_head]" fi - descr+=("@~${distance_from_head}":"${label} $k") # CROSSREF: use the same label as below + ## Disabled because _describe renders the output unhelpfuly when this function + ## is called twice during a single completion operation, and list-grouped is + ## in its default setting (enabled). + #descr+=("@~${distance_from_head}":"${label} $k") # CROSSREF: use the same label as below # Prepare for the next first-parent-ancestry commit. (( ++distance_from_head )) -- cgit v1.2.3 From 682e779a211fdfa0baa41c06d821f0ea9acf4941 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 31 Oct 2015 09:54:04 -0700 Subject: unposted (cf. 36998,36999): undo 36956 / restore 34451 with expanded comment about the flip-flopping --- ChangeLog | 5 +++++ Completion/Unix/Command/_qemu | 4 ++-- Src/mem.c | 7 +++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 499c871e4..a35b6056f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-31 Barton E. Schaefer + + * unposted (cf. 36998,36999): Src/mem.c: undo 36956 / restore 34451 + with expanded comment about the flip-flopping + 2015-10-31 Daniel Shahaf * 37032: Completion/Unix/Command/_git: Temporarily revert 36959. diff --git a/Completion/Unix/Command/_qemu b/Completion/Unix/Command/_qemu index db07eba33..3c21c3e74 100644 --- a/Completion/Unix/Command/_qemu +++ b/Completion/Unix/Command/_qemu @@ -2,7 +2,7 @@ _qemu_log_items () { local -a opts hline - $service -d \? | while read -A hline; do + $service -d \? 2>/dev/null | while read -A hline; do [[ $hline[1] = Log ]] && continue opts=($opts "${hline[1]}[${hline[2,-1]}]") done @@ -11,7 +11,7 @@ _qemu_log_items () { local _qemu_machines -_qemu_machines=(${${${(f)"$($service -M \?)"}[2,-1]}%% *}) +_qemu_machines=(${${${(f)"$($service -M \? 2>/dev/null)"}[2,-1]}%% *}) _arguments \ '-'{fda,fdb,hda,hdb,hdc,hdd,cdrom}':disk image:_files' \ diff --git a/Src/mem.c b/Src/mem.c index 62d18d0cd..e31145e1e 100644 --- a/Src/mem.c +++ b/Src/mem.c @@ -79,16 +79,15 @@ #include -#if 0 /* - * This change was designed to enable use of memory mapping on MacOS. + * This definition is designed to enable use of memory mapping on MacOS. * However, performance tests indicate that MacOS mapped regions are - * significantly slower to allocate than memory from malloc(). + * somewhat slower to allocate than memory from malloc(), so whether + * using this improves performance depends on details of zhalloc(). */ #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) #define MAP_ANONYMOUS MAP_ANON #endif -#endif /* 0 */ #if defined(MAP_ANONYMOUS) && defined(MAP_PRIVATE) -- cgit v1.2.3 From 607a7a85b65527fb98e1a47c02dca6a777595eec Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Sat, 31 Oct 2015 19:06:47 +0100 Subject: 36993: zed: fix argument parsing --- ChangeLog | 4 ++++ Functions/Misc/zed | 31 ++++++++++--------------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index a35b6056f..9068f13a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-10-31 Oliver Kiddle + + * 36993: Eric Cook: Functions/Misc/zed: fix argument parsing + 2015-10-31 Barton E. Schaefer * unposted (cf. 36998,36999): Src/mem.c: undo 36956 / restore 34451 diff --git a/Functions/Misc/zed b/Functions/Misc/zed index 010b69bee..94dd9ce5b 100644 --- a/Functions/Misc/zed +++ b/Functions/Misc/zed @@ -6,31 +6,20 @@ # Use ^X^W to save, ^C to abort. # Option -f: edit shell functions. (Also if called as fned.) -local var opt zed_file_name +local var opts zed_file_name # We do not want timeout while we are editing a file integer TMOUT=0 okargs=1 fun bind local -a expand -while getopts "fbx:" opt; do - case $opt in - (f) - fun=1 - ;; - - (b) - bind=1 - ;; - - (x) - if [[ $OPTARG != <-> ]]; then - print -r "Integer expected after -x: $OPTARG" >&2 - return 1 - fi - expand=(-x $OPTARG) - ;; - esac -done -shift $(( OPTIND - 1 )) +zparseopts -D -A opts f b x: +fun=$+opts[-f] +bind=$+opts[-b] +if [[ $opts[-x] == <-> ]]; then + expand=(-x $opts[-x]) +elif (( $+opts[-x] )); then + print -r "Integer expected after -x: $opts[-x]" >&2 + return 1 +fi [[ $0 = fned ]] && fun=1 (( bind )) && okargs=0 -- cgit v1.2.3 From 098319df9922441ca70c233195151cb1965556a8 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Sat, 31 Oct 2015 19:10:27 +0100 Subject: 37028: new scl completion --- ChangeLog | 2 ++ Completion/Redhat/Command/_scl | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 Completion/Redhat/Command/_scl diff --git a/ChangeLog b/ChangeLog index 9068f13a0..86510979c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-10-31 Oliver Kiddle + * 37028: Completion/Redhat/Command/_scl: new completion + * 36993: Eric Cook: Functions/Misc/zed: fix argument parsing 2015-10-31 Barton E. Schaefer diff --git a/Completion/Redhat/Command/_scl b/Completion/Redhat/Command/_scl new file mode 100644 index 000000000..e1a4b69db --- /dev/null +++ b/Completion/Redhat/Command/_scl @@ -0,0 +1,38 @@ +#compdef scl + +local curcontext="$curcontext" dashes ret=1 +local -a state line force alts cmd + +[[ $words[2] = deregister ]] && + force=( '--force[deregister even SCL installed as packages]' ) + +_arguments -C $force \ + '(- 1)'{-l,--list}'[list installed software collections or packages within a collection]' \ + '(-l --list)1:action:(enable register deregister)' \ + '(-)*:collections:->collections' && ret=0 + +if [[ -n $state ]]; then + (( $#line > 1 )) && curcontext="${curcontext%:*}-$line[1]:" + if [[ $line[1] = register ]]; then + _directories -P / -W / + return + fi + if (( ${dashes:=$words[(I)--]} )); then + shift dashes words + (( CURRENT -= dashes )) + _normal + return + fi + if [[ $CURRENT -gt 3 && $words[CURRENT] = - ]]; then + compadd - -- + return + fi + [[ $line[1] = enable && $CURRENT -gt 3 ]] && + cmd='command:command:_cmdstring' + + _alternative 'collections:collection:compadd + $(_call_program collections ${words[1]} -l)' \ + $cmd && ret=0 +fi + +return ret -- cgit v1.2.3 From fa59375e36e1718e060048ba7efd7346b3c8e94a Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Sat, 31 Oct 2015 19:14:36 +0100 Subject: 37029: update options and new tr completion --- ChangeLog | 4 ++++ Completion/Unix/Command/_date | 17 +++++++++++--- Completion/Unix/Command/_sed | 8 ++----- Completion/Unix/Command/_tail | 14 ++++++++---- Completion/Unix/Command/_tr | 53 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 Completion/Unix/Command/_tr diff --git a/ChangeLog b/ChangeLog index 86510979c..20d848320 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-10-31 Oliver Kiddle + * 37029: Completion/Unix/Command/_date, + Completion/Unix/Command/_sed, Completion/Unix/Command/_tail, + Completion/Unix/Command/_tr: update options and new tr completion + * 37028: Completion/Redhat/Command/_scl: new completion * 36993: Eric Cook: Functions/Misc/zed: fix argument parsing diff --git a/Completion/Unix/Command/_date b/Completion/Unix/Command/_date index e596ac038..ff3bac398 100644 --- a/Completion/Unix/Command/_date +++ b/Completion/Unix/Command/_date @@ -1,6 +1,6 @@ #compdef date gdate -local -a args +local -a args alts if _pick_variant gnu="Free Software Foundation" unix --version; then args=( @@ -20,16 +20,27 @@ else solaris*) args=( '-a:adjustment' ) ;; + darwin*|dragonfly*|netbsd*|openbsd*) + args+=( '-r[specify reference time]:seconds since epoch' ) + ;| freebsd*|darwin*|dragonfly*|netbsd*|openbsd*) args=( '-n[only set time on current machine]' '-d:daylight saving time value' '-j[do not try to set date]' - '-r:seconds since epoch' '-t:minutes west of GMT' ) ;| - freebsd*) args+=( '-R[RFC2822 format]' ) ;| + freebsd*) + alts=( + 'seconds:sec:_guard "(0x[0-9a-fA-F]#|[0-9]#)" "seconds since epoch"' + 'files:file:_files' + ) + args+=( + '-r[reference time: file modification or literal time]:reference: _alternative $alts' + '-R[RFC2822 format]' + ) + ;| freebsd*|dragonfly*|darwin*) args+=( '-f:parsing format' '-v:adjustment value' ) ;; diff --git a/Completion/Unix/Command/_sed b/Completion/Unix/Command/_sed index 8e2385cc8..cc7a9631d 100644 --- a/Completion/Unix/Command/_sed +++ b/Completion/Unix/Command/_sed @@ -38,12 +38,8 @@ else '-a[delay opening files listed with w function]' ) ;| - darwin*|freebsd*|netbsd*) - args+=( - '-i'$inplace - '-l[make output line buffered]' - ) - ;| + darwin*|freebsd*|netbsd*|openbsd*) args+=( '-i'$inplace ) ;| + darwin*|freebsd*|netbsd*) args+=( '-l[make output line buffered]' ) ;| freebsd*) args+=( '-u[disable data buffering]' ) ;| freebsd*|netbsd*) args+=( diff --git a/Completion/Unix/Command/_tail b/Completion/Unix/Command/_tail index 6e1445328..fbe30f13a 100644 --- a/Completion/Unix/Command/_tail +++ b/Completion/Unix/Command/_tail @@ -1,6 +1,6 @@ #compdef tail -local curcontext=$curcontext state state_descr line expl opts args ret=1 +local curcontext=$curcontext state state_descr line opts args ret=1 typeset -A opt_args if _pick_variant gnu=GNU unix --version; then @@ -27,9 +27,13 @@ else '(-F -r)-f[wait for new data to be appended to the file]' ) case $OSTYPE in - (freebsd*|darwin*|dragonfly*|netbsd*|openbsd*) + (freebsd*|darwin*|dragonfly*|netbsd*|openbsd*|solaris*) args+=( '(-f -F)-r[display the file in reverse order]' + ) + ;| + (freebsd*|darwin*|dragonfly*|netbsd*|openbsd*) + args+=( '(-c -n)-b+[start at the specified block (512-byte)]:blocks relative to the end (with +, beginning) of file' ) ;| @@ -42,14 +46,14 @@ else esac fi -_arguments -C -s -S $opts : $args '*:file:_files' && return 0 +_arguments -C -s -S $opts : $args '*:file:_files' && return case $state in (number) local mlt sign digit - mlt='multiplier:multiplier:((b\:512 K\:1024 KB\:1000 M\:1024\^2' + 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='sign:sign:((+\:"start at the specified byte/line"' + 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 diff --git a/Completion/Unix/Command/_tr b/Completion/Unix/Command/_tr new file mode 100644 index 000000000..d55fab5ff --- /dev/null +++ b/Completion/Unix/Command/_tr @@ -0,0 +1,53 @@ +#compdef tr + +local curcontext="$curcontext" state line expl ret=1 +local args variant +local -A descr +descr=( + -c '[complement characters specified by first string]' + -d '[delete specified characters from input]' + -s '[squeeze repeated instances of character to a single instance]' +) + +_pick_variant -r variant gnu=GNU $OSTYPE --version +case $variant in + gnu) + args=( + '(-c -C --complement)'{-c,-C,--complement}"${descr[-c]}" + '(-d --delete 2)'{-d,--delete}"${descr[-d]}" + '(-s --squeeze-repeats)'{-s,--squeeze-repeats}"${descr[-s]}" + '(- 1 2)--help[display help information]' + '(- 1 2)--version[display version information]' + ) + ;; + darwin*|dragonfly*|*bsd*) + args+=( "(-c)-C$descr[-c]" ) + ;| + darwin*|dragonfly*|freebsd*) + args+=( '-u[guarantee that output is unbuffered]' ) + ;| + *) + for k in c d s; do + args+=( -$k$descr[$k] ) + done + ;; +esac + +_arguments -C -s $args \ + '1:character set:->chsets' \ + '2:character set:->chsets' && ret=0 + +if [[ -n $state ]]; then + if compset -P '*\[:'; then + _wanted characters expl 'character class' \ + compadd -S ":${${QIPREFIX:+]}:-\]}$compstate[quote] " \ + alnum alpha blank cntrl digit graph lower print punct space upper \ + xdigit && return + elif compset -P '*\\'; then + _describe -t characters character \ + '(\\\\:backslash a:alert b:backspace f:form\ feed n:new\ line r:return t:tab v:vertical\ tab)' -S '' && return + fi + _message -e characters 'character set' +fi + +return ret -- cgit v1.2.3 From ba36967b575ca57ebde3349e62c190ca69b73832 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 1 Nov 2015 18:12:40 +0000 Subject: 37038: add -l option to emulate to list options in emulations --- ChangeLog | 5 +++++ Doc/Zsh/builtins.yo | 10 +++++++++- Src/builtin.c | 33 +++++++++++++++++++++++++-------- Src/options.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 20d848320..13f262bea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-01 Peter Stephenson + + * 37038: Doc/Zsh/builtins.yo, Src/builtin.c, Src/options.c: add + -l option to emulate. + 2015-10-31 Oliver Kiddle * 37029: Completion/Unix/Command/_date, diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 85d1742f0..985e7267f 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -477,7 +477,7 @@ cindex(compatibility, csh) cindex(sh, compatibility) cindex(ksh, compatibility) cindex(csh, compatibility) -item(tt(emulate) [ tt(-LR) ] [ {tt(zsh)|tt(sh)|tt(ksh)|tt(csh)} [ var(flags) ... ] ])( +item(tt(emulate) [ tt(-lLR) ] [ {tt(zsh)|tt(sh)|tt(ksh)|tt(csh)} [ var(flags) ... ] ])( Without any argument print current emulation mode. With single argument set up zsh options to emulate the specified shell @@ -518,6 +518,14 @@ function, if any; normally these options are turned off in all emulation modes except tt(ksh). The tt(-L) switch is mutually exclusive with the use of tt(-c) in var(flags). +If there is a single argument and the tt(-l) switch is given, the +options that would be set or unset (the latter indicated with the prefix +`tt(no)') are listed. tt(-l) can be combined with tt(-L) or tt(-R) and +the list will be modified in the appropriate way. Note the list does +not depend on the current setting of options, i.e. it includes all +options that may in principle change, not just those that would actually +change. + The var(flags) may be any of the invocation-time flags described in ifnzman(noderef(Invocation))\ ifzman(the section INVOCATION in zmanref(zsh)), diff --git a/Src/builtin.c b/Src/builtin.c index 8045bc8f7..0be20a5d2 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -58,7 +58,7 @@ static struct builtin builtins[] = BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmprs", NULL), BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL), BUILTIN("echo", BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"), - BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "LR", NULL), + BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "lLR", NULL), 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), @@ -5425,10 +5425,11 @@ eval(char **argv) /**/ int -bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) +bin_emulate(char *nam, char **argv, Options ops, UNUSED(int func)) { int opt_L = OPT_ISSET(ops, 'L'); int opt_R = OPT_ISSET(ops, 'R'); + int opt_l = OPT_ISSET(ops, 'l'); int saveemulation, savehackchar; int ret = 1, new_emulation; unsigned int savepatterns; @@ -5443,7 +5444,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) /* without arguments just print current emulation */ if (!shname) { if (opt_L || opt_R) { - zwarnnam("emulate", "not enough arguments"); + zwarnnam(nam, "not enough arguments"); return 1; } @@ -5471,27 +5472,43 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) /* with single argument set current emulation */ if (!argv[1]) { - emulate(shname, opt_R, &emulation, opts); + char *cmdopts; + if (opt_l) { + cmdopts = (char *)zhalloc(OPT_SIZE); + memcpy(cmdopts, opts, OPT_SIZE); + } else + cmdopts = opts; + emulate(shname, opt_R, &emulation, cmdopts); if (opt_L) - opts[LOCALOPTIONS] = opts[LOCALTRAPS] = opts[LOCALPATTERNS] = 1; + cmdopts[LOCALOPTIONS] = cmdopts[LOCALTRAPS] = + cmdopts[LOCALPATTERNS] = 1; + if (opt_l) { + list_emulate_options(cmdopts, opt_R); + return 0; + } clearpatterndisables(); return 0; } + if (opt_l) { + zwarnnam(nam, "too many arguments for -l"); + return 1; + } + argv++; memcpy(saveopts, opts, sizeof(opts)); memcpy(new_opts, opts, sizeof(opts)); savehackchar = keyboardhackchar; emulate(shname, opt_R, &new_emulation, new_opts); optlist = newlinklist(); - if (parseopts("emulate", &argv, new_opts, &cmd, optlist)) { + if (parseopts(nam, &argv, new_opts, &cmd, optlist)) { ret = 1; goto restore; } /* parseopts() has consumed anything that looks like an option */ if (*argv) { - zwarnnam("emulate", "unknown argument %s", *argv); + zwarnnam(nam, "unknown argument %s", *argv); goto restore; } @@ -5510,7 +5527,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) */ if (cmd) { if (opt_L) { - zwarnnam("emulate", "option -L incompatible with -c"); + zwarnnam(nam, "option -L incompatible with -c"); goto restore2; } *--argv = cmd; /* on stack, never free()d, see execbuiltin() */ diff --git a/Src/options.c b/Src/options.c index 3bf9f39a4..2678626c7 100644 --- a/Src/options.c +++ b/Src/options.c @@ -902,3 +902,33 @@ printoptionlist_printequiv(int optno) optno *= (isneg ? -1 : 1); printf(" equivalent to --%s%s\n", isneg ? "no-" : "", optns[optno-1].node.nam); } + +/**/ +static char *print_emulate_opts; + +/**/ +static void +print_emulate_option(HashNode hn, int fully) +{ + Optname on = (Optname) hn; + + if (!(on->node.flags & OPT_ALIAS) && + ((fully && !(on->node.flags & OPT_SPECIAL)) || + (on->node.flags & OPT_EMULATE))) + { + if (!print_emulate_opts[on->optno]) + fputs("no", stdout); + puts(on->node.nam); + } +} + +/* + * List the settings of options associated with an emulation + */ + +/**/ +void list_emulate_options(char *cmdopts, int fully) +{ + print_emulate_opts = cmdopts; + scanhashtable(optiontab, 1, 0, 0, print_emulate_option, fully); +} -- cgit v1.2.3 From 9642aeeaebd654565a045475d4d3ba101bfaec8f Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 2 Nov 2015 02:55:15 +0100 Subject: 35303: remove Completion/Unix/Command/_systemd systemd's upstream version seems to be maintained well, and e.g. on Arch Linux the version from Zsh gets removed in favour of it. --- ChangeLog | 5 + Completion/Unix/Command/_systemd | 470 --------------------------------------- 2 files changed, 5 insertions(+), 470 deletions(-) delete mode 100644 Completion/Unix/Command/_systemd diff --git a/ChangeLog b/ChangeLog index 13f262bea..bb6575b3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-02 Daniel Hahler + + * 35303: Completion/Unix/Command/_systemd: remove it in favour of the + one from upstream. + 2015-11-01 Peter Stephenson * 37038: Doc/Zsh/builtins.yo, Src/builtin.c, Src/options.c: add diff --git a/Completion/Unix/Command/_systemd b/Completion/Unix/Command/_systemd deleted file mode 100644 index 028ecddd9..000000000 --- a/Completion/Unix/Command/_systemd +++ /dev/null @@ -1,470 +0,0 @@ -#compdef systemctl systemd-loginctl - -# Copyright (c) 2011 Foudil Bre'tel -# -# This file is released under the GPLv3. -# -# inspired from _yum and systemctl-bash-completion.sh (shipped with systemctl) -# -# TODO: enable options after commands. Ex: systemctl list-units --all --full - -# Main dispatcher -_systemd() -{ - local curcontext="$curcontext" state lstate line - - case "$service" in - systemctl) - # -s for aggregated options like -aP - _arguments -s \ - {-h,--help}'[Show help]' \ - '--version[Show package version]' \ - {-t,--type=}'[List only units of a particular type]:unit type:(automount device mount path service snapshot socket swap target timer)' \ - \*{-p,--property=}'[Show only properties by specific name]:unit property:()' \ - {-a,--all}'[Show all units/properties, including dead/empty ones]' \ - '--failed[Show only failed units]' \ - "--full[Don't ellipsize unit names on output]" \ - '--fail[When queueing a new job, fail if conflicting jobs are pending]' \ - '--ignore-dependencies[When queueing a new job, ignore all its dependencies]' \ - '--kill-mode=[How to send signal]:killmode:(control-group process)' \ - '--kill-who=[Who to send signal to]:killwho:(main control all)' \ - {-s,--signal=}'[Which signal to send]:signal:_signals' \ - {-H,--host=}'[Show information for remote host]:userathost:_hosts_or_user_at_host' \ - {-P,--privileged}'[Acquire privileges before execution]' \ - {-q,--quiet}'[Suppress output]' \ - '--no-block[Do not wait until operation finished]' \ - "--no-wall[Don't send wall message before halt/power-off/reboot]" \ - "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \ - '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \ - '--no-pager[Do not pipe output into a pager]' \ - '--no-ask-password[Do not ask for system passwords]' \ - '--order[When generating graph for dot, show only order]' \ - '--require[When generating graph for dot, show only requirement]' \ - '--system[Connect to system manager]' \ - '--user[Connect to user service manager]' \ - '--global[Enable/disable unit files globally]' \ - {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \ - '--root=[Enable unit files in the specified root directory]:directory:_directories' \ - '--runtime[Enable unit files only temporarily until next reboot]' \ - '*::systemctl command:_systemctl_command' - ;; - - systemd-loginctl) - _arguments -s \ - {-h,--help}'[Show help]' \ - '--version[Show package version]' \ - \*{-p,--property=}'[Show only properties by this name]:unit property:' \ - {-a,--all}'[Show all properties, including empty ones]' \ - '--failed[Show only failed units]' \ - '--kill-who=[Who to send signal to]:killwho:(main control all)' \ - {-s,--signal=}'[Which signal to send]:signal:_signals' \ - {-H,--host=}'[Show information for remote host]:userathost:_hosts_or_user_at_host' \ - {-P,--privileged}'[Acquire privileges before execution]' \ - '--no-pager[Do not pipe output into a pager]' \ - '*::systemd-loginctl command:_systemd_loginctl_command' - ;; - - *) _message 'eh?' ;; - esac - -} - -_hosts_or_user_at_host() -{ - _alternative \ - 'users-hosts:: _user_at_host' \ - 'hosts:: _hosts' -} - -(( $+functions[_systemctl_command] )) || _systemctl_command() -{ - local -a _systemctl_cmds - _systemctl_cmds=( - "list-units:List units" - "start:Start (activate) one or more units" - "stop:Stop (deactivate) one or more units" - "reload:Reload one or more units" - "restart:Start or restart one or more units" - "condrestart:Restart one or more units if active" - "try-restart:Restart one or more units if active" - "reload-or-restart:Reload one or more units is possible, otherwise start or restart" - "force-reload:Reload one or more units is possible, otherwise restart if active" - "reload-or-try-restart:Reload one or more units is possible, otherwise restart if active" - "isolate:Start one unit and stop all others" - "kill:Send signal to processes of a unit" - "is-active:Check whether units are active" - "status:Show runtime status of one or more units" - "show:Show properties of one or more units/jobs or the manager" - "reset-failed:Reset failed state for all, one, or more units" - "load:Load one or more units" - "list-unit-files:List installed unit files" - "enable:Enable one or more unit files" - "disable:Disable one or more unit files" - "reenable:Reenable one or more unit files" - "preset:Enable/disable one or more unit files based on preset configuration" - "mask:Mask one or more units" - "unmask:Unmask one or more units" - "link:Link one or more units files into the search path" - "is-enabled:Check whether unit files are enabled" - "list-jobs:List jobs" - "cancel:Cancel all, one, or more jobs" - "dump:Dump server status" - "dot:Dump dependency graph for dot(1)" - "snapshot:Create a snapshot" - "delete:Remove one or more snapshots" - "show-environment:Dump environment" - "set-environment:Set one or more environment variables" - "unset-environment:Unset one or more environment variables" - "daemon-reload:Reload systemd manager configuration" - "daemon-reexec:Reexecute systemd manager" - "default:Enter system default mode" - "rescue:Enter system rescue mode" - "emergency:Enter system emergency mode" - "halt:Shut down and halt the system" - "poweroff:Shut down and power-off the system" - "reboot:Shut down and reboot the system" - "kexec:Shut down and reboot the system with kexec" - "exit:Ask for user instance termination" - "switch-root:Change to a different root file system" - "suspend:Suspend the system" - "hibernate:Hibernate the system" - "hibernate-sleep:Hibernate and suspend the system" - ) - - if (( CURRENT == 1 )); then - _describe -t commands 'systemctl command' _systemctl_cmds - else - local curcontext="$curcontext" ret - - cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}" - # Deal with any aliases - case $cmd in - condrestart) cmd="try-restart";; - force-reload) cmd="reload-or-try-restart";; - esac - - if (( $#cmd )); then - curcontext="${curcontext%:*:*}:systemctl-${cmd}:" - - local update_policy - zstyle -s ":completion:${curcontext}:" cache-policy update_policy - if [[ -z "$update_policy" ]]; then - zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy - fi - - _call_function ret _systemctl_$cmd || _message 'no more arguments' - else - _message "unknown systemctl command: $words[1]" - fi - return ret - fi -} - -__systemctl() -{ - systemctl --full --no-legend --no-pager "$@" -} - - -# Fills the unit list -_systemctl_all_units() -{ - if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) && - ! _retrieve_cache SYS_ALL_UNITS; - then - _sys_all_units=( $(__systemctl list-units --all | { while read a b; do echo "$a"; done; }) ) - _store_cache SYS_ALL_UNITS _sys_all_units - fi -} - -# Fills the unit list including all file units -_systemctl_really_all_units() -{ - local -a all_unit_files; - local -a really_all_units; - if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS ) && - ! _retrieve_cache SYS_REALLY_ALL_UNITS; - then - all_unit_files=( $(__systemctl list-unit-files | { while read a b; do echo "$a"; done; }) ) - _systemctl_all_units - really_all_units=($_sys_all_units $all_unit_files) - _sys_really_all_units=(${(u)really_all_units}) - _store_cache SYS_REALLY_ALL_UNITS _sys_really_all_units - fi -} - -_filter_units_by_property() { - local property=$1 value=$2 ; shift ; shift - local -a units ; units=($*) - local prop unit - for ((i=1; $i <= ${#units[*]}; i++)); do - # FIXME: "Failed to issue method call: Unknown unit" errors are ignored for - # now (related to DBUS_ERROR_UNKNOWN_OBJECT). in the future, we need to - # revert to calling 'systemctl show' once for all units, which is way - # faster - unit=${units[i]} - prop=$(systemctl show --no-pager --property="$property" ${unit} 2>/dev/null) - if [[ "${prop}" = "$property=$value" ]]; then - echo "${unit}" - fi - done -} - -_systemctl_active_units() {_sys_active_units=( $(__systemctl list-units | { while read a b; do echo "$a"; done; }) )} -_systemctl_inactive_units(){_sys_inactive_units=($(__systemctl list-units --all | { while read a b c d; do [[ $c == "inactive" ]] && echo "$a"; done; }) )} -_systemctl_failed_units() {_sys_failed_units=( $(__systemctl list-units --failed | { while read a b; do echo "$a"; done; }) )} -_systemctl_enabled_units() {_sys_enabled_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "enabled" ]] && echo "$a"; done; }) )} -_systemctl_disabled_units(){_sys_disabled_units=($(__systemctl list-unit-files | { while read a b; do [[ $b == "disabled" ]] && echo "$a"; done; }) )} -_systemctl_masked_units() {_sys_masked_units=( $(__systemctl list-unit-files | { while read a b; do [[ $b == "masked" ]] && echo "$a"; done; }) )} - -# Completion functions for ALL_UNITS -for fun in is-active is-enabled status show mask preset ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_really_all_units - compadd "$@" -a - _sys_really_all_units - } -done - -# Completion functions for ENABLED_UNITS -for fun in disable reenable ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_enabled_units - compadd "$@" -a - _sys_enabled_units - } -done - -# Completion functions for DISABLED_UNITS -(( $+functions[_systemctl_enable] )) || _systemctl_enable() -{ - _systemctl_disabled_units - compadd "$@" -a - _sys_disabled_units -} - -# Completion functions for FAILED_UNITS -(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed() -{ - _systemctl_failed_units - compadd "$@" -a - _sys_failed_units || _message "no failed unit found" -} - -# Completion functions for STARTABLE_UNITS -(( $+functions[_systemctl_start] )) || _systemctl_start() -{ - _systemctl_inactive_units - compadd "$@" -a - _sys_inactive_units -} - -# Completion functions for STOPPABLE_UNITS -for fun in stop kill try-restart condrestart ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_active_units - compadd "$@" - $( _filter_units_by_property CanStop yes \ - ${_sys_active_units[*]} ) - } -done - -# Completion functions for ISOLATABLE_UNITS -(( $+functions[_systemctl_isolate] )) || _systemctl_isolate() -{ - _systemctl_all_units - compadd "$@" - $( _filter_units_by_property AllowIsolate yes \ - ${_sys_all_units[*]} ) -} - -# Completion functions for RELOADABLE_UNITS -for fun in reload reload-or-try-restart force-reload ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_active_units - compadd "$@" - $( _filter_units_by_property CanReload yes \ - ${_sys_active_units[*]} ) - } -done - -# Completion functions for RESTARTABLE_UNITS -for fun in restart reload-or-restart ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - _systemctl_all_units - compadd "$@" - $( _filter_units_by_property CanStart yes \ - ${_sys_all_units[*]} | while read line; do \ - [[ "$line" =~ \.(device|snapshot|socket|timer)$ ]] || echo "$line"; \ - done ) - } -done - -# Completion functions for MASKED_UNITS -(( $+functions[_systemctl_unmask] )) || _systemctl_unmask() -{ - _systemctl_masked_units - compadd "$@" -a - _sys_masked_units || _message "no masked unit found" -} - -# Completion functions for JOBS -(( $+functions[_systemctl_cancel] )) || _systemctl_cancel() -{ - compadd "$@" - $(__systemctl list-jobs \ - | cut -d' ' -f1 2>/dev/null ) || _message "no job found" -} - -# Completion functions for SNAPSHOTS -(( $+functions[_systemctl_delete] )) || _systemctl_delete() -{ - compadd "$@" - $(__systemctl list-units --type snapshot --all \ - | cut -d' ' -f1 2>/dev/null ) || _message "no snampshot found" -} - -# Completion functions for ENVS -for fun in set-environment unset-environment ; do - (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() - { - local fun=$0 ; fun=${fun##_systemctl_} - local suf - if [[ "${fun}" = "set-environment" ]]; then - suf='-S=' - fi - - compadd "$@" ${suf} - $(systemctl show-environment \ - | while read line; do echo "${line%%\=}";done ) - } -done - -(( $+functions[_systemctl_link] )) || _systemctl_link() { _files } - -(( $+functions[_systemctl_switch-root] )) || _systemctl_switch-root() -{ - if (( CURRENT == 2 )); then - _directories - fi -} - -# no systemctl completion for: -# [STANDALONE]='daemon-reexec daemon-reload default dot dump -# emergency exit halt kexec list-jobs list-units -# list-unit-files poweroff reboot rescue show-environment' -# [NAME]='snapshot load' - -_systemctl_caching_policy() -{ - local _sysunits - local -a oldcache - - # rebuild if cache is more than a day old - oldcache=( "$1"(mh+1) ) - (( $#oldcache )) && return 0 - - _sysunits=($(__systemctl --all | cut -d' ' -f1)) - - if (( $#_sysunits )); then - for unit in $_sysunits; do - [[ "$unit" -nt "$1" ]] && return 0 - done - fi - - return 1 -} - - - -_systemd_loginctl_all_sessions(){_sys_all_sessions=($(systemd-loginctl list-sessions | { while read a b; do echo "$a"; done; }) )} -_systemd_loginctl_all_users() {_sys_all_users=( $(systemd-loginctl list-users | { while read a b; do echo "$a"; done; }) )} -_systemd_loginctl_all_seats() {_sys_all_seats=( $(systemd-loginctl list-seats | { while read a b; do echo "$a"; done; }) )} - -# Completion functions for SESSIONS -for fun in session-status show-session activate lock-session unlock-session terminate-session kill-session ; do - (( $+functions[_systemd_loginctl_$fun] )) || _systemd_loginctl_$fun() - { - _systemd_loginctl_all_sessions - compadd "$@" -a - _sys_all_sessions - } -done - -# Completion functions for USERS -for fun in user-status show-user enable-linger disable-linger terminate-user kill-user ; do - (( $+functions[_systemd_loginctl_$fun] )) || _systemd_loginctl_$fun() - { - _systemd_loginctl_all_users - compadd "$@" -a - _sys_all_users - } -done - -# Completion functions for SEATS -(( $+functions[_systemd_loginctl_seats] )) || _systemd_loginctl_seats() -{ - _systemd_loginctl_all_seats - compadd "$@" -a - _sys_all_seats -} -for fun in seat-status show-seat terminate-seat ; do - (( $+functions[_systemd_loginctl_$fun] )) || _systemd_loginctl_$fun() - { _systemd_loginctl_seats } -done - -# Completion functions for ATTACH -(( $+functions[_systemd_loginctl_attach] )) || _systemd_loginctl_attach() -{ - _systemd_loginctl_all_seats - - _arguments -w -C -S -s \ - ':seat:_systemd_loginctl_seats' \ - '*:device:_files' -} - -# no systemd-loginctl completion for: -# [STANDALONE]='list-sessions list-users list-seats flush-devices' - -(( $+functions[_systemd_loginctl_command] )) || _systemd_loginctl_command() -{ - local -a _systemd_loginctl_cmds - _systemd_loginctl_cmds=( - "list-sessions:List sessions" - "session-status:Show session status" - "show-session:Show properties of one or more sessions" - "activate:Activate a session" - "lock-session:Screen lock one or more sessions" - "unlock-session:Screen unlock one or more sessions" - "terminate-session:Terminate one or more sessions" - "kill-session:Send signal to processes of a session" - "list-users:List users" - "user-status:Show user status" - "show-user:Show properties of one or more users" - "enable-linger:Enable linger state of one or more users" - "disable-linger:Disable linger state of one or more users" - "terminate-user:Terminate all sessions of one or more users" - "kill-user:Send signal to processes of a user" - "list-seats:List seats" - "seat-status:Show seat status" - "show-seat:Show properties of one or more seats" - "attach:Attach one or more devices to a seat" - "flush-devices:Flush all device associations" - "terminate-seat:Terminate all sessions on one or more seats" - ) - - if (( CURRENT == 1 )); then - _describe -t commands 'systemd-loginctl command' _systemd_loginctl_cmds || compadd "$@" - else - local curcontext="$curcontext" - - cmd="${${_systemd_loginctl_cmds[(r)$words[1]:*]%%:*}}" - - if (( $#cmd )); then - curcontext="${curcontext%:*:*}:systemd_loginctl-${cmd}:" - - _call_function ret _systemd_loginctl_$cmd || _message 'no more arguments' - else - _message "unknown systemd-loginctl command: $words[1]" - fi - return ret - fi -} - -_systemd "$@" - -# Local Variables: -# mode: sh -# sh-indentation: 2 -# indent-tabs-mode: nil -# sh-basic-offset: 2 -# End: -- cgit v1.2.3 From 20153c573e1d9156fdee02fb854298bc0b88545f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 4 Nov 2015 17:37:17 +0000 Subject: 37062: tentative mechanism for git commit descriptions. Mechanism for forcing completion system into verbose mode is subject to change. --- ChangeLog | 6 ++++++ Completion/Unix/Command/_git | 42 +++++++++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index bb6575b3a..6b4a38a85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-11-04 Peter Stephenson + + * 37062: Completion/Unix/Command/_git: allow verbose + descriptions of commits and branches using git log. Mechanism + for turning this on subject to change. + 2015-11-02 Daniel Hahler * 35303: Completion/Unix/Command/_systemd: remove it in favour of the diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index df7a7d900..61386bfac 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5004,6 +5004,33 @@ __git_is_in_middle_of_merge () { [[ -f $gitdir/MERGE_HEAD ]] } +(( $+functions[__git_describe_branch] )) || +__git_describe_branch () { + local __commits_in=$1 + local __tag=$2 + local __desc=$3 + shift 3 + + integer maxverbose + if zstyle -s :completion:$curcontext max-verbose maxverbose && + (( ${compstate[nmatches]} <= maxverbose )); then + local __c + local -a __commits + for __c in ${(P)__commits_in}; do + __commits+=("${__c}:${$(_call_program describe git log -1 --oneline $__c)//:/\\:}") + done + _describe -t $__tag $__desc __commits "$@" + else + local expl + _wanted $__tag expl $__desc compadd "$@" -a - $__commits_in + fi +} + +(( $+functions[__git_describe_commit] )) || +__git_describe_commit () { + __git_describe_branch $1 $2 $3 -M 'r:|/=**' "${(@)argv[4,-1]}" +} + # Completion Wrappers (( $+functions[__git_ignore_line] )) || @@ -5541,29 +5568,27 @@ __git_branch_names () { branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}) __git_command_successful $pipestatus || return 1 - _wanted branch-names expl branch-name compadd -M 'r:|/=**' "$@" -a - branch_names + __git_describe_commit branch_names branch-names 'branch name' "$@" } (( $+functions[__git_remote_branch_names] )) || __git_remote_branch_names () { - local expl declare -a branch_names branch_names=(${${(f)"$(_call_program remote-branch-refs git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}#refs/remotes/}) __git_command_successful $pipestatus || return 1 - _wanted remote-branch-names expl 'remote branch name' compadd -M 'r:|/=**' "$@" -a - branch_names + __git_describe_commit branch_names remote-branch-names 'remote branch name' "$@" } (( $+functions[__git_remote_branch_names_noprefix] )) || __git_remote_branch_names_noprefix () { - local expl declare -a heads branch_names=(${${${${(f)"$(_call_program remote-branch-refs-noprefix git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}#refs/remotes/}#*/}:#HEAD}) __git_command_successful $pipestatus || return 1 - _wanted remote-branch-names-noprefix expl 'remote branch name' compadd -M 'r:|/=**' "$@" -a - branch_names + __git_describe_commit branch_names remote-branch-names-noprefix 'remote branch name' "$@" } (( $+functions[__git_commit_objects_prefer_recent] )) || @@ -5603,7 +5628,7 @@ __git_heads () { (( $+functions[__git_heads_local] )) || __git_heads_local () { - local gitdir expl start + local gitdir declare -a heads heads=(${(f)"$(_call_program headrefs git for-each-ref --format='"%(refname:short)" refs/heads' 2>/dev/null)"}) @@ -5615,17 +5640,16 @@ __git_heads_local () { [[ -f $gitdir/refs/stash ]] && heads+=stash fi - _wanted heads-local expl "local head" compadd -M 'r:|/=**' "$@" -a - heads + __git_describe_commit heads heads-local "local head" "$@" } (( $+functions[__git_heads_remote] )) || __git_heads_remote () { - local gitdir expl start declare -a heads heads=(${(f)"$(_call_program headrefs git for-each-ref --format='"%(refname:short)" refs/remotes' 2>/dev/null)"}) - _wanted heads-remote expl "remote head" compadd -M 'r:|/=**' "$@" -a - heads + __git_describe_commit heads heads-remote "remote head" "$@" } (( $+functions[__git_commit_objects] )) || -- cgit v1.2.3 From 0fcc6c8fb28f4cc61520770da2156de3a124e432 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 6 Nov 2015 17:28:02 +0000 Subject: 37073: another SH_WORD_SPLIT problem. In cases like x${:- y} the space was simply removed instead of being used for splitting. --- ChangeLog | 6 ++++++ Src/subst.c | 40 +++++++++++++++++++++++++++++++------ Test/D04parameter.ztst | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6b4a38a85..71d44bc90 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-11-06 Peter Stephenson + + * 37073: Src/subst.c, Test/D04parameter.ztst: fix case of + SH_WORD_SPLIT with string before parameter substitution and + nested string that starts with a space e.g. x${:- y}. + 2015-11-04 Peter Stephenson * 37062: Completion/Unix/Command/_git: allow verbose diff --git a/Src/subst.c b/Src/subst.c index 021d23444..528912134 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -430,11 +430,16 @@ singsub(char **s) * set to 1. Otherwise, *isarr is set to 0, and the result is put into *s, * with any necessary joining of multiple elements using sep (which can be * NULL to use IFS). The return value is true iff the expansion resulted - * in an empty list. */ + * in an empty list. + * + * *ws_at_start is set to 1 if the string had whitespace at thes start + * that should cause word splitting against any preceeding string. + */ /**/ static int -multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep) +multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, + int *ws_at_start) { int l; char **r, **p, *x = *s; @@ -450,6 +455,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep) l++; if (!iwsep(STOUC(c))) break; + *ws_at_start = 1; } } @@ -1717,6 +1723,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * This is for compatibility. */ int horrible_offset_hack = 0; + /* + * Signal back from multsub: with something like + * x${:- $foo} + * with word-splitting active we need to split on that leading + * whitespace. However, if there's no "x" the whitespace is + * simply removed. + */ + int ws_at_start = 0; *s++ = '\0'; /* @@ -2265,7 +2279,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * remove the aspar test and extract a value from an array, if * necessary, when we handle (P) lower down. */ - if (multsub(&val, 0, (aspar ? NULL : &aval), &isarr, NULL) && quoted) { + if (multsub(&val, 0, (aspar ? NULL : &aval), &isarr, NULL, + &ws_at_start) && quoted) { /* Empty quoted string --- treat as null string, not elided */ isarr = -1; aval = (char **) hcalloc(sizeof(char *)); @@ -2736,7 +2751,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) split_flags = PREFORK_NOSHWORDSPLIT; } multsub(&val, split_flags, (aspar ? NULL : &aval), - &isarr, NULL); + &isarr, NULL, &ws_at_start); copied = 1; spbreak = 0; /* Leave globsubst on if forced */ @@ -2765,13 +2780,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * behavior on caller choice of PREFORK_SHWORDSPLIT. */ multsub(&val, spbreak ? PREFORK_SINGLE : PREFORK_NOSHWORDSPLIT, - NULL, &isarr, NULL); + NULL, &isarr, NULL, &ws_at_start); } else { if (spbreak) split_flags = PREFORK_SPLIT|PREFORK_SHWORDSPLIT; else split_flags = PREFORK_NOSHWORDSPLIT; - multsub(&val, split_flags, &aval, &isarr, NULL); + multsub(&val, split_flags, &aval, &isarr, NULL, + &ws_at_start); spbreak = 0; } if (arrasg) { @@ -3303,6 +3319,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) } if (haserr || errflag) return NULL; + ws_at_start = 0; } /* * This handles taking a length with ${#foo} and variations. @@ -3341,6 +3358,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) sprintf(buf, "%ld", len); val = dupstring(buf); isarr = 0; + ws_at_start = 0; } /* At this point we make sure that our arrayness has affected the * arrayness of the linked list. Then, we can turn our value into @@ -3370,6 +3388,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) if (isarr) { val = sepjoin(aval, sep, 1); isarr = 0; + ws_at_start = 0; } if (!ssub && (spbreak || spsep)) { aval = sepsplit(val, spsep, 0, 1); @@ -3649,6 +3668,15 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * equivalent and only locally decide if we need to treat it * as a scalar.) */ + + /* + * If a multsub result had whitespace at the start and we're + * splitting and there's a previous string, now's the time to do so. + */ + if (ws_at_start && aptr > ostr) { + insertlinknode(l, n, dupstrpfx(ostr, aptr - ostr)), incnode(n); + ostr = aptr; + } if (isarr) { char *x; char *y; diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index cb7079c98..59c14a408 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1744,3 +1744,57 @@ >3_4_5_6 >6 >1_2_3_4_5_6 + + (setopt shwordsplit + do_test() { + print $#: "$@" + } + foo=bar + foo2="bar bar" + do_test ${:- foo} + do_test ${:- foo bar} + do_test ${:- $foo} + do_test ${:- $foo2} + do_test x${:- foo} + do_test x${:- foo bar} + do_test x${:- $foo} + do_test x${:- $foo2} + do_test x${foo:+ $foo} + ) +0:We Love SH_WORD_SPLIT Day celebrated with space at start of internal subst +>1: foo +>2: foo bar +>1: bar +>2: bar bar +>2: x foo +>3: x foo bar +>2: x bar +>3: x bar bar +>2: x bar + + (unsetopt shwordsplit # default, for clarity + do_test() { + print $#: "$@" + } + foo=bar + foo2="bar bar" + do_test ${:- foo} + do_test ${:- foo bar} + do_test ${:- $foo} + do_test ${:- $foo2} + do_test x${:- foo} + do_test x${:- foo bar} + do_test x${:- $foo} + do_test x${:- $foo2} + do_test x${foo:+ $foo} + ) +0:We Love NO_SH_WORD_SPLIT Even More Day celebrated as sanity check +>1: foo +>1: foo bar +>1: bar +>1: bar bar +>1: x foo +>1: x foo bar +>1: x bar +>1: x bar bar +>1: x bar -- cgit v1.2.3 From e8d6041f69f8bfde92ebdd09410bde3ae88978ff Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 7 Nov 2015 18:05:43 +0000 Subject: 37074: extend previous fix to over whitespace at end --- ChangeLog | 5 ++++ Src/subst.c | 50 ++++++++++++++++++++++++++++----------- Test/D04parameter.ztst | 64 +++++++++++++++++++++++++------------------------- 3 files changed, 73 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 71d44bc90..1334e29d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-07 Peter Stephenson + + * 37074: Src/subst.c, Test/D04parameter.ztst: extend previous + fix to cover whitespace at end of substitution. + 2015-11-06 Peter Stephenson * 37073: Src/subst.c, Test/D04parameter.ztst: fix case of diff --git a/Src/subst.c b/Src/subst.c index 528912134..febdc9bea 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -420,6 +420,22 @@ singsub(char **s) DPUTS(nonempty(&foo), "BUG: singsub() produced more than one word!"); } +/* + * Bit flags passed back from multsub() to paramsubst(). + */ +enum { + /* + * Set if the string had whitespace at the start + * that should cause word splitting against any preceeding string. + */ + WS_AT_START = 1, + /* + * Set if the string had whitespace at the end + * that should cause word splitting against any following string. + */ + WS_AT_END = 2 +}; + /* Perform substitution on a single word, *s. Unlike with singsub(), the * result can be more than one word. If split is non-zero, the string is * first word-split using IFS, but only for non-quoted "whitespace" (as @@ -432,14 +448,13 @@ singsub(char **s) * NULL to use IFS). The return value is true iff the expansion resulted * in an empty list. * - * *ws_at_start is set to 1 if the string had whitespace at thes start - * that should cause word splitting against any preceeding string. + * *ws_at_start is set to bits in the enum above as neeed. */ /**/ static int multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, - int *ws_at_start) + int *ws_sub) { int l; char **r, **p, *x = *s; @@ -455,7 +470,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, l++; if (!iwsep(STOUC(c))) break; - *ws_at_start = 1; + *ws_sub |= WS_AT_START; } } @@ -487,8 +502,10 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, if (!WC_ZISTYPE(c, ISEP)) break; } - if (!*x) + if (!*x) { + *ws_sub |= WS_AT_END; break; + } insertlinknode(&foo, n, (void *)x), incnode(n); } } @@ -1730,7 +1747,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * whitespace. However, if there's no "x" the whitespace is * simply removed. */ - int ws_at_start = 0; + int ws_sub = 0; *s++ = '\0'; /* @@ -2280,7 +2297,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * necessary, when we handle (P) lower down. */ if (multsub(&val, 0, (aspar ? NULL : &aval), &isarr, NULL, - &ws_at_start) && quoted) { + &ws_sub) && quoted) { /* Empty quoted string --- treat as null string, not elided */ isarr = -1; aval = (char **) hcalloc(sizeof(char *)); @@ -2751,7 +2768,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) split_flags = PREFORK_NOSHWORDSPLIT; } multsub(&val, split_flags, (aspar ? NULL : &aval), - &isarr, NULL, &ws_at_start); + &isarr, NULL, &ws_sub); copied = 1; spbreak = 0; /* Leave globsubst on if forced */ @@ -2780,14 +2797,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * behavior on caller choice of PREFORK_SHWORDSPLIT. */ multsub(&val, spbreak ? PREFORK_SINGLE : PREFORK_NOSHWORDSPLIT, - NULL, &isarr, NULL, &ws_at_start); + NULL, &isarr, NULL, &ws_sub); } else { if (spbreak) split_flags = PREFORK_SPLIT|PREFORK_SHWORDSPLIT; else split_flags = PREFORK_NOSHWORDSPLIT; multsub(&val, split_flags, &aval, &isarr, NULL, - &ws_at_start); + &ws_sub); spbreak = 0; } if (arrasg) { @@ -3319,7 +3336,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) } if (haserr || errflag) return NULL; - ws_at_start = 0; + ws_sub = 0; } /* * This handles taking a length with ${#foo} and variations. @@ -3358,7 +3375,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) sprintf(buf, "%ld", len); val = dupstring(buf); isarr = 0; - ws_at_start = 0; + ws_sub = 0; } /* At this point we make sure that our arrayness has affected the * arrayness of the linked list. Then, we can turn our value into @@ -3388,7 +3405,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) if (isarr) { val = sepjoin(aval, sep, 1); isarr = 0; - ws_at_start = 0; + ws_sub = 0; } if (!ssub && (spbreak || spsep)) { aval = sepsplit(val, spsep, 0, 1); @@ -3673,10 +3690,15 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * If a multsub result had whitespace at the start and we're * splitting and there's a previous string, now's the time to do so. */ - if (ws_at_start && aptr > ostr) { + if ((ws_sub & WS_AT_START) && aptr > ostr) { insertlinknode(l, n, dupstrpfx(ostr, aptr - ostr)), incnode(n); ostr = aptr; } + /* Likewise at the end */ + if ((ws_sub & WS_AT_END) && *fstr) { + insertlinknode(l, n, dupstring(fstr)); /* appended, no incnode */ + *fstr = '\0'; + } if (isarr) { char *x; char *y; diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 59c14a408..694b613c5 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1751,26 +1751,26 @@ } foo=bar foo2="bar bar" - do_test ${:- foo} - do_test ${:- foo bar} - do_test ${:- $foo} - do_test ${:- $foo2} - do_test x${:- foo} - do_test x${:- foo bar} - do_test x${:- $foo} - do_test x${:- $foo2} - do_test x${foo:+ $foo} + do_test ${:- foo } + do_test ${:- foo bar } + do_test ${:- $foo } + do_test ${:- $foo2 } + do_test x${:- foo }y + do_test x${:- foo bar }y + do_test x${:- $foo }y + do_test x${:- $foo2 }y + do_test x${foo:+ $foo }y ) 0:We Love SH_WORD_SPLIT Day celebrated with space at start of internal subst >1: foo >2: foo bar >1: bar >2: bar bar ->2: x foo ->3: x foo bar ->2: x bar ->3: x bar bar ->2: x bar +>3: x foo y +>4: x foo bar y +>3: x bar y +>4: x bar bar y +>3: x bar y (unsetopt shwordsplit # default, for clarity do_test() { @@ -1778,23 +1778,23 @@ } foo=bar foo2="bar bar" - do_test ${:- foo} - do_test ${:- foo bar} - do_test ${:- $foo} - do_test ${:- $foo2} - do_test x${:- foo} - do_test x${:- foo bar} - do_test x${:- $foo} - do_test x${:- $foo2} - do_test x${foo:+ $foo} + do_test ${:- foo } + do_test ${:- foo bar } + do_test ${:- $foo } + do_test ${:- $foo2 } + do_test x${:- foo }y + do_test x${:- foo bar }y + do_test x${:- $foo }y + do_test x${:- $foo2 }y + do_test x${foo:+ $foo }y ) 0:We Love NO_SH_WORD_SPLIT Even More Day celebrated as sanity check ->1: foo ->1: foo bar ->1: bar ->1: bar bar ->1: x foo ->1: x foo bar ->1: x bar ->1: x bar bar ->1: x bar +>1: foo +>1: foo bar +>1: bar +>1: bar bar +>1: x foo y +>1: x foo bar y +>1: x bar y +>1: x bar bar y +>1: x bar y -- cgit v1.2.3 From 7277cc1bedaa335b96ce609b4390618358198c32 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 8 Nov 2015 12:42:00 -0800 Subject: 37079: better description of "optstr" field in struct builtin as used in BUILTIN() macro --- ChangeLog | 5 +++++ Etc/zsh-development-guide | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1334e29d8..cee715d33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-08 Barton E. Schaefer + + * 37079: Etc/zsh-development-guide: better description of "optstr" + field in struct builtin as used in BUILTIN() macro + 2015-11-07 Peter Stephenson * 37074: Src/subst.c, Test/D04parameter.ztst: extend previous diff --git a/Etc/zsh-development-guide b/Etc/zsh-development-guide index 9ca441bd8..c4aa1b243 100644 --- a/Etc/zsh-development-guide +++ b/Etc/zsh-development-guide @@ -503,7 +503,9 @@ arguments are: - the options the builtin accepts, given as a string containing the option characters (the above example makes the builtin accept the options `f', `l', `a', `g', and `s'). Passing NULL here disables - all flag handling, i.e. even "--". + all flag handling, i.e. even "--". Each option letter may be + followed by one of ":" (argument must follow), "::" (optional + argument may follow), or ":%" (optional numeric argument). - and finally a optional string containing option characters that will always be reported as set when calling the C-function (this, too, can be used when using one C-function to implement multiple -- cgit v1.2.3 From 30b90f166ef0ca0883985461d498c066e4f723da Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 8 Nov 2015 12:44:31 -0800 Subject: 37080: use paramtab abstraction more consistently, add explanatory comments --- ChangeLog | 3 +++ Src/builtin.c | 11 +++++++---- Src/params.c | 6 ++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index cee715d33..110f10743 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-11-08 Barton E. Schaefer + * 37080: Src/builtin.c, Src/params.c: use paramtab abstraction more + consistently, add explanatory comments + * 37079: Etc/zsh-development-guide: better description of "optstr" field in struct builtin as used in BUILTIN() macro diff --git a/Src/builtin.c b/Src/builtin.c index 0be20a5d2..18dfdce05 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -2334,7 +2334,8 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), } else if ((on & PM_LOCAL) && locallevel) { *subscript = 0; pm = (Param) (paramtab == realparamtab ? - gethashnode2(paramtab, pname) : + /* getnode2() to avoid autoloading */ + paramtab->getnode2(paramtab, pname) : paramtab->getnode(paramtab, pname)); *subscript = '['; if (!pm || pm->level != locallevel) { @@ -2825,11 +2826,12 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func) /* Take arguments literally. Don't glob */ while ((asg = getasg(&argv, assigns))) { HashNode hn = (paramtab == realparamtab ? - gethashnode2(paramtab, asg->name) : + /* getnode2() to avoid autoloading */ + paramtab->getnode2(paramtab, asg->name) : paramtab->getnode(paramtab, asg->name)); if (OPT_ISSET(ops,'p')) { if (hn) - printparamnode(hn, printflags); + paramtab->printnode(hn, printflags); else { zwarnnam(name, "no such variable: %s", asg->name); returnval = 1; @@ -3319,7 +3321,8 @@ bin_unset(char *name, char **argv, Options ops, int func) *ss = 0; } pm = (Param) (paramtab == realparamtab ? - gethashnode2(paramtab, s) : + /* getnode2() to avoid autoloading */ + paramtab->getnode2(paramtab, s) : paramtab->getnode(paramtab, s)); /* * Unsetting an unset variable is not an error. diff --git a/Src/params.c b/Src/params.c index de456c144..3ed771e3b 100644 --- a/Src/params.c +++ b/Src/params.c @@ -447,7 +447,7 @@ newparamtable(int size, char const *name) ht->cmpnodes = strcmp; ht->addnode = addhashnode; ht->getnode = getparamnode; - ht->getnode2 = getparamnode; + ht->getnode2 = gethashnode2; ht->removenode = removehashnode; ht->disablenode = NULL; ht->enablenode = NULL; @@ -869,6 +869,7 @@ createparam(char *name, int flags) if (name != nulstring) { oldpm = (Param) (paramtab == realparamtab ? + /* gethashnode2() for direct table read */ gethashnode2(paramtab, name) : paramtab->getnode(paramtab, name)); @@ -3111,7 +3112,8 @@ unsetparam(char *s) queue_signals(); if ((pm = (Param) (paramtab == realparamtab ? - gethashnode2(paramtab, s) : + /* getnode2() to avoid autoloading */ + paramtab->getnode2(paramtab, s) : paramtab->getnode(paramtab, s)))) unsetparam_pm(pm, 0, 1); unqueue_signals(); -- cgit v1.2.3 From d3d5325d27db3a56b7caf5313617d5e84aae8fe7 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 8 Nov 2015 16:19:37 -0800 Subject: 37081: new module zsh/param/private for private-scoped parameters in functions --- ChangeLog | 5 + Doc/Makefile.in | 4 +- Doc/Zsh/mod_private.yo | 89 +++++++ Src/Modules/param_private.c | 587 ++++++++++++++++++++++++++++++++++++++++++ Src/Modules/param_private.mdd | 7 + Test/V10private.ztst | 265 +++++++++++++++++++ 6 files changed, 955 insertions(+), 2 deletions(-) create mode 100644 Doc/Zsh/mod_private.yo create mode 100644 Src/Modules/param_private.c create mode 100644 Src/Modules/param_private.mdd create mode 100644 Test/V10private.ztst diff --git a/ChangeLog b/ChangeLog index 110f10743..622b0dbd8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2015-11-08 Barton E. Schaefer + * 37081: Doc/Makefile.in, Doc/Zsh/mod_private.yo, + Src/Modules/param_private.c, Src/Modules/param_private.mdd, + Test/V10private.ztst: new module zsh/param/private for + private-scoped parameters in functions + * 37080: Src/builtin.c, Src/params.c: use paramtab abstraction more consistently, add explanatory comments diff --git a/Doc/Makefile.in b/Doc/Makefile.in index 7645f42f7..d5899917e 100644 --- a/Doc/Makefile.in +++ b/Doc/Makefile.in @@ -62,8 +62,8 @@ 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_parameter.yo Zsh/mod_pcre.yo Zsh/mod_regex.yo \ -Zsh/mod_sched.yo Zsh/mod_socket.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 \ Zsh/mod_termcap.yo Zsh/mod_terminfo.yo \ Zsh/mod_zftp.yo Zsh/mod_zle.yo Zsh/mod_zleparameter.yo \ diff --git a/Doc/Zsh/mod_private.yo b/Doc/Zsh/mod_private.yo new file mode 100644 index 000000000..c08da6791 --- /dev/null +++ b/Doc/Zsh/mod_private.yo @@ -0,0 +1,89 @@ +COMMENT(!MOD!zsh/param/private +Builtins for managing private-scoped parameters in function context. +!MOD!) +The tt(zsh/param/private) module is used to create parameters whose scope +is limited to the current function body, and em(not) to other functions +called by the current function. + +This module provides a single autoloaded builtin: +ifnzman() +startitem() +findex(private) +cindex(private parameter, creating) +item(tt(private) [ {tt(PLUS())|tt(-)}tt(AHUahlprtux) ] \ +[ {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. + +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 +(ifzman(zmanref(zshoptions))ifnzman(noderef(Options))). Used inside a +function scope, tt(private) creates a local parameter similar to one +declared with tt(local), except having special properties noted below. + +Special parameters which expose or manipulate internal shell state, such +as tt(ARGC), tt(argv), tt(COLUMNS), tt(LINES), tt(UID), tt(EUID), tt(IFS), +tt(PROMPT), tt(RANDOM), tt(SECONDS), etc., cannot be made private unless +the `tt(-)tt(h)' option is used to hide the special meaning of the +parameter. This may change in the future. +) +enditem() + +As with other tt(typeset) equivalents, tt(private) is both a builtin and a +reserved word, so arrays may be assigned with parenthesized word list +var(name)tt(=LPAR())var(value)...tt(RPAR()) syntax. However, the reserved +word `tt(private)' is not available until tt(zsh/param/private) is loaded, +so care must be taken with order of execution and parsing for function +definitions which use tt(private). To compensate for this, the module +also adds the option `tt(-P)' to the `tt(local)' builtin to declare private +parameters. + +For example, this construction fails if tt(zsh/param/private) has not yet +been loaded when `tt(failing)' is defined: +example(bad_declaration+LPAR()RPAR() { + zmodload zsh/param/private + private array=LPAR() one two three RPAR() +}) + +This construction works because tt(local) is already a keyword, and the +module is loaded before the statement is executed: +example(good_declaration+LPAR()RPAR() { + zmodload zsh/param/private + local -P array=LPAR() one two three RPAR() +}) + +The following is usable in scripts but may have trouble with tt(autoload): +example(zmodload zsh/param/private +iffy_declaration+LPAR()RPAR() { + private array=LPAR() one two three RPAR() +}) + +The tt(private) builtin may always be used with scalar assignments and +for declarations without assignments. + +Parameters declared with tt(private) have the following properties: +ifnzman() +startitemize() +itemiz(Within the function body where it is declared, the parameter +behaves as a local, except as noted above for tied or special parameters.) +itemiz(The type of a parameter declared private cannot be changed in the +scope where it was declared, even if the parameter is unset. Thus an +array cannot be assigned to a private scalar, etc.) +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.) +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.) +enditemize() + +Note that this differs from the static scope defined by compiled languages +derived from C, in that the a new call to the same function creates a new +scope, i.e., the parameter is still associated with the call stack rather +than with the function definition. It differs from ksh `tt(typeset -S)' +because the syntax used to define the function has no bearing on whether +the parameter scope is respected. diff --git a/Src/Modules/param_private.c b/Src/Modules/param_private.c new file mode 100644 index 000000000..7f9aa7921 --- /dev/null +++ b/Src/Modules/param_private.c @@ -0,0 +1,587 @@ +/* + * param_private.c - bindings for private parameter scopes + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 2015 Barton E. Schaefer + * 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 Barton E. Schaefer 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 Barton E. Schaefer and the Zsh + * Development Group have been advised of the possibility of such damage. + * + * Barton E. Schaefer 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 + * Barton E. Schaefer and the Zsh Development Group have no + * obligation to provide maintenance, support, updates, enhancements, or + * modifications. + * + */ + +#include "param_private.mdh" +#include "param_private.pro" + +struct gsu_closure { + union { + struct gsu_scalar s; + struct gsu_integer i; + struct gsu_float f; + struct gsu_array a; + struct gsu_hash h; + } u; + void *g; +}; + +const struct gsu_scalar scalar_private_gsu = +{ pps_getfn, pps_setfn, pps_unsetfn }; + +const struct gsu_integer integer_private_gsu = +{ ppi_getfn, ppi_setfn, ppi_unsetfn }; + +const struct gsu_float float_private_gsu = +{ ppf_getfn, ppf_setfn, ppf_unsetfn }; + +const struct gsu_array array_private_gsu = +{ ppa_getfn, ppa_setfn, ppa_unsetfn }; + +const struct gsu_hash hash_private_gsu = +{ pph_getfn, pph_setfn, pph_unsetfn }; + +/* + * The trick here is: + * + * bin_private() opens a new parameter scope, then calls bin_typeset(). + * + * bin_typeset() handles the usual parameter creation and error checks. + * + * makeprivate() then finds all parameters created in the new scope and + * rejects them if they can't be "promoted" to the surrounding scope. + * Otherwise it swaps out their GSU structure and promotes them so they + * will be removed when the surrounding scope ends. + * + * bin_private() then ends the current scope, which discards any of the + * parameters rejected by makeprivate(). + * + */ + +static int makeprivate_error = 0; + +static void +makeprivate(HashNode hn, UNUSED(int flags)) +{ + Param pm = (Param)hn; + if (pm->level == locallevel) { + if (pm->ename || (pm->node.flags & PM_NORESTORE) || + (pm->old && + (pm->old->level == locallevel - 1 || + ((pm->node.flags & (PM_SPECIAL|PM_REMOVABLE)) == PM_SPECIAL && + /* typeset_single() line 2300 discards PM_REMOVABLE -- why? */ + !is_private(pm->old))))) { + zwarnnam("private", "can't change scope of existing param: %s", + pm->node.nam); + makeprivate_error = 1; + return; + } + struct gsu_closure *gsu = zhalloc(sizeof(struct gsu_closure)); + switch (PM_TYPE(pm->node.flags)) { + case PM_SCALAR: + gsu->g = (void *)(pm->gsu.s); + gsu->u.s = scalar_private_gsu; + pm->gsu.s = (GsuScalar)gsu; + break; + case PM_INTEGER: + gsu->g = (void *)(pm->gsu.i); + gsu->u.i = integer_private_gsu; + pm->gsu.i = (GsuInteger)gsu; + break; + case PM_EFLOAT: + case PM_FFLOAT: + gsu->g = (void *)(pm->gsu.f); + gsu->u.f = float_private_gsu; + pm->gsu.f = (GsuFloat)gsu; + break; + case PM_ARRAY: + gsu->g = (void *)(pm->gsu.a); + gsu->u.a = array_private_gsu; + pm->gsu.a = (GsuArray)gsu; + break; + case PM_HASHED: + gsu->g = (void *)(pm->gsu.h); + gsu->u.h = hash_private_gsu; + pm->gsu.h = (GsuHash)gsu; + break; + default: + makeprivate_error = 1; + break; + } + /* PM_HIDE so new parameters in deeper scopes do not shadow */ + pm->node.flags |= (PM_HIDE|PM_SPECIAL|PM_REMOVABLE); + pm->level -= 1; + } +} + +/**/ +static int +is_private(Param pm) +{ + switch (PM_TYPE(pm->node.flags)) { + case PM_SCALAR: + if (!pm->gsu.s || pm->gsu.s->unsetfn != pps_unsetfn) + return 0; + break; + case PM_INTEGER: + if (!pm->gsu.i || pm->gsu.i->unsetfn != ppi_unsetfn) + return 0; + break; + case PM_EFLOAT: + case PM_FFLOAT: + if (!pm->gsu.f || pm->gsu.f->unsetfn != ppf_unsetfn) + return 0; + break; + case PM_ARRAY: + if (!pm->gsu.a || pm->gsu.a->unsetfn != ppa_unsetfn) + return 0; + break; + case PM_HASHED: + if (!pm->gsu.h || pm->gsu.h->unsetfn != pph_unsetfn) + return 0; + break; + default: + /* error */ + return 0; + } + return 1; +} + +static int fakelevel; + +/**/ +static int +bin_private(char *nam, char **args, LinkList assigns, Options ops, int func) +{ + int from_typeset = 1; + makeprivate_error = 0; + + if (!OPT_ISSET(ops, 'P')) + return bin_typeset(nam, args, assigns, ops, func); + else if (OPT_ISSET(ops, 'T')) { + zwarn("bad option: -T"); + return 1; + } + + if (locallevel == 0) { + if (isset(WARNCREATEGLOBAL)) + zwarnnam(nam, "invalid local scope, using globals"); + return bin_typeset("private", args, assigns, ops, func); + } + + ops->ind['g'] = 2; /* force bin_typeset() to behave as "local" */ + + queue_signals(); + fakelevel = locallevel; + startparamscope(); + from_typeset = bin_typeset("private", args, assigns, ops, func); + scanhashtable(paramtab, 0, 0, 0, makeprivate, 0); + endparamscope(); + fakelevel = 0; + unqueue_signals(); + + return makeprivate_error | from_typeset; +} + +static void +setfn_error(Param pm) +{ + pm->node.flags |= PM_UNSET; + zerr("%s: attempt to assign private in nested scope", pm->node.nam); +} + +/* + * How the GSU functions work: + * + * The getfn and setfn family compare to locallevel and then call through + * to the original getfn or setfn. This means you can't assign at a + * deeper scope to any parameter declared private unless you first declare + * it local again at the new scope. Testing locallevel in getfn is most + * likely unnecessary given the scopeprivate() wrapper installed below. + * + * The unsetfn family compare locallevel and restore the old GSU before + * calling the original unsetfn. This assures that if the old unsetfn + * wants to use its getfn or setfn, they're unconditionally present. + * + */ + +/**/ +static char * +pps_getfn(Param pm) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.s); + GsuScalar gsu = (GsuScalar)(c->g); + + if (locallevel >= pm->level) + return gsu->getfn(pm); + else + return (char *) hcalloc(1); +} + +/**/ +static void +pps_setfn(Param pm, char *x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.s); + GsuScalar gsu = (GsuScalar)(c->g); + if (locallevel == pm->level) + gsu->setfn(pm, x); + else + setfn_error(pm); +} + +/**/ +static void +pps_unsetfn(Param pm, int x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.s); + GsuScalar gsu = (GsuScalar)(c->g); + pm->gsu.s = gsu; + if (locallevel <= pm->level) + gsu->unsetfn(pm, x); +} + +/**/ +static zlong +ppi_getfn(Param pm) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.i); + GsuInteger gsu = (GsuInteger)(c->g); + if (locallevel >= pm->level) + return gsu->getfn(pm); + else + return 0; +} + +/**/ +static void +ppi_setfn(Param pm, zlong x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.i); + GsuInteger gsu = (GsuInteger)(c->g); + if (locallevel == pm->level) + gsu->setfn(pm, x); + else + setfn_error(pm); +} + +/**/ +static void +ppi_unsetfn(Param pm, int x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.i); + GsuInteger gsu = (GsuInteger)(c->g); + pm->gsu.i = gsu; + if (locallevel <= pm->level) + gsu->unsetfn(pm, x); +} + +/**/ +static double +ppf_getfn(Param pm) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.f); + GsuFloat gsu = (GsuFloat)(c->g); + if (locallevel >= pm->level) + return gsu->getfn(pm); + else + return 0; +} + +/**/ +static void +ppf_setfn(Param pm, double x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.f); + GsuFloat gsu = (GsuFloat)(c->g); + if (locallevel == pm->level) + gsu->setfn(pm, x); + else + setfn_error(pm); +} + +/**/ +static void +ppf_unsetfn(Param pm, int x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.f); + GsuFloat gsu = (GsuFloat)(c->g); + pm->gsu.f = gsu; + if (locallevel <= pm->level) + gsu->unsetfn(pm, x); +} + +/**/ +static char ** +ppa_getfn(Param pm) +{ + static char *nullarray = NULL; + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.a); + GsuArray gsu = (GsuArray)(c->g); + if (locallevel >= pm->level) + return gsu->getfn(pm); + else + return &nullarray; +} + +/**/ +static void +ppa_setfn(Param pm, char **x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.a); + GsuArray gsu = (GsuArray)(c->g); + if (locallevel == pm->level) + gsu->setfn(pm, x); + else + setfn_error(pm); +} + +/**/ +static void +ppa_unsetfn(Param pm, int x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.a); + GsuArray gsu = (GsuArray)(c->g); + pm->gsu.a = gsu; + if (locallevel <= pm->level) + gsu->unsetfn(pm, x); +} + +static HashTable emptytable; + +/**/ +static HashTable +pph_getfn(Param pm) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.h); + GsuHash gsu = (GsuHash)(c->g); + if (locallevel >= pm->level) + return gsu->getfn(pm); + else + return emptytable; +} + +/**/ +static void +pph_setfn(Param pm, HashTable x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.h); + GsuHash gsu = (GsuHash)(c->g); + if (locallevel == pm->level) + gsu->setfn(pm, x); + else + setfn_error(pm); +} + +/**/ +static void +pph_unsetfn(Param pm, int x) +{ + struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.h); + GsuHash gsu = (GsuHash)(c->g); + pm->gsu.h = gsu; + if (locallevel <= pm->level) + gsu->unsetfn(pm, x); +} + +/* + * How visibility works: + * + * Upon entering a new function scope, we find all the private parameters + * at this locallevel. Any that we find are marked PM_UNSET. If they are + * already unset, they are also marked as PM_NORESTORE. + * + * On exit from the scope, we find the same parameters again and remove + * the PM_UNSET and PM_NORESTORE flags as appropriate. We're guaraneed + * by makeprivate() that PM_NORESTORE won't conflict with anything here. + * + */ + +static void +scopeprivate(HashNode hn, int onoff) +{ + Param pm = (Param)hn; + if (pm->level == locallevel) { + if (!is_private(pm)) + return; + if (onoff == PM_UNSET) + if (pm->node.flags & PM_UNSET) + pm->node.flags |= PM_NORESTORE; + else + pm->node.flags |= PM_UNSET; + else if (!(pm->node.flags & PM_NORESTORE)) + pm->node.flags &= ~PM_UNSET; + pm->node.flags &= ~PM_NORESTORE; + } +} + +static struct funcwrap wrapper[] = { + WRAPDEF(wrap_private) +}; + +/**/ +static int +wrap_private(Eprog prog, FuncWrap w, char *name) +{ + static int wraplevel = 0; + + if (wraplevel < locallevel /* && strcmp(name, "(anon)") != 0 */) { + int owl = wraplevel; + wraplevel = locallevel; + scanhashtable(paramtab, 0, 0, 0, scopeprivate, PM_UNSET); + runshfunc(prog, w, name); + scanhashtable(paramtab, 0, 0, 0, scopeprivate, 0); + wraplevel = owl; + return 0; + } + return 1; +} + +static HashNode (*getparamnode) _((HashTable, const char *)); + +/**/ +static HashNode +getprivatenode(HashTable ht, const char *nam) +{ + HashNode hn = getparamnode(ht, nam); + Param pm = (Param) hn; + + while (!fakelevel && pm && locallevel > pm->level && is_private(pm)) + pm = pm->old; + return (HashNode)pm; +} + +/**/ +static HashNode +getprivatenode2(HashTable ht, const char *nam) +{ + /* getparamnode() would follow autoloads, we must not do that here */ + HashNode hn = gethashnode2(ht, nam); + Param pm = (Param) hn; + + while (!fakelevel && pm && locallevel > pm->level && is_private(pm)) + pm = pm->old; + return (HashNode)pm; +} + +/**/ +static void +printprivatenode(HashNode hn, int printflags) +{ + Param pm = (Param) hn; + while (pm && (!fakelevel || + (fakelevel > pm->level && (pm->node.flags & PM_UNSET))) && + locallevel > pm->level && is_private(pm)) + pm = pm->old; + /* Ideally, we'd print the word "private" here instead of "typeset" + * when the parameter is in fact a private, but that would require + * re-implementing the entirety of printparamnode(). */ + if (pm) + printparamnode((HashNode)pm, printflags); +} + +/* + * Standard module configuration/linkage + */ + +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") +}; + +static struct features module_features = { + bintab, sizeof(bintab)/sizeof(*bintab), + NULL, 0, + NULL, 0, + NULL, 0, + 0 +}; + +static struct builtin save_local; +static struct reswd reswd_private = {{NULL, "private", 0}, TYPESET}; + +/**/ +int +setup_(UNUSED(Module m)) +{ + HashNode hn = builtintab->getnode(builtintab, "local"); + + /* Horrible, horrible hack */ + getparamnode = realparamtab->getnode; + realparamtab->getnode = getprivatenode; + realparamtab->getnode2 = getprivatenode2; + realparamtab->printnode = printprivatenode; + + /* Even more horrible hack */ + save_local = *(Builtin)hn; + ((Builtin)hn)->handlerfunc = bintab[0].handlerfunc; + ((Builtin)hn)->optstr = bintab[0].optstr; + + reswdtab->addnode(reswdtab, reswd_private.node.nam, &reswd_private); + + 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_(Module m) +{ + emptytable = newparamtable(1, "private"); + return addwrapper(m, wrapper); +} + +/**/ +int +cleanup_(Module m) +{ + HashNode hn = builtintab->getnode(builtintab, "local"); + *(Builtin)hn = save_local; + + removehashnode(reswdtab, "private"); + + realparamtab->getnode = getparamnode; + realparamtab->getnode2 = gethashnode2; + realparamtab->printnode = printparamnode; + + deletewrapper(m, wrapper); + return setfeatureenables(m, &module_features, NULL); +} + +/**/ +int +finish_(UNUSED(Module m)) +{ + deletehashtable(emptytable); + return 0; +} diff --git a/Src/Modules/param_private.mdd b/Src/Modules/param_private.mdd new file mode 100644 index 000000000..e6eb3228f --- /dev/null +++ b/Src/Modules/param_private.mdd @@ -0,0 +1,7 @@ +name=zsh/param/private +link=dynamic +load=yes + +autofeatures="b:private" + +objects="param_private.o" diff --git a/Test/V10private.ztst b/Test/V10private.ztst new file mode 100644 index 000000000..444b5b4ea --- /dev/null +++ b/Test/V10private.ztst @@ -0,0 +1,265 @@ +# Tests for the zsh/param/private module + +%prep + + zmodload zsh/param/private + +%test + + (zmodload -u zsh/param/private && zmodload zsh/param/private) +0:unload and reload the module without crashing + + typeset scalar_test=toplevel + () { + print $scalar_test + private scalar_test + print $+scalar_test + unset scalar_test + print $+scalar_test + } + print $scalar_test +0:basic scope hiding +>toplevel +>1 +>0 +>toplevel + + typeset scalar_test=toplevel + print $scalar_test + () { + private scalar_test=function + print $scalar_test + } + print $scalar_test +0:enter and exit a scope +>toplevel +>function +>toplevel + + print $+unset_test + () { + private unset_test + print $+unset_test + unset_test=setme + print $unset_test + } + print $+unset_test +0:variable defined only in scope +>0 +>1 +>setme +>0 + + # Depends on zsh-5.0.9 typeset keyword + typeset -a array_test=(top level) + () { + local -Pa array_test=(in function) + () { + private array_test + print $+array_test + } + print $array_test + } + print $array_test +0:nested scope with different type, correctly restored +>1 +>in function +>top level + + typeset -a array_test=(top level) + () { + private array_test + array_test=(in function) + } +1:type of private may not be changed by assignment +?(anon):2: array_test: attempt to assign array value to non-array + + typeset -A hash_test=(top level) + () { + setopt localoptions noglob + private hash_test[top] + } +1:associative array fields may not be private +?(anon):private:2: hash_test[top]: can't create local array elements + + () { + private path + } +1:tied params may not be private, part 1 +?(anon):private:1: can't change scope of existing param: path + + () { + private PATH + } +1:tied params may not be private, part 2 +?(anon):private:1: can't change scope of existing param: PATH + + () { + private -h path + print X$path + } +0:privates may hide tied paramters +>X + + # Deliberate type mismatch here + typeset -a hash_test=(top level) + typeset -p hash_test + inner () { + private -p hash_test + print ${(t)hash_test} ${(kv)hash_test} + } + outer () { + local -PA hash_test=(in function) + typeset -p hash_test + inner + } + outer + print ${(kv)hash_test} +0:private hides value from surrounding scope in nested scope +>typeset -a hash_test +>hash_test=( top level ) +>typeset -A hash_test +>hash_test=( in function ) +>typeset -a hash_test +>hash_test=( top level ) +>array-local top level +>top level +F:note "typeset" rather than "private" in output from outer + + () { + private -a array_test + local array_test=scalar + } +1:private cannot be re-declared as local +?(anon):local:2: array_test: inconsistent type for assignment + + () { + local hash_test=scalar + private -A hash_test + } +1:local cannot be re-declared as private +?(anon):private:2: can't change scope of existing param: hash_test + + inner () { + print $+scalar_test + $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test' + } + () { + private -x scalar_test=whaat + $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test' + inner + print Y $scalar_test + } +0:exported private behaves like a local, part 1 +>X whaat +>0 +>X whaat +>Y whaat + + inner () { + typeset -p array_test + $ZTST_testdir/../Src/zsh -fc 'print X $array_test' + } + () { + local -Pax array_test=(whaat) + print Y $array_test + $ZTST_testdir/../Src/zsh -fc 'print X $array_test' + inner + } +0:exported private behaves like a local, part 2 (arrays do not export) +?inner:typeset:1: no such variable: array_test +>Y whaat +>X +>X + + inner () { + print $+scalar_test + $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test' + } + () { + private scalar_test=whaat + export scalar_test + $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test' + inner + () { + print $+scalar_test + $ZTST_testdir/../Src/zsh -fc 'print X $scalar_test' + } + print Y $scalar_test + } +0:exported private behaves like a local, part 3 (export does not change scope) +>X whaat +>0 +>X whaat +>0 +>X whaat +>Y whaat + + typeset -A hash_test=(top level) + () { + local -PA hash_test=(in function) + () { + print X ${(kv)hash_test} + } + print Y ${(kv)hash_test} + } + print ${(kv)hash_test} +0:privates are not visible in anonymous functions, part 1 +>X top level +>Y in function +>top level + + typeset -A hash_test=(top level) + () { + local -PA hash_test=(in function) + () { + print X ${(kv)hash_test} + hash_test[in]=deeper + } + print Y ${(kv)hash_test} + } + print ${(okv)hash_test} +0:privates are not visible in anonymous functions, part 2 +>X top level +>Y in function +>deeper in level top + + typeset -A hash_test=(top level) + () { + local -Pa array_test=(in function) + local -PA hash_test=($array_test) + () { + print X ${(kv)hash_test} + hash_test=(even deeper) + array_test+=(${(kv)hash_test}) + } + print Y ${(kv)hash_test} Z $array_test + } + print ${(kv)hash_test} +0:privates are not visible in anonymous functions, part 3 +>X top level +>Y in function Z in function +>even deeper + + typeset -A hash_test=(top level) + () { + local -PA hash_test=(in function) + () { + print X ${(kv)hash_test} + unset hash_test + } + print Y ${(kv)hash_test} + } + print ${(t)hash_test} ${(kv)hash_test} +0:privates are not visible in anonymous functions, part 4 +>X top level +>Y in function +> + + # Subshell because otherwise this silently dumps core when broken + ( () { private SECONDS } ) +1:special parameters cannot be made private +?(anon):private: can't change scope of existing param: SECONDS + + () { private -h SECONDS } +0:private parameter may hide a special parameter -- cgit v1.2.3 From 623d3185814963898655457abcd6577703312a2d Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Mon, 9 Nov 2015 23:48:24 +0900 Subject: 37085: fix doc: DEBUG_BEFORE_CMD is set by default --- ChangeLog | 5 +++++ Doc/Zsh/options.yo | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 622b0dbd8..0eca17064 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-09 Jun-ichi Takimoto + + * 37085: Doc/Zsh/options.yo: DEBUG_BEFORE_CMD is set by default. + Also fix entries in the option index. + 2015-11-08 Barton E. Schaefer * 37081: Doc/Makefile.in, Doc/Zsh/mod_private.yo, diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 60379cabc..f37753991 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1568,13 +1568,13 @@ ifnzman(noderef(Arithmetic Evaluation))\ ifzman(the section ARITHMETIC EVALUATION in zmanref(zshmisc)) has an explicit list. ) -pindex(DEBUG_BEFORE_CMD ) -pindex(NO_DEBUG_BEFORE_CMD ) -pindex(DEBUGBEFORECMD ) -pindex(NODEBUGBEFORECMD ) +pindex(DEBUG_BEFORE_CMD) +pindex(NO_DEBUG_BEFORE_CMD) +pindex(DEBUGBEFORECMD) +pindex(NODEBUGBEFORECMD) cindex(traps, DEBUG, before or after command) cindex(DEBUG trap, before or after command) -item(tt(DEBUG_BEFORE_CMD))( +item(tt(DEBUG_BEFORE_CMD) )( Run the tt(DEBUG) trap before each command; otherwise it is run after each command. Setting this option mimics the behaviour of ksh 93; with the option unset the behaviour is that of ksh 88. -- cgit v1.2.3 From 6783c4538f6aa18d97798e2a0362dfa7487644d3 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Mon, 9 Nov 2015 10:07:17 -0800 Subject: Jun T. proofreading --- ChangeLog | 6 +++++- Doc/Zsh/mod_private.yo | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 622b0dbd8..14e6afea4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ -2015-11-08 Barton E. Schaefer +2015-11-09 Barton E. Schaefer + + * unposted (cf. Jun T.: 37083): Doc/Zsh/mod_private.yo: proofreading + +2015-11-08 Barton E. Schaefer * 37081: Doc/Makefile.in, Doc/Zsh/mod_private.yo, Src/Modules/param_private.c, Src/Modules/param_private.mdd, diff --git a/Doc/Zsh/mod_private.yo b/Doc/Zsh/mod_private.yo index c08da6791..78aee0acf 100644 --- a/Doc/Zsh/mod_private.yo +++ b/Doc/Zsh/mod_private.yo @@ -41,7 +41,7 @@ also adds the option `tt(-P)' to the `tt(local)' builtin to declare private parameters. For example, this construction fails if tt(zsh/param/private) has not yet -been loaded when `tt(failing)' is defined: +been loaded when `tt(bad_declaration)' is defined: example(bad_declaration+LPAR()RPAR() { zmodload zsh/param/private private array=LPAR() one two three RPAR() -- cgit v1.2.3 From 5ed0cb8bc5eab686937ba8c857b482b031d05e45 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 10 Nov 2015 09:32:04 +0000 Subject: 37084: add implementation check to zsh/parm/private test --- ChangeLog | 5 +++++ Test/V10private.ztst | 3 +++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5b193ab7c..e05ccd77b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-10 Peter Stephenson + + * 37084: Test/V10private.ztst: add check for zsh/param/private + implementation to test. + 2015-11-09 Jun-ichi Takimoto * 37085: Doc/Zsh/options.yo: DEBUG_BEFORE_CMD is set by default. diff --git a/Test/V10private.ztst b/Test/V10private.ztst index 444b5b4ea..6c38e3974 100644 --- a/Test/V10private.ztst +++ b/Test/V10private.ztst @@ -2,6 +2,9 @@ %prep + if ! (zmodload zsh/param/private >/dev/null 2>/dev/null); then + ZTST_unimplemented="can't load the zsh/param/private module for testing" + fi zmodload zsh/param/private %test -- cgit v1.2.3 From f1312d1e2272ba97b08396328c2bf25f433f1c8c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 11 Nov 2015 16:09:28 +0000 Subject: 37091: clear lastline and lastlinesz when freeing --- Src/Zle/zle_utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index ffff8fd1c..6e9a98bde 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -1436,6 +1436,8 @@ freeundo(void) freechanges(changes); freechanges(nextchanges); zfree(lastline, lastlinesz); + lastline = NULL; + lastlinesz = 0; } /**/ -- cgit v1.2.3 From f30b1bc7d16f6eab195f47dfd812527d69b0b315 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 11 Nov 2015 17:38:13 +0000 Subject: missed log entry --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index e05ccd77b..5f6c59c0a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-11 Peter Stephenson + + * 37091: Src/Zle/zle_utils.c: clear lastline and lastlinesz when + freeing. + 2015-11-10 Peter Stephenson * 37084: Test/V10private.ztst: add check for zsh/param/private -- cgit v1.2.3 From 830d54e629e8e12eb5a219a65a013876662e7b3e Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 11 Nov 2015 18:04:20 +0000 Subject: 37092: make nested ${(P)name} properly refer to parameter on return --- ChangeLog | 5 +++ Doc/Zsh/expn.yo | 11 ++++- Src/Zle/compctl.c | 4 +- Src/Zle/zle_tricky.c | 2 +- Src/cond.c | 2 +- Src/exec.c | 16 ++++---- Src/glob.c | 2 +- Src/subst.c | 114 +++++++++++++++++++++++++++++++-------------------- Src/zsh.h | 51 +++++++++++++++++------ 9 files changed, 138 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5f6c59c0a..e9bef7d68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2015-11-11 Peter Stephenson + * 37092: Doc/Zsh/expn.yo, Src/Zle/compctl.c, + Src/Zle/zle_tricky.c, Src/cond.c, Src/exec.c, Src/glob.c, + Src/subst.c, Src/zsh.h: make a ${(P)name} subexpression properly + refer to a parameter name. + * 37091: Src/Zle/zle_utils.c: clear lastline and lastlinesz when freeing. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 20e0c8d35..4c373d1f2 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1033,7 +1033,16 @@ var(name) used in this fashion. If used with a nested parameter or command substitution, the result of that will be taken as a parameter name in the same way. For example, if you have `tt(foo=bar)' and `tt(bar=baz)', the strings tt(${(P)foo}), -tt(${(P)${foo}}), and tt(${(P)$(echo bar)}) will be expanded to `tt(baz)'. +tt(${(P)${foo}}), and tt(${(P)$(echo bar)}) will be expanded to +`tt(baz)'. + +Likewise, if the reference is itself nested, the expression with the +flag is treated as if it were directly replaced by the parameter name. +It is an error if this nested substitution produces an array with more +than one word. For example, if `tt(name=assoc)' where the parameter +tt(assoc) is an associative array, then +`tt(${${(P)name}[elt]})' refers to the element of the associative +subscripted `tt(elt)'. ) item(tt(q))( Quote characters that are special to the shell in the resulting words with diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index bac533e7e..8381867d0 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -2116,7 +2116,7 @@ getreal(char *str) noerrs = 1; addlinknode(l, dupstring(str)); - prefork(l, 0); + prefork(l, 0, NULL); noerrs = ne; if (!errflag && nonempty(l) && ((char *) peekfirst(l)) && ((char *) peekfirst(l))[0]) @@ -3728,7 +3728,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) errflag &= ~ERRFLAG_ERROR; zcontext_restore(); /* Fine, now do full expansion. */ - prefork(foo, 0); + prefork(foo, 0, NULL); if (!errflag) { globlist(foo, 0); if (!errflag) diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index e26f66379..4e6854928 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -2223,7 +2223,7 @@ doexpansion(char *s, int lst, int olst, int explincmd) else if (*ts == '\'') *ts = Snull; addlinknode(vl, ss); - prefork(vl, 0); + prefork(vl, 0, NULL); if (errflag) goto end; if (lst == COMP_LIST_EXPAND || lst == COMP_EXPAND) { diff --git a/Src/cond.c b/Src/cond.c index df9065660..c5ab65eea 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -43,7 +43,7 @@ static void cond_subst(char **strp, int glob_ok) checkglobqual(*strp, strlen(*strp), 1, NULL)) { LinkList args = newlinklist(); addlinknode(args, *strp); - prefork(args, 0); + prefork(args, 0, NULL); while (!errflag && args && nonempty(args) && has_token((char *)peekfirst(args))) zglob(args, firstnode(args), 0); diff --git a/Src/exec.c b/Src/exec.c index f0d1d2f70..c0ee527b7 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -2290,7 +2290,7 @@ addvars(Estate state, Wordcode pc, int addflags) if (vl && htok) { prefork(vl, (isstr ? (PREFORK_SINGLE|PREFORK_ASSIGN) : - PREFORK_ASSIGN)); + PREFORK_ASSIGN), NULL); if (errflag) { state->pc = opc; return; @@ -2416,7 +2416,7 @@ void execsubst(LinkList strs) { if (strs) { - prefork(strs, esprefork); + prefork(strs, esprefork, NULL); if (esglob && !errflag) { LinkList ostrs = strs; globlist(strs, 0); @@ -2721,7 +2721,7 @@ execcmd(Estate state, int input, int output, int how, int last1) /* Do prefork substitutions */ esprefork = (assign || isset(MAGICEQUALSUBST)) ? PREFORK_TYPESET : 0; if (args && htok) - prefork(args, esprefork); + prefork(args, esprefork, NULL); if (type == WC_SIMPLE || type == WC_TYPESET) { int unglobbed = 0; @@ -3558,7 +3558,7 @@ execcmd(Estate state, int input, int output, int how, int last1) */ /* Unused dummy value for name */ (void)ecgetstr(state, EC_DUPTOK, &htok); - prefork(&svl, PREFORK_TYPESET); + prefork(&svl, PREFORK_TYPESET, NULL); if (errflag) { state->pc = opc; break; @@ -3584,7 +3584,7 @@ execcmd(Estate state, int input, int output, int how, int last1) } continue; } - prefork(&svl, PREFORK_SINGLE); + prefork(&svl, PREFORK_SINGLE, NULL); name = empty(&svl) ? "" : (char *)getdata(firstnode(&svl)); } @@ -3600,7 +3600,9 @@ execcmd(Estate state, int input, int output, int how, int last1) } else { if (htok) { init_list1(svl, val); - prefork(&svl, PREFORK_SINGLE|PREFORK_ASSIGN); + prefork(&svl, + PREFORK_SINGLE|PREFORK_ASSIGN, + NULL); if (errflag) { state->pc = opc; break; @@ -3622,7 +3624,7 @@ execcmd(Estate state, int input, int output, int how, int last1) EC_DUPTOK, &htok); if (asg->value.array) { - prefork(asg->value.array, PREFORK_ASSIGN); + prefork(asg->value.array, PREFORK_ASSIGN, NULL); if (errflag) { state->pc = opc; break; diff --git a/Src/glob.c b/Src/glob.c index 51ffeb5d5..94b3f620d 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2093,7 +2093,7 @@ xpandredir(struct redir *fn, LinkList redirtab) /* Stick the name in a list... */ init_list1(fake, fn->name); /* ...which undergoes all the usual shell expansions */ - prefork(&fake, isset(MULTIOS) ? 0 : PREFORK_SINGLE); + prefork(&fake, isset(MULTIOS) ? 0 : PREFORK_SINGLE, NULL); /* Globbing is only done for multios. */ if (!errflag && isset(MULTIOS)) globlist(&fake, 0); diff --git a/Src/subst.c b/Src/subst.c index febdc9bea..f3a4ad44d 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -44,15 +44,23 @@ char nulstring[] = {Nularg, '\0'}; * - Brace expansion * - Tilde and equals substitution * - * PREFORK_* flags are defined in zsh.h + * "flag"s contains PREFORK_* flags, defined in zsh.h. + * + * "ret_flags" is used to return values from nested parameter + * substitions. It may be NULL in which case PREFORK_SUBEXP + * must not appear in flags; any return value from below + * will be discarded. */ /**/ mod_export void -prefork(LinkList list, int flags) +prefork(LinkList list, int flags, int *ret_flags) { LinkNode node, stop = 0; int keep = 0, asssub = (flags & PREFORK_TYPESET) && isset(KSHTYPESET); + int ret_flags_local = 0; + if (!ret_flags) + ret_flags = &ret_flags_local; /* will be discarded */ queue_signals(); for (node = firstnode(list); node; incnode(node)) { @@ -75,10 +83,8 @@ prefork(LinkList list, int flags) setdata(node, cptr); } if (!(node = stringsubst(list, node, - flags & (PREFORK_SINGLE|PREFORK_SPLIT| - PREFORK_SHWORDSPLIT| - PREFORK_NOSHWORDSPLIT), - asssub))) { + flags & ~(PREFORK_TYPESET|PREFORK_ASSIGN), + ret_flags, asssub))) { unqueue_signals(); return; } @@ -149,7 +155,8 @@ stringsubstquote(char *strstart, char **pstrdpos) /**/ static LinkNode -stringsubst(LinkList list, LinkNode node, int pf_flags, int asssub) +stringsubst(LinkList list, LinkNode node, int pf_flags, int *ret_flags, + int asssub) { int qt; char *str3 = (char *)getdata(node); @@ -235,7 +242,8 @@ stringsubst(LinkList list, LinkNode node, int pf_flags, int asssub) pf_flags |= PREFORK_SHWORDSPLIT; node = paramsubst( list, node, &str, qt, - pf_flags & (PREFORK_SINGLE|PREFORK_SHWORDSPLIT)); + pf_flags & (PREFORK_SINGLE|PREFORK_SHWORDSPLIT| + PREFORK_SUBEXP), ret_flags); if (errflag || !node) return NULL; str3 = (char *)getdata(node); @@ -413,29 +421,13 @@ singsub(char **s) init_list1(foo, *s); - prefork(&foo, PREFORK_SINGLE); + prefork(&foo, PREFORK_SINGLE, NULL); if (errflag) return; *s = (char *) ugetnode(&foo); DPUTS(nonempty(&foo), "BUG: singsub() produced more than one word!"); } -/* - * Bit flags passed back from multsub() to paramsubst(). - */ -enum { - /* - * Set if the string had whitespace at the start - * that should cause word splitting against any preceeding string. - */ - WS_AT_START = 1, - /* - * Set if the string had whitespace at the end - * that should cause word splitting against any following string. - */ - WS_AT_END = 2 -}; - /* Perform substitution on a single word, *s. Unlike with singsub(), the * result can be more than one word. If split is non-zero, the string is * first word-split using IFS, but only for non-quoted "whitespace" (as @@ -448,13 +440,13 @@ enum { * NULL to use IFS). The return value is true iff the expansion resulted * in an empty list. * - * *ws_at_start is set to bits in the enum above as neeed. + * *ms_flags is set to bits in the enum above as neeed. */ /**/ static int multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, - int *ws_sub) + int *ms_flags) { int l; char **r, **p, *x = *s; @@ -470,7 +462,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, l++; if (!iwsep(STOUC(c))) break; - *ws_sub |= WS_AT_START; + *ms_flags |= MULTSUB_WS_AT_START; } } @@ -503,7 +495,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, break; } if (!*x) { - *ws_sub |= WS_AT_END; + *ms_flags |= MULTSUB_WS_AT_END; break; } insertlinknode(&foo, n, (void *)x), incnode(n); @@ -532,7 +524,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, } } - prefork(&foo, pf_flags); + prefork(&foo, pf_flags, ms_flags); if (errflag) { if (isarr) *isarr = 0; @@ -1517,7 +1509,8 @@ check_colon_subscript(char *str, char **endp) /**/ static LinkNode -paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) +paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, + int *ret_flags) { char *aptr = *str, c, cc; char *s = aptr, *fstr, *idbeg, *idend, *ostr = (char *) getdata(n); @@ -1747,7 +1740,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * whitespace. However, if there's no "x" the whitespace is * simply removed. */ - int ws_sub = 0; + int ms_flags = 0; *s++ = '\0'; /* @@ -2296,8 +2289,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * remove the aspar test and extract a value from an array, if * necessary, when we handle (P) lower down. */ - if (multsub(&val, 0, (aspar ? NULL : &aval), &isarr, NULL, - &ws_sub) && quoted) { + if (multsub(&val, PREFORK_SUBEXP, (aspar ? NULL : &aval), &isarr, NULL, + &ms_flags) && quoted) { /* Empty quoted string --- treat as null string, not elided */ isarr = -1; aval = (char **) hcalloc(sizeof(char *)); @@ -2311,6 +2304,28 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) */ while (inull(*s)) s++; + if (ms_flags & MULTSUB_PARAM_NAME) { + /* + * Downbelow has told us this is a parameter name, e.g. + * ${${(P)name}...}. We're going to behave as if + * we have exactly that name followed by the rest of + * the parameter for subscripting etc. + * + * See below for where we set the flag in the nested + * substitution. + */ + if (isarr) { + if (aval[1]) { + zerr("parameter name reference used with array"); + return NULL; + } + val = aval[0]; + isarr = 0; + } + s = dyncat(val, s); + /* Now behave po-faced as if it was always like that... */ + subexp = aspar = 0; + } v = (Value) NULL; } else if (aspar) { /* @@ -2328,13 +2343,24 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) } else vunset = 1; } + if (aspar && (pf_flags & PREFORK_SUBEXP)) { + /* + * This is the inner handling for the case referred to above + * where we have something like ${${(P)name}...}. + * + * Treat this as as a normal value here; all transformations on + * result are in outer instance. + */ + aspar = 0; + *ret_flags |= MULTSUB_PARAM_NAME; + } /* * We need to retrieve a value either if we haven't already * got it from a subexpression, or if the processing so * far has just yielded us a parameter name to be processed * with (P). */ - if (!subexp || aspar) { + else if (!subexp || aspar) { char *ov = val; /* @@ -2768,7 +2794,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) split_flags = PREFORK_NOSHWORDSPLIT; } multsub(&val, split_flags, (aspar ? NULL : &aval), - &isarr, NULL, &ws_sub); + &isarr, NULL, &ms_flags); copied = 1; spbreak = 0; /* Leave globsubst on if forced */ @@ -2797,14 +2823,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * behavior on caller choice of PREFORK_SHWORDSPLIT. */ multsub(&val, spbreak ? PREFORK_SINGLE : PREFORK_NOSHWORDSPLIT, - NULL, &isarr, NULL, &ws_sub); + NULL, &isarr, NULL, &ms_flags); } else { if (spbreak) split_flags = PREFORK_SPLIT|PREFORK_SHWORDSPLIT; else split_flags = PREFORK_NOSHWORDSPLIT; multsub(&val, split_flags, &aval, &isarr, NULL, - &ws_sub); + &ms_flags); spbreak = 0; } if (arrasg) { @@ -3336,7 +3362,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) } if (haserr || errflag) return NULL; - ws_sub = 0; + ms_flags = 0; } /* * This handles taking a length with ${#foo} and variations. @@ -3375,7 +3401,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) sprintf(buf, "%ld", len); val = dupstring(buf); isarr = 0; - ws_sub = 0; + ms_flags = 0; } /* At this point we make sure that our arrayness has affected the * arrayness of the linked list. Then, we can turn our value into @@ -3405,7 +3431,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) if (isarr) { val = sepjoin(aval, sep, 1); isarr = 0; - ws_sub = 0; + ms_flags = 0; } if (!ssub && (spbreak || spsep)) { aval = sepsplit(val, spsep, 0, 1); @@ -3690,12 +3716,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * If a multsub result had whitespace at the start and we're * splitting and there's a previous string, now's the time to do so. */ - if ((ws_sub & WS_AT_START) && aptr > ostr) { + if ((ms_flags & MULTSUB_WS_AT_START) && aptr > ostr) { insertlinknode(l, n, dupstrpfx(ostr, aptr - ostr)), incnode(n); ostr = aptr; } /* Likewise at the end */ - if ((ws_sub & WS_AT_END) && *fstr) { + if ((ms_flags & MULTSUB_WS_AT_END) && *fstr) { insertlinknode(l, n, dupstring(fstr)); /* appended, no incnode */ *fstr = '\0'; } @@ -3777,7 +3803,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) *--fstr = Marker; init_list1(tl, fstr); - if (!eval && !stringsubst(&tl, firstnode(&tl), ssub, 0)) + if (!eval && !stringsubst(&tl, firstnode(&tl), ssub, ret_flags, 0)) return NULL; *str = aptr; tn = firstnode(&tl); diff --git a/Src/zsh.h b/Src/zsh.h index a6f039741..d3bfcefcc 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1866,18 +1866,45 @@ enum { }; /* Flags as the second argument to prefork */ -/* argument handled like typeset foo=bar */ -#define PREFORK_TYPESET 0x01 -/* argument handled like the RHS of foo=bar */ -#define PREFORK_ASSIGN 0x02 -/* single word substitution */ -#define PREFORK_SINGLE 0x04 -/* explicitly split nested substitution */ -#define PREFORK_SPLIT 0x08 -/* SHWORDSPLIT in parameter expn */ -#define PREFORK_SHWORDSPLIT 0x10 -/* SHWORDSPLIT forced off in nested subst */ -#define PREFORK_NOSHWORDSPLIT 0x20 +enum { + /* argument handled like typeset foo=bar */ + PREFORK_TYPESET = 0x01, + /* argument handled like the RHS of foo=bar */ + PREFORK_ASSIGN = 0x02, + /* single word substitution */ + PREFORK_SINGLE = 0x04, + /* explicitly split nested substitution */ + PREFORK_SPLIT = 0x08, + /* SHWORDSPLIT in parameter expn */ + PREFORK_SHWORDSPLIT = 0x10, + /* SHWORDSPLIT forced off in nested subst */ + PREFORK_NOSHWORDSPLIT = 0x20, + /* Prefork is part of a parameter subexpression */ + PREFORK_SUBEXP = 0x40 +}; + +/* + * Bit flags passed back from multsub() to paramsubst(). + * Some flags go from a nested parmsubst() through the enclosing + * stringsubst() and prefork(). + */ +enum { + /* + * Set if the string had whitespace at the start + * that should cause word splitting against any preceeding string. + */ + MULTSUB_WS_AT_START = 1, + /* + * Set if the string had whitespace at the end + * that should cause word splitting against any following string. + */ + MULTSUB_WS_AT_END = 2, + /* + * Set by nested paramsubst() to indicate the return + * value is a parameter name, rather than a value. + */ + MULTSUB_PARAM_NAME = 4 +}; /* * Structure for adding parameters in a module. -- cgit v1.2.3 From 7a951ef93ef2cc6baac9ec3b51909ad44e4bfe15 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 11 Nov 2015 22:14:16 +0000 Subject: 37094: Further tweaks to parameter name references. Safety in array test. Make nested references work. Add parameter tests. --- Src/subst.c | 6 +++--- Test/D04parameter.ztst | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Src/subst.c b/Src/subst.c index f3a4ad44d..c1369b5a7 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2315,7 +2315,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, * substitution. */ if (isarr) { - if (aval[1]) { + if (aval[0] && aval[1]) { zerr("parameter name reference used with array"); return NULL; } @@ -2324,7 +2324,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, } s = dyncat(val, s); /* Now behave po-faced as if it was always like that... */ - subexp = aspar = 0; + subexp = 0; } v = (Value) NULL; } else if (aspar) { @@ -2360,7 +2360,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, * far has just yielded us a parameter name to be processed * with (P). */ - else if (!subexp || aspar) { + if (!subexp || aspar) { char *ov = val; /* diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 694b613c5..6f325d293 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1798,3 +1798,52 @@ >1: x bar y >1: x bar bar y >1: x bar y + + testfn() { + local scalar=obfuscation + local -a array=(alpha bravo charlie delta echo foxtrot) + local -A assoc=(one eins two zwei three drei four vier) + local name subscript + for name subscript in scalar 3 array 5 assoc three; do + print ${${(P)name}[$subscript]} + done + } + testfn +0:${(P)...} with normal subscripting +>f +>echo +>drei + + testfn() { + local s1=foo s2=bar + local -a val=(s1) + print ${${(P)val}[1,3]} + val=(s1 s2) + print ${${(P)val}[1,3]} + } + testfn +1:${(P)...} with array as name +>foo +?testfn:5: parameter name reference used with array + + testfn() { + local -A assoc=(one buckle two show three knock four door) + local name='assoc[two]' + print ${${(P)name}[2,3]} + } + testfn +0:${(P)...} with internal subscripting +>ho + + testfn() { + local one=two + local two=three + local three=four + local -a four=(all these worlds belong to foo) + print ${${(P)${(P)${(P)one}}}} + print ${${(P)${(P)${(P)one}}}[3]} + } + testfn +0:nested parameter name references +>all these worlds belong to foo +>worlds -- cgit v1.2.3 From d814071b1420418a3243642a5cdeb3946e7d1939 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 12 Nov 2015 14:28:15 +0000 Subject: 37096: Another $${(P)...} tweak. Make a top level (P) work with nested ones, i.e. ${(P)${(P)...}...} --- ChangeLog | 8 ++++++++ Src/subst.c | 19 +++++++++++++++++-- Test/D04parameter.ztst | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9bef7d68..5397c6c51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2015-11-12 Peter Stephenson + + * 37096: Src/subst.c, Test/D04parameter.ztst: make top-level + ${(P)...} with nested ${(P)...} to the right thing. + + * 37094: Src/subst.c, Test/D04parameter.ztst: Further tweaks to + parameter name references: array safety; nested parameters; tests. + 2015-11-11 Peter Stephenson * 37092: Doc/Zsh/expn.yo, Src/Zle/compctl.c, diff --git a/Src/subst.c b/Src/subst.c index c1369b5a7..b7f8338c7 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1741,6 +1741,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, * simply removed. */ int ms_flags = 0; + /* + * We need to do an extra fetch to honour the (P) flag. + * Complicated by the use of subexpressions that may have + * nested (P) flags. + */ + int fetch_needed; *s++ = '\0'; /* @@ -2325,9 +2331,18 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, s = dyncat(val, s); /* Now behave po-faced as if it was always like that... */ subexp = 0; - } + /* + * If this is a (P) (first test) and at the top level + * (second test) we can't rely on the caller fetching + * the result from the pending aspar. So do it below. + */ + fetch_needed = aspar && !(pf_flags & PREFORK_SUBEXP); + } else + fetch_needed = 0; /* any initial aspar fetch already done */ v = (Value) NULL; - } else if (aspar) { + } else + fetch_needed = aspar; /* aspar fetch still needed */ + if (fetch_needed) { /* * No subexpression, but in any case the value is going * to give us the name of a parameter on which we do diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 6f325d293..210c0d854 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1840,7 +1840,7 @@ local two=three local three=four local -a four=(all these worlds belong to foo) - print ${${(P)${(P)${(P)one}}}} + print ${(P)${(P)${(P)one}}} print ${${(P)${(P)${(P)one}}}[3]} } testfn -- cgit v1.2.3 From ff85c8b1c99bd655a64564fc8beba3167d229c23 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Fri, 13 Nov 2015 00:16:20 +0900 Subject: 37090: correctly handle blank lines in yodl macro example() --- ChangeLog | 5 +++++ Doc/zman.yo | 2 ++ Doc/ztexi.yo | 2 ++ 3 files changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5397c6c51..3fd4d9908 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-13 Jun-ichi Takimoto + + * 37090: Doc/zman.yo, Doc/ztexi.yo: handle blank lines correctly + in yodl macro example() + 2015-11-12 Peter Stephenson * 37096: Src/subst.c, Test/D04parameter.ztst: make top-level diff --git a/Doc/zman.yo b/Doc/zman.yo index 73cc186e0..5050edb8b 100644 --- a/Doc/zman.yo +++ b/Doc/zman.yo @@ -174,9 +174,11 @@ def(itemiz)(1)(\ COMMENT(--- special effects ---) def(example)(1)(\ + undef(PARAGRAPH)\ NOTRANS(.RS)+NL()NOTRANS(.nf)+NL()\ NOTRANS(\fB)ARG1+NOTRANS(\fP)\ +NL()NOTRANS(.fi)+NL()NOTRANS(.RE)\ + STDPAR()\ ) def(nofill)(1)(\ diff --git a/Doc/ztexi.yo b/Doc/ztexi.yo index 699567724..e8783459e 100644 --- a/Doc/ztexi.yo +++ b/Doc/ztexi.yo @@ -225,9 +225,11 @@ def(nofill)(1)(\ ) def(example)(1)(\ + undef(PARAGRAPH)\ NOTRANS(@example)+NL()\ ARG1\ +NL()NOTRANS(@end example)\ + STDPAR()\ ) def(indent)(1)(\ -- cgit v1.2.3 From d5ba08af4933fdef596f5151b3e903868d352f65 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Fri, 13 Nov 2015 01:02:37 +0900 Subject: unposted: a few cosmetic format fixes in docs --- ChangeLog | 4 ++++ Doc/Zsh/builtins.yo | 3 +-- Doc/Zsh/contrib.yo | 5 ++--- Doc/Zsh/func.yo | 3 +-- Doc/Zsh/grammar.yo | 3 +-- Doc/Zsh/mod_pcre.yo | 8 ++------ Doc/Zsh/params.yo | 4 +--- Doc/Zsh/zle.yo | 5 +++-- 8 files changed, 15 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3fd4d9908..46bb02f48 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,10 @@ * 37090: Doc/zman.yo, Doc/ztexi.yo: handle blank lines correctly in yodl macro example() + * unposted: Doc/Zsh/builtins.yo, Doc/Zsh/contrib.yo, + Doc/Zsh/func.yo, Doc/Zsh/grammar.yo, Doc/Zsh/mod_pcre.yo, + Doc/Zsh/params.yo, Doc/Zsh/zle.yo: cosmetic format fix + 2015-11-12 Peter Stephenson * 37096: Src/subst.c, Test/D04parameter.ztst: make top-level diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 985e7267f..49806e4d8 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -558,8 +558,7 @@ For example: example(emulate sh -c 'fni+LPAR()RPAR() { setopt cshnullglob; } fno+LPAR()RPAR() { fni; }' -fno -) +fno) The two functions tt(fni) and tt(fno) are defined with sticky tt(sh) emulation. tt(fno) is then executed, causing options associated diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index f74f7d709..07a5eb08e 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1755,7 +1755,7 @@ a customised bookmark string for the tt(hg) backend. Again, we start off by registering a function: example(zstyle ':vcs_info:hg+gen-hg-bookmark-string:*' hooks hgbookmarks) -And then we define the `tt(+vi-hgbookmarks) function: +And then we define the `tt(+vi-hgbookmarks)' function: example( function +vi-hgbookmarks+LPAR()RPAR() { # The default is to connect all bookmark names by @@ -1780,8 +1780,7 @@ function +vi-hgbookmarks+LPAR()RPAR() { # something other than the default zero: ret=1 return 0 -} -) +}) Some longer examples and code snippets which might be useful are available in the examples file located at Misc/vcs_info-examples in the Zsh source diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo index ace0a4051..d500a78ae 100644 --- a/Doc/Zsh/func.yo +++ b/Doc/Zsh/func.yo @@ -111,8 +111,7 @@ arguments, at the end. For example, suppose the autoload file tt(func) contains example(func+LPAR()RPAR() { print This is func; } -print func is initialized -) +print func is initialized) then `tt(func; func)' with tt(KSH_AUTOLOAD) set will produce both messages on the first call, but only the message `tt(This is func)' on the second diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index 83968fedf..2a76964f3 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -421,8 +421,7 @@ works, but example(if true { # Does not work! print yes -} -) +}) does em(not), since the test is not suitably delimited. ) diff --git a/Doc/Zsh/mod_pcre.yo b/Doc/Zsh/mod_pcre.yo index d6b4bd15d..c2817f519 100644 --- a/Doc/Zsh/mod_pcre.yo +++ b/Doc/Zsh/mod_pcre.yo @@ -54,8 +54,7 @@ used to implement the "find all non-overlapping matches" functionality. A simple example of "find all non-overlapping matches": -example( -string="The following zip codes: 78884 90210 99513" +example(string="The following zip codes: 78884 90210 99513" pcre_compile -m "\d{5}" accum=() pcre_match -b -- $string @@ -64,10 +63,7 @@ while [[ $? -eq 0 ]] do accum+=$MATCH pcre_match -b -n $b[2] -- $string done -print -l $accum - - -) +print -l $accum) ) enditem() diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index ba2856b34..b896e2d70 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -383,9 +383,7 @@ as part of an arithmetic expression in an ordinary subscript. To avoid subscript parsing limitations in assignments to associative array elements, use the append syntax: -example( - aa+=('key with "*strange*" characters' 'value string') -) +example(aa+=('key with "*strange*" characters' 'value string')) The basic rule to remember when writing a subscript expression is that all text between the opening `tt([)' and the closing `tt(])' is interpreted diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 05bb14829..7047b43d9 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -2274,6 +2274,7 @@ the command line or key bindings temporarily. The following widget, tt(caps-lock), serves as an example. + example(self-insert-ucase+LPAR()RPAR() { LBUFFER+=${(U)KEYS[-1]} } @@ -2293,8 +2294,8 @@ zle -D save-caps-lock (( stat )) && zle send-break -return $stat -) +return $stat) + This causes typed letters to be inserted capitalised until either tt(accept-line) (i.e. typically the return key) is typed or the tt(caps-lock) widget is invoked again; the later is handled by saving -- cgit v1.2.3 From f59864ce7a4a18efbfa5a330895d120ea1ce18f2 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 30 Oct 2015 15:08:53 +0000 Subject: 37025: vcs_info git: Add a cherry-pick patch-format --- ChangeLog | 5 +++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/ChangeLog b/ChangeLog index 46bb02f48..f314e82f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-13 Daniel Shahaf + + * 37025: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: + vcs_info git: Add a cherry-pick patch-format + 2015-11-13 Jun-ichi Takimoto * 37090: Doc/zman.yo, Doc/ztexi.yo: handle blank lines correctly diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index fcee47c13..704c1890e 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -266,6 +266,28 @@ elif [[ -f "${gitdir}/MERGE_HEAD" ]]; then # Not touching git_patches_unapplied + VCS_INFO_git_handle_patches +elif [[ -f "${gitdir}/CHERRY_PICK_HEAD" ]]; then + # 'git cherry-pick' without -n, that conflicted. (With -n, git doesn't + # record the CHERRY_PICK_HEAD information anywhere, as of git 2.6.2.) + # + # ### 'git cherry-pick foo bar baz' only records the "remaining" part of + # ### the queue in the .git dir: if 'bar' has a conflict, the .git dir + # ### has a record of 'baz' being queued, but no record of 'foo' having been + # ### part of the queue as well. Therefore, the %n/%c applied/unapplied + # ### expandos will be memoryless: the "applied" counter will always + # ### be "1". The %u/%c tuple will assume the values [(1,2), (1,1), (1,0)], + # ### whereas the correct sequence would be [(1,2), (2,1), (3,0)]. + local subject + IFS='' read -r subject < "${gitdir}/MERGE_MSG" + git_patches_applied=( "$(<${gitdir}/CHERRY_PICK_HEAD) ${subject}" ) + if [[ -f "${gitdir}/sequencer/todo" ]]; then + # Get the next patches, and remove the one that's in CHERRY_PICK_HEAD. + git_patches_unapplied=( ${${(M)${(f)"$(<"${gitdir}/sequencer/todo")"}:#pick *}#pick } ) + git_patches_unapplied[1]=() + else + git_patches_unapplied=() + fi VCS_INFO_git_handle_patches else gitmisc='' -- cgit v1.2.3 From 6198f7ffbae48230561fdd6996358fd553d954db Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 31 Oct 2015 12:52:46 +0000 Subject: 37031: _git-merge: Exclude ancestors of HEAD from recent commit completion As done for _git-cherry-pick in a428c6b62cb2 (36328 + 36340). --- ChangeLog | 3 +++ Completion/Unix/Command/_git | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f314e82f4..9fd23ada9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-11-13 Daniel Shahaf + * 37031: Completion/Unix/Command/_git: _git-merge: Exclude + ancestors of HEAD from recent commit completion + * 37025: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: vcs_info git: Add a cherry-pick patch-format diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 61386bfac..3dfd604e9 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -1131,6 +1131,7 @@ _git-log () { _git-merge () { local -a merge_options __git_setup_merge_options + local -a git_commit_opts=(--all --not HEAD --not) _arguments -w -S -s \ $merge_options \ @@ -1138,7 +1139,7 @@ _git-merge () { '( --no-rerere-autoupdate)--rerere-autoupdate[allow the rerere mechanism to update the index]' \ '(--rerere-autoupdate )--no-rerere-autoupdate[do not allow the rerere mechanism to update the index]' \ '--abort[restore the original branch and abort the merge operation]' \ - '*: :__git_commits' + '*: : __git_commits -O expl:git_commit_opts' } (( $+functions[_git-mv] )) || -- cgit v1.2.3 From 9ab9da49f7f5d7e8a32c14bde1c7b2c7f264d6fa Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 13 Nov 2015 20:18:22 +0000 Subject: unposted: Make $EDITOR's jump-to-matching-brace happy. --- ChangeLog | 3 +++ Src/Zle/zle_tricky.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9fd23ada9..52c770b00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-11-13 Daniel Shahaf + * unposted: Src/Zle/zle_tricky.c: Make $EDITOR's + jump-to-matching-brace happy. + * 37031: Completion/Unix/Command/_git: _git-merge: Exclude ancestors of HEAD from recent commit completion diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 4e6854928..cc4b7d673 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -1878,6 +1878,7 @@ get_comp_string(void) if (!isset(IGNOREBRACES)) { /* Try and deal with foo{xxx etc. */ + /*}*/ char *curs = s + (isset(COMPLETEINWORD) ? offs : (int)strlen(s)); char *predup = dupstring(s), *dp = predup; char *bbeg = NULL, *bend = NULL, *dbeg = NULL; @@ -1889,6 +1890,7 @@ get_comp_string(void) * we try to get braces after a parameter expansion right, * but this may fail sometimes. sorry. */ + /*}*/ if (*p == String || *p == Qstring) { if (p[1] == Inbrace || p[1] == Inpar || p[1] == Inbrack) { char *tp = p + 1; -- cgit v1.2.3 From 9ce000db220d0c676ff14cfe4fa436e6988f59ad Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 14 Nov 2015 21:22:17 -0800 Subject: 37115: update for changes in ${(P)...} evaluation. --- ChangeLog | 5 +++++ Completion/Unix/Command/_git | 2 +- Doc/Zsh/expn.yo | 27 ++++++++++++++++++++++----- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 52c770b00..a27c49817 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-14 Barton E. Schaefer + + * 37115: Completion/Unix/Commmand/_git, Doc/Zsh/expn.yo: update + for changes in ${(P)...} evaluation. + 2015-11-13 Daniel Shahaf * unposted: Src/Zle/zle_tricky.c: Make $EDITOR's diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 3dfd604e9..614185ebb 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5244,7 +5244,7 @@ _git_commands () { for cmdtype in aliases $cmdtypes; do local -a ${cmdtype}_d (( $#disp )) && set -A ${cmdtype}_d \ - ${${(Pr.COLUMNS-4.)cmdtype/(#s)(#m)[^:]##:/${(r.len.)MATCH[1,-2]} $sep }%% #} + ${${(r.COLUMNS-4.)${(P)cmdtype}/(#s)(#m)[^:]##:/${(r.len.)MATCH[1,-2]} $sep }%% #} alts+=( "${cmdtype//_/-}:${${cmdtype//_/ }%%(e|)s}:compadd ${(e)disp} -a ${cmdtype}_m" ) done diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 4c373d1f2..6f08d7d47 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1380,9 +1380,13 @@ outermost. The flags are not propagated up to enclosing substitutions; the nested substitution will return either a scalar or an array as determined by the flags, possibly adjusted for quoting. All the following steps take place where applicable at all levels of substitution. -Note that, unless the `tt((P))' flag is present, the flags and any subscripts -apply directly to the value of the nested substitution; for example, the -expansion tt(${${foo}}) behaves exactly the same as tt(${foo}). + +Note that, unless the `tt((P))' flag is present, the flags and any +subscripts apply directly to the value of the nested substitution; for +example, the expansion tt(${${foo}}) behaves exactly the same as +tt(${foo}). When the `tt((P))' flag is present in a nested substitution, +the other substitution rules are applied to the value em(before) it is +interpreted as a name, so tt(${${(P)foo}}) may differ from tt(${(P)foo}). At each nested level of substitution, the substituted words undergo all forms of single-word substitution (i.e. not filename generation), including @@ -1400,6 +1404,12 @@ in particular the tt(L), tt(R), tt(Z), tt(u) and tt(l) flags for padding and capitalization, are applied directly to the parameter value. Note these flags are options to the command, e.g. `tt(typeset -Z)'; they are not the same as the flags used within parameter substitutions. + +At the outermost level of substitution, the `tt((P))' flag ignores these +transformations and uses the unmodified value of the parameter as the name +to be replaced. This is usually the desired behavior because padding may +make the value syntactically illegal as a parameter name, but if +capitalization changes are desired, use the tt(${${(P)foo}}) form. ) item(tt(3.) em(Parameter subscripting))( If the value is a raw parameter reference with a subscript, such as @@ -1413,8 +1423,10 @@ original array). Any number of subscripts may appear. Flags such as tt((k)) and tt((v)) which alter the result of subscripting are applied. ) item(tt(4.) em(Parameter name replacement))( -The effect of any tt((P)) flag, which treats the value so far as a -parameter name and replaces it with the corresponding value, is applied. +At the outermost level of nesting only, the effect of any tt((P)) flag, +which treats the value so far as a parameter name and replaces it with the +corresponding value, is applied. This replacement occurs later if the +tt((P)) flag appears in a nested substitution. ) item(tt(5.) em(Double-quoted joining))( If the value after this process is an array, and the substitution @@ -1534,6 +1546,11 @@ Strictly speaking, the removal happens later as the same happens with other forms of substitution; the point to note here is simply that it occurs after any of the above parameter operations. ) +item(tt(25.) em(Parameter name replacement))( +If the `tt((P))' flag is present and this has not yet been done, the value +so far is looked up as a parameter name. Errors may occur if the value is +neither a valid identifier nor an identifier plus subscript expression. +) enditem() subsect(Examples) -- cgit v1.2.3 From a24487d73aabca9979d8b5b71c40513fe6982898 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 15 Nov 2015 10:16:52 -0800 Subject: 37119: further "Rules" clarifications --- ChangeLog | 4 ++++ Doc/Zsh/expn.yo | 72 +++++++++++++++++++++++++++++++-------------------------- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index a27c49817..ed17d4bbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-11-15 Barton E. Schaefer + + * 37119: Doc/Zsh/expn.yo: further "Rules" clarifications + 2015-11-14 Barton E. Schaefer * 37115: Completion/Unix/Commmand/_git, Doc/Zsh/expn.yo: update diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 6f08d7d47..123722e0f 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -1399,17 +1399,18 @@ substitution then applies the modifier tt(:h) and takes the directory part of the path.) ) item(tt(2.) em(Internal parameter flags))( -Any parameter flags set by one of the tt(typeset) family of commands, -in particular the tt(L), tt(R), tt(Z), tt(u) and tt(l) flags for padding -and capitalization, are applied directly to the parameter value. -Note these flags are options to the command, e.g. `tt(typeset -Z)'; -they are not the same as the flags used within parameter substitutions. - -At the outermost level of substitution, the `tt((P))' flag ignores these -transformations and uses the unmodified value of the parameter as the name -to be replaced. This is usually the desired behavior because padding may -make the value syntactically illegal as a parameter name, but if -capitalization changes are desired, use the tt(${${(P)foo}}) form. +Any parameter flags set by one of the tt(typeset) family of commands, in +particular the tt(-L), tt(-R), tt(-Z), tt(-u) and tt(-l) options for +padding and capitalization, are applied directly to the parameter value. +Note these flags are options to the command, e.g. `tt(typeset -Z)'; they +are not the same as the flags used within parameter substitutions. + +At the outermost level of substitution, the `tt((P))' flag (rule tt(4.)) +ignores these transformations and uses the unmodified value of the +parameter as the name to be replaced. This is usually the desired +behavior because padding may make the value syntactically illegal as a +parameter name, but if capitalization changes are desired, use the +tt(${${(P)foo}}) form (rule tt(25.)). ) item(tt(3.) em(Parameter subscripting))( If the value is a raw parameter reference with a subscript, such as @@ -1420,21 +1421,25 @@ subscript. Thus if tt(var) is an array, tt(${var[1][2]}) is the second character of the first word, but tt(${var[2,4][2]}) is the entire third word (the second word of the range of words two through four of the original array). Any number of subscripts may appear. Flags such as -tt((k)) and tt((v)) which alter the result of subscripting are applied. +`tt((k))' and `tt((v))' which alter the result of subscripting are applied. ) item(tt(4.) em(Parameter name replacement))( -At the outermost level of nesting only, the effect of any tt((P)) flag, -which treats the value so far as a parameter name and replaces it with the -corresponding value, is applied. This replacement occurs later if the -tt((P)) flag appears in a nested substitution. +At the outermost level of nesting only, the `tt((P))' flag is applied. This +treats the value so far as a parameter name (which may include a subscript +expression) and replaces that with the corresponding value. This +replacement occurs later if the `tt((P))' flag appears in a nested +substitution. + +If the value so far names a parameter that has internal flags (rule tt(2.)), +those internal flags are applied to the new value after replacement. ) item(tt(5.) em(Double-quoted joining))( If the value after this process is an array, and the substitution -appears in double quotes, and neither an tt((@)) flag nor a tt(#) +appears in double quotes, and neither an `tt((@))' flag nor a `tt(#)' length operator is present at the current level, then words of the value are joined with the first character of the parameter tt($IFS), by default a space, between each word (single word arrays are not -modified). If the tt((j)) flag is present, that is used for joining +modified). If the `tt((j))' flag is present, that is used for joining instead of tt($IFS). ) item(tt(6.) em(Nested subscripting))( @@ -1448,22 +1453,22 @@ returns a scalar because of the quotes). ) item(tt(7.) em(Modifiers))( Any modifiers, as specified by a trailing `tt(#)', `tt(%)', `tt(/)' -(possibly doubled) or by a set of modifiers of the form tt(:...) (see +(possibly doubled) or by a set of modifiers of the form `tt(:...)' (see noderef(Modifiers) in noderef(History Expansion)), are applied to the words of the value at this level. ) item(tt(8.) em(Character evaluation))( -Any tt((#)) flag is applied, evaluating the result so far numerically +Any `tt((#))' flag is applied, evaluating the result so far numerically as a character. ) item(tt(9.) em(Length))( -Any initial tt(#) modifier, i.e. in the form tt(${#)var(var)tt(}), is +Any initial `tt(#)' modifier, i.e. in the form tt(${#)var(var)tt(}), is used to evaluate the length of the expression so far. ) item(tt(10.) em(Forced joining))( If the `tt((j))' flag is present, or no `tt((j))' flag is present but the string is to be split as given by rule tt(11.), and joining -did not take place at step tt(5.), any words in the value are joined +did not take place at rule tt(5.), any words in the value are joined together using the given string or the first character of tt($IFS) if none. Note that the `tt((F))' flag implicitly supplies a string for joining in this manner. @@ -1480,22 +1485,22 @@ occurrences of any of the characters in tt($IFS). Note this step, too, takes place at all levels of a nested substitution. ) item(tt(12.) em(Case modification))( -Any case modification from one of the flags tt((L)), tt((U)) or tt((C)) +Any case modification from one of the flags `tt((L))', `tt((U))' or `tt((C))' is applied. ) item(tt(13.) em(Escape sequence replacement))( -First any replacements from the tt((g)) flag are performed, then any -prompt-style formatting from the tt((%)) family of flags is applied. +First any replacements from the `tt((g))' flag are performed, then any +prompt-style formatting from the `tt((%))' family of flags is applied. ) item(tt(14.) em(Quote application))( -Any quoting or unquoting using tt((q)) and tt((Q)) and related flags +Any quoting or unquoting using `tt((q))' and `tt((Q))' and related flags is applied. ) item(tt(15.) em(Directory naming))( -Any directory name substitution using tt((D)) flag is applied. +Any directory name substitution using `tt((D))' flag is applied. ) item(tt(16.) em(Visibility enhancement))( -Any modifications to make characters visible using the tt((V)) flag +Any modifications to make characters visible using the `tt((V))' flag are applied. ) item(tt(17.) em(Lexical word splitting))( @@ -1533,7 +1538,7 @@ In contexts where expansion semantics requires a single word to result, all words are rejoined with the first character of tt(IFS) between. So in `tt(${LPAR()P)tt(RPAR()${LPAR()f)tt(RPAR()lines}})' the value of tt(${lines}) is split at newlines, but then must be -joined again before the tt(P) flag can be applied. +joined again before the `tt((P))' flag can be applied. If a single word is not required, this rule is skipped. ) @@ -1546,10 +1551,11 @@ Strictly speaking, the removal happens later as the same happens with other forms of substitution; the point to note here is simply that it occurs after any of the above parameter operations. ) -item(tt(25.) em(Parameter name replacement))( -If the `tt((P))' flag is present and this has not yet been done, the value -so far is looked up as a parameter name. Errors may occur if the value is -neither a valid identifier nor an identifier plus subscript expression. +item(tt(25.) em(Nested parameter name replacement))( +If the `tt((P))' flag is present and rule tt(4.) has not applied, the +value so far is treated as a parameter name (which may include a subscript +expression) and replaced with the corresponding value, with internal flags +(rule tt(2.)) applied to the new value. ) enditem() -- cgit v1.2.3 From f01cf05e538dc4c8839253aefc09d3a58654ba6a Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Sun, 1 Nov 2015 22:21:14 -0500 Subject: _sockstat: minor improvements allow -p, -P and -f's argument to be completed in the same word. Complete -P's argument using /etc/protocols again, while allowing a comma delimited list of protocols. --- ChangeLog | 5 +++++ Completion/BSD/Command/_sockstat | 21 ++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index ed17d4bbc..69f5182b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-16 Mikael Magnusson + + * Eric Cook: 37050: Completion/BSD/Command/_sockstat: _sockstat: + minor improvements + 2015-11-15 Barton E. Schaefer * 37119: Doc/Zsh/expn.yo: further "Rules" clarifications diff --git a/Completion/BSD/Command/_sockstat b/Completion/BSD/Command/_sockstat index 1b11ba473..daad946fc 100644 --- a/Completion/BSD/Command/_sockstat +++ b/Completion/BSD/Command/_sockstat @@ -1,5 +1,6 @@ #compdef sockstat -local -a args +local -a args protocols +local proto case $OSTYPE in *bsd*) @@ -8,27 +9,37 @@ case $OSTYPE in '-6[show AF_INET6 (IPv6) sockets]' '-c[show connected sockets]' '-l[show listening sockets]' - '*-p[specify port number]:port numbers (comma delimited)' + '*-p+[specify port number]:port numbers (comma delimited)' '-u[show AF_LOCAL (UNIX) sockets]' ) ;| freebsd*) + for proto in ${${(M)${(f)"$( Date: Tue, 27 Oct 2015 12:15:47 -0400 Subject: zed: Add -- to the `functions' builtin calls Reported on IRC: % autoload zed; zed -f -- "-zgen-prezto-load" zed:83: bad option: -g -zgen-prezto-load() { } --- ChangeLog | 6 ++++-- Functions/Misc/zed | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 69f5182b9..0c26ced2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,9 @@ 2015-11-16 Mikael Magnusson - * Eric Cook: 37050: Completion/BSD/Command/_sockstat: _sockstat: - minor improvements + * Eric Cook: 36986: Functions/Misc/zed: Add -- to the `functions' + builtin calls + + * Eric Cook: 37050: Completion/BSD/Command/_sockstat: minor improvements 2015-11-15 Barton E. Schaefer diff --git a/Functions/Misc/zed b/Functions/Misc/zed index 94dd9ce5b..eb8f557ea 100644 --- a/Functions/Misc/zed +++ b/Functions/Misc/zed @@ -69,10 +69,10 @@ 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="$1() { }" -- cgit v1.2.3 From bc543abbf6e90ea8678b97cc36732e6f94bbe199 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 17 Nov 2015 10:43:23 +0000 Subject: 37127: document indexing of $signals --- ChangeLog | 5 +++++ Doc/Zsh/params.yo | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0c26ced2e..8b11e2d09 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-17 Peter Stephenson + + * 37127 (minor tweak): Doc/Zsh/params.yo: document indexing of + $signals. + 2015-11-16 Mikael Magnusson * Eric Cook: 36986: Functions/Misc/zed: Add -- to the `functions' diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index b896e2d70..eb31286e4 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -771,7 +771,13 @@ Incremented by one each time a new shell is started. ) vindex(signals) item(tt(signals))( -An array containing the names of the signals. +An array containing the names of the signals. Note that with +the standard zsh numbering of array indices, where the first element +has index 1, the signals are offset by 1 from the signal number +used by the operating system. For example, on typical Unix-like systems +tt(HUP) is signal number 1, but is referred to as tt($signals[2]). This +is because of tt(EXIT) at position 1 in the array, which is used +internally by zsh but is not known to the operating system. ) vindex(TRY_BLOCK_ERROR) item(tt(TRY_BLOCK_ERROR) )( -- cgit v1.2.3 From ca0cb170119b3cef4ccdfc743b6c225e9e6eed53 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 17 Nov 2015 17:44:12 +0000 Subject: 37128: work around alias expansion trashing subscript parsing --- ChangeLog | 3 +++ Src/lex.c | 28 ++++++++++++++++++++++------ Test/D06subscript.ztst | 17 +++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b11e2d09..1000ae611 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-11-17 Peter Stephenson + * 37128: Src/lex.c, Test/D06subscript.ztst: work around alias + expansion trashing subcript being parsed. + * 37127 (minor tweak): Doc/Zsh/params.yo: document indexing of $signals. diff --git a/Src/lex.c b/Src/lex.c index 89af96123..81904c171 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -1617,7 +1617,7 @@ parsestrnoerr(char **s) mod_export char * parse_subscript(char *s, int sub, int endchar) { - int l = strlen(s), err; + int l = strlen(s), err, toklen; char *t; if (!*s || *s == endchar) @@ -1626,18 +1626,34 @@ parse_subscript(char *s, int sub, int endchar) untokenize(t = dupstring(s)); inpush(t, 0, NULL); strinbeg(0); + /* + * Warning to Future Generations: + * + * This way of passing the subscript through the lexer is brittle. + * Code above this for several layers assumes that when we tokenise + * the input it goes into the same place as the original string. + * However, the lexer may overwrite later bits of the string or + * reallocate it, in particular when expanding aliaes. To get + * around this, we copy the string and then copy it back. This is a + * bit more robust but still relies on the underlying assumption of + * length preservation. + */ lexbuf.len = 0; - lexbuf.ptr = tokstr = s; + lexbuf.ptr = tokstr = dupstring(s); lexbuf.siz = l + 1; err = dquote_parse(endchar, sub); + toklen = (int)(lexbuf.ptr - tokstr); + DPUTS(toklen > l, "Bad length for parsed subscript"); + memcpy(s, tokstr, toklen); if (err) { - err = *lexbuf.ptr; - *lexbuf.ptr = '\0'; + char *strend = s + toklen; + err = *strend; + *strend = '\0'; untokenize(s); - *lexbuf.ptr = err; + *strend = err; s = NULL; } else { - s = lexbuf.ptr; + s += toklen; } strinend(); inpop(); diff --git a/Test/D06subscript.ztst b/Test/D06subscript.ztst index cffca742e..144923667 100644 --- a/Test/D06subscript.ztst +++ b/Test/D06subscript.ztst @@ -249,3 +249,20 @@ string[0]=! 1:Can't set only element zero of string ?(eval):1: string: assignment to invalid subscript range + + typeset -A assoc=(leader topcat officer dibble sidekick choochoo) + alias myind='echo leader' myletter='echo 1' myletter2='echo 4' + print ${assoc[$(myind)]} + print $assoc[$(myind)] + print ${assoc[$(myind)][$(myletter)]}${assoc[$(myind)][$(myletter2)]} + assoc[$(myind)]='of the gang' + print ${assoc[$(myind)]} + print $assoc[$(myind)] + print $assoc[leader] +0: Parsing subscript with non-trivial tokenisation +>topcat +>topcat +>tc +>of the gang +>of the gang +>of the gang -- cgit v1.2.3 From afc4d416524f186e3bdb01c512b7c7795eb5572b Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Tue, 17 Nov 2015 22:14:04 +0000 Subject: 37129: _git: Complete 'commit -p' --- ChangeLog | 4 ++++ Completion/Unix/Command/_git | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1000ae611..14e5783c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-11-17 Daniel Shahaf + + * 37129: Completion/Unix/Command/_git: _git: Complete 'commit -p' + 2015-11-17 Peter Stephenson * 37128: Src/lex.c, Test/D06subscript.ztst: work around alias diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index 614185ebb..c97fed399 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -656,7 +656,7 @@ _git-commit () { '( --porcelain --dry-run)--short[output dry run in short format]' \ '(--short --dry-run)--porcelain[output dry run in porcelain-ready format]' \ '(--short --porcelain --dry-run -z --null)'{-z,--null}'[separate dry run entry output with NUL]' \ - '--patch[use the interactive patch selection interface to chose which changes to commit]' \ + {-p,--patch}'[use the interactive patch selection interface to chose which changes to commit]' \ '(--reset-author)--author[override the author name used in the commit]:author name' \ '--date=[override the author date used in the commit]:date' \ '(-s --signoff)'{-s,--signoff}'[add Signed-off-by line at the end of the commit message]' \ -- cgit v1.2.3 From f39ae235a261df353d85578c7bc760f91c4b763b Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 18 Nov 2015 14:57:33 +0000 Subject: 37140: note that <<(...) is < <(...) --- ChangeLog | 4 ++++ Doc/Zsh/expn.yo | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index 14e5783c2..86de73a25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-11-18 Peter Stephenson + + * 37140: Doc/Zsh/expn.yo: note that <<(...) is < <(...). + 2015-11-17 Daniel Shahaf * 37129: Completion/Unix/Command/_git: _git: Complete 'commit -p' diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 123722e0f..564c70dd1 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -410,6 +410,12 @@ are only expanded when first parsing command or assignment arguments. Process substitutions may be used following redirection operators; in this case, the substitution must appear with no trailing string. +Note that `tt(<) forms, the shell runs the commands in var(list) as a subprocess of the job executing the shell command line. If the system supports the tt(/dev/fd) -- cgit v1.2.3 From 59235205c6c8b189b7227f206754aaf485010136 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 18 Nov 2015 11:11:37 -0800 Subject: 37145: suppress alias expansion in skipcomm() Thus defer parsing aliases in $(...) et al. into the subshell --- ChangeLog | 5 +++++ Src/lex.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 86de73a25..59b3cc6d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-18 Barton E. Schaefer + + * 37145: Src/lex.c: suppress alias expansion in skipcomm() to + defer parsing aliases in $(...) et al. into the subshell + 2015-11-18 Peter Stephenson * 37140: Doc/Zsh/expn.yo: note that <<(...) is < <(...). diff --git a/Src/lex.c b/Src/lex.c index 81904c171..0f260d08f 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -2022,7 +2022,9 @@ skipcomm(void) int new_lexstop, new_lex_add_raw; int save_infor = infor; struct lexbufstate new_lexbuf; + int noalias = noaliases; + noaliases = 1; infor = 0; cmdpush(CS_CMDSUBST); SETPARBEGIN @@ -2140,6 +2142,7 @@ skipcomm(void) SETPAREND cmdpop(); infor = save_infor; + noaliases = noalias; return lexstop; #endif -- cgit v1.2.3 From 5d0859a40113dcb57aba9ee877a0b531b6622584 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 19 Nov 2015 14:19:40 +0000 Subject: unposted: describe separators between values in array assignment --- ChangeLog | 5 +++++ Doc/Zsh/params.yo | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index 59b3cc6d2..42deaf073 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-19 Peter Stephenson + + * unposted: Doc/Zsh/params.yo: describe separators between + values in array assignment. + 2015-11-18 Barton E. Schaefer * 37145: Src/lex.c: suppress alias expansion in skipcomm() to diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index eb31286e4..21bb87442 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -99,6 +99,11 @@ the syntax: ifzman() indent(var(name)tt(+=LPAR())var(value) ...tt(RPAR())) +Within the parentheses on the right hand side of either form of the +assignment, newlines and semicolons are treated the same as white space, +separating individual var(value)s. Any consecutive sequence of such +characters has the same effect. + Ordinary array parameters may also be explicitly declared with: findex(typeset, use of) ifzman() -- cgit v1.2.3 From 4353bec49f5997f7581d8a33d52fd87deba57b6c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 19 Nov 2015 17:19:12 +0000 Subject: 37159: Update to NEWS and README --- ChangeLog | 4 +++- NEWS | 30 ++++++++++++++++++++++++++++++ README | 12 ++++++++++-- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 42deaf073..5355abaa6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-11-19 Peter Stephenson + * 37159: NEWS, README: update for next version. + * unposted: Doc/Zsh/params.yo: describe separators between values in array assignment. @@ -63,7 +65,7 @@ 2015-11-12 Peter Stephenson * 37096: Src/subst.c, Test/D04parameter.ztst: make top-level - ${(P)...} with nested ${(P)...} to the right thing. + ${(P)...} with nested ${(P)...} do the right thing. * 37094: Src/subst.c, Test/D04parameter.ztst: Further tweaks to parameter name references: array safety; nested parameters; tests. diff --git a/NEWS b/NEWS index bc14a8beb..3964da732 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,36 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH Note also the list of incompatibilities in the README file. +Changes from 5.1.1 to 5.2 +------------------------- + +The new module zsh/param/private can be loaded to allow the shell +to define parameters that are private to a function scope (i.e. are +not propagated to nested functions called within this function). + +The parameter flag ${(P)...} is now more useful when it appears in +a nested expansion. For example, + + typeset -A assoc=(one un two deux three trois) + name=assoc + print ${${(P)name}[one]} + +now prints "un". In previous versions of the shell the value of the +substitution was fully expanded on return from ${(P)name}, making +associative array subscripting difficult. As a side effect, flags +for formatting appearing in the inner substitution now affect the +substitution of the name (into "assoc" in this case), which is not +normally useful: flags that should apply to the value must be in the +outer substitution. + +The GLOB_STAR_SHORT option allows the pattern **/* to be shortened to +just ** if no / follows. so **.c searches recursively for a file whose +name has the suffix ".c". + +The effect of the WARN_CREATE_GLOBAL option has been significantly +extended, so expect it to cause additional warning messages about +parameters created globally within function scope. + Changes from 5.1 to 5.1.1 ------------------------- diff --git a/README b/README index 957152114..9cb352a5f 100644 --- a/README +++ b/README @@ -32,8 +32,16 @@ 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. -Incompatibilites between 5.0.8 and 5.1 --------------------------------------- +Incompatibilities between 5.1 and 5.2 +------------------------------------- + +The behaviour of the parameter flag (P) has changed when it appears +in a nested parameter group, in order to make it more useful in +such cases. A (P) in the outermost parameter group behaves as +before. See NEWS for more. + +Incompatibilities between 5.0.8 and 5.1 +--------------------------------------- The default behaviour when text is pasted into an X Windows terminal has changed significantly (unless you are using a very old terminal emulator -- cgit v1.2.3 From d554f31bcbe1264f69e22e990d356ab7ee6e87a8 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 20 Nov 2015 03:39:26 +0000 Subject: 37149: _git: Complete 'bisect/bad' ref --- ChangeLog | 5 +++++ Completion/Unix/Command/_git | 1 + 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5355abaa6..5ab68f7a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-20 Daniel Shahaf + + * 37149: Completion/Unix/Command/_git: _git: Complete + 'bisect/bad' ref + 2015-11-19 Peter Stephenson * 37159: NEWS, README: update for next version. diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git index c97fed399..6e8e9c665 100644 --- a/Completion/Unix/Command/_git +++ b/Completion/Unix/Command/_git @@ -5639,6 +5639,7 @@ __git_heads_local () { [[ -f $gitdir/$f ]] && heads+=$f done [[ -f $gitdir/refs/stash ]] && heads+=stash + [[ -f $gitdir/refs/bisect/bad ]] && heads+=bisect/bad fi __git_describe_commit heads heads-local "local head" "$@" -- cgit v1.2.3 From c563f1ba83c40aab632ac958a1d3a57277ca22cc Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 20 Nov 2015 03:39:47 +0000 Subject: 37164: _tmux: Complete external commands --- ChangeLog | 3 +++ Completion/Unix/Command/_tmux | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ab68f7a1..252f2fc5f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-11-20 Daniel Shahaf + * 37164: Completion/Unix/Command/_tmux: _tmux: Complete external + commands + * 37149: Completion/Unix/Command/_git: _git: Complete 'bisect/bad' ref diff --git a/Completion/Unix/Command/_tmux b/Completion/Unix/Command/_tmux index 6f2cac790..d218cc3f3 100644 --- a/Completion/Unix/Command/_tmux +++ b/Completion/Unix/Command/_tmux @@ -640,7 +640,7 @@ function _tmux-new-session() { '-t[specify target session]:sessions:__tmux-sessions' '-x[specify width]:width:_guard "[0-9]#" "numeric value"' '-y[specify height]:height:_guard "[0-9]#" "numeric value"' - '*:: :_command' + '*:: :_cmdstring' ) _arguments -s ${args} } @@ -657,7 +657,7 @@ function _tmux-new-window() { '-n[specify a window name]:window name:' '-P[print information about new window after it is created]' '-t[specify target window]:windows:__tmux-windows' - '*:: :_command' + '*:: :_cmdstring' ) _arguments ${args} } @@ -776,7 +776,7 @@ function _tmux-respawn-pane() { args=( '-k[kill window if it is in use]' '-t[choose target pane]:window:__tmux-pane' - '*::command:_command' + '*::command:_cmdstring' ) _arguments ${args} } @@ -787,7 +787,7 @@ function _tmux-respawn-window() { args=( '-k[kill window if it is in use]' '-t[choose target window]:window:__tmux-windows' - '*::command:_command' + '*::command:_cmdstring' ) _arguments ${args} } @@ -809,7 +809,7 @@ function _tmux-run-shell() { args=( '-b[run shell command in background]' '-t[choose target pane]:pane:__tmux-panes' - '*::command:_command' + '*::command:_cmdstring' ) _arguments ${args} } @@ -1042,7 +1042,7 @@ function _tmux-split-window() { # changing the command's name might annoy users. So it stays like # this. '-t[choose target pane]:window:__tmux-panes' - '*:: :_command' + '*:: :_cmdstring' ) _arguments ${args} && return } -- cgit v1.2.3 From 72a67716aca9896cb75a2b92457fdaed060d8e9e Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 20 Nov 2015 11:18:16 +0000 Subject: 20974: Bug with scalar assignment to special array in typeset --- ChangeLog | 5 +++++ Src/builtin.c | 24 ++++++++++++++++++++---- Test/D04parameter.ztst | 19 +++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 252f2fc5f..7a507fe00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-20 Peter Stephenson + + * 20974: Src/builtin.c, Test/D04parameter.ztst: fix bug + when scalar value assigned to special array in typeset. + 2015-11-20 Daniel Shahaf * 37164: Completion/Unix/Command/_tmux: _tmux: Complete external diff --git a/Src/builtin.c b/Src/builtin.c index 18dfdce05..01eb5b84c 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -2438,10 +2438,26 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), if (ASG_VALUEP(asg) && !dont_set) { Param ipm = pm; if (pm->node.flags & (PM_ARRAY|PM_HASHED)) { - DPUTS(!ASG_ARRAYP(asg), "BUG: inconsistent scalar value for array"); - if (!(pm=assignaparam(pname, asg->value.array ? - zlinklist2array(asg->value.array) : - mkarray(NULL), 0))) + char **arrayval; + if (!ASG_ARRAYP(asg)) { + /* + * Attempt to assign a scalar value to an array. + * This can happen if the array is special. + * We'll be lenient and guess what the user meant. + * This is how normal assigment works. + */ + if (*asg->value.scalar) { + /* Array with one value */ + arrayval = mkarray(ztrdup(asg->value.scalar)); + } else { + /* Empty array */ + arrayval = mkarray(NULL); + } + } else if (asg->value.array) + arrayval = zlinklist2array(asg->value.array); + else + arrayval = mkarray(NULL); + if (!(pm=assignaparam(pname, arrayval, 0))) return NULL; } else { DPUTS(ASG_ARRAYP(asg), "BUG: inconsistent array value for scalar"); diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 210c0d854..a3c5d71df 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1847,3 +1847,22 @@ 0:nested parameter name references >all these worlds belong to foo >worlds + + ( + path=(/random /value) + testfn1() { + local path= + print $#path + } + testfn1 + testfn2() { + local path=/somewhere + print $#path $path + } + testfn2 + print $#path $path + ) +0:Local special variables with loose typing +>0 +>1 /somewhere +>2 /random /value -- cgit v1.2.3 From 2737ae4a669c37638bc377e85cce9d50281b3bc2 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 20 Nov 2015 11:55:07 +0000 Subject: 37168: No WARN_CREATE_GLOBAL on special parameters --- ChangeLog | 2 ++ Src/params.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7a507fe00..5ab317e4b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-11-20 Peter Stephenson + * 37168: Src/params.c: no WARN_CREATE_GLOBAL on special parameters. + * 20974: Src/builtin.c, Test/D04parameter.ztst: fix bug when scalar value assigned to special array in typeset. diff --git a/Src/params.c b/Src/params.c index 3ed771e3b..b121bd6ad 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2702,7 +2702,7 @@ check_warn_create(Param pm, const char *pmtype) Funcstack i; const char *name; - if (pm->level != 0) + if (pm->level != 0 || (pm->node.flags & PM_SPECIAL)) return; name = NULL; -- cgit v1.2.3 From 4add5258834ffbbf3e26ef25195a90b6004ca0bf Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 20 Nov 2015 12:42:35 +0000 Subject: 37170: suppress global create warning in function --- ChangeLog | 3 +++ Functions/Zle/smart-insert-last-word | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ab317e4b..33c05680f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-11-20 Peter Stephenson + * 37170: Functions/Zle/smart-insert-last-word: suppress + WARN_CREATE_GLOBAL for intentional creation of global variables. + * 37168: Src/params.c: no WARN_CREATE_GLOBAL on special parameters. * 20974: Src/builtin.c, Test/D04parameter.ztst: fix bug diff --git a/Functions/Zle/smart-insert-last-word b/Functions/Zle/smart-insert-last-word index 67adea760..cf8715dfe 100644 --- a/Functions/Zle/smart-insert-last-word +++ b/Functions/Zle/smart-insert-last-word @@ -60,7 +60,7 @@ then lcursor=$_ilw_lcursor else NUMERIC=1 - _ilw_lcursor=$lcursor + typeset -g _ilw_lcursor=$lcursor fi # Handle the up to three arguments of .insert-last-word if (( $+1 )) @@ -73,8 +73,8 @@ then (( NUMERIC )) || LBUFFER[lcursor+1,cursor+1]='' numeric=$((-(${2:--numeric}))) fi -_ilw_hist=$HISTNO -_ilw_count=$NUMERIC +typeset -g _ilw_hist=$HISTNO +typeset -g _ilw_count=$NUMERIC if [[ -z "$numeric" ]] then @@ -119,7 +119,7 @@ fi (( NUMERIC > $#lastcmd )) && return 1 LBUFFER[lcursor+1,cursor+1]=$lastcmd[-NUMERIC] -_ilw_cursor=$CURSOR +typeset -g _ilw_cursor=$CURSOR # This is necessary to update UNDO_CHANGE_NO immediately -zle split-undo && _ilw_changeno=$UNDO_CHANGE_NO +zle split-undo && typeset -g _ilw_changeno=$UNDO_CHANGE_NO -- cgit v1.2.3 From ae0420c46a756116fc9a325596275701678d3485 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Thu, 19 Nov 2015 16:15:42 +0100 Subject: 37161: Disable the heuristic setting RPROMPT_INDENT to 0 --- ChangeLog | 5 +++++ Src/init.c | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 33c05680f..a11455b93 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-20 Mikael Magnusson + + * 37161: Src/init.c: Disable the heuristic setting RPROMPT_INDENT + to 0 + 2015-11-20 Peter Stephenson * 37170: Functions/Zle/smart-insert-last-word: suppress diff --git a/Src/init.c b/Src/init.c index 22db4b3b2..dcce1d7ce 100644 --- a/Src/init.c +++ b/Src/init.c @@ -790,8 +790,10 @@ init_term(void) tcstr[TCCLEARSCREEN] = ztrdup("\14"); tclen[TCCLEARSCREEN] = 1; } - /* This might work, but there may be more to it */ - rprompt_indent = ((hasam && !hasbw) || hasye || !tccan(TCLEFT)); + rprompt_indent = 1; + /* The following is an attempt at a heuristic, + * but it fails in some cases */ + /* rprompt_indent = ((hasam && !hasbw) || hasye || !tccan(TCLEFT)); */ } return 1; } -- cgit v1.2.3 From e59a857b69e8402cca53b3ba1020c44a0b5e46b8 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Fri, 20 Nov 2015 14:15:43 -0800 Subject: unposted: document order of entries for $history and $historywords --- ChangeLog | 5 +++++ Doc/Zsh/mod_parameter.yo | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a11455b93..26e0c8403 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-20 Barton E. Schaefer + + * unposted: Doc/Zsh/mod_paramter.yo: document order of entries + for $history and $historywords + 2015-11-20 Mikael Magnusson * 37161: Src/init.c: Disable the heuristic setting RPROMPT_INDENT diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo index 9d1dc8b7d..3d260f8e9 100644 --- a/Doc/Zsh/mod_parameter.yo +++ b/Doc/Zsh/mod_parameter.yo @@ -123,10 +123,14 @@ directory, the current working directory. vindex(history) item(tt(history))( This associative array maps history event numbers to the full history lines. +Although it is presented as an associative array, the array of all values +(tt(${history[@]})) is guaranteed to be returned in order from most recent +to oldest history event, that is, by decreasing history event number. ) vindex(historywords) item(tt(historywords))( -A special array containing the words stored in the history. +A special array containing the words stored in the history. These also +appear in most to least recent order. ) vindex(jobdirs) item(tt(jobdirs))( -- cgit v1.2.3 From cce4261a3c6f4bf78b483db61623c80e3c98d10b Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 21 Nov 2015 18:09:27 +0000 Subject: unposted: Make 5.1.1-test-1 in preparation for 5.2 --- ChangeLog | 5 +++++ Config/version.mk | 4 ++-- Etc/FAQ.yo | 2 +- README | 11 ++++------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 26e0c8403..8dbd45686 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-21 Peter Stephenson + + * unposted: Config/version.mk, Etc/FAQ.yo, README: make + 5.1.1-test-1 in preparation for 5.2. + 2015-11-20 Barton E. Schaefer * unposted: Doc/Zsh/mod_paramter.yo: document order of entries diff --git a/Config/version.mk b/Config/version.mk index 7ec276df2..ff259cd5b 100644 --- a/Config/version.mk +++ b/Config/version.mk @@ -27,5 +27,5 @@ # This must also serve as a shell script, so do not add spaces around the # `=' signs. -VERSION=5.1.1-dev-0 -VERSION_DATE='September 11, 2015' +VERSION=5.1.1-test-1 +VERSION_DATE='November 21, 2015' diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo index 0cd1e81ca..e71dd5310 100644 --- a/Etc/FAQ.yo +++ b/Etc/FAQ.yo @@ -306,7 +306,7 @@ sect(On what machines will it run?) sect(What's the latest version?) - Zsh 5.1/1 is the latest production version. For details of all the + Zsh 5.2 is the latest production version. For details of all the changes, see the NEWS file in the source distribution. A beta of the next version is sometimes available. Development of zsh is diff --git a/README b/README index 9cb352a5f..2e2ebce2b 100644 --- a/README +++ b/README @@ -5,13 +5,10 @@ THE Z SHELL (ZSH) Version ------- -This is version 5.1.1 of the shell. This is a stable release. There are -a few visible improvements since 5.0.8 as well as many bugfixes. Note -in particular the two changes highlighted under "Incompatibilites -between 5.0.8 and 5.1" below. See NEWS for more information. - -There are mostly bug fixes between 5.1 and 5.1.1; however, a few minor -features useful in resolving problems with shell functions were added. +This is version 5.2 of the shell. This is a stable release. There are +a few visible improvements since 5.1.1 as well as many bugfixes. Note +in particular the changs highlighted under "Incompatibilites +between 5.1 and 5.2" below. See NEWS for more information. Installing Zsh -------------- -- cgit v1.2.3