summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--Src/Zle/zle_word.c313
-rw-r--r--Src/utils.c11
3 files changed, 236 insertions, 92 deletions
diff --git a/ChangeLog b/ChangeLog
index 45acd817d..bd7f13e38 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2008-04-17 Peter Stephenson <pws@csr.com>
+ * 24825: Src/utils.c, Src/Zle/zle_word.c: fix internal
+ word-boundary widgets and make zero-width punctuation
+ characters always part of a word.
+
* unposted: NEWS: list new features so far since 4.3.6.
* Vincent Lefevre: 24818: Doc/Zsh/options.yo (modified),
diff --git a/Src/Zle/zle_word.c b/Src/Zle/zle_word.c
index c1fff7213..ef8220056 100644
--- a/Src/Zle/zle_word.c
+++ b/Src/Zle/zle_word.c
@@ -31,9 +31,13 @@
#include "zle_word.pro"
/*
- * HERE: our handling of combining characters may be wrong. We
- * should make sure we only consider a combining character part of
- * a word if the base character is.
+ * In principle we shouldn't consider a zero-length punctuation
+ * character (i.e. a modifier of some sort) part of the word unless
+ * the base character has. However, we only consider them part of
+ * a word if we so consider all alphanumerics, so the distinction
+ * only applies if the characters are modifying something they probably
+ * ought not to be modifying. It's not really clear we need to
+ * be clever about this not very useful case.
*/
/**/
@@ -147,11 +151,20 @@ viforwardblankwordend(UNUSED(char **args))
if (n < 0)
return 1;
while (n--) {
- /* HERE: the zlecs + 1 here is suspect */
- while (zlecs != zlell && ZC_iblank(zleline[zlecs + 1]))
- INCCS();
- while (zlecs != zlell && !ZC_iblank(zleline[zlecs + 1]))
- INCCS();
+ while (zlecs != zlell) {
+ int pos = zlecs;
+ INCPOS(pos);
+ if (!ZC_iblank(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
+ while (zlecs != zlell) {
+ int pos = zlecs;
+ INCPOS(pos);
+ if (ZC_iblank(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
}
if (zlecs != zlell && virangeflag)
INCCS();
@@ -173,15 +186,37 @@ viforwardwordend(char **args)
}
while (n--) {
/* HERE: the zlecs + 1 here is suspect */
- if (ZC_iblank(zleline[zlecs + 1]))
- while (zlecs != zlell && ZC_iblank(zleline[zlecs + 1]))
- INCCS();
- if (Z_vialnum(zleline[zlecs + 1]))
- while (zlecs != zlell && Z_vialnum(zleline[zlecs + 1]))
- INCCS();
- else
- while (zlecs != zlell && !Z_vialnum(zleline[zlecs + 1]) && !ZC_iblank(zleline[zlecs + 1]))
- INCCS();
+ int pos;
+ while (zlecs != zlell) {
+ pos = zlecs;
+ INCPOS(pos);
+ if (!ZC_inblank(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
+ if (zlecs != zlell) {
+ pos = zlecs;
+ INCPOS(pos);
+ if (Z_vialnum(zleline[pos])) {
+ for (;;) {
+ zlecs = pos;
+ if (zlecs == zlell)
+ break;
+ INCPOS(pos);
+ if (!Z_vialnum(zleline[pos]))
+ break;
+ }
+ } else {
+ for (;;) {
+ zlecs = pos;
+ if (zlecs == zlell)
+ break;
+ INCPOS(pos);
+ if (Z_vialnum(zleline[pos]) || ZC_iblank(zleline[pos]))
+ break;
+ }
+ }
+ }
}
if (zlecs != zlell && virangeflag)
INCCS();
@@ -202,11 +237,20 @@ backwardword(char **args)
return ret;
}
while (n--) {
- /* HERE: the zlecs - 1 here is suspect */
- while (zlecs && !ZC_iword(zleline[zlecs - 1]))
- DECCS();
- while (zlecs && ZC_iword(zleline[zlecs - 1]))
- DECCS();
+ while (zlecs) {
+ int pos = zlecs;
+ DECPOS(pos);
+ if (ZC_iword(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
+ while (zlecs) {
+ int pos = zlecs;
+ DECPOS(pos);
+ if (!ZC_iword(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
}
return 0;
}
@@ -225,15 +269,36 @@ vibackwardword(char **args)
return ret;
}
while (n--) {
- /* HERE: the zlecs - 1 here is suspect */
- while (zlecs && ZC_iblank(zleline[zlecs - 1]))
- DECCS();
- if (Z_vialnum(zleline[zlecs - 1]))
- while (zlecs && Z_vialnum(zleline[zlecs - 1]))
- DECCS();
- else
- while (zlecs && !Z_vialnum(zleline[zlecs - 1]) && !ZC_iblank(zleline[zlecs - 1]))
- DECCS();
+ while (zlecs) {
+ int pos = zlecs;
+ DECPOS(pos);
+ if (!ZC_iblank(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
+ if (zlecs) {
+ int pos = zlecs;
+ DECPOS(pos);
+ if (Z_vialnum(zleline[pos])) {
+ for (;;) {
+ zlecs = pos;
+ if (zlecs == 0)
+ break;
+ DECPOS(pos);
+ if (!Z_vialnum(zleline[pos]))
+ break;
+ }
+ } else {
+ for (;;) {
+ zlecs = pos;
+ if (zlecs == 0)
+ break;
+ DECPOS(pos);
+ if (Z_vialnum(zleline[pos]) || ZC_iblank(zleline[pos]))
+ break;
+ }
+ }
+ }
}
return 0;
}
@@ -252,10 +317,20 @@ vibackwardblankword(char **args)
return ret;
}
while (n--) {
- while (zlecs && ZC_iblank(zleline[zlecs - 1]))
- DECCS();
- while (zlecs && !ZC_iblank(zleline[zlecs - 1]))
- DECCS();
+ while (zlecs) {
+ int pos = zlecs;
+ DECPOS(pos);
+ if (!ZC_iblank(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
+ while (zlecs) {
+ int pos = zlecs;
+ DECPOS(pos);
+ if (ZC_iblank(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
}
return 0;
}
@@ -274,10 +349,20 @@ emacsbackwardword(char **args)
return ret;
}
while (n--) {
- while (zlecs && !ZC_iword(zleline[zlecs - 1]))
- DECCS();
- while (zlecs && ZC_iword(zleline[zlecs - 1]))
- DECCS();
+ while (zlecs) {
+ int pos = zlecs;
+ DECPOS(pos);
+ if (ZC_iword(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
+ while (zlecs) {
+ int pos = zlecs;
+ DECPOS(pos);
+ if (!ZC_iword(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
}
return 0;
}
@@ -296,14 +381,20 @@ backwarddeleteword(char **args)
return ret;
}
while (n--) {
- /*
- * HERE: the zlecs - 1 here is suspect, and we should
- * do the DECCS() thing.
- */
- while (x && !ZC_iword(zleline[x - 1]))
- x--;
- while (x && ZC_iword(zleline[x - 1]))
- x--;
+ while (x) {
+ int pos = x;
+ DECPOS(pos);
+ if (ZC_iword(zleline[pos]))
+ break;
+ x = pos;
+ }
+ while (x) {
+ int pos = x;
+ DECPOS(pos);
+ if (!ZC_iword(zleline[pos]))
+ break;
+ x = pos;
+ }
}
backdel(zlecs - x, CUT_RAW);
return 0;
@@ -320,18 +411,36 @@ vibackwardkillword(UNUSED(char **args))
return 1;
/* this taken from "vibackwardword" */
while (n--) {
- /*
- * HERE: the zlecs - 1 here is suspect, and we should
- * do the DECCS() thing.
- */
- while ((x > lim) && ZC_iblank(zleline[x - 1]))
- x--;
- if (Z_vialnum(zleline[x - 1]))
- while ((x > lim) && Z_vialnum(zleline[x - 1]))
- x--;
- else
- while ((x > lim) && !Z_vialnum(zleline[x - 1]) && !ZC_iblank(zleline[x - 1]))
- x--;
+ while (x > lim) {
+ int pos = x;
+ DECPOS(pos);
+ if (!ZC_iblank(zleline[pos]))
+ break;
+ x = pos;
+ }
+ if (x > lim) {
+ int pos = x;
+ DECPOS(pos);
+ if (Z_vialnum(zleline[pos])) {
+ for (;;) {
+ x = pos;
+ if (x <= lim)
+ break;
+ DECPOS(pos);
+ if (!Z_vialnum(zleline[pos]))
+ break;
+ }
+ } else {
+ for (;;) {
+ x = pos;
+ if (x <= lim)
+ break;
+ DECPOS(pos);
+ if (Z_vialnum(zleline[pos]) || ZC_iblank(zleline[pos]))
+ break;
+ }
+ }
+ }
}
backkill(zlecs - x, CUT_FRONT);
return 0;
@@ -352,14 +461,20 @@ backwardkillword(char **args)
return ret;
}
while (n--) {
- /*
- * HERE: the zlecs - 1 here is suspect, and we should
- * do the DECCS() thing.
- */
- while (x && !ZC_iword(zleline[x - 1]))
- x--;
- while (x && ZC_iword(zleline[x - 1]))
- x--;
+ while (x) {
+ int pos = x;
+ DECPOS(pos);
+ if (ZC_iword(zleline[x]))
+ break;
+ x = pos;
+ }
+ while (x) {
+ int pos = x;
+ DECPOS(pos);
+ if (!ZC_iword(zleline[x]))
+ break;
+ x = pos;
+ }
}
backkill(zlecs - x, CUT_FRONT);
return 0;
@@ -451,11 +566,10 @@ deleteword(char **args)
return ret;
}
while (n--) {
- /* HERE: we should do the INCCS() thing */
while (x != zlell && !ZC_iword(zleline[x]))
- x++;
+ INCPOS(x);
while (x != zlell && ZC_iword(zleline[x]))
- x++;
+ INCPOS(x);
}
foredel(x - zlecs, CUT_RAW);
return 0;
@@ -476,11 +590,10 @@ killword(char **args)
return ret;
}
while (n--) {
- /* HERE: we should do the INCCS() thing */
while (x != zlell && !ZC_iword(zleline[x]))
- x++;
+ INCPOS(x);
while (x != zlell && ZC_iword(zleline[x]))
- x++;
+ INCPOS(x);
}
forekill(x - zlecs, CUT_RAW);
return 0;
@@ -490,7 +603,7 @@ killword(char **args)
int
transposewords(UNUSED(char **args))
{
- int p1, p2, p3, p4, len, x = zlecs;
+ int p1, p2, p3, p4, len, x = zlecs, pos;
ZLE_STRING_T temp, pp;
int n = zmult;
int neg = n < 0, ocs = zlecs;
@@ -498,28 +611,54 @@ transposewords(UNUSED(char **args))
if (neg)
n = -n;
while (n--) {
- /*
- * HERE: we should do the INCCS() thing.
- * A great deal of the following needs rewriting.
- */
while (x != zlell && zleline[x] != ZWC('\n') && !ZC_iword(zleline[x]))
- x++;
+ INCPOS(x);
if (x == zlell || zleline[x] == ZWC('\n')) {
x = zlecs;
- while (x && zleline[x - 1] != ZWC('\n') && !ZC_iword(zleline[x]))
- x--;
- if (!x || zleline[x - 1] == ZWC('\n'))
+ while (x) {
+ if (ZC_iword(zleline[x]))
+ break;
+ pos = x;
+ DECPOS(pos);
+ if (zleline[pos] == ZWC('\n'))
+ break;
+ x = pos;
+ }
+ if (!x)
+ return 1;
+ pos = x;
+ DECPOS(pos);
+ if (zleline[pos] == ZWC('\n'))
return 1;
+ x = pos;
+ }
+ for (p4 = x; p4 != zlell && ZC_iword(zleline[p4]); INCPOS(p4))
+ ;
+ for (p3 = p4; p3; ) {
+ pos = p3;
+ DECPOS(pos);
+ if (!ZC_iword(zleline[pos]))
+ break;
+ p3 = pos;
}
- for (p4 = x; p4 != zlell && ZC_iword(zleline[p4]); p4++);
- for (p3 = p4; p3 && ZC_iword(zleline[p3 - 1]); p3--);
if (!p3)
return 1;
- for (p2 = p3; p2 && !ZC_iword(zleline[p2 - 1]); p2--);
+ for (p2 = p3; p2; ) {
+ pos = p2;
+ DECPOS(pos);
+ if (ZC_iword(zleline[pos]))
+ break;
+ p2 = pos;
+ }
if (!p2)
return 1;
- for (p1 = p2; p1 && ZC_iword(zleline[p1 - 1]); p1--);
-
+ for (p1 = p2; p1; ) {
+ pos = p1;
+ DECPOS(pos);
+ if (!ZC_iword(zleline[pos]))
+ break;
+ p1 = pos;
+ }
pp = temp = (ZLE_STRING_T)zhalloc((p4 - p1)*ZLE_CHAR_SIZE);
len = p4 - p3;
ZS_memcpy(pp, zleline + p3, len);
diff --git a/Src/utils.c b/Src/utils.c
index b4770befe..21a3a0c34 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3082,12 +3082,13 @@ wcsitype(wchar_t c, int itype)
if (iswalnum(c))
return 1;
/*
- * If we are handling combining characters, anything
- * printable with zero width needs to be considered
- * part of a word.
+ * If we are handling combining characters, any punctuation
+ * characters with zero width needs to be considered part of
+ * a word. If we are not handling combining characters then
+ * logically they are still part of the word, even if they
+ * don't get displayed properly, so always do this.
*/
- if (isset(COMBININGCHARS) &&
- iswprint(c) && wcwidth(c) == 0)
+ if (iswpunct(c) && wcwidth(c) == 0)
return 1;
return !!wmemchr(wordchars_wide.chars, c, wordchars_wide.len);