]> git.ipfire.org Git - thirdparty/readline.git/blobdiff - complete.c
Readline-8.1 distribution sources and documentation
[thirdparty/readline.git] / complete.c
index adce0d69ac1d9bbf57a335c1fb0c6df36d9320c2..fc5c3adb3564d6408214f74a0a3e64a0f0437cd4 100644 (file)
@@ -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.
 
 #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,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, &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;