[binutils-gdb] Use emoji to indicate errors and warnings

Tom Tromey tromey@sourceware.org
Fri May 2 19:26:46 GMT 2025


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

commit a048980c4eb93f8a965b4addc7134e8a527874a2
Author: Tom Tromey <tromey@adacore.com>
Date:   Fri Dec 20 14:00:39 2024 -0700

    Use emoji to indicate errors and warnings
    
    This patch adds, at long last, some emoji output to gdb.  In
    particular, warnings are indicated with the U+26A0 (WARNING SIGN), and
    errors with U+274C (CROSS MARK).
    
    There is a new setting to control whether emoji output can be used.
    It defaults to "auto", which means emoji will be used if the host
    charset is UTF-8.  Note that disabling styling will also disable
    emoji, handy for traditionalists.
    
    I've refactored mingw console output a little, so that emoji will not
    be printed to the console.  Note the previous code here was a bit
    strange in that it assumed that the first use of gdb_console_fputs
    would be to stdout.
    
    This version lets the user control the prefixes directly, so different
    emoji can be chosen if desired.
    
    Reviewed-By: Eli Zaretskii <eliz@gnu.org>
    Reviewed-By: Keith Seitz <keiths@redhat.com>
    Reviewed-By: Guinevere Larsen <guinevere@redhat.com>

Diff:
---
 gdb/NEWS                         |  13 +++++
 gdb/cli/cli-style.c              | 110 +++++++++++++++++++++++++++++++++++++++
 gdb/cli/cli-style.h              |  14 +++++
 gdb/doc/gdb.texinfo              |  24 +++++++++
 gdb/exceptions.c                 |   3 ++
 gdb/main.c                       |   2 +
 gdb/main.h                       |   3 ++
 gdb/mingw-hdep.c                 |  42 +++++++++------
 gdb/testsuite/gdb.base/style.exp |  12 +++++
 gdb/utils.c                      |   1 +
 10 files changed, 207 insertions(+), 17 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 077d28a33e4..a82b7e3342c 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -65,6 +65,19 @@ show riscv numeric-register-names
   (e.g 'x1') or their abi names (e.g. 'ra').
   Defaults to 'off', matching the old behaviour (abi names).
 
+set style emoji on|off|auto
+show style emoji
+  Controls whether GDB can display emoji.  The default is "auto",
+  which means emoji will be displayed in some situations when
+  the host charset is UTF-8.
+
+set style warning-prefix STRING
+set style error-prefix STRING
+  These commands control the prefix that is printed before warnings
+  and errors, respectively.  This functionality is intended for use
+  with emoji display, and so the prefixes are only displayed if emoji
+  styling is enabled.
+
 info linker-namespaces
 info linker-namespaces [[N]]
   Print information about the given linker namespace (identified as N),
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index 30c7afb5d3b..34592f079fb 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -23,6 +23,7 @@
 #include "cli/cli-style.h"
 #include "source-cache.h"
 #include "observable.h"
+#include "charset.h"
 
 /* True if styling is enabled.  */
 
@@ -42,6 +43,10 @@ bool source_styling = true;
 
 bool disassembler_styling = true;
 
+/* User-settable variable controlling emoji output.  */
+
+static auto_boolean emoji_styling = AUTO_BOOLEAN_AUTO;
+
 /* Names of intensities; must correspond to
    ui_file_style::intensity.  */
 static const char * const cli_intensities[] = {
@@ -410,6 +415,85 @@ show_style_disassembler (struct ui_file *file, int from_tty,
     gdb_printf (file, _("Disassembler output styling is disabled.\n"));
 }
 
+/* Implement 'show style emoji'.  */
+
+static void
+show_emoji_styling (struct ui_file *file, int from_tty,
+		    struct cmd_list_element *c, const char *value)
+{
+  if (emoji_styling == AUTO_BOOLEAN_TRUE)
+    gdb_printf (file, _("CLI emoji styling is enabled.\n"));
+  else if (emoji_styling == AUTO_BOOLEAN_FALSE)
+    gdb_printf (file, _("CLI emoji styling is disabled.\n"));
+  else
+    gdb_printf (file, _("CLI emoji styling is automatic (currently %s).\n"),
+		emojis_ok () ? _("enabled") : _("disabled"));
+}
+
+/* See cli-style.h.  */
+
+bool
+emojis_ok ()
+{
+  if (!cli_styling || emoji_styling == AUTO_BOOLEAN_FALSE)
+    return false;
+  if (emoji_styling == AUTO_BOOLEAN_TRUE)
+    return true;
+  return strcmp (host_charset (), "UTF-8") == 0;
+}
+
+/* See cli-style.h.  */
+
+void
+no_emojis ()
+{
+  emoji_styling = AUTO_BOOLEAN_FALSE;
+}
+
+/* Emoji warning prefix.  */
+static std::string warning_prefix = "⚠️ ";
+
+/* Implement 'show warning-prefix'.  */
+
+static void
+show_warning_prefix (struct ui_file *file, int from_tty,
+		     struct cmd_list_element *c, const char *value)
+{
+  gdb_printf (file, _("Warning prefix is \"%s\".\n"),
+	      warning_prefix.c_str ());
+}
+
+/* See cli-style.h.  */
+
+void
+print_warning_prefix (ui_file *file)
+{
+  if (emojis_ok ())
+    gdb_puts (warning_prefix.c_str (), file);
+}
+
+/* Emoji error prefix.  */
+static std::string error_prefix = "❌️ ";
+
+/* Implement 'show error-prefix'.  */
+
+static void
+show_error_prefix (struct ui_file *file, int from_tty,
+		     struct cmd_list_element *c, const char *value)
+{
+  gdb_printf (file, _("Error prefix is \"%s\".\n"),
+	      error_prefix.c_str ());
+}
+
+/* See cli-style.h.  */
+
+void
+print_error_prefix (ui_file *file)
+{
+  if (emojis_ok ())
+    gdb_puts (error_prefix.c_str (), file);
+}
+
 void _initialize_cli_style ();
 void
 _initialize_cli_style ()
@@ -431,6 +515,13 @@ If enabled, output to the terminal is styled."),
 			   set_style_enabled, show_style_enabled,
 			   &style_set_list, &style_show_list);
 
+  add_setshow_auto_boolean_cmd ("emoji", no_class, &emoji_styling, _("\
+Set whether emoji output is enabled."), _("\
+Show whether emoji output is enabled."), _("\
+If enabled, emojis may be displayed."),
+			   nullptr, show_emoji_styling,
+			   &style_set_list, &style_show_list);
+
   add_setshow_boolean_cmd ("sources", no_class, &source_styling, _("\
 Set whether source code styling is enabled."), _("\
 Show whether source code styling is enabled."), _("\
@@ -627,4 +718,23 @@ coming from your source code."),
 		 &style_disasm_set_list);
   add_alias_cmd ("symbol", function_prefix_cmds.show, no_class, 0,
 		 &style_disasm_show_list);
+
+  add_setshow_string_cmd ("warning-prefix", no_class,
+			  &warning_prefix,
+			  _("Set the warning prefix text."),
+			  _("Show the warning prefix text."),
+			  _("\
+The warning prefix text is displayed before any warning, when\n\
+emoji output is enabled."),
+			  nullptr, show_warning_prefix,
+			  &style_set_list, &style_show_list);
+  add_setshow_string_cmd ("error-prefix", no_class,
+			  &error_prefix,
+			  _("Set the error prefix text."),
+			  _("Show the error prefix text."),
+			  _("\
+The error prefix text is displayed before any error, when\n\
+emoji output is enabled."),
+			  nullptr, show_error_prefix,
+			  &style_set_list, &style_show_list);
 }
diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h
index 77f4ac2ffc2..b1a950a539c 100644
--- a/gdb/cli/cli-style.h
+++ b/gdb/cli/cli-style.h
@@ -190,4 +190,18 @@ private:
   bool m_old_value;
 };
 
+/* Return true if emoji styling is allowed.  */
+extern bool emojis_ok ();
+
+/* Disable emoji styling.  This is here so that Windows can disable
+   emoji when the console is in use.  It shouldn't be called
+   elsewhere.  */
+extern void no_emojis ();
+
+/* Print the warning prefix, if desired.  */
+extern void print_warning_prefix (ui_file *file);
+
+/* Print the error prefix, if desired.  */
+extern void print_error_prefix (ui_file *file);
+
 #endif /* GDB_CLI_CLI_STYLE_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9b4aa5b47b2..b9fc160a171 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -27974,6 +27974,19 @@ value, then @value{GDBN} will change this to @samp{off} at startup.
 @item show style enabled
 Show the current state of styling.
 
+@item set style emoji @samp{auto|on|off}
+Enable or disable the use of emoji.  On most hosts, the default is
+@samp{auto}, meaning that emoji will only be used if the host
+character set is @samp{UTF-8}; however, on Windows the default is
+@samp{off} when using the console.  Note that disabling styling as a
+whole will also prevent emoji display.
+
+Currently, emoji are printed whenever @value{GDBN} reports an error or
+a warning.
+
+@item show style emoji
+Show the current state of emoji output.
+
 @item set style sources @samp{on|off}
 Enable or disable source code styling.  This affects whether source
 code, such as the output of the @code{list} command, is styled.  The
@@ -27987,6 +28000,17 @@ is used.  Otherwise, if @value{GDBN} was configured with Python
 scripting support, and if the Python Pygments package is available,
 then it will be used.
 
+@item set style warning-prefix
+@itemx show style warning-prefix
+@itemx set style error-prefix
+@itemx show style error-prefix
+
+These commands control the prefix that is printed before warnings and
+errors, respectively.  This functionality is intended for use with
+emoji display, and so the prefixes are only displayed if emoji styling
+is enabled.  The defaults are the warning sign emoji for warnings, and
+and the cross mark emoji for errors.
+
 @item show style sources
 Show the current state of source code styling.
 
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index 6af3a7e379f..35400f3eb3d 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -25,6 +25,7 @@
 #include "serial.h"
 #include "ui.h"
 #include <optional>
+#include "cli/cli-style.h"
 
 static void
 print_flush (void)
@@ -105,6 +106,7 @@ exception_print (struct ui_file *file, const struct gdb_exception &e)
   if (e.reason < 0 && e.message != NULL)
     {
       print_flush ();
+      print_error_prefix (file);
       print_exception (file, e);
     }
 }
@@ -118,6 +120,7 @@ exception_fprintf (struct ui_file *file, const struct gdb_exception &e,
       va_list args;
 
       print_flush ();
+      print_error_prefix (file);
 
       /* Print the prefix.  */
       va_start (args, prefix);
diff --git a/gdb/main.c b/gdb/main.c
index 9220092d1e5..2dcb67d7ce8 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -672,6 +672,8 @@ captured_main_1 (struct captured_main_args *context)
   /* Ensure stderr is unbuffered.  A Cygwin pty or pipe is implemented
      as a Windows pipe, and Windows buffers on pipes.  */
   setvbuf (stderr, NULL, _IONBF, BUFSIZ);
+
+  windows_initialize_console ();
 #endif
 
   /* Note: `error' cannot be called before this point, because the
diff --git a/gdb/main.h b/gdb/main.h
index 4830b59d809..0f50b713b39 100644
--- a/gdb/main.h
+++ b/gdb/main.h
@@ -44,6 +44,9 @@ extern std::string interpreter_p;
    return value is in malloc'ed storage.  */
 extern char *windows_get_absolute_argv0 (const char *argv0);
 
+/* Initialize Windows console settings.  */
+extern void windows_initialize_console ();
+
 extern void set_gdb_data_directory (const char *new_data_dir);
 
 #endif /* GDB_MAIN_H */
diff --git a/gdb/mingw-hdep.c b/gdb/mingw-hdep.c
index dc7ca42fc7e..84a7b9f7a52 100644
--- a/gdb/mingw-hdep.c
+++ b/gdb/mingw-hdep.c
@@ -22,6 +22,7 @@
 #include "gdbsupport/event-loop.h"
 #include "gdbsupport/gdb_select.h"
 #include "inferior.h"
+#include "cli/cli-style.h"
 
 #include <windows.h>
 #include <signal.h>
@@ -212,7 +213,30 @@ static int mingw_console_initialized;
 static HANDLE hstdout = INVALID_HANDLE_VALUE;
 
 /* Text attribute to use for normal text (the "none" pseudo-color).  */
-static SHORT  norm_attr;
+static SHORT norm_attr;
+
+/* Initialize settings related to the console.  */
+
+void
+windows_initialize_console ()
+{
+  hstdout = (HANDLE)_get_osfhandle (fileno (stdout));
+  DWORD cmode;
+  CONSOLE_SCREEN_BUFFER_INFO csbi;
+
+  if (hstdout != INVALID_HANDLE_VALUE
+      && GetConsoleMode (hstdout, &cmode) != 0
+      && GetConsoleScreenBufferInfo (hstdout, &csbi))
+    {
+      norm_attr = csbi.wAttributes;
+      mingw_console_initialized = 1;
+    }
+  else if (hstdout != INVALID_HANDLE_VALUE)
+    mingw_console_initialized = -1; /* valid, but not a console device */
+
+  if (mingw_console_initialized > 0)
+    no_emojis ();
+}
 
 /* The most recently applied style.  */
 static ui_file_style last_style;
@@ -223,22 +247,6 @@ static ui_file_style last_style;
 int
 gdb_console_fputs (const char *linebuf, FILE *fstream)
 {
-  if (!mingw_console_initialized)
-    {
-      hstdout = (HANDLE)_get_osfhandle (fileno (fstream));
-      DWORD cmode;
-      CONSOLE_SCREEN_BUFFER_INFO csbi;
-
-      if (hstdout != INVALID_HANDLE_VALUE
-	  && GetConsoleMode (hstdout, &cmode) != 0
-	  && GetConsoleScreenBufferInfo (hstdout, &csbi))
-	{
-	  norm_attr = csbi.wAttributes;
-	  mingw_console_initialized = 1;
-	}
-      else if (hstdout != INVALID_HANDLE_VALUE)
-	mingw_console_initialized = -1; /* valid, but not a console device */
-    }
   /* If our stdout is not a console device, let the default 'fputs'
      handle the task. */
   if (mingw_console_initialized <= 0)
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index 59c93ee9837..c10be3bc12a 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -329,6 +329,18 @@ proc run_style_tests { } {
 		"The \033\\\[38;2;254;210;16;48;5;255;22;27m.*\".*version.*\".*style.*\033\\\[m foreground color is: #FED210" \
 		"Version's TrueColor foreground style"
 	}
+
+	gdb_test_no_output "set host-charset UTF-8"
+	# Chosen since it will print an error.
+	gdb_test "maint translate-address" \
+	    "❌️ requires argument.*" \
+	    "emoji output"
+
+	gdb_test_no_output "set style error-prefix abcd:" \
+	    "set the error prefix"
+	gdb_test "maint translate-address" \
+	    "abcd:requires argument.*" \
+	    "error prefix"
     }
 }
 
diff --git a/gdb/utils.c b/gdb/utils.c
index ce3c26ef140..6cdc3f48751 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -177,6 +177,7 @@ vwarning (const char *string, va_list args)
 	  target_terminal::ours_for_output ();
 	}
       gdb_puts (warning_pre_print, gdb_stderr);
+      print_warning_prefix (gdb_stderr);
       gdb_puts (_("warning: "), gdb_stderr);
       gdb_vprintf (gdb_stderr, string, args);
       gdb_printf (gdb_stderr, "\n");


More information about the Gdb-cvs mailing list