Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: fixes related to prompt attribute leftovers
- X-seq: zsh-workers 54036
- From: Oliver Kiddle <opk@xxxxxxx>
- To: Zsh workers <zsh-workers@xxxxxxx>
- Subject: PATCH: fixes related to prompt attribute leftovers
- Date: Wed, 05 Nov 2025 16:29:40 +0100
- Archived-at: <https://zsh.org/workers/54036>
- List-id: <zsh-workers.zsh.org>
This is a follow-on to 51281 which kept track of attributes left on
at the end of the prompt to try to preserve backward compatibility for
anyone who does that. That's still not a particularly good idea but this
patch does make things cleaner such as to avoid attributes bleeding into
completion listings and ensuring that a background colour is not
replaced when you use backspace or used insconsistently around ellipses.
There are further places where a space in default attributes is
added but I've only changed code that I knew how to reach.
Oliver
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index 091ad03b1..ea18434a3 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -2049,6 +2049,8 @@ complistmatches(UNUSED(Hookdef dummy), Chdata dat)
if (mlistp && !*mlistp)
mlistp = "%SAt %p: Hit TAB for more, or the character to insert%s";
trashzle();
+ treplaceattrs(0); /* complist does it's own attributes so wipe any zle residue */
+ applytextattributes(0);
showinglist = listshown = 0;
lastlistlen = 0;
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 1afb1bf58..f5348c59b 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -2072,8 +2072,6 @@ trashzle(void)
trashedzle = 1;
zrefresh();
showinglist = sl;
- treplaceattrs(prompt_attr);
- applytextattributes(0);
moveto(nlnct, 0);
if (clearflag && tccan(TCCLEAREOD)) {
tcout(TCCLEAREOD);
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index f076bdd61..e89daf506 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -600,7 +600,8 @@ unset_region_highlight(Param pm, int exp)
static void
tcoutclear(int cap)
{
- cleartextattributes(0);
+ treplaceattrs((cap == TCCLEAREOL) ? prompt_attr : 0);
+ applytextattributes(0);
tcout(cap);
}
@@ -983,7 +984,7 @@ zrefresh(void)
#ifdef MULTIBYTE_SUPPORT
int width; /* width of wide character */
#endif
-
+ const REFRESH_ELEMENT zr_pad = { ZWC(' '), prompt_attr };
/* If this is called from listmatches() (indirectly via trashzle()), and *
* that was called from the end of zrefresh(), then we don't need to do *
@@ -1195,7 +1196,7 @@ zrefresh(void)
rpms.sen = *nbuf + winw;
for (t = tmpline, tmppos = 0; tmppos < tmpll; t++, tmppos++) {
zattr base_attr = mixattrs(default_attr, prompt_attr);
- zattr all_attr;
+ zattr all_attr = 0;
struct region_highlight *rhp;
int layer, nextlayer = 0;
/*
@@ -1493,7 +1494,7 @@ zrefresh(void)
rpms.sen = rpms.s + winw - 7;
for (; rpms.s < rpms.sen; rpms.s++) {
if (rpms.s->chr == ZWC('\0')) {
- ZR_memset(rpms.s, zr_sp, rpms.sen - rpms.s);
+ ZR_memset(rpms.s, zr_pad, rpms.sen - rpms.s);
/* make sure we don't trigger the WEOF test */
rpms.sen->chr = ZWC('\0');
break;
@@ -1511,6 +1512,7 @@ zrefresh(void)
}
#endif
ZR_memcpy(rpms.sen, zr_end_ellipsis, ZR_END_ELLIPSIS_SIZE);
+ rpms.sen[0].atr = prompt_attr;
rpms.sen[1].atr = ellipsis_attr;
#ifdef MULTIBYTE_SUPPORT
/* Extend to the end if we backed off for a wide character */
@@ -1591,7 +1593,7 @@ zrefresh(void)
t0 = t0 > ZR_START_ELLIPSIS_SIZE ? ZR_START_ELLIPSIS_SIZE : t0;
ZR_memcpy(nbuf[0] + lpromptw, zr_start_ellipsis, t0);
(*nbuf + lpromptw)->atr = ellipsis_attr;
- ZR_memset(nbuf[0] + lpromptw + t0, zr_sp, winw - t0 - lpromptw);
+ ZR_memset(nbuf[0] + lpromptw + t0, zr_pad, winw - t0 - lpromptw);
(*nbuf + lpromptw + t0)->atr = prompt_attr;
nbuf[0][winw] = nbuf[0][winw + 1] = zr_zr;
}
@@ -1740,6 +1742,7 @@ refreshline(int ln)
ins_last, /* insert pushed last character off line */
nllen, ollen, /* new and old line buffer lengths */
rnllen; /* real new line buffer length */
+ const REFRESH_ELEMENT zr_pad = { ZWC(' '), prompt_attr };
/* 0: setup */
nl = nbuf[ln];
@@ -1786,7 +1789,7 @@ refreshline(int ln)
} else if (ollen > nllen) { /* make new line at least as long as old */
p1 = zhalloc((ollen + 1) * sizeof(*p1));
ZR_memcpy(p1, nl, nllen);
- ZR_memset(p1 + nllen, zr_sp, ollen - nllen);
+ ZR_memset(p1 + nllen, zr_pad, ollen - nllen);
p1[ollen] = zr_zr;
nl = p1;
nllen = ollen;
@@ -1802,13 +1805,18 @@ refreshline(int ln)
else {
col_cleareol = -1;
if (tccan(TCCLEAREOL) && (nllen == winw || put_rpmpt != oput_rpmpt)) {
- for (i = nllen; i && ZR_equal(zr_sp, nl[i - 1]); i--)
+ zattr a = nl[nllen - 1].atr;
+ for (i = nllen; i && nl[i - 1].chr == ' ' && nl[i - 1].atr == a; i--)
;
- for (j = ollen; j && ZR_equal(ol[j - 1], zr_sp); j--)
- ;
- if ((j > i + tclen[TCCLEAREOL]) /* new buf has enough spaces */
- || (nllen == winw && ZR_equal(zr_sp, nl[winw - 1])))
+ if (nllen == winw && i < nllen) {
col_cleareol = i;
+ } else {
+ a = ol[ollen - 1].atr;
+ for (j = ollen; j && ol[j - 1].chr == ' ' && ol[j - 1].atr == a; j--)
+ ;
+ if ((j > i + tclen[TCCLEAREOL])) /* new buf has enough spaces */
+ col_cleareol = i;
+ }
}
}
@@ -1914,7 +1922,7 @@ refreshline(int ln)
else {
vcs += i;
while (i-- > 0)
- zputc(&zr_sp);
+ zputc(&zr_pad);
}
return;
}
@@ -1958,10 +1966,11 @@ refreshline(int ln)
/*
* Some terminals will output the current
* attributes into cells added at the end by
- * deletions, so turn off text attributes.
+ * deletions, so apply the text area attributes.
*/
if (first) {
- cleartextattributes(0);
+ treplaceattrs(prompt_attr);
+ applytextattributes(0);
first = 0;
}
tc_delchars(i);
diff --git a/Src/prompt.c b/Src/prompt.c
index 7467cdfb9..586447aa1 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -1702,14 +1702,6 @@ applytextattributes(int flags)
txtcurrentattrs = txtpendingattrs;
}
-/**/
-mod_export void
-cleartextattributes(int flags)
-{
- treplaceattrs(0);
- applytextattributes(flags);
-}
-
/**/
mod_export void
treplaceattrs(zattr newattrs)
Messages sorted by:
Reverse Date,
Date,
Thread,
Author