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>
This commit is contained in:
Tom Tromey
2024-12-20 14:00:39 -07:00
parent 5c87b330e9
commit a048980c4e
10 changed files with 207 additions and 17 deletions

View File

@@ -65,6 +65,19 @@ show riscv numeric-register-names
(e.g 'x1') or their abi names (e.g. 'ra'). (e.g 'x1') or their abi names (e.g. 'ra').
Defaults to 'off', matching the old behaviour (abi names). 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
info linker-namespaces [[N]] info linker-namespaces [[N]]
Print information about the given linker namespace (identified as N), Print information about the given linker namespace (identified as N),

View File

@@ -23,6 +23,7 @@
#include "cli/cli-style.h" #include "cli/cli-style.h"
#include "source-cache.h" #include "source-cache.h"
#include "observable.h" #include "observable.h"
#include "charset.h"
/* True if styling is enabled. */ /* True if styling is enabled. */
@@ -42,6 +43,10 @@ bool source_styling = true;
bool disassembler_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 /* Names of intensities; must correspond to
ui_file_style::intensity. */ ui_file_style::intensity. */
static const char * const cli_intensities[] = { 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")); 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 ();
void void
_initialize_cli_style () _initialize_cli_style ()
@@ -431,6 +515,13 @@ If enabled, output to the terminal is styled."),
set_style_enabled, show_style_enabled, set_style_enabled, show_style_enabled,
&style_set_list, &style_show_list); &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, _("\ add_setshow_boolean_cmd ("sources", no_class, &source_styling, _("\
Set whether source code styling is enabled."), _("\ Set whether source code styling is enabled."), _("\
Show 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); &style_disasm_set_list);
add_alias_cmd ("symbol", function_prefix_cmds.show, no_class, 0, add_alias_cmd ("symbol", function_prefix_cmds.show, no_class, 0,
&style_disasm_show_list); &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);
} }

View File

@@ -190,4 +190,18 @@ private:
bool m_old_value; 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 */ #endif /* GDB_CLI_CLI_STYLE_H */

View File

@@ -27974,6 +27974,19 @@ value, then @value{GDBN} will change this to @samp{off} at startup.
@item show style enabled @item show style enabled
Show the current state of styling. 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} @item set style sources @samp{on|off}
Enable or disable source code styling. This affects whether source Enable or disable source code styling. This affects whether source
code, such as the output of the @code{list} command, is styled. The 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, scripting support, and if the Python Pygments package is available,
then it will be used. 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 @item show style sources
Show the current state of source code styling. Show the current state of source code styling.

View File

@@ -25,6 +25,7 @@
#include "serial.h" #include "serial.h"
#include "ui.h" #include "ui.h"
#include <optional> #include <optional>
#include "cli/cli-style.h"
static void static void
print_flush (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) if (e.reason < 0 && e.message != NULL)
{ {
print_flush (); print_flush ();
print_error_prefix (file);
print_exception (file, e); print_exception (file, e);
} }
} }
@@ -118,6 +120,7 @@ exception_fprintf (struct ui_file *file, const struct gdb_exception &e,
va_list args; va_list args;
print_flush (); print_flush ();
print_error_prefix (file);
/* Print the prefix. */ /* Print the prefix. */
va_start (args, prefix); va_start (args, prefix);

View File

@@ -672,6 +672,8 @@ captured_main_1 (struct captured_main_args *context)
/* Ensure stderr is unbuffered. A Cygwin pty or pipe is implemented /* Ensure stderr is unbuffered. A Cygwin pty or pipe is implemented
as a Windows pipe, and Windows buffers on pipes. */ as a Windows pipe, and Windows buffers on pipes. */
setvbuf (stderr, NULL, _IONBF, BUFSIZ); setvbuf (stderr, NULL, _IONBF, BUFSIZ);
windows_initialize_console ();
#endif #endif
/* Note: `error' cannot be called before this point, because the /* Note: `error' cannot be called before this point, because the

View File

@@ -44,6 +44,9 @@ extern std::string interpreter_p;
return value is in malloc'ed storage. */ return value is in malloc'ed storage. */
extern char *windows_get_absolute_argv0 (const char *argv0); 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); extern void set_gdb_data_directory (const char *new_data_dir);
#endif /* GDB_MAIN_H */ #endif /* GDB_MAIN_H */

View File

@@ -22,6 +22,7 @@
#include "gdbsupport/event-loop.h" #include "gdbsupport/event-loop.h"
#include "gdbsupport/gdb_select.h" #include "gdbsupport/gdb_select.h"
#include "inferior.h" #include "inferior.h"
#include "cli/cli-style.h"
#include <windows.h> #include <windows.h>
#include <signal.h> #include <signal.h>
@@ -212,7 +213,30 @@ static int mingw_console_initialized;
static HANDLE hstdout = INVALID_HANDLE_VALUE; static HANDLE hstdout = INVALID_HANDLE_VALUE;
/* Text attribute to use for normal text (the "none" pseudo-color). */ /* 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. */ /* The most recently applied style. */
static ui_file_style last_style; static ui_file_style last_style;
@@ -223,22 +247,6 @@ static ui_file_style last_style;
int int
gdb_console_fputs (const char *linebuf, FILE *fstream) 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' /* If our stdout is not a console device, let the default 'fputs'
handle the task. */ handle the task. */
if (mingw_console_initialized <= 0) if (mingw_console_initialized <= 0)

View 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" \ "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" "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"
} }
} }

View File

@@ -177,6 +177,7 @@ vwarning (const char *string, va_list args)
target_terminal::ours_for_output (); target_terminal::ours_for_output ();
} }
gdb_puts (warning_pre_print, gdb_stderr); gdb_puts (warning_pre_print, gdb_stderr);
print_warning_prefix (gdb_stderr);
gdb_puts (_("warning: "), gdb_stderr); gdb_puts (_("warning: "), gdb_stderr);
gdb_vprintf (gdb_stderr, string, args); gdb_vprintf (gdb_stderr, string, args);
gdb_printf (gdb_stderr, "\n"); gdb_printf (gdb_stderr, "\n");