diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | Doc/Zsh/compwid.yo | 18 | ||||
-rw-r--r-- | Src/Zle/computil.c | 58 |
3 files changed, 51 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog index fc5fbbb3d..cb079ad23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2008-10-18 Peter Stephenson <p.w.stephenson@ntlworld.com> + * 25912: Doc/Zsh/compwid.yo, Src/Zle/computil.c: fix yet another + Meta bug in completion with matchers in compfiles; remove 25893 + because that wasn't it at all. + * 25911: Test/D07multibyte.ztst: see if we can work around file system idiosyncracies. diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo index dcf2d1569..05b8ab9b2 100644 --- a/Doc/Zsh/compwid.yo +++ b/Doc/Zsh/compwid.yo @@ -942,16 +942,14 @@ line match the corresponding upper case character in the trial completion you can use `tt(m:{[:lower:]}={[:upper:]})'. Although the matching system does not yet handle multibyte characters, this is likely to be a future extension, at which point this syntax will handle -arbitrary alphabets; until then it is safer to use the older syntax -that only handles ASCII characters, `tt(m:{a-z}={A-Z}) as this does -not have side effects in the case of multibyte characters. - -In other cases `tt([:)var(name)tt(:])' forms are allowed. If the two forms -on the left and right are the same, the characters must match exactly. In -remaining cases, the corresponding tests are applied to both characters, -but they are not otherwise constrained; any matching character in one set -goes with any matching character in the other set: this is equivalent to -the behaviour of ordinary character classes. +arbitrary alphabets; hence this form, rather than the use of explicit +ranges, is the recommended form. In other cases +`tt([:)var(name)tt(:])' forms are allowed. If the two forms on the left +and right are the same, the characters must match exactly. In remaining +cases, the corresponding tests are applied to both characters, but they +are not otherwise constrained; any matching character in one set goes +with any matching character in the other set: this is equivalent to the +behaviour of ordinary character classes. The pattern var(tpat) may also be one or two stars, `tt(*)' or `tt(**)'. This means that the pattern on the command line can match diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index 0801e0c2d..e70a05f1a 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -4024,7 +4024,7 @@ cfp_matcher_range(Cmatcher *ms, char *add) * management is difficult. */ for (;;) { - for (mp = ms; *add; add++, mp++) { + for (mp = ms; *add; ) { if (!(m = *mp)) { /* * No matcher, so just match the character @@ -4034,13 +4034,13 @@ cfp_matcher_range(Cmatcher *ms, char *add) * metacharacter? */ if (ret) { - if (imeta(*add)) { + if (*add == Meta) { *p++ = Meta; - *p++ = *add ^ 32; + *p++ = add[1]; } else *p++ = *add; } else - len += imeta(*add) ? 2 : 1; + len += (*add == Meta) ? 2 : 1; } else if (m->flags & CMF_RIGHT) { /* * Right-anchored: match anything followed @@ -4049,15 +4049,16 @@ cfp_matcher_range(Cmatcher *ms, char *add) if (ret) { *p++ = '*'; /* TODO: quote again? */ - if (imeta(*add)) { + if (*add == Meta) { *p++ = Meta; - *p++ = *add ^ 32; + *p++ = add[1]; } else *p++ = *add; } else - len += imeta(*add) ? 3 : 2; + len += (*add == Meta) ? 3 : 2; } else { /* The usual set of matcher possibilities. */ + int chr = (*add == Meta) ? add[1] ^ 32 : *add; int ind; if (m->line->tp == CPAT_EQUIV && m->word->tp == CPAT_EQUIV) { @@ -4072,21 +4073,21 @@ cfp_matcher_range(Cmatcher *ms, char *add) */ if (ret) { *p++ = '['; - if (imeta(*add)) { + if (*add == Meta) { *p++ = Meta; - *p++ = *add ^ 32; + *p++ = add[1]; } else *p++ = *add; } else - len += imeta(*add) ? 3 : 2; - if (PATMATCHRANGE(m->line->u.str, CONVCAST(*add), + len += (*add == Meta) ? 3 : 2; + if (PATMATCHRANGE(m->line->u.str, CONVCAST(chr), &ind, &mt)) { /* * Find the equivalent match for ind in the * word pattern. */ if ((ind = pattern_match_equivalence - (m->word, ind, mt, CONVCAST(*add))) != -1) { + (m->word, ind, mt, CONVCAST(chr))) != -1) { if (ret) { if (imeta(ind)) { *p++ = Meta; @@ -4158,7 +4159,7 @@ cfp_matcher_range(Cmatcher *ms, char *add) * if *add is ] and ] is also the first * character in the range. */ - addadd = !pattern_match1(m->word, CONVCAST(*add), &mt); + addadd = !pattern_match1(m->word, CONVCAST(chr), &mt); if (addadd && *add == ']') { if (ret) *p++ = *add; @@ -4218,6 +4219,13 @@ cfp_matcher_range(Cmatcher *ms, char *add) } } } + if (*add == Meta) { + add += 2; + mp += 2; + } else { + add++; + mp++; + } } if (ret) { *p = '\0'; @@ -4236,19 +4244,19 @@ cfp_matcher_pats(char *matcher, char *add) if (m && m != pcm_err) { char *tmp; - int al = strlen(add), tl; - VARARR(Cmatcher, ms, al); + int al = strlen(add), zl = ztrlen(add), tl, cl; + VARARR(Cmatcher, ms, zl); Cmatcher *mp; Cpattern stopp; int stopl = 0; - memset(ms, 0, al * sizeof(Cmatcher)); + memset(ms, 0, zl * sizeof(Cmatcher)); for (; m && *add; m = m->next) { stopp = NULL; if (!(m->flags & (CMF_LEFT|CMF_RIGHT))) { if (m->llen == 1 && m->wlen == 1) { - for (tmp = add, tl = al, mp = ms; tl; tl--, tmp++, mp++) { + for (tmp = add, tl = al, mp = ms; tl; ) { if (pattern_match(m->line, tmp, NULL, NULL)) { if (*mp) { *tmp = '\0'; @@ -4257,6 +4265,10 @@ cfp_matcher_pats(char *matcher, char *add) } else *mp = m; } + cl = (*tmp == Meta) ? 2 : 1; + tl -= cl; + tmp += cl; + mp += cl; } } else { stopp = m->line; @@ -4264,7 +4276,7 @@ cfp_matcher_pats(char *matcher, char *add) } } else if (m->flags & CMF_RIGHT) { if (m->wlen < 0 && !m->llen && m->ralen == 1) { - for (tmp = add, tl = al, mp = ms; tl; tl--, tmp++, mp++) { + for (tmp = add, tl = al, mp = ms; tl; ) { if (pattern_match(m->right, tmp, NULL, NULL)) { if (*mp || (tmp == add && *tmp == '.')) { *tmp = '\0'; @@ -4273,6 +4285,10 @@ cfp_matcher_pats(char *matcher, char *add) } else *mp = m; } + cl = (*tmp == Meta) ? 2 : 1; + tl -= cl; + tmp += cl; + mp += cl; } } else if (m->llen) { stopp = m->line; @@ -4289,12 +4305,16 @@ cfp_matcher_pats(char *matcher, char *add) stopl = m->lalen; } if (stopp) - for (tmp = add, tl = al; tl >= stopl; tl--, tmp++) + for (tmp = add, tl = al; tl >= stopl; ) { if (pattern_match(stopp, tmp, NULL, NULL)) { *tmp = '\0'; al = tmp - add; break; } + cl = (*tmp == Meta) ? 2 : 1; + tl -= cl; + tmp += cl; + } } if (*add) return cfp_matcher_range(ms, add); |