X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=complete.c;fp=complete.c;h=fc5c3adb3564d6408214f74a0a3e64a0f0437cd4;hb=cf3c762ecfff5b2f445647a0f1543693984a5540;hp=adce0d69ac1d9bbf57a335c1fb0c6df36d9320c2;hpb=c5ad6be530f5c1daf64a2d20df4baba9f6b57aa4;p=thirdparty%2Freadline.git diff --git a/complete.c b/complete.c index adce0d6..fc5c3ad 100644 --- a/complete.c +++ b/complete.c @@ -1,6 +1,6 @@ /* complete.c -- filename completion for readline. */ -/* Copyright (C) 1987-2017 Free Software Foundation, Inc. +/* Copyright (C) 1987-2020 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -21,11 +21,18 @@ #define READLINE_LIBRARY +#if defined (__TANDEM) +# define _XOPEN_SOURCE_EXTENDED 1 +#endif + #if defined (HAVE_CONFIG_H) # include #endif #include +#if defined (__TANDEM) +# include +#endif #include #if defined (HAVE_SYS_FILE_H) # include @@ -141,6 +148,7 @@ static int complete_fncmp PARAMS((const char *, int, const char *, int)); static void display_matches PARAMS((char **)); static int compute_lcd_of_matches PARAMS((char **, int, const char *)); static int postprocess_matches PARAMS((char ***, int)); +static int compare_match PARAMS((char *, const char *)); static int complete_get_screenwidth PARAMS((void)); static char *make_quoted_replacement PARAMS((char *, int, char *)); @@ -406,6 +414,7 @@ int rl_sort_completion_matches = 1; /* Local variable states what happened during the last completion attempt. */ static int completion_changed_buffer; +static int last_completion_failed = 0; /* The result of the query to the user about displaying completion matches */ static int completion_y_or_n; @@ -428,7 +437,11 @@ rl_complete (int ignore, int invoking_key) if (rl_inhibit_completion) return (_rl_insert_char (ignore, invoking_key)); - else if (rl_last_func == rl_complete && !completion_changed_buffer) +#if 0 + else if (rl_last_func == rl_complete && completion_changed_buffer == 0 && last_completion_failed == 0) +#else + else if (rl_last_func == rl_complete && completion_changed_buffer == 0) +#endif return (rl_complete_internal ('?')); else if (_rl_complete_show_all) return (rl_complete_internal ('!')); @@ -477,7 +490,7 @@ rl_completion_mode (rl_command_func_t *cfunc) /* */ /************************************/ -/* Reset readline state on a signal or other event. */ +/* Reset public readline state on a signal or other event. */ void _rl_reset_completion_state (void) { @@ -1330,12 +1343,13 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text) memset (&ps2, 0, sizeof (mbstate_t)); } #endif - if (_rl_completion_case_fold) + for (si = 0; (c1 = match_list[i][si]) && (c2 = match_list[i + 1][si]); si++) { - for (si = 0; - (c1 = _rl_to_lower(match_list[i][si])) && - (c2 = _rl_to_lower(match_list[i + 1][si])); - si++) + if (_rl_completion_case_fold) + { + c1 = _rl_to_lower (c1); + c2 = _rl_to_lower (c2); + } #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { @@ -1347,35 +1361,17 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text) break; continue; } - wc1 = towlower (wc1); - wc2 = towlower (wc2); + if (_rl_completion_case_fold) + { + wc1 = towlower (wc1); + wc2 = towlower (wc2); + } if (wc1 != wc2) break; else if (v1 > 1) si += v1 - 1; } else -#endif - if (c1 != c2) - break; - } - else - { - for (si = 0; - (c1 = match_list[i][si]) && - (c2 = match_list[i + 1][si]); - si++) -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - mbstate_t ps_back; - ps_back = ps1; - if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2)) - break; - else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1) - si += v - 1; - } - else #endif if (c1 != c2) break; @@ -1969,6 +1965,26 @@ _rl_free_match_list (char **matches) xfree (matches); } +/* Compare a possibly-quoted filename TEXT from the line buffer and a possible + MATCH that is the product of filename completion, which acts on the dequoted + text. */ +static int +compare_match (char *text, const char *match) +{ + char *temp; + int r; + + if (rl_filename_completion_desired && rl_filename_quoting_desired && + rl_completion_found_quote && rl_filename_dequoting_function) + { + temp = (*rl_filename_dequoting_function) (text, rl_completion_quote_character); + r = strcmp (temp, match); + free (temp); + return r; + } + return (strcmp (text, match)); +} + /* Complete the word at or before point. WHAT_TO_DO says what to do with the completion. `?' means list the possible completions. @@ -1986,10 +2002,12 @@ rl_complete_internal (int what_to_do) int start, end, delimiter, found_quote, i, nontrivial_lcd; char *text, *saved_line_buffer; char quote_char; - int tlen, mlen; + int tlen, mlen, saved_last_completion_failed; RL_SETSTATE(RL_STATE_COMPLETING); + saved_last_completion_failed = last_completion_failed; + set_completion_defaults (what_to_do); saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL; @@ -2013,7 +2031,7 @@ rl_complete_internal (int what_to_do) matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char); /* nontrivial_lcd is set if the common prefix adds something to the word being completed. */ - nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; + nontrivial_lcd = matches && compare_match (text, matches[0]) != 0; if (what_to_do == '!' || what_to_do == '@') tlen = strlen (text); xfree (text); @@ -2023,6 +2041,7 @@ rl_complete_internal (int what_to_do) rl_ding (); FREE (saved_line_buffer); completion_changed_buffer = 0; + last_completion_failed = 1; RL_UNSETSTATE(RL_STATE_COMPLETING); _rl_reset_completion_state (); return (0); @@ -2038,11 +2057,15 @@ rl_complete_internal (int what_to_do) rl_ding (); FREE (saved_line_buffer); completion_changed_buffer = 0; + last_completion_failed = 1; RL_UNSETSTATE(RL_STATE_COMPLETING); _rl_reset_completion_state (); return (0); } + if (matches && matches[0] && *matches[0]) + last_completion_failed = 0; + switch (what_to_do) { case TAB: @@ -2098,6 +2121,15 @@ rl_complete_internal (int what_to_do) break; case '?': + /* Let's try to insert a single match here if the last completion failed + but this attempt returned a single match. */ + if (saved_last_completion_failed && matches[0] && *matches[0] && matches[1] == 0) + { + insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); + append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd); + break; + } + if (rl_completion_display_matches_hook == 0) { _rl_sigcleanup = _rl_complete_sigcleanup; @@ -2761,7 +2793,7 @@ rl_old_menu_complete (int count, int invoking_key) { insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); append_to_match (matches[match_list_index], delimiter, quote_char, - strcmp (orig_text, matches[match_list_index])); + compare_match (orig_text, matches[match_list_index])); } completion_changed_buffer = 1; @@ -2835,7 +2867,7 @@ rl_menu_complete (int count, int ignore) matches = gen_completion_matches (orig_text, orig_start, orig_end, our_func, found_quote, quote_char); - nontrivial_lcd = matches && strcmp (orig_text, matches[0]) != 0; + nontrivial_lcd = matches && compare_match (orig_text, matches[0]) != 0; /* If we are matching filenames, the attempted completion function will have set rl_filename_completion_desired to a non-zero value. The basic @@ -2942,7 +2974,7 @@ rl_menu_complete (int count, int ignore) { insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); append_to_match (matches[match_list_index], delimiter, quote_char, - strcmp (orig_text, matches[match_list_index])); + compare_match (orig_text, matches[match_list_index])); } completion_changed_buffer = 1;