diff options
author | Doug Evans <xdje42@gmail.com> | 2015-01-31 14:11:54 -0800 |
---|---|---|
committer | Doug Evans <xdje42@gmail.com> | 2015-01-31 14:11:54 -0800 |
commit | 82083d6dbbc0b2f6a76095582c6e7ffb3e06432a (patch) | |
tree | be2581d31b188398863a27e60e2ac2ad69c0d910 /gdb/tui/tui-io.c | |
parent | f57d2163da62044205c3f53e0ecf186923296b63 (diff) | |
download | gdb-82083d6dbbc0b2f6a76095582c6e7ffb3e06432a.zip gdb-82083d6dbbc0b2f6a76095582c6e7ffb3e06432a.tar.gz gdb-82083d6dbbc0b2f6a76095582c6e7ffb3e06432a.tar.bz2 |
Unify CLI/TUI interface to readline tab completion.
This copies a lot of code from readline, but this is temporary.
Readline currently doesn't export what we need.
The plan is to have something that has been working for awhile,
and then we'll have a complete story to present to the readline
maintainers.
gdb/ChangeLog:
* cli-out.c: #include completer.h, readline/readline.h.
(cli_mld_crlf, cli_mld_putch, cli_mld_puts): New functions.
(cli_mld_flush, cld_mld_erase_entire_line): Ditto.
(cli_mld_beep, cli_mld_read_key, cli_display_match_list): Ditto.
* cli-out.h (cli_display_match_list): Declare.
* completer.c (MB_INVALIDCH, MB_NULLWCH): New macros.
(ELLIPSIS_LEN): Ditto.
(gdb_get_y_or_n, gdb_display_match_list_pager): New functions.
(gdb_path_isdir, gdb_printable_part, gdb_fnwidth): Ditto.
(gdb_fnprint, gdb_print_filename): Ditto.
(gdb_complete_get_screenwidth, gdb_display_match_list_1): Ditto.
(gdb_display_match_list): Ditto.
* completer.h (mld_crlf_ftype, mld_putch_ftype): New typedefs.
(mld_puts_ftype, mld_flush_ftype, mld_erase_entire_line_ftype): Ditto.
(mld_beep_ftype, mld_read_key_ftype): Ditto.
(match_list_displayer): New struct.
(gdb_display_match_list): Declare.
* top.c (init_main): Set rl_completion_display_matches_hook.
* tui/tui-io.c: #include completer.h.
(printable_part, PUTX, print_filename, get_y_or_n): Delete.
(tui_mld_crlf, tui_mld_putch, tui_mld_puts): New functions.
(tui_mld_flush, tui_mld_erase_entire_line, tui_mld_beep): Ditto.
(tui_mld_getc, tui_mld_read_key): Ditto.
(tui_rl_display_match_list): Rewrite.
(tui_handle_resize_during_io): New arg for_completion. All callers
updated.
Diffstat (limited to 'gdb/tui/tui-io.c')
-rw-r--r-- | gdb/tui/tui-io.c | 248 |
1 files changed, 88 insertions, 160 deletions
diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c index 19e9485..831705c 100644 --- a/gdb/tui/tui-io.c +++ b/gdb/tui/tui-io.c @@ -37,7 +37,7 @@ #include <fcntl.h> #include <signal.h> #include "filestuff.h" - +#include "completer.h" #include "gdb_curses.h" /* This redefines CTRL if it is not already defined, so it must come @@ -146,7 +146,7 @@ static int tui_readline_pipe[2]; This may be the main gdb prompt or a secondary prompt. */ static char *tui_rl_saved_prompt; -static unsigned int tui_handle_resize_during_io (unsigned int); +static int tui_handle_resize_during_io (int, int); static void tui_putc (char c) @@ -346,182 +346,106 @@ tui_readline_output (int error, gdb_client_data data) } #endif -/* Return the portion of PATHNAME that should be output when listing - possible completions. If we are hacking filename completion, we - are only interested in the basename, the portion following the - final slash. Otherwise, we return what we were passed. +/* TUI version of displayer.crlf. */ - Comes from readline/complete.c. */ -static const char * -printable_part (const char *pathname) +static void +tui_mld_crlf (const struct match_list_displayer *displayer) { - return rl_filename_completion_desired ? lbasename (pathname) : pathname; + tui_putc ('\n'); } -/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and - we are using it, check for and output a single character for - `special' filenames. Return the number of characters we - output. */ - -#define PUTX(c) \ - do { \ - if (CTRL_CHAR (c)) \ - { \ - tui_puts ("^"); \ - tui_putc (UNCTRL (c)); \ - printed_len += 2; \ - } \ - else if (c == RUBOUT) \ - { \ - tui_puts ("^?"); \ - printed_len += 2; \ - } \ - else \ - { \ - tui_putc (c); \ - printed_len++; \ - } \ - } while (0) +/* TUI version of displayer.putch. */ -static int -print_filename (const char *to_print, const char *full_pathname) +static void +tui_mld_putch (const struct match_list_displayer *displayer, int ch) { - int printed_len = 0; - const char *s; - - for (s = to_print; *s; s++) - { - PUTX (*s); - } - return printed_len; + tui_putc (ch); } -/* The user must press "y" or "n". Non-zero return means "y" pressed. - Comes from readline/complete.c. */ -static int -get_y_or_n (void) +/* TUI version of displayer.puts. */ + +static void +tui_mld_puts (const struct match_list_displayer *displayer, const char *s) { - extern int _rl_abort_internal (); - int c; + tui_puts (s); +} - for (;;) - { - c = rl_read_key (); - if (c == 'y' || c == 'Y' || c == ' ') - return (1); - if (c == 'n' || c == 'N' || c == RUBOUT) - return (0); - if (c == ABORT_CHAR) - _rl_abort_internal (); - beep (); - } +/* TUI version of displayer.flush. */ + +static void +tui_mld_flush (const struct match_list_displayer *displayer) +{ + wrefresh (TUI_CMD_WIN->generic.handle); } -/* A convenience function for displaying a list of strings in - columnar format on readline's output stream. MATCHES is the list - of strings, in argv format, LEN is the number of strings in MATCHES, - and MAX is the length of the longest string in MATCHES. +/* TUI version of displayer.erase_entire_line. */ - Comes from readline/complete.c and modified to write in - the TUI command window using tui_putc/tui_puts. */ static void -tui_rl_display_match_list (char **matches, int len, int max) +tui_mld_erase_entire_line (const struct match_list_displayer *displayer) { - typedef int QSFUNC (const void *, const void *); - extern int _rl_qsort_string_compare (const void *, - const void *); - extern int _rl_print_completions_horizontally; - - int count, limit, printed_len; - int i, j, k, l; - const char *temp; + WINDOW *w = TUI_CMD_WIN->generic.handle; - /* Screen dimension correspond to the TUI command window. */ - int screenwidth = TUI_CMD_WIN->generic.width; + wmove (w, TUI_CMD_WIN->detail.command_info.cur_line, 0); + wclrtoeol (w); + wmove (w, TUI_CMD_WIN->detail.command_info.cur_line, 0); +} - /* If there are many items, then ask the user if she really wants to - see them all. */ - if (len >= rl_completion_query_items) - { - char msg[256]; +/* TUI version of displayer.beep. */ - xsnprintf (msg, sizeof (msg), - "\nDisplay all %d possibilities? (y or n)", len); - tui_puts (msg); - if (get_y_or_n () == 0) - { - tui_puts ("\n"); - return; - } - } +static void +tui_mld_beep (const struct match_list_displayer *displayer) +{ + beep (); +} + +/* Helper function for tui_mld_read_key. + This temporarily replaces tui_getc for use during tab-completion + match list display. */ + +static int +tui_mld_getc (FILE *fp) +{ + WINDOW *w = TUI_CMD_WIN->generic.handle; + int c = wgetch (w); - /* How many items of MAX length can we fit in the screen window? */ - max += 2; - limit = screenwidth / max; - if (limit != 1 && (limit * max == screenwidth)) - limit--; + c = tui_handle_resize_during_io (c, 1); - /* Avoid a possible floating exception. If max > screenwidth, limit - will be 0 and a divide-by-zero fault will result. */ - if (limit == 0) - limit = 1; + return c; +} - /* How many iterations of the printing loop? */ - count = (len + (limit - 1)) / limit; +/* TUI version of displayer.read_key. */ - /* Watch out for special case. If LEN is less than LIMIT, then - just do the inner printing loop. - 0 < len <= limit implies count = 1. */ +static int +tui_mld_read_key (const struct match_list_displayer *displayer) +{ + rl_getc_func_t *prev = rl_getc_function; + int c; - /* Sort the items if they are not already sorted. */ - if (rl_ignore_completion_duplicates == 0) - qsort (matches + 1, len, sizeof (char *), - (QSFUNC *)_rl_qsort_string_compare); + /* We can't use tui_getc as we need NEWLINE to not get emitted. */ + rl_getc_function = tui_mld_getc; + c = rl_read_key (); + rl_getc_function = prev; + return c; +} - tui_putc ('\n'); +/* TUI version of rl_completion_display_matches_hook. + See gdb_display_match_list for a description of the arguments. */ - if (_rl_print_completions_horizontally == 0) - { - /* Print the sorted items, up-and-down alphabetically, like ls. */ - for (i = 1; i <= count; i++) - { - for (j = 0, l = i; j < limit; j++) - { - if (l > len || matches[l] == 0) - break; - else - { - temp = printable_part (matches[l]); - printed_len = print_filename (temp, matches[l]); - - if (j + 1 < limit) - for (k = 0; k < max - printed_len; k++) - tui_putc (' '); - } - l += count; - } - tui_putc ('\n'); - } - } - else - { - /* Print the sorted items, across alphabetically, like ls -x. */ - for (i = 1; matches[i]; i++) - { - temp = printable_part (matches[i]); - printed_len = print_filename (temp, matches[i]); - /* Have we reached the end of this line? */ - if (matches[i+1]) - { - if (i && (limit > 1) && (i % limit) == 0) - tui_putc ('\n'); - else - for (k = 0; k < max - printed_len; k++) - tui_putc (' '); - } - } - tui_putc ('\n'); - } +static void +tui_rl_display_match_list (char **matches, int len, int max) +{ + struct match_list_displayer displayer; + + rl_get_screen_size (&displayer.height, &displayer.width); + displayer.crlf = tui_mld_crlf; + displayer.putch = tui_mld_putch; + displayer.puts = tui_mld_puts; + displayer.flush = tui_mld_flush; + displayer.erase_entire_line = tui_mld_erase_entire_line; + displayer.beep = tui_mld_beep; + displayer.read_key = tui_mld_read_key; + + gdb_display_match_list (matches, len, max, &displayer); } /* Setup the IO for curses or non-curses mode. @@ -679,7 +603,7 @@ tui_getc (FILE *fp) #endif ch = wgetch (w); - ch = tui_handle_resize_during_io (ch); + ch = tui_handle_resize_during_io (ch, 0); /* The \n must be echoed because it will not be printed by readline. */ @@ -803,17 +727,21 @@ tui_expand_tabs (const char *string, int col) /* Cleanup when a resize has occured. Returns the character that must be processed. */ -static unsigned int -tui_handle_resize_during_io (unsigned int original_ch) + +static int +tui_handle_resize_during_io (int original_ch, int for_completion) { if (tui_win_resized ()) { tui_resize_all (); tui_refresh_all_win (); - dont_repeat (); tui_set_win_resized_to (FALSE); - return '\n'; + if (!for_completion) + { + dont_repeat (); + return '\n'; + } } - else - return original_ch; + + return original_ch; } |