summaryrefslogtreecommitdiff
path: root/gdb/completer.c
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2020-05-23 09:23:09 -0600
committerTom Tromey <tom@tromey.com>2020-05-23 14:53:33 -0600
commiteca1f90cf47a2edc1a1cd22e12c6c0f3b900654e (patch)
tree78a5fffcd39bab954df305868e98f774c749f01e /gdb/completer.c
parent51e2cfa2dc2dd600727c91701c747c28fa67a5df (diff)
downloadbinutils-gdb-eca1f90cf47a2edc1a1cd22e12c6c0f3b900654e.tar.gz
Add completion styling
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. This version incorporates an Emacs idea, via Eli: style the prefix, the "difference character", and the suffix differently. gdb/ChangeLog 2020-05-23 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_prefix_style) (completion_difference_style, completion_suffix_style): New globals. (_initialize_cli_style): Register new globals. * cli/cli-style.h (completion_prefix_style) (completion_difference_style, completion_suffix_style): Declare. gdb/doc/ChangeLog 2020-05-23 Tom Tromey <tom@tromey.com> * gdb.texinfo (Output Styling): Mention completion styling. (Editing): Mention readline completion styling. gdb/testsuite/ChangeLog 2020-05-23 Tom Tromey <tom@tromey.com> * gdb.base/style.exp: Add completion styling test. * lib/gdb-utils.exp (style): Add completion styles.
Diffstat (limited to 'gdb/completer.c')
-rw-r--r--gdb/completer.c57
1 files changed, 50 insertions, 7 deletions
diff --git a/gdb/completer.c b/gdb/completer.c
index ad33b98c696..bc0501abf0a 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. */
@@ -2714,6 +2715,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. */
@@ -2722,7 +2725,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;
@@ -2735,14 +2738,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_prefix_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;
@@ -2751,6 +2758,16 @@ 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;
+ }
+
+ /* There are 3 states: the initial state (#0), when we use the
+ prefix style; the difference state (#1), which lasts a single
+ character; and then the suffix state (#2). */
+ int state = 0;
s = to_print + prefix_bytes;
while (*s)
@@ -2802,8 +2819,31 @@ gdb_fnprint (const char *to_print, int prefix_bytes,
printed_len++;
#endif
}
+ if (common_prefix_len > 0 && (s - to_print) >= common_prefix_len)
+ {
+ if (!style.is_default ())
+ displayer->puts (displayer, ui_file_style ().to_ansi ().c_str ());
+
+ ++state;
+ if (state == 1)
+ {
+ common_prefix_len = 1;
+ style = completion_difference_style.style ();
+ }
+ else
+ {
+ common_prefix_len = 0;
+ style = completion_suffix_style.style ();
+ }
+
+ if (!style.is_default ())
+ displayer->puts (displayer, style.to_ansi ().c_str ());
+ }
}
+ if (!style.is_default ())
+ displayer->puts (displayer, ui_file_style ().to_ansi ().c_str ());
+
return printed_len;
}
@@ -2912,7 +2952,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 *);
@@ -2931,19 +2970,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_prefix_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;
}