diff options
Diffstat (limited to 'readline/complete.c')
-rw-r--r-- | readline/complete.c | 219 |
1 files changed, 136 insertions, 83 deletions
diff --git a/readline/complete.c b/readline/complete.c index 985e8981eee..714a2bf49dc 100644 --- a/readline/complete.c +++ b/readline/complete.c @@ -85,6 +85,15 @@ extern void _rl_move_vert (); extern int _rl_vis_botlin; extern int rl_display_fixed; +/* If non-zero, then this is the address of a function to call when + completing a word would normally display the list of possible matches. + This function is called instead of actually doing the display. + It takes three arguments: (char **matches, int num_matches, int max_length) + where MATCHES is the array of strings that matched, NUM_MATCHES is the + number of strings in that array, and MAX_LENGTH is the length of the + longest string in that array. */ +VFunction *rl_completion_display_matches_hook = (VFunction *)NULL; + /* Forward declarations for functions defined and used in this file. */ char *filename_completion_function (); char **completion_matches (); @@ -674,6 +683,7 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) we are doing filename completion and the application has defined a filename dequoting function. */ temp = (char *)NULL; + if (found_quote && our_func == (Function *)filename_completion_function && rl_filename_dequoting_function) { @@ -682,7 +692,7 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) text = temp; /* not freeing text is not a memory leak */ } - matches = completion_matches (text, our_func); + matches = completion_matches (text, (CPFunction *)our_func); FREE (temp); return matches; } @@ -813,8 +823,7 @@ compute_lcd_of_matches (match_list, matches, text) } static int -postprocess_matches (text, matchesp, matching_filenames) - char *text; +postprocess_matches (matchesp, matching_filenames) char ***matchesp; int matching_filenames; { @@ -845,7 +854,6 @@ postprocess_matches (text, matchesp, matching_filenames) if (matches == 0 || matches[0] == 0) { FREE (matches); - ding (); *matchesp = (char **)0; return 0; } @@ -857,7 +865,7 @@ postprocess_matches (text, matchesp, matching_filenames) if (i > 1 && i < nmatch) { t = matches[0]; - compute_lcd_of_matches (matches, i - 1, text); + compute_lcd_of_matches (matches, i - 1, t); FREE (t); } } @@ -867,66 +875,19 @@ postprocess_matches (text, matchesp, matching_filenames) return (1); } -static void -display_matches (matches) +/* 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. */ +void +rl_display_match_list (matches, len, max) char **matches; + int len, max; { - int len, count, limit, max, printed_len; + int count, limit, printed_len; int i, j, k, l; char *temp; - /* Move to the last visible line of a possibly-multiple-line command. */ - _rl_move_vert (_rl_vis_botlin); - - /* Handle simple case first. What if there is only one answer? */ - if (matches[1] == 0) - { - temp = printable_part (matches[0]); - crlf (); - print_filename (temp, matches[0]); - crlf (); -#if 0 - rl_on_new_line (); -#else - rl_forced_update_display (); - rl_display_fixed = 1; -#endif - return; - } - - /* There is more than one answer. Find out how many there are, - and find the maximum printed length of a single entry. */ - for (max = 0, i = 1; matches[i]; i++) - { - temp = printable_part (matches[i]); - len = strlen (temp); - - if (len > max) - max = len; - } - - len = i - 1; - - /* If there are many items, then ask the user if she really wants to - see them all. */ - if (len >= rl_completion_query_items) - { - crlf (); - fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len); - fflush (rl_outstream); - if (get_y_or_n () == 0) - { - crlf (); -#if 0 - rl_on_new_line (); -#else - rl_forced_update_display (); - rl_display_fixed = 1; -#endif - return; - } - } - /* How many items of MAX length can we fit in the screen window? */ max += 2; limit = screenwidth / max; @@ -993,13 +954,85 @@ display_matches (matches) } crlf (); } +} + +/* Display MATCHES, a list of matching filenames in argv format. This + handles the simple case -- a single match -- first. If there is more + than one match, we compute the number of strings in the list and the + length of the longest string, which will be needed by the display + function. If the application wants to handle displaying the list of + matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the + address of a function, and we just call it. If we're handling the + display ourselves, we just call rl_display_match_list. We also check + that the list of matches doesn't exceed the user-settable threshold, + and ask the user if he wants to see the list if there are more matches + than RL_COMPLETION_QUERY_ITEMS. */ +static void +display_matches (matches) + char **matches; +{ + int len, max, i; + char *temp; + + /* Move to the last visible line of a possibly-multiple-line command. */ + _rl_move_vert (_rl_vis_botlin); + + /* Handle simple case first. What if there is only one answer? */ + if (matches[1] == 0) + { + temp = printable_part (matches[0]); + crlf (); + print_filename (temp, matches[0]); + crlf (); + + rl_forced_update_display (); + rl_display_fixed = 1; + + return; + } + + /* There is more than one answer. Find out how many there are, + and find the maximum printed length of a single entry. */ + for (max = 0, i = 1; matches[i]; i++) + { + temp = printable_part (matches[i]); + len = strlen (temp); + + if (len > max) + max = len; + } + + len = i - 1; + + /* If the caller has defined a display hook, then call that now. */ + if (rl_completion_display_matches_hook) + { + (*rl_completion_display_matches_hook) (matches, len, max); + return; + } + + /* If there are many items, then ask the user if she really wants to + see them all. */ + if (len >= rl_completion_query_items) + { + crlf (); + fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len); + fflush (rl_outstream); + if (get_y_or_n () == 0) + { + crlf (); + + rl_forced_update_display (); + rl_display_fixed = 1; + + return; + } + } + + rl_display_match_list (matches, len, max); -#if 0 - rl_on_new_line (); -#else rl_forced_update_display (); rl_display_fixed = 1; -#endif } static char * @@ -1026,11 +1059,8 @@ make_quoted_replacement (match, mtype, qc) rl_filename_quoting_desired; if (should_quote) -#if defined (SHELL) - should_quote = should_quote && (!qc || !*qc || *qc == '"' || *qc == '\''); -#else /* !SHELL */ - should_quote = should_quote && (!qc || !*qc); -#endif /* !SHELL */ + should_quote = should_quote && (!qc || !*qc || + (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc))); if (should_quote) { @@ -1168,6 +1198,17 @@ insert_all_matches (matches, point, qc) rl_end_undo_group (); } +static void +free_match_list (matches) + char **matches; +{ + register int i; + + for (i = 0; matches[i]; i++) + free (matches[i]); + free (matches); +} + /* Complete the word at or before point. WHAT_TO_DO says what to do with the completion. `?' means list the possible completions. @@ -1210,27 +1251,34 @@ rl_complete_internal (what_to_do) text = rl_copy_text (start, end); matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char); + free (text); if (matches == 0) { ding (); FREE (saved_line_buffer); - free (text); return (0); } +#if 0 /* If we are matching filenames, our_func will have been set to filename_completion_function */ i = our_func == (Function *)filename_completion_function; - if (postprocess_matches (text, &matches, i) == 0) +#else + /* If we are matching filenames, the attempted completion function will + have set rl_filename_completion_desired to a non-zero value. The basic + filename_completion_function does this. */ + i = rl_filename_completion_desired; +#endif + + if (postprocess_matches (&matches, i) == 0) { + ding (); FREE (saved_line_buffer); - free (text); + completion_changed_buffer = 0; return (0); } - free (text); - switch (what_to_do) { case TAB: @@ -1277,9 +1325,7 @@ rl_complete_internal (what_to_do) return 1; } - for (i = 0; matches[i]; i++) - free (matches[i]); - free (matches); + free_match_list (matches); /* Check to see if the line has changed through all of this manipulation. */ if (saved_line_buffer) @@ -1358,10 +1404,10 @@ completion_matches (text, entry_function) character (usually `~'). */ char * username_completion_function (text, state) - int state; char *text; + int state; { -#if defined (__GO32__) || defined (__WIN32__) +#if defined (__GO32__) || defined (__WIN32__) || defined (__OPENNT) return (char *)NULL; #else /* !__GO32__ */ static char *username = (char *)NULL; @@ -1415,8 +1461,8 @@ username_completion_function (text, state) completion for a command. */ char * filename_completion_function (text, state) - int state; char *text; + int state; { static DIR *directory = (DIR *)NULL; static char *filename = (char *)NULL; @@ -1574,7 +1620,7 @@ filename_completion_function (text, state) strcpy (temp, users_dirname); } - strcpy (temp + dirlen, entry->d_name); /* strcat (temp, entry->d_name); */ + strcpy (temp + dirlen, entry->d_name); } else temp = savestring (entry->d_name); @@ -1649,10 +1695,17 @@ rl_menu_complete (count, ignore) matches = gen_completion_matches (orig_text, orig_start, orig_end, our_func, found_quote, quote_char); +#if 0 /* If we are matching filenames, our_func will have been set to filename_completion_function */ matching_filenames = our_func == (Function *)filename_completion_function; - if (matches == 0 || postprocess_matches (orig_text, &matches, matching_filenames) == 0) +#else + /* If we are matching filenames, the attempted completion function will + have set rl_filename_completion_desired to a non-zero value. The basic + filename_completion_function does this. */ + matching_filenames = rl_filename_completion_desired; +#endif + if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0) { ding (); FREE (matches); @@ -1686,7 +1739,7 @@ rl_menu_complete (count, ignore) if (match_list_index < 0) match_list_index += match_list_size; - if (match_list_index == 0) + if (match_list_index == 0 && match_list_size > 1) { ding (); insert_match (orig_text, orig_start, MULT_MATCH, "e_char); |