]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Use emoji to indicate errors and warnings
authorTom Tromey <tromey@adacore.com>
Fri, 20 Dec 2024 21:00:39 +0000 (14:00 -0700)
committerTom Tromey <tromey@adacore.com>
Fri, 2 May 2025 18:52:09 +0000 (12:52 -0600)
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>
gdb/NEWS
gdb/cli/cli-style.c
gdb/cli/cli-style.h
gdb/doc/gdb.texinfo
gdb/exceptions.c
gdb/main.c
gdb/main.h
gdb/mingw-hdep.c
gdb/testsuite/gdb.base/style.exp
gdb/utils.c

index 077d28a33e4b2161e5d8abbef543cfbcc2f7a3fe..a82b7e3342c57b9b066e9012c5a961ad6ba839f0 100644 (file)
--- 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),
index 30c7afb5d3b99e0a91e7dfb8c32f5635fd29f2ee..34592f079fbd0e4bee8bb37948aed440a3c901d5 100644 (file)
@@ -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);
 }
index 77f4ac2ffc28915b26df9608f19ff7e800c9d761..b1a950a539cb8eaf5381f3ea546ee9fa3e87500b 100644 (file)
@@ -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 */
index 9b4aa5b47b2efe09e667aed0987ee96573216618..b9fc160a17180f0f2fe70c87a916d8f5433275ac 100644 (file)
@@ -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.
 
index 6af3a7e379f6ef7e7e1d6bc04d1bc2b0717d13d9..35400f3eb3d4d3e8a7eaa34d03ae8cdef9efd871 100644 (file)
@@ -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);
index 9220092d1e5166b48673bdcc418b7dc9a3a4da26..2dcb67d7ce8f7a2d3f9398238ec0d7fa724cb9b6 100644 (file)
@@ -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
index 4830b59d809edb3777e5aa3a4116ced0309fb40a..0f50b713b39c65c2b821883173822ca4fa514357 100644 (file)
@@ -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 */
index dc7ca42fc7e35a9c1e25157adb70a3e9538db3c9..84a7b9f7a528129ce2189d6be212337981a1ffda 100644 (file)
@@ -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)
index 59c93ee98379d8bf90f569b5cda7784f3ac2b35a..c10be3bc12aa10f5a13856cb14f7fad86f32ff90 100644 (file)
@@ -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"
     }
 }
 
index ce3c26ef1402e99303f4a53e55824e7c7fb03604..6cdc3f4875111d2ac81d45e2217d6f71843bb8db 100644 (file)
@@ -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");