summaryrefslogtreecommitdiffstats
path: root/gnu/lib/libreadline/complete.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/lib/libreadline/complete.c')
-rw-r--r--gnu/lib/libreadline/complete.c110
1 files changed, 73 insertions, 37 deletions
diff --git a/gnu/lib/libreadline/complete.c b/gnu/lib/libreadline/complete.c
index 037222d..2180132 100644
--- a/gnu/lib/libreadline/complete.c
+++ b/gnu/lib/libreadline/complete.c
@@ -19,6 +19,7 @@
is generally kept in a file called COPYING or LICENSE. If you do not
have a copy of the license, write to the Free Software Foundation,
675 Mass Ave, Cambridge, MA 02139, USA. */
+#define READLINE_LIBRARY
#include <stdio.h>
#include <sys/types.h>
@@ -63,7 +64,7 @@ extern struct passwd *getpwent ();
#include "rldefs.h"
/* Some standard library routines. */
-#include <readline/readline.h>
+#include "readline.h"
/* Possible values for do_replace in rl_complete_internal. */
#define NO_MATCH 0
@@ -225,6 +226,13 @@ int rl_ignore_completion_duplicates = 1;
within a completion entry finder function. */
int rl_filename_completion_desired = 0;
+/* Non-zero means that the results of the matches are to be quoted using
+ double quotes (or an application-specific quoting mechanism) if the
+ filename contains any characters in rl_word_break_chars. This is
+ ALWAYS non-zero on entry, and can only be changed within a completion
+ entry finder function. */
+int rl_filename_quoting_desired = 1;
+
/* This function, if defined, is called by the completer when real
filename completion is done, after all the matching names have been
generated. It is passed a (char**) known as matches in the code below.
@@ -367,9 +375,7 @@ rl_complete_internal (what_to_do)
char *text, *saved_line_buffer;
char *replacement;
char quote_char = '\0';
-#if defined (SHELL)
int found_quote = 0;
-#endif
if (rl_line_buffer)
saved_line_buffer = savestring (rl_line_buffer);
@@ -381,8 +387,9 @@ rl_complete_internal (what_to_do)
else
our_func = (Function *)filename_completion_function;
- /* Only the completion entry function can change this. */
+ /* Only the completion entry function can change these. */
rl_filename_completion_desired = 0;
+ rl_filename_quoting_desired = 1;
/* We now look backwards for the start of a filename/variable word. */
end = rl_point;
@@ -406,6 +413,7 @@ rl_complete_internal (what_to_do)
if (rl_line_buffer[scan] == '\\')
{
pass_next = 1;
+ found_quote |= 4;
continue;
}
@@ -424,12 +432,11 @@ rl_complete_internal (what_to_do)
/* Found start of a quoted substring. */
quote_char = rl_line_buffer[scan];
rl_point = scan + 1;
-#if defined (SHELL)
+ /* Shell-like quoting conventions. */
if (quote_char == '\'')
found_quote |= 1;
else if (quote_char == '"')
found_quote |= 2;
-#endif
}
}
}
@@ -437,34 +444,37 @@ rl_complete_internal (what_to_do)
if (rl_point == end)
{
int quoted = 0;
- /* We didn't find an unclosed quoted substring up which to do
+ /* We didn't find an unclosed quoted substring upon which to do
completion, so use the word break characters to find the
substring on which to complete. */
while (--rl_point)
{
scan = rl_line_buffer[rl_point];
+
+ if (strchr (rl_completer_word_break_characters, scan) == 0)
+ continue;
+
#if defined (SHELL)
/* Don't let word break characters in quoted substrings break
words for the completer. */
- if (found_quote)
- {
- if (strchr (rl_completer_quote_characters, scan))
- {
- quoted = !quoted;
- continue;
- }
- if (quoted)
- continue;
- }
+ if (found_quote && char_is_quoted (rl_line_buffer, rl_point))
+ continue;
#endif /* SHELL */
- if (strchr (rl_completer_word_break_characters, scan))
- break;
+
+ /* Convoluted code, but it avoids an n^2 algorithm with calls
+ to char_is_quoted. */
+ break;
}
}
- /* If we are at a word break, then advance past it. */
+ /* If we are at an unquoted word break, then advance past it. */
scan = rl_line_buffer[rl_point];
+#if defined (SHELL)
+ if ((found_quote == 0 || char_is_quoted (rl_line_buffer, rl_point) == 0) &&
+ strchr (rl_completer_word_break_characters, scan))
+#else
if (strchr (rl_completer_word_break_characters, scan))
+#endif
{
/* If the character that caused the word break was a quoting
character, then remember it as the delimiter. */
@@ -521,6 +531,7 @@ rl_complete_internal (what_to_do)
else
{
register int i;
+ int should_quote;
/* It seems to me that in all the cases we handle we would like
to ignore duplicate possiblilities. Scan for the text to
@@ -603,8 +614,18 @@ rl_complete_internal (what_to_do)
matches don't require a quoted substring. */
replacement = matches[0];
- if (matches[0] && rl_completer_quote_characters && !quote_char &&
- rl_filename_completion_desired)
+ should_quote = matches[0] && rl_completer_quote_characters &&
+ rl_filename_completion_desired &&
+ rl_filename_quoting_desired;
+
+ if (should_quote)
+#if defined (SHELL)
+ should_quote = should_quote && (!quote_char || quote_char == '"');
+#else
+ should_quote = should_quote && !quote_char;
+#endif
+
+ if (should_quote)
{
int do_replace;
@@ -614,17 +635,17 @@ rl_complete_internal (what_to_do)
This also checks whether the common prefix of several
matches needs to be quoted. If the common prefix should
not be checked, add !matches[1] to the if clause. */
- if (rl_strpbrk (matches[0], rl_completer_word_break_characters)
+ should_quote = rl_strpbrk (matches[0], rl_completer_word_break_characters) != 0;
#if defined (SHELL)
- || rl_strpbrk (matches[0], "$`")
+ should_quote = should_quote || rl_strpbrk (matches[0], "#$`") != 0;
#endif
- )
+
+ if (should_quote)
do_replace = matches[1] ? MULT_MATCH : SINGLE_MATCH;
if (do_replace != NO_MATCH)
{
#if defined (SHELL)
- /* XXX - experimental */
/* Quote the replacement, since we found an
embedded word break character in a potential
match. */
@@ -648,7 +669,18 @@ rl_complete_internal (what_to_do)
rlen = strlen (rtext);
replacement = xmalloc (rlen + 1);
- strcpy (replacement, rtext);
+ /* If we're completing on a quoted string where the user
+ has already supplied the opening quote, we don't want
+ the quote in the replacement text, and we reset
+ QUOTE_CHAR to 0 to avoid an extra closing quote. */
+ if (quote_char == '"')
+ {
+ strcpy (replacement, rtext + 1);
+ rlen--;
+ quote_char = 0;
+ }
+ else
+ strcpy (replacement, rtext);
if (do_replace == MULT_MATCH)
replacement[rlen - 1] = '\0';
free (rtext);
@@ -927,7 +959,13 @@ static int
compare_strings (s1, s2)
char **s1, **s2;
{
- return (strcmp (*s1, *s2));
+ int result;
+
+ result = **s1 - **s2;
+ if (result == 0)
+ result = strcmp (*s1, *s2);
+
+ return result;
}
/* A completion function for usernames.
@@ -976,7 +1014,7 @@ username_completion_function (text, state)
}
else
{
- char *value = (char *)xmalloc (2 + strlen (entry->pw_name));
+ char *value = xmalloc (2 + strlen (entry->pw_name));
*value = *text;
@@ -1083,7 +1121,7 @@ completion_matches (text, entry_function)
if (low > si) low = si;
i++;
}
- match_list[0] = (char *)xmalloc (low + 1);
+ match_list[0] = xmalloc (low + 1);
strncpy (match_list[0], match_list[1], low);
match_list[0][low] = '\0';
}
@@ -1111,7 +1149,7 @@ filename_completion_function (text, state)
static char *users_dirname = (char *)NULL;
static int filename_len;
- struct direct *entry = (struct direct *)NULL;
+ struct dirent *entry = (struct dirent *)NULL;
/* If we don't have any state, then do some initialization. */
if (!state)
@@ -1185,8 +1223,8 @@ filename_completion_function (text, state)
{
/* Otherwise, if these match up to the length of filename, then
it is a match. */
- if (((int)D_NAMLEN (entry)) >= filename_len &&
- (entry->d_name[0] == filename[0]) &&
+ if ((entry->d_name[0] == filename[0]) &&
+ (((int)D_NAMLEN (entry)) >= filename_len) &&
(strncmp (filename, entry->d_name, filename_len) == 0))
break;
}
@@ -1199,7 +1237,6 @@ filename_completion_function (text, state)
closedir (directory);
directory = (DIR *)NULL;
}
-
if (dirname)
{
free (dirname);
@@ -1228,7 +1265,7 @@ filename_completion_function (text, state)
if (rl_complete_with_tilde_expansion && *users_dirname == '~')
{
int dirlen = strlen (dirname);
- temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry));
+ temp = xmalloc (2 + dirlen + D_NAMLEN (entry));
strcpy (temp, dirname);
/* Canonicalization cuts off any final slash present. We need
to add it back. */
@@ -1240,8 +1277,7 @@ filename_completion_function (text, state)
}
else
{
- temp = (char *)
- xmalloc (1 + strlen (users_dirname) + D_NAMLEN (entry));
+ temp = xmalloc (1 + strlen (users_dirname) + D_NAMLEN (entry));
strcpy (temp, users_dirname);
}
OpenPOWER on IntegriCloud