Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] prompt, etc: trust when termcap says we have no colour



On Wed 22 Apr 2026, at 20:06, Oliver Kiddle wrote:
> However, I don't follow the logic behind using this as a heuristic for
> italic and faint.

we discussed this on irc a few times. oliver said it's not uncommon for
him to see italic missing from termcap where it should be supported

at his suggestion i was going to replace my 'heuristic' by a hard-coded
exemption for the linux console. but at the last minute i thought to
check console_codes(4) and it actually says that dim, italic, and
underscore are 'simulated with color on a color display'

so it's meant to look like that after all

here's a revised patch:

- leave polyfills alone, since TERM=dumb ignores them via another path
  and i don't have evidence that it causes problems for anything else

- avoid setting colours also if the terminal is unknown

- remove ZLS_COLORS override. comptest uses list colours to add 'tags'
  to the match list. we can probably do this in a way that supports that
  use case but it needs more thought

dana


diff --git a/Doc/Zsh/prompt.yo b/Doc/Zsh/prompt.yo
index d68f00826..3154901b7 100644
--- a/Doc/Zsh/prompt.yo
+++ b/Doc/Zsh/prompt.yo
@@ -222,6 +222,14 @@ and may work if the system supports them.
 enditem()
 
 subsect(Visual Effects)
+These sequences affect the way text is displayed.  Where applicable,
+their behaviour depends on the capabilities supported by the terminal
+type currently in use (normally dictated by the tt(TERM) environment
+variable).  For example, the terminal type tt(dumb) doesn't support
+underline, so `tt(TERM=dumb print -P %Utest%u)' prints the unformatted
+string `tt(test)'.  This can be exploited to conditionally disable
+colours and styling in scripts.
+
 startitem()
 item(tt(%B) LPAR()tt(%b)RPAR())(
 Start (stop) boldface mode.
diff --git a/Src/init.c b/Src/init.c
index f36bc332b..55fbf5cf3 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -790,6 +790,8 @@ init_term(void)
     static char termbuf[2048];	/* the termcap buffer */
 #endif
 
+    termflags &= ~TERM_NOCOLOUR;
+
     if (!*term) {
 	termflags |= TERM_UNKNOWN;
 	return 0;
@@ -838,6 +840,8 @@ init_term(void)
 	tccolumns = tgetnum("co");
 	tccolours = tgetnum("Co");
 
+	termflags |= tccolours <= 0 ? TERM_NOCOLOUR : 0;
+
 	/* if there's no termcap entry for cursor up, use single line mode: *
 	 * this is flagged by termflags which is examined in zle_refresh.c  *
 	 */
@@ -890,6 +894,8 @@ init_term(void)
 	/* rprompt_indent = ((hasam && !hasbw) || hasye || !tccan(TCLEFT)); */
 
 	/* if there's no termcap entry for italics, use CSI 3 m */
+	/* note that these have no effect on TERM=dumb due to the check for */
+	/* TERM_NOUP in tsetcap() */
 	if (!tccan(TCITALICSBEG)) {
 	    zsfree(tcstr[TCITALICSBEG]);
 	    tcstr[TCITALICSBEG] = ztrdup("\033[3m");
diff --git a/Src/prompt.c b/Src/prompt.c
index 7db074da8..9546b45cd 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -2444,6 +2444,9 @@ set_colour_attribute(zattr atr, int fg_bg, int flags)
     int colour, tc, def, use_truecolor;
     int is_default_zle_highlight = 1;
 
+    if (termflags & (TERM_UNKNOWN | TERM_NOCOLOUR))
+	return;
+
     if (fg_bg == COL_SEQ_FG) {
 	colour = txtchangeget(atr, TXT_ATTR_FG_COL);
 	tc = TCFGCOLOUR;
diff --git a/Src/zsh.h b/Src/zsh.h
index 1f1ecc3e6..d2c1e026e 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2633,6 +2633,7 @@ struct ttyinfo {
 #define TERM_NOUP	0x04	/* terminal has no up capability */
 #define TERM_SHORT	0x08	/* terminal is < 3 lines high */
 #define TERM_NARROW	0x10	/* terminal is < 3 columns wide */
+#define TERM_NOCOLOUR	0x20	/* terminal is known but has no colour */
 
 /* interesting termcap strings */
 
diff --git a/Test/D01prompt.ztst b/Test/D01prompt.ztst
index f42e19714..1719ef02c 100644
--- a/Test/D01prompt.ztst
+++ b/Test/D01prompt.ztst
@@ -283,3 +283,18 @@
 -fD:RPS1 and RPROMPT are aliases (regression from 5.0.6) (workers/49600)
 >foo foo
 >bar bar
+
+  if
+    zmodload -s zsh/terminfo &&
+    ( TERM=xterm-color; (( terminfo[colors] >= 8 )) ) &&
+    ( TERM=dumb;        (( terminfo[colors] <= 0 )) )
+  then
+    str='%B %S %U %1F %2K test %k %f %u %s %b'
+    for 1 in xterm-color dumb not-a-real-terminal; do (
+      TERM=$1 print -Pr - $str | grep -q $'\e' && print -r - $1 has colours
+    ) 2> /dev/null; done
+  else
+    ZTST_skip="missing terminfo module or can't trust database"
+  fi
+-:unknown/dumb terminal suppresses text style attributes
+>xterm-color has colours




Messages sorted by: Reverse Date, Date, Thread, Author