Bug 14126 - Color escape sequences don't work in tui mode
Summary: Color escape sequences don't work in tui mode
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: tui (show other bugs)
Version: unknown
: P2 normal
Target Milestone: 8.3
Assignee: Tom Tromey
URL:
Keywords:
Depends on:
Blocks: 32284
  Show dependency treegraph
 
Reported: 2012-05-21 03:57 UTC by Jan Larres
Modified: 2025-07-01 22:20 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:


Attachments
Screenshot of color escape sequences working in new GDB build (78.71 KB, image/png)
2025-07-01 22:20 UTC, Nav
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Larres 2012-05-21 03:57:50 UTC
If TUI mode is enabled then coloring the prompt or output using escape sequences doesn't work, the sequences are instead shown as-is.

Example:

In normal mode, "echo \033[32mFOO\033[0m\n" will print "FOO" in green. However, if the TUI is enabled, it will print "^[[32mFOO^[[0m" instead. This makes trying to make the output more readable rather difficult.
Comment 1 dilyan.palauzov@aegee.org 2015-07-08 15:44:59 UTC
\w is expanded to the working directory, the problem with TUI and extended-prompt are (only) the escape sequences.  The proposed patch below just discards all non-printing characters, between \[ and \], in TUI mode.

diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index a2df254..cab10d2 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -5137,7 +5137,8 @@ Substitute the current working directory.
 Begin a sequence of non-printing characters.  These sequences are
 typically used with the ESC character, and are not counted in the string
 length.  Example: ``\[\e[0;34m\](gdb)\[\e[0m\]'' will return a
-blue-colored ``(gdb)'' prompt where the length is five.
+blue-colored ``(gdb)'' prompt where the length is five.  In TUI mode
+these characters are discarded.
 @item \]
 End a sequence of non-printing characters.
 @end table
diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c
index 97906ce..b77866a 100644
--- a/gdb/tui/tui-io.c
+++ b/gdb/tui/tui-io.c
@@ -232,6 +232,22 @@ tui_redisplay_readline (void)
   height = 1;
   for (in = 0; prompt && prompt[in]; in++)
     {
+      /* Drop characters from extended-prompt between \[ == \001 and \] = \002
+         The point is, that waddch prints ^ instead of control characters and
+         in turn the latter are not interpreted by the terminal. TUI prints
+         then ^ and this is ugly.
+
+         It seems there is no way to send escape characters to the terminal
+         under curses, at least not with fputc (c , stdout);
+
+         Skiping escape sequences, which are not within \[ and \] is hard, as
+         only the terminal has knowledge where the sequence ends and where the
+         actual input starts. */
+      if (prompt[in] == '\001')
+        {
+          do { in++; } while (prompt[in] != '\002' && prompt[in] != '\0');
+          continue;
+        }
       waddch (w, prompt[in]);
       getyx (w, line, col);
       if (col <= prev_col)
Comment 2 Tom Tromey 2018-09-01 19:06:41 UTC
I can think of two options here.

One is to change the tui-out object to be able to parse
terminal escape sequences.  Then it could turn these into
ncurses color calls.  This seems like a pain but maybe it
would not be too bad.

The other is to change extended-prompt to have explicit
color support and then change the TUI to understand that somehow.
This route may not be so easy since normally gdb just
prints whatever the python code gave it.
Comment 3 Tom Tromey 2018-09-02 20:27:45 UTC
I'm working on a patch for this.
Comment 4 Sourceware Commits 2018-12-28 21:01:20 UTC
The master branch has been updated by Tom Tromey <tromey@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1d1d0bf76f3bc3056a1456e53c066f40ca4d0837

commit 1d1d0bf76f3bc3056a1456e53c066f40ca4d0837
Author: Tom Tromey <tom@tromey.com>
Date:   Mon Sep 3 12:42:59 2018 -0600

    Make ANSI terminal escape sequences work in TUI
    
    PR tui/14126 notes that ANSI terminal escape sequences don't affect
    the colors shown in the TUI.  A simple way to see this is to try the
    extended-prompt example from the gdb manual.
    
    Curses does not pass escape sequences through to the terminal.
    Instead, it replaces non-printable characters with a visible
    representation, for example "^[" for the ESC character.
    
    This patch fixes the problem by adding a simple ANSI terminal sequence
    parser to gdb.  These sequences are decoded and those that are
    recognized are turned into the appropriate curses calls.
    
    The curses approach to color handling is unusual and so there are some
    oddities in the implementation.
    
    Standard curses has no notion of the default colors of the terminal.
    So, if you set the foreground color, it is not possible to reset it --
    you have to pick some other color.  ncurses provides an extension to
    handle this, so this patch updates configure and uses it when
    available.
    
    Second, in curses, colors always come in pairs: you cannot set just
    the foreground.  This patch handles this by tracking actually-used
    pairs of colors and keeping a table of these for reuse.
    
    Third, there are a limited number of such pairs available.  In this
    patch, if you try to use too many color combinations, gdb will just
    ignore some color changes.
    
    Finally, in addition to limiting the number of color pairs, curses
    also limits the number of colors.  This means that, when using
    extended 8- or 24-bit color sequences, it may be possible to exhaust
    the curses color table.
    
    I am very sour on the curses design now.
    
    I do not know how to write a test for this, so I did not.
    
    gdb/ChangeLog
    2018-12-28  Tom Tromey  <tom@tromey.com>
    
    	PR tui/14126:
    	* tui/tui.c (tui_enable): Call start_color and
    	use_default_colors.
    	* tui/tui-io.c (struct color_pair): New.
    	(color_pair_map, last_color_pair, last_style): New globals.
    	(tui_setup_io): Clean up color map when shutting down.
    	(curses_colors): New constant.
    	(get_color_pair, apply_ansi_escape): New functions.
    	(tui_write): Rewrite.
    	(tui_puts_internal): New function, from tui_puts.  Add "height"
    	parameter.
    	(tui_puts): Use tui_puts_internal.
    	(tui_redisplay_readline): Use tui_puts_internal.
    	(_initialize_tui_io): New function.
    	(color_map): New globals.
    	(get_color): New function.
    	* configure.ac: Check for use_default_colors.
    	* config.in, configure: Rebuild.
Comment 5 Tom Tromey 2018-12-28 21:12:06 UTC
Fixed.
Comment 6 Nav 2025-06-08 19:32:36 UTC
Apologies for posting on an old thread...

It seems this issue still occurs when GDB outputs responses for qRcmd commands.

My GDB server uses color escape sequences when returning responses to some qRcmd commands, which works fine when TUI mode is disabled. But when TUI mode is enabled, the escape sequences are ignored and printed in the output:

(gdb) mon lr porta
`[94mport[0m`, `[94mcfglr[0m`....

The proper output should be:

(gdb) mon lr porta
`port`, `cfglr`....

Where the foreground color of "port" and "cfglr" is set to "blue"
Comment 7 Tom Tromey 2025-06-11 20:08:05 UTC
Reopening.
Comment 8 Tom Tromey 2025-06-11 20:32:52 UTC
The issue might be that rcmd and remote_console_output work
one character at a time.

Ideally this wouldn't affect the TUI but I suspect it's maybe
a bit dumb about this.

However -- which gdb are you using?
I hacked gdbserver to colorize the "monitor help" output
and tried with gdb trunk.  This works... which I think
should be expected now that the TUI I/O stuff was removed.
Comment 9 Nav 2025-06-11 22:09:05 UTC
(In reply to Tom Tromey from comment #8)
> The issue might be that rcmd and remote_console_output work
> one character at a time.
> 
> Ideally this wouldn't affect the TUI but I suspect it's maybe
> a bit dumb about this.
> 
> However -- which gdb are you using?
> I hacked gdbserver to colorize the "monitor help" output
> and tried with gdb trunk.  This works... which I think
> should be expected now that the TUI I/O stuff was removed.

Hey, so I was using GDB 13.1, but I just built and tried 16.3, and the same issue occurs. Works fine with TUI mode disabled, but not when it's enabled.

In case it helps, here's the raw response packet that my server sends to GDB, in response to a qRcmd command:

$O601b5b39346d706f7274621b5b306d602c20601b5b39346d646472621b5b306d602c202244445242222c20307830303030303032342c20382d626974207c201b5b33336d307830301b5b306d20281b5b33336d301b5b306d2c201b5b33336d306230303030303030301b5b306d290a#db
Comment 10 Tom Tromey 2025-06-13 18:07:35 UTC
Sorry about this -- I forgot to enter TUI mode when doing
my tests :(

I tried again and I can reproduce the problem.
It's what I thought: the TUI I/O layer is too naive about
looking for terminal escape sequences.
Comment 12 Sourceware Commits 2025-07-01 22:00:26 UTC
The master branch has been updated by Tom Tromey <tromey@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7b18593a9ef94694e2a16ac25133aa8c19dc6a87

commit 7b18593a9ef94694e2a16ac25133aa8c19dc6a87
Author: Tom Tromey <tom@tromey.com>
Date:   Fri Jun 13 12:54:16 2025 -0600

    Fix handling of terminal escape sequences in TUI
    
    A user noticed that if the remote sends terminal escape sequences from
    the "monitor" command, then these will not be correctly displayed when
    in TUI mode.
    
    I tracked this down to remote.c emitting one character at a time --
    something the TUI output functions did not handle correctly.
    
    I decided in the end to fix in this in the ui-file layer, because the
    same bug seems to affect logging and, as is evidenced by the test case
    in this patch, Python output in TUI mode.
    
    The idea is simple: buffer escape sequences until they are either
    complete or cannot possibly be recognized by gdb.
    
    Regression tested on x86-64 Fedora 40.
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=14126
    Approved-By: Andrew Burgess <aburgess@redhat.com>
Comment 13 Tom Tromey 2025-07-01 22:01:37 UTC
Fixed again for 17.1.
I'm not sure if I should update the target milestone or not so
I've left it.
Comment 14 Nav 2025-07-01 22:20:51 UTC
Created attachment 16156 [details]
Screenshot of color escape sequences working in new GDB build

(In reply to Tom Tromey from comment #13)
> Fixed again for 17.1.
> I'm not sure if I should update the target milestone or not so
> I've left it.

Have just built from the master branch and can confirm it's now working as expected (see attached screenshot).

Thank you for sorting that so quickly!