[PATCH] Add completion styling

Tom Tromey tom@tromey.com
Thu Apr 9 02:41:12 GMT 2020


Readline has a styling feature for completion -- if it is enabled, the
common prefix of completions will be displayed in a different style.
This doesn't work in gdb, because gdb implements its own completer.

This patch implements the feature.  However, it doesn't directly use
the Readline feature, because gdb can do a bit better: it can let the
user control the styling using the existing mechanisms.

gdb/ChangeLog
2020-04-08  Tom Tromey  <tom@tromey.com>

	* NEWS: Add entry for completion styling.
	* completer.c (_rl_completion_prefix_display_length): Move
	declaration earlier.
	(gdb_fnprint): Use completion_style.
	(gdb_display_match_list_1): Likewise.
	* cli/cli-style.c (completion_style): New global.
	(_initialize_cli_style): Register new global.
	* cli/cli-style.h (completion_style): Declare.

gdb/doc/ChangeLog
2020-04-08  Tom Tromey  <tom@tromey.com>

	* gdb.texinfo (Output Styling): Mention "completion" styling.
	(Editing): Mention readline completion styling.

gdb/testsuite/ChangeLog
2020-04-08  Tom Tromey  <tom@tromey.com>

	* gdb.base/style.exp: Add completion styling test.
	* lib/gdb-utils.exp (style): Add "completion" style.
---
 gdb/ChangeLog                    | 11 ++++++++++
 gdb/NEWS                         |  6 ++++++
 gdb/cli/cli-style.c              | 11 ++++++++++
 gdb/cli/cli-style.h              |  3 +++
 gdb/completer.c                  | 35 +++++++++++++++++++++++++-------
 gdb/doc/ChangeLog                |  5 +++++
 gdb/doc/gdb.texinfo              |  8 ++++++++
 gdb/testsuite/ChangeLog          |  5 +++++
 gdb/testsuite/gdb.base/style.exp | 12 +++++++++++
 gdb/testsuite/lib/gdb-utils.exp  |  1 +
 10 files changed, 90 insertions(+), 7 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 6657f6fadce..331b9967a7b 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -55,6 +55,12 @@ show exec-file-mismatch -- Show exec-file-mismatch handling (ask|warn|off).
   whether to load the process executable file; if 'warn', just display
   a warning; if 'off', don't attempt to detect a mismatch.
 
+set style completion foreground COLOR
+set style completion background COLOR
+set style completion intensity VALUE
+  Control the styling of completions.  The common prefix of completion
+  candidates will be shown with this style.
+
 tui new-layout NAME WINDOW WEIGHT [WINDOW WEIGHT]...
   Define a new TUI layout, specifying its name and the windows that
   will be displayed.
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index d2d9928acd5..efada5e2ca9 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -98,6 +98,10 @@ cli_style_option metadata_style ("metadata", ui_file_style::DIM);
 
 /* See cli-style.h.  */
 
+cli_style_option completion_style ("completion", ui_file_style::MAGENTA);
+
+/* See cli-style.h.  */
+
 cli_style_option::cli_style_option (const char *name,
 				    ui_file_style::basic_color fg)
   : changed (name),
@@ -409,6 +413,13 @@ Configure metadata colors and display intensity\n\
 The \"metadata\" style is used when GDB displays information about\n\
 your data, for example \"<unavailable>\""), false);
 
+  STYLE_ADD_SETSHOW_COMMANDS (completion_style,
+			      _("\
+Completion display styling.\n\
+Configure completion colors and display intensity\n\
+The \"completion\" style is used when GDB displays possible completions,\n\
+for example in response to the TAB key."), false);
+
   STYLE_ADD_SETSHOW_COMMANDS (tui_border_style,
 			      _("\
 TUI border display styling.\n\
diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h
index 04009aa3615..d9ed8c28d54 100644
--- a/gdb/cli/cli-style.h
+++ b/gdb/cli/cli-style.h
@@ -126,6 +126,9 @@ extern cli_style_option tui_border_style;
 /* The border style of a TUI window that does have the focus.  */
 extern cli_style_option tui_active_border_style;
 
+/* The completion style.  */
+extern cli_style_option completion_style;
+
 /* True if source styling is enabled.  */
 extern bool source_styling;
 
diff --git a/gdb/completer.c b/gdb/completer.c
index 67dce30fbe3..364362b50a8 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -31,6 +31,7 @@
 #include <algorithm>
 #include "linespec.h"
 #include "cli/cli-decode.h"
+#include "cli/cli-style.h"
 
 /* FIXME: This is needed because of lookup_cmd_1 ().  We should be
    calling a hook instead so we eliminate the CLI dependency.  */
@@ -2702,6 +2703,8 @@ gdb_fnwidth (const char *string)
   return width;
 }
 
+extern int _rl_completion_prefix_display_length;
+
 /* Print TO_PRINT, one matching completion.
    PREFIX_BYTES is number of common prefix bytes.
    Based on readline/complete.c:fnprint.  */
@@ -2710,7 +2713,7 @@ static int
 gdb_fnprint (const char *to_print, int prefix_bytes,
 	     const struct match_list_displayer *displayer)
 {
-  int printed_len, w;
+  int common_prefix_len, printed_len, w;
   const char *s;
 #if defined (HANDLE_MULTIBYTE)
   mbstate_t ps;
@@ -2723,14 +2726,18 @@ gdb_fnprint (const char *to_print, int prefix_bytes,
   memset (&ps, 0, sizeof (mbstate_t));
 #endif
 
-  printed_len = 0;
+  printed_len = common_prefix_len = 0;
 
   /* Don't print only the ellipsis if the common prefix is one of the
      possible completions */
   if (to_print[prefix_bytes] == '\0')
     prefix_bytes = 0;
 
-  if (prefix_bytes)
+  ui_file_style style = completion_style.style ();
+  if (!style.is_default ())
+    displayer->puts (displayer, style.to_ansi ().c_str ());
+
+  if (prefix_bytes && _rl_completion_prefix_display_length > 0)
     {
       char ellipsis;
 
@@ -2739,6 +2746,11 @@ gdb_fnprint (const char *to_print, int prefix_bytes,
 	displayer->putch (displayer, ellipsis);
       printed_len = ELLIPSIS_LEN;
     }
+  else if (prefix_bytes && !style.is_default ())
+    {
+      common_prefix_len = prefix_bytes;
+      prefix_bytes = 0;
+    }
 
   s = to_print + prefix_bytes;
   while (*s)
@@ -2790,6 +2802,12 @@ gdb_fnprint (const char *to_print, int prefix_bytes,
 	  printed_len++;
 #endif
 	}
+      if (common_prefix_len > 0 && (s - to_print) >= common_prefix_len
+	  && !style.is_default ())
+	{
+	  displayer->puts (displayer, ui_file_style ().to_ansi ().c_str ());
+	  common_prefix_len = 0;
+	}
     }
 
   return printed_len;
@@ -2900,7 +2918,6 @@ gdb_complete_get_screenwidth (const struct match_list_displayer *displayer)
   return displayer->width;
 }
 
-extern int _rl_completion_prefix_display_length;
 extern int _rl_print_completions_horizontally;
 
 EXTERN_C int _rl_qsort_string_compare (const void *, const void *);
@@ -2919,19 +2936,23 @@ gdb_display_match_list_1 (char **matches, int len, int max,
   char *temp, *t;
   int page_completions = displayer->height != INT_MAX && pagination_enabled;
 
+  bool want_style = !completion_style.style ().is_default ();
+
   /* Find the length of the prefix common to all items: length as displayed
      characters (common_length) and as a byte index into the matches (sind) */
   common_length = sind = 0;
-  if (_rl_completion_prefix_display_length > 0)
+  if (_rl_completion_prefix_display_length > 0 || want_style)
     {
       t = gdb_printable_part (matches[0]);
       temp = strrchr (t, '/');
       common_length = temp ? gdb_fnwidth (temp) : gdb_fnwidth (t);
       sind = temp ? strlen (temp) : strlen (t);
 
-      if (common_length > _rl_completion_prefix_display_length && common_length > ELLIPSIS_LEN)
+      if (_rl_completion_prefix_display_length > 0
+	  && common_length > _rl_completion_prefix_display_length
+	  && common_length > ELLIPSIS_LEN)
 	max -= common_length - ELLIPSIS_LEN;
-      else
+      else if (!want_style || common_length > max || sind > max)
 	common_length = sind = 0;
     }
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 385c832f222..0176b60e5ff 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -25267,6 +25267,10 @@ This command accepts the current line for execution and fetches the
 next line relative to the current line from the history for editing.
 Any argument is ignored.
 
+Note that @value{GDBN} ignores the Readline
+@code{colored-completion-prefix} setting.  Instead, this is handled
+using the @code{completion} style (@xref{Output Styling}).
+
 @node Command History
 @section Command History
 @cindex command history
@@ -25600,6 +25604,10 @@ general styling to @value{GDBN}.  @xref{TUI Configuration}.
 Control the styling of the active TUI border; that is, the TUI window
 that has the focus.
 
+@item completion
+Control the styling of completion.  When completing, the common prefix
+of completion candidates will be shown with this style.
+
 @end table
 
 @node Numbers
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index 47ef8c93c7c..d33041e3154 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -152,4 +152,16 @@ save_vars { env(TERM) } {
 	"warning: [style .*? file] is not a directory\\..*"
     gdb_test "show data-directory" \
 	"GDB's data directory is \"[style .*? file]\"\\..*"
+
+    if {[readline_is_used]} {
+	set test "complete print VALUE_"
+	# ESC-? is the readline binding to show all completions.
+	send_gdb "print VALUE_\x1b?"
+	set val [style VALUE_ completion]
+	gdb_test_multiple "" $test {
+	    -re "${val}ONE\[ \t\]+${val}TWO.*$gdb_prompt print VALUE_$" {
+		gdb_test "ONE" " = .*"
+	    }
+	}
+    }
 }
diff --git a/gdb/testsuite/lib/gdb-utils.exp b/gdb/testsuite/lib/gdb-utils.exp
index 9741f0a9591..c6dad81e853 100644
--- a/gdb/testsuite/lib/gdb-utils.exp
+++ b/gdb/testsuite/lib/gdb-utils.exp
@@ -55,6 +55,7 @@ proc style {str style} {
 	variable { set style 36 }
 	address { set style 34 }
 	metadata { set style 2 }
+	completion { set style 35 }
     }
     return "\033\\\[${style}m${str}\033\\\[m"
 }
-- 
2.17.2



More information about the Gdb-patches mailing list