zsh-workers
 help / color / mirror / code / Atom feed
From: Oliver Kiddle <opk@zsh.org>
To: Zsh workers <zsh-workers@zsh.org>
Subject: Re: PATCH: remove OFF flags for display attributes in zattr
Date: Wed, 04 Jan 2023 00:22:35 +0100	[thread overview]
Message-ID: <33364-1672788155.511966@XhH4.5XEP.IFzg> (raw)
In-Reply-To: <81616-1672338153.037786@CNij.sb4i.9Ck4>

Following is an additional patch which clears up some things like macro
names and resolves a couple of issues found with further testing.

The first issue was with colours from an earlier ${(%)...} substitution
being restored following %b in PROMPT_EOL_MARK. This now marks all
attributes as unknown before evaluating it which accurately reflects
the fact that attributes can be anything following the user command.
zrefresh() explicitly unsets all attributes followed by (superfluously?)
standout and underline but that doesn't occur until later.

Another fix was to limit the restored attributes (after %b) to
TXT_ATTR_ALL because we only care about, e.g. TXTFGCOLOUR and not
anything in TXT_ATTR_FG_MASK

The wider use of a mask of unknown attributes required more complete
handling of its value. I'm not certain this is ever needed in the case
of the treplaceattrs() function but it is at least complete and
consistent that to include it there.

Oliver

diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index 97cc7d797..1a3e4c241 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -490,11 +490,7 @@ typedef struct {
      */
     REFRESH_CHAR chr;
     /*
-     * Its attributes.  'On' attributes (TXT_ATTR_ON_MASK) are
-     * applied before the character, 'off' attributes (TXT_ATTR_OFF_MASK)
-     * after it.  'On' attributes are present for all characters that
-     * need the effect; 'off' attributes are only present for the
-     * last character in the sequence.
+     * Its attributes.
      */
     zattr atr;
 } REFRESH_ELEMENT;
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 05e0e4dce..d56478147 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -599,7 +599,7 @@ zwcputc(const REFRESH_ELEMENT *c)
     VARARR(char, mbtmp, MB_CUR_MAX + 1);
 #endif
 
-    txtpendingattrs = c->atr;
+    treplaceattrs(c->atr);
     applytextattributes(0);
 
 #ifdef MULTIBYTE_SUPPORT
@@ -1107,7 +1107,7 @@ zrefresh(void)
 	tsetcap(TCALLATTRSOFF, 0);
 	tsetcap(TCSTANDOUTEND, 0);
 	tsetcap(TCUNDERLINEEND, 0);
-	txtcurrentattrs = txtunknownattrs = 0;
+	txtcurrentattrs = txtpendingattrs = txtunknownattrs = 0;
 
 	if (trashedzle && !clearflag)
 	    reexpandprompt(); 
@@ -1132,7 +1132,7 @@ zrefresh(void)
 	    if (lpromptwof == winw)
 		zputs("\n", shout);	/* works with both hasam and !hasam */
 	} else {
-	    txtpendingattrs = pmpt_attr;
+	    treplaceattrs(pmpt_attr);
 	    applytextattributes(0);
 	}
 	if (clearflag) {
@@ -1205,7 +1205,7 @@ zrefresh(void)
 	if (special_attr & (TXTFGCOLOUR|TXTBGCOLOUR)) {
 	    /* keep colours from special attributes */
 	    all_attr = special_attr |
-		(base_attr & ~TXT_ATTR_COLOUR_ON_MASK);
+		(base_attr & ~TXT_ATTR_COLOUR_MASK);
 	} else {
 	    /* keep colours from standard attributes */
 	    all_attr = special_attr | base_attr;
@@ -1629,7 +1629,7 @@ zrefresh(void)
 		vcs = 0;
 	    }
 	    /* reset character attributes to that set by the main prompt */
-	    txtpendingattrs = pmpt_attr;
+	    treplaceattrs(pmpt_attr);
 	    applytextattributes(0);
 	}
     }
@@ -1645,7 +1645,7 @@ individually */
 
 /* reset character attributes */
     if (clearf && postedit) {
-	txtpendingattrs = pmpt_attr ? pmpt_attr : rpmpt_attr;
+	treplaceattrs(pmpt_attr ? pmpt_attr : rpmpt_attr);
 	applytextattributes(0);
     }
     clearf = 0;
@@ -2037,7 +2037,7 @@ refreshline(int ln)
 	    break;
 	do {
 #endif
-	    txtpendingattrs = nl->atr;
+	    treplaceattrs(nl->atr);
 	    applytextattributes(0);
 
 	    /*
@@ -2434,7 +2434,7 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs)
 		t0 < rhp->end + offset) {
 		if (base_attr & (TXTFGCOLOUR|TXTBGCOLOUR)) {
 		    /* keep colour already set */
-		    base_attr |= rhp->atr & ~TXT_ATTR_COLOUR_ON_MASK;
+		    base_attr |= rhp->atr & ~TXT_ATTR_COLOUR_MASK;
 		} else {
 		    /* no colour set yet */
 		    base_attr |= rhp->atr;
@@ -2444,7 +2444,7 @@ singlerefresh(ZLE_STRING_T tmpline, int tmpll, int tmpcs)
 	if (special_attr & (TXTFGCOLOUR|TXTBGCOLOUR)) {
 	    /* keep colours from special attributes */
 	    all_attr = special_attr |
-		(base_attr & ~TXT_ATTR_COLOUR_ON_MASK);
+		(base_attr & ~TXT_ATTR_COLOUR_MASK);
 	} else {
 	    /* keep colours from standard attributes */
 	    all_attr = special_attr | base_attr;
diff --git a/Src/builtin.c b/Src/builtin.c
index 49f940e1c..4c295d11f 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4603,7 +4603,8 @@ bin_print(char *name, char **args, Options ops, int func)
     /* compute lengths, and interpret according to -P, -D, -e, etc. */
     argc = arrlen(args);
     len = (int *) hcalloc(argc * sizeof(int));
-    txtunknownattrs = TXT_ATTR_ALL;
+    if (OPT_ISSET(ops, 'P'))
+	txtunknownattrs = TXT_ATTR_ALL;
     for (n = 0; n < argc; n++) {
 	/* first \ sequences */
 	if (fmt ||
@@ -4656,7 +4657,6 @@ bin_print(char *name, char **args, Options ops, int func)
 	    unqueue_signals();
 	}
     }
-    txtunknownattrs = 0;
 
     /* -o and -O -- sort the arguments */
     if (OPT_ISSET(ops,'o') || OPT_ISSET(ops,'O')) {
diff --git a/Src/prompt.c b/Src/prompt.c
index 8f0a5073d..880194f87 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -1593,18 +1593,19 @@ applytextattributes(int flags)
     if (keepcount < turncount || (change & ~txtpendingattrs & TXTBOLDFACE)) {
 	tsetcap(TCALLATTRSOFF, flags);
 	/* this cleared all attributes, may need to restore some */
-	change = txtpendingattrs;
+	change = txtpendingattrs & TXT_ATTR_ALL & ~txtunknownattrs;
 	txtunknownattrs = 0;
     } else {
 	if (change & ~txtpendingattrs & TXTSTANDOUT) {
 	    tsetcap(TCSTANDOUTEND, flags);
 	    /* in some cases, that clears all attributes */
-	    change = txtpendingattrs | (TXTUNDERLINE & change);
+	    change = (txtpendingattrs & TXT_ATTR_ALL & ~txtunknownattrs) |
+		    (TXTUNDERLINE & change);
 	}
 	if (change & ~txtpendingattrs & TXTUNDERLINE) {
 	    tsetcap(TCUNDERLINEEND, flags);
 	    /* in some cases, that clears all attributes */
-	    change = txtpendingattrs;
+	    change = txtpendingattrs & TXT_ATTR_ALL & ~txtunknownattrs;
 	}
     }
     if (change & txtpendingattrs & TXTBOLDFACE)
@@ -1614,9 +1615,9 @@ applytextattributes(int flags)
     if (change & txtpendingattrs & TXTUNDERLINE)
 	tsetcap(TCUNDERLINEBEG, flags);
 
-    if (change & TXT_ATTR_FG_ON_MASK)
+    if (change & TXT_ATTR_FG_MASK)
 	set_colour_attribute(txtpendingattrs, COL_SEQ_FG, flags);
-    if (change & TXT_ATTR_BG_ON_MASK)
+    if (change & TXT_ATTR_BG_MASK)
 	set_colour_attribute(txtpendingattrs, COL_SEQ_BG, flags);
 
     txtcurrentattrs = txtpendingattrs;
@@ -1626,12 +1627,27 @@ applytextattributes(int flags)
 mod_export void
 cleartextattributes(int flags)
 {
-    txtpendingattrs = 0;
+    treplaceattrs(0);
     applytextattributes(flags);
 }
 
 /**/
-void
+mod_export void
+treplaceattrs(zattr newattrs)
+{
+    if (txtunknownattrs) {
+	/* Set current attributes to the opposite of the new ones
+	 * for any that are unknown so that applytextattributes()
+	 * detects them as changed. */
+	txtcurrentattrs &= ~txtunknownattrs;
+	txtcurrentattrs |= txtunknownattrs & ~newattrs;
+    }
+
+    txtpendingattrs = newattrs;
+}
+
+/**/
+mod_export void
 tsetattrs(zattr newattrs)
 {
     /* assume any unknown attributes that we're now setting were unset */
@@ -1639,18 +1655,17 @@ tsetattrs(zattr newattrs)
 
     txtpendingattrs |= newattrs & TXT_ATTR_ALL;
     if (newattrs & TXTFGCOLOUR) {
-	txtpendingattrs = (txtpendingattrs &
-	    ~(TXT_ATTR_FG_COL_MASK|TXT_ATTR_FG_24BIT)) |
-	    (newattrs & (TXT_ATTR_FG_ON_MASK|TXT_ATTR_FG_24BIT));
+	txtpendingattrs &= ~TXT_ATTR_FG_MASK;
+	txtpendingattrs |= newattrs & TXT_ATTR_FG_MASK;
     }
     if (newattrs & TXTBGCOLOUR) {
-	txtpendingattrs &= ~(TXT_ATTR_BG_COL_MASK|TXT_ATTR_BG_24BIT);
-	txtpendingattrs |= newattrs & TXT_ATTR_BG_ON_MASK;
+	txtpendingattrs &= ~TXT_ATTR_BG_MASK;
+	txtpendingattrs |= newattrs & TXT_ATTR_BG_MASK;
     }
 }
 
 /**/
-void
+mod_export void
 tunsetattrs(zattr newattrs)
 {
     /* assume any unknown attributes that we're now unsetting were set */
@@ -1658,9 +1673,9 @@ tunsetattrs(zattr newattrs)
 
     txtpendingattrs &= ~(newattrs & TXT_ATTR_ALL);
     if (newattrs & TXTFGCOLOUR)
-	txtpendingattrs &= ~(TXTFGCOLOUR|TXT_ATTR_FG_COL_MASK|TXT_ATTR_FG_24BIT);
+	txtpendingattrs &= ~TXT_ATTR_FG_MASK;
     if (newattrs & TXTBGCOLOUR)
-	txtpendingattrs &= ~(TXTBGCOLOUR|TXT_ATTR_BG_COL_MASK|TXT_ATTR_BG_24BIT);
+	txtpendingattrs &= ~TXT_ATTR_BG_MASK;
 }
 
 /*****************************************************************************
diff --git a/Src/subst.c b/Src/subst.c
index 1e8350ffe..897188862 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -3716,6 +3716,8 @@ colonsubscript:
     if (presc) {
 	int ops = opts[PROMPTSUBST], opb = opts[PROMPTBANG];
 	int opp = opts[PROMPTPERCENT];
+	zattr savecurrent = txtcurrentattrs;
+	zattr saveunknown = txtunknownattrs;
 
 	if (presc < 2) {
 	    opts[PROMPTPERCENT] = 1;
@@ -3753,7 +3755,9 @@ colonsubscript:
 	    val = dupstring(tmps);
 	    free(tmps);
 	}
-	txtunknownattrs = 0;
+
+	txtpendingattrs = txtcurrentattrs = savecurrent;
+	txtunknownattrs = saveunknown;
 	opts[PROMPTSUBST] = ops;
 	opts[PROMPTBANG] = opb;
 	opts[PROMPTPERCENT] = opp;
diff --git a/Src/utils.c b/Src/utils.c
index 8b60d652c..55f2d1ab0 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1543,6 +1543,7 @@ preprompt(void)
 	if (!eolmark)
 	    eolmark = "%B%S%#%s%b";
 	opts[PROMPTPERCENT] = 1;
+	txtunknownattrs = TXT_ATTR_ALL;
 	str = promptexpand(eolmark, 1, NULL, NULL);
 	countprompt(str, &w, 0, -1);
 	opts[PROMPTPERCENT] = percents;
diff --git a/Src/zsh.h b/Src/zsh.h
index b9fa253d7..35ae033e3 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2707,16 +2707,16 @@ struct ttyinfo {
 #define TXT_ATTR_BG_24BIT        0x8000
 
 /* Mask out everything to do with setting a foreground colour */
-#define TXT_ATTR_FG_ON_MASK \
+#define TXT_ATTR_FG_MASK \
     (TXTFGCOLOUR|TXT_ATTR_FG_COL_MASK|TXT_ATTR_FG_24BIT)
 
 /* Mask out everything to do with setting a background colour */
-#define TXT_ATTR_BG_ON_MASK \
+#define TXT_ATTR_BG_MASK \
     (TXTBGCOLOUR|TXT_ATTR_BG_COL_MASK|TXT_ATTR_BG_24BIT)
 
 /* Mask out everything to do with activating colours */
-#define TXT_ATTR_COLOUR_ON_MASK			\
-    (TXT_ATTR_FG_ON_MASK|TXT_ATTR_BG_ON_MASK)
+#define TXT_ATTR_COLOUR_MASK \
+    (TXT_ATTR_FG_MASK|TXT_ATTR_BG_MASK)
 
 #define txtchangeget(T,A)	(((T) & A ## _MASK) >> A ## _SHIFT)
 
diff --git a/Test/D01prompt.ztst b/Test/D01prompt.ztst
index ae8c78ef6..a0abb7e1d 100644
--- a/Test/D01prompt.ztst
+++ b/Test/D01prompt.ztst
@@ -264,6 +264,13 @@
   [[ $A3 = $A1$A2 && -n $A1 && -n $A2 ]]
 0:Attribute optimisation - preserve initial disabling of attribute but drop useless later one
 
+  : ${(%):-%K{blue}}
+  A1="${(%):-%b}x"
+  : ${(%):-%k}
+  A2="${(%):-%b}x"
+  [[ $A1 = $A2 && -n $A1 && -n $A2 ]]
+0:Don't restore attributes from earlier substitution after disabling bold
+
  (RPS1=foo; echo $RPS1 $RPROMPT)
  (RPS2=bar; echo $RPS2 $RPROMPT2)
 -fD:RPS1 and RPROMPT are aliases (regression from 5.0.6) (workers/49600)


  reply	other threads:[~2023-01-03 23:23 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-29 18:22 Oliver Kiddle
2023-01-03 23:22 ` Oliver Kiddle [this message]
2023-01-03 23:36   ` Bart Schaefer
2023-01-04  1:28     ` Oliver Kiddle
2023-01-06 22:31       ` Oliver Kiddle
2023-01-08 13:10         ` Daniel Shahaf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=33364-1672788155.511966@XhH4.5XEP.IFzg \
    --to=opk@zsh.org \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).