about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2023-01-10 20:57:03 +0100
committerOliver Kiddle <opk@zsh.org>2023-01-10 20:57:03 +0100
commitc01479a2ede78b9b53057322e4b9f5bd0a103a00 (patch)
treefb02cafa81ade7ee2dbbfc72c81b09c8d9add1bb
parent667ead3a64e590ac758e9f0a053849c7aaccec66 (diff)
downloadzsh-c01479a2ede78b9b53057322e4b9f5bd0a103a00.tar.gz
zsh-c01479a2ede78b9b53057322e4b9f5bd0a103a00.tar.xz
zsh-c01479a2ede78b9b53057322e4b9f5bd0a103a00.zip
51280: add support for italic and faint fonts in the line editor
-rw-r--r--ChangeLog4
-rw-r--r--Doc/Zsh/zle.yo10
-rw-r--r--Src/Zle/zle_refresh.c26
-rw-r--r--Src/init.c19
-rw-r--r--Src/prompt.c39
-rw-r--r--Src/zsh.h52
6 files changed, 101 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index b3518f1bf..9e2938bf8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2023-01-10  Oliver Kiddle  <opk@zsh.org>
 
+	* 51280: Doc/Zsh/zle.yo, Src/Zle/zle_refresh.c, Src/init.c,
+	Src/prompt.c, Src/zsh.h: add support for italic and faint
+	fonts in the line editor
+
 	* 51258, 51272: Src/Modules/watch.c, Src/Zle/complist.c,
 	Src/Zle/zle.h, Src/Zle/zle_main.c, Src/Zle/zle_refresh.c,
 	Src/Zle/zle_tricky.c, Src/Zle/zle_utils.c, Src/builtin.c,
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 58700072a..60254e828 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -2780,9 +2780,13 @@ This works similarly to the foreground colour, except the background is
 not usually affected by the bold attribute.
 )
 item(tt(bold))(
-The characters in the given context are shown in a bold font.
+The characters in the given context are shown with a bold font weight.
 Not all terminals distinguish bold fonts.
 )
+item(tt(faint))(
+The characters in the given context are shown with a faint font weight.
+Not all terminals distinguish faint fonts.
+)
 item(tt(standout))(
 The characters in the given context are shown in the terminal's standout
 mode.  The actual effect is specific to the terminal; on many terminals it
@@ -2796,6 +2800,10 @@ The characters in the given context are shown underlined.  Some
 terminals show the foreground in a different colour instead; in this
 case whitespace will not be highlighted.
 )
+item(tt(italic))(
+The characters in the given context are shown in a italic font.
+Not all terminals support italic fonts.
+)
 enditem()
 
 The characters described above as `special' are as follows.  The
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index ae8e5c109..d40400886 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -1193,23 +1193,10 @@ zrefresh(void)
 		offset = predisplaylen; /* increment over it */
 	    if (rhp->start + offset <= tmppos &&
 		tmppos < rhp->end + offset) {
-		if (rhp->atr & (TXTFGCOLOUR|TXTBGCOLOUR)) {
-		    /* override colour with later entry */
-		    base_attr = rhp->atr;
-		} else {
-		    /* no colour set yet */
-		    base_attr |= rhp->atr;
-		}
+		base_attr = mixattrs(rhp->atr, base_attr);
 	    }
 	}
-	if (special_attr & (TXTFGCOLOUR|TXTBGCOLOUR)) {
-	    /* keep colours from special attributes */
-	    all_attr = special_attr |
-		(base_attr & ~TXT_ATTR_COLOUR_MASK);
-	} else {
-	    /* keep colours from standard attributes */
-	    all_attr = special_attr | base_attr;
-	}
+	all_attr = mixattrs(special_attr, base_attr);
 
 	if (t == scs)			/* if cursor is here, remember it */
 	    rpms.nvcs = rpms.s - nbuf[rpms.nvln = rpms.ln];
@@ -2441,14 +2428,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_MASK);
-	} else {
-	    /* keep colours from standard attributes */
-	    all_attr = special_attr | base_attr;
-	}
+	all_attr = mixattrs(special_attr, base_attr);
 
 	if (tmpline[t0] == ZWC('\t')) {
 	    for (*vp++ = zr_sp; (vp - vbuf) & 7; )
diff --git a/Src/init.c b/Src/init.c
index 75ef2e094..68621a0ad 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -747,7 +747,7 @@ init_shout(void)
 static char *tccapnams[TC_COUNT] = {
     "cl", "le", "LE", "nd", "RI", "up", "UP", "do",
     "DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta",
-    "md", "so", "us", "me", "se", "ue", "ch",
+    "md", "mh", "so", "us", "ZH", "me", "se", "ue", "ZR", "ch",
     "ku", "kd", "kl", "kr", "sc", "rc", "bc", "AF", "AB"
 };
 
@@ -872,6 +872,23 @@ init_term(void)
 	/* The following is an attempt at a heuristic,
 	 * but it fails in some cases */
 	/* rprompt_indent = ((hasam && !hasbw) || hasye || !tccan(TCLEFT)); */
+
+	/* if there's no termcap entry for italics, use CSI 3 m */
+	if (!tccan(TCITALICSBEG)) {
+	    zsfree(tcstr[TCITALICSBEG]);
+	    tcstr[TCITALICSBEG] = ztrdup("\033[3m");
+	    tclen[TCITALICSBEG] = 4;
+	}
+	if (!tccan(TCITALICSEND)) {
+	    zsfree(tcstr[TCITALICSEND]);
+	    tcstr[TCITALICSEND] = ztrdup("\033[23m");
+	    tclen[TCITALICSEND] = 5;
+	}
+	if (!tccan(TCFAINTBEG)) {
+	    zsfree(tcstr[TCFAINTBEG]);
+	    tcstr[TCFAINTBEG] = ztrdup("\033[2m");
+	    tclen[TCFAINTBEG] = 4;
+	}
     }
     return 1;
 }
diff --git a/Src/prompt.c b/Src/prompt.c
index 880194f87..488a90d09 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -1590,7 +1590,15 @@ applytextattributes(int flags)
 	    turnoff &= turnoff - 1;
     }
 
-    if (keepcount < turncount || (change & ~txtpendingattrs & TXTBOLDFACE)) {
+    /* enabling bold can be relied upon to disable faint
+     * (the converse not so as that commonly does nothing at all) */
+    if (txtcurrentattrs & TXTFAINT && txtpendingattrs & TXTBOLDFACE) {
+	--turncount;
+	change &= ~TXTFAINT;
+    }
+
+    if (keepcount < turncount ||
+	    (change & ~txtpendingattrs & TXT_ATTR_FONT_WEIGHT)) {
 	tsetcap(TCALLATTRSOFF, flags);
 	/* this cleared all attributes, may need to restore some */
 	change = txtpendingattrs & TXT_ATTR_ALL & ~txtunknownattrs;
@@ -1607,13 +1615,19 @@ applytextattributes(int flags)
 	    /* in some cases, that clears all attributes */
 	    change = txtpendingattrs & TXT_ATTR_ALL & ~txtunknownattrs;
 	}
+	if (change & ~txtpendingattrs & TXTITALIC)
+	    tsetcap(TCITALICSEND, flags);
     }
     if (change & txtpendingattrs & TXTBOLDFACE)
 	tsetcap(TCBOLDFACEBEG, flags);
+    if (change & txtpendingattrs & TXTFAINT)
+	tsetcap(TCFAINTBEG, flags);
     if (change & txtpendingattrs & TXTSTANDOUT)
 	tsetcap(TCSTANDOUTBEG, flags);
     if (change & txtpendingattrs & TXTUNDERLINE)
 	tsetcap(TCUNDERLINEBEG, flags);
+    if (change & txtpendingattrs & TXTITALIC)
+	tsetcap(TCITALICSBEG, flags);
 
     if (change & TXT_ATTR_FG_MASK)
 	set_colour_attribute(txtpendingattrs, COL_SEQ_FG, flags);
@@ -1678,6 +1692,25 @@ tunsetattrs(zattr newattrs)
 	txtpendingattrs &= ~TXT_ATTR_BG_MASK;
 }
 
+/* Merge two attribute sets. In an case where attributes might conflict
+ * choose those from the first parameter.  Foreground and background
+ * colours are taken together - less likely to end up with unreadable
+ * combinations. */
+
+/**/
+mod_export zattr
+mixattrs(zattr primary, zattr secondary)
+{
+    zattr result = secondary;
+    /* take colours from primary */
+    if (primary & (TXTFGCOLOUR|TXTBGCOLOUR))
+        result &= ~TXT_ATTR_COLOUR_MASK;
+    /* take font weight from primary */
+    if (primary & TXT_ATTR_FONT_WEIGHT)
+        result &= ~TXT_ATTR_FONT_WEIGHT;
+    return result | primary;
+}
+
 /*****************************************************************************
  * Utilities dealing with colour and other forms of highlighting.
  *
@@ -1700,9 +1733,11 @@ struct highlight {
 
 static const struct highlight highlights[] = {
     { "none", 0, TXT_ATTR_ALL },
-    { "bold", TXTBOLDFACE, 0 },
+    { "bold", TXTBOLDFACE, TXTFAINT },
+    { "faint", TXTFAINT, TXTBOLDFACE },
     { "standout", TXTSTANDOUT, 0 },
     { "underline", TXTUNDERLINE, 0 },
+    { "italic", TXTITALIC, 0 },
     { NULL, 0, 0 }
 };
 
diff --git a/Src/zsh.h b/Src/zsh.h
index 35ae033e3..e834c7e06 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2646,22 +2646,25 @@ struct ttyinfo {
 #define TCDELLINE      16
 #define TCNEXTTAB      17
 #define TCBOLDFACEBEG  18
-#define TCSTANDOUTBEG  19
-#define TCUNDERLINEBEG 20
-#define TCALLATTRSOFF  21
-#define TCSTANDOUTEND  22
-#define TCUNDERLINEEND 23
-#define TCHORIZPOS     24
-#define TCUPCURSOR     25
-#define TCDOWNCURSOR   26
-#define TCLEFTCURSOR   27
-#define TCRIGHTCURSOR  28
-#define TCSAVECURSOR   29
-#define TCRESTRCURSOR  30
-#define TCBACKSPACE    31
-#define TCFGCOLOUR     32
-#define TCBGCOLOUR     33
-#define TC_COUNT       34
+#define TCFAINTBEG     19
+#define TCSTANDOUTBEG  20
+#define TCUNDERLINEBEG 21
+#define TCITALICSBEG   22
+#define TCALLATTRSOFF  23
+#define TCSTANDOUTEND  24
+#define TCUNDERLINEEND 25
+#define TCITALICSEND   27
+#define TCHORIZPOS     27
+#define TCUPCURSOR     28
+#define TCDOWNCURSOR   29
+#define TCLEFTCURSOR   30
+#define TCRIGHTCURSOR  31
+#define TCSAVECURSOR   32
+#define TCRESTRCURSOR  33
+#define TCBACKSPACE    34
+#define TCFGCOLOUR     35
+#define TCBGCOLOUR     36
+#define TC_COUNT       37
 
 #define tccan(X) (tclen[X])
 
@@ -2676,12 +2679,14 @@ struct ttyinfo {
 #endif
 
 #define TXTBOLDFACE   0x0001
-#define TXTSTANDOUT   0x0002
-#define TXTUNDERLINE  0x0004
-#define TXTFGCOLOUR   0x0008
-#define TXTBGCOLOUR   0x0010
+#define TXTFAINT      0x0002
+#define TXTSTANDOUT   0x0004
+#define TXTUNDERLINE  0x0008
+#define TXTITALIC     0x0010
+#define TXTFGCOLOUR   0x0020
+#define TXTBGCOLOUR   0x0040
 
-#define TXT_ATTR_ALL  0x001F
+#define TXT_ATTR_ALL  0x007F
 
 /*
  * Indicates to zle_refresh.c that the character entry is an
@@ -2690,7 +2695,10 @@ struct ttyinfo {
 #define TXT_MULTIWORD_MASK  0x0400
 
 /* used when, e.g an invalid colour is specified */
-#define TXT_ERROR 0xF00000F000000800
+#define TXT_ERROR 0xF00000F000000003
+
+/* Mask for font weight */
+#define TXT_ATTR_FONT_WEIGHT     (TXTBOLDFACE|TXTFAINT)
 
 /* Mask for colour to use in foreground */
 #define TXT_ATTR_FG_COL_MASK     0x000000FFFFFF0000