From: Guinevere Larsen Date: Mon, 15 Sep 2025 14:56:17 +0000 (-0300) Subject: gdb: Make startup message more user friendly X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f6df8aa48f120b78f0670b429f8a3363020a47dc;p=thirdparty%2Fbinutils-gdb.git gdb: Make startup message more user friendly Currently, on startup, GDB prints a lot of licensing information and then a few hints for new users. While there is an attempt to separate the hints from the rest of the text, my user testing showed that it is not good enough, and most unfamiliar users will just skip the information. Especially considering that the documentation link happens before the separation. This commit attempts to make the startup message more friendly to new users by visually separating the most important commands from the copyright. If there is enough space available, a box is printed containing the hints (either using unicode box drawing characters, if emojis are allowed, or using ascii). If there isn't space for a box, a simple line separator is printed. The code deems "enough space available" when there is enough space to print the documentation URL inside the box, since the other hints will be broken into multiple lines if necessary. Here are examples of the 2 possible startups, with enough space: +-----------------------------------------------------------------+ | Find the GDB manual online at: | | http://www.gnu.org/software/gdb/documentation/ | | For help, type "help". | | Type "apropos " to search for commands related to "word". | +-----------------------------------------------------------------+ And with limited space: --------------------------------------------- Find the GDB manual documentation resources o nline at: . For help, type "help". Type "apropos word" to search for commands re lated to "word". Approved-By: Tom Tromey --- diff --git a/gdb/main.c b/gdb/main.c index 58a744bb2b7..0fa2b0ecbe4 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -1200,6 +1200,8 @@ captured_main_1 (struct captured_main_args *context) /* Print all the junk at the top, with trailing "..." if we are about to read a symbol file (possibly slowly). */ print_gdb_version (gdb_stdout, true); + gdb_printf ("\n"); + print_gdb_hints (gdb_stdout); if (symarg) gdb_printf (".."); gdb_printf ("\n"); diff --git a/gdb/top.c b/gdb/top.c index dc22a3f58fb..2e3b373d5e2 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -1357,17 +1357,114 @@ There is NO WARRANTY, to the extent permitted by law.", styled_string (file_name_style.style (), REPORT_BUGS_TO)); } - gdb_printf (stream, - _("Find the GDB manual and other documentation \ -resources online at:\n <%ps>."), - styled_string (file_name_style.style (), - "http://www.gnu.org/software/gdb/documentation/")); - gdb_printf (stream, "\n\n"); - gdb_printf (stream, _("For help, type \"%ps\".\n"), +} + +/* Print MESSAGE to STREAM in lines of maximum size WIDTH, so that it fits + in an ascii art box of width WIDTH+4. Messages may be broken on + spaces. */ +static void +box_one_message (ui_file *stream, std::string message, int width) +{ + const char *wall = emojis_ok () ? u8"\u2503" : "|"; + while (!message.empty ()) + { + std::string line; + int n_escape_chars = 0; + const char *escape = message.c_str (); + while ((escape = strchr (escape, '\033')) != nullptr) + { + int tmp; + if (skip_ansi_escape (escape, &tmp)) + n_escape_chars += tmp; + else + break; + escape += tmp; + } + if ((message.length () - n_escape_chars) > width) + { + line = message.substr (0, message.rfind (" ", width)); + message = message.substr (line.length ()); + } + else + { + line = message; + message = ""; + } + + if ((line.length () - n_escape_chars) < width) + line.append (width - line.length () + n_escape_chars, ' '); + + gdb_printf (stream, "%s %s %s\n", wall, line.c_str (), wall); + } +} + +/* Print some hints about how to use GDB in a very visible manner. */ +void +print_gdb_hints (struct ui_file *stream) +{ + int width = get_chars_per_line (); + + /* Arbitrarily setting maximum width to 80 characters, so that + things are big and visible but not overwhelming. */ + if (80 < width) + width = 80; + + std::string docs_url = "http://www.gnu.org/software/gdb/documentation/"; + std::array styled_msg { + string_file (true), + string_file (true), + string_file (true), + string_file (true) + }; + + gdb_printf (&styled_msg[0], _("Find the GDB manual online at:")); + gdb_printf (&styled_msg[1], _("%ps."), + styled_string (file_name_style.style (), docs_url.c_str ())); + gdb_printf (&styled_msg[2], _("For help, type \"%ps\"."), styled_string (command_style.style (), "help")); - gdb_printf (stream, - _("Type \"%ps\" to search for commands related to \"word\"."), - styled_string (command_style.style (), "apropos word")); + gdb_printf (&styled_msg[3], + _("Type \"%ps\" to search for commands related to "), + styled_string (command_style.style (), "apropos ")); + + /* If there isn't enough space to display the longest URL in a boxed + style, use the simple styling of a singular visual break. The longest + URL is used because the other messages may be broken into multiple + lines, but URLs can't. */ + if (width - 3 <= docs_url.length ()) + { + std::string sep (width, '-'); + for (string_file &msg : styled_msg) + gdb_printf (stream, "%s\n", msg.c_str ()); + + return; + } + else + { + std::string sep (width-2, '-'); + + if (emojis_ok ()) + { + gdb_printf (stream, u8"\u250f"); + for (int i = 0; i < (width - 2); i++) + gdb_printf (stream, u8"\u2501"); + gdb_printf (stream, u8"\u2513\n"); + } + else + gdb_printf (stream, "+%s+\n", sep.c_str ()); + + for (string_file &msg : styled_msg) + box_one_message (stream, msg.release (), width - 4); + + if (emojis_ok ()) + { + gdb_printf (stream, u8"\u2517"); + for (int i = 0; i < (width - 2); i++) + gdb_printf (stream, u8"\u2501"); + gdb_printf (stream, u8"\u251b\n"); + } + else + gdb_printf (stream, "+%s+\n", sep.c_str ()); + } } /* Print the details of GDB build-time configuration. */ diff --git a/gdb/top.h b/gdb/top.h index 41af51acecf..f90515ea740 100644 --- a/gdb/top.h +++ b/gdb/top.h @@ -36,6 +36,10 @@ extern auto_boolean interactive_mode; mentioned. */ extern void print_gdb_version (struct ui_file *stream, bool interactive); +/* Print some hints for an inexperienced user on how to get more + information about using GDB. */ +extern void print_gdb_hints (struct ui_file *stream); + extern void print_gdb_configuration (struct ui_file *); extern void read_command_file (FILE *);