summaryrefslogtreecommitdiff
path: root/complete.c
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2021-01-18 13:42:55 -0500
committerChet Ramey <chet.ramey@case.edu>2021-01-18 13:42:55 -0500
commitcf3c762ecfff5b2f445647a0f1543693984a5540 (patch)
treee21eb36970a06b1d8a2df6a97a161da43410e136 /complete.c
parentc5ad6be530f5c1daf64a2d20df4baba9f6b57aa4 (diff)
downloadreadline-cf3c762ecfff5b2f445647a0f1543693984a5540.tar.gz
Readline-8.1 distribution sources and documentationreadline-8.1
Diffstat (limited to 'complete.c')
-rw-r--r--complete.c104
1 files changed, 68 insertions, 36 deletions
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 <config.h>
#endif
#include <sys/types.h>
+#if defined (__TANDEM)
+# include <sys/stat.h>
+#endif
#include <fcntl.h>
#if defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
@@ -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,8 +1361,11 @@ 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)
@@ -1359,27 +1376,6 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
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;
- }
if (low > si)
low = si;
@@ -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, &quote_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, &quote_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, &quote_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;