* readline.h (rl_completer_quote_characters): Add declaration.

* readline.c (rl_completer_quote_characters):  Add global var.
	* readline.c (strpbrk):  Add prototype and function.
	* readline.c (rl_complete_internal):  Add code to handle
	expansion of quoted strings.
This commit is contained in:
Fred Fish 1992-06-09 06:10:54 +00:00
parent d630b6150e
commit dd823a49ca
2 changed files with 125 additions and 12 deletions

View file

@ -1,3 +1,11 @@
Mon Jun 8 23:10:07 1992 Fred Fish (fnf@cygnus.com)
* readline.h (rl_completer_quote_characters): Add declaration.
* readline.c (rl_completer_quote_characters): Add global var.
* readline.c (strpbrk): Add prototype and function.
* readline.c (rl_complete_internal): Add code to handle
expansion of quoted strings.
Mon May 11 12:39:30 1992 John Gilmore (gnu at cygnus.com)
* readline.c: Can't initialize FILE *'s with stdin and stdout,

View file

@ -179,7 +179,7 @@ typedef sighandler SigHandler ();
#define HANDLE_SIGNALS
#ifdef __GO32__
#include <pc.h>
#include <sys/pc.h>
#undef HANDLE_SIGNALS
#endif
@ -241,7 +241,7 @@ static jmp_buf readline_top_level;
static FILE *in_stream, *out_stream;
/* The names of the streams that we do input and output to. */
FILE *rl_instream = stdin, *rl_outstream = stdout;
FILE *rl_instream, *rl_outstream;
/* Non-zero means echo characters as they are read. */
int readline_echoing_p = 1;
@ -292,6 +292,7 @@ static unsigned char parsing_conditionalized_out = 0;
/* Caseless strcmp (). */
static int stricmp (), strnicmp ();
static char *strpbrk ();
/* Non-zero means to save keys that we dispatch on in a kbd macro. */
static int defining_kbd_macro = 0;
@ -1119,6 +1120,12 @@ readline_initialize_everything ()
/* Find out if we are running in Emacs. */
running_in_emacs = getenv ("EMACS");
/* Set up input and output if they aren't already. */
if (!rl_instream)
rl_instream = stdin;
if (!rl_outstream)
rl_outstream = stdout;
/* Allocate data structures. */
if (!rl_line_buffer)
rl_line_buffer =
@ -3619,6 +3626,12 @@ char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
rl_basic_word_break_characters. */
char *rl_completer_word_break_characters = (char *)NULL;
/* The list of characters which are used to quote a substring of the command
line. Command completion occurs on the entire substring, and within the
substring rl_completer_word_break_characters are treated as any other
character, unless they also appear within this list. */
char *rl_completer_quote_characters = (char *)NULL;
/* List of characters that are word break characters, but should be left
in TEXT when it is passed to the completion function. The shell uses
this to help determine what kind of completing to do. */
@ -3654,8 +3667,10 @@ rl_complete_internal (what_to_do)
char *filename_completion_function ();
char **completion_matches (), **matches;
Function *our_func;
int start, end, delimiter = 0;
int start, scan, end, delimiter = 0;
char *text, *saved_line_buffer;
char quote_char = '\0';
char *replacement;
if (the_line)
saved_line_buffer = savestring (the_line);
@ -3675,8 +3690,41 @@ rl_complete_internal (what_to_do)
if (rl_point)
{
while (--rl_point &&
!rindex (rl_completer_word_break_characters, the_line[rl_point]));
if (rl_completer_quote_characters)
{
/* We have a list of characters which can be used in pairs to quote
substrings for completion. Try to find the start of an unclosed
quoted substring.
FIXME: Doesn't yet handle '\' escapes to hid embedded quotes */
for (scan = 0; scan < end; scan++)
{
if (quote_char != '\0')
{
/* Ignore everything until the matching close quote char */
if (the_line[scan] == quote_char)
{
/* Found matching close quote. Abandon this substring. */
quote_char = '\0';
rl_point = end;
}
}
else if (rindex (rl_completer_quote_characters, the_line[scan]))
{
/* Found start of a quoted substring. */
quote_char = the_line[scan];
rl_point = scan + 1;
}
}
}
if (rl_point == end)
{
/* 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 do completion. */
while (--rl_point &&
!rindex (rl_completer_word_break_characters,
the_line[rl_point])) {;}
}
/* If we are at a word break, then advance past it. */
if (rindex (rl_completer_word_break_characters, the_line[rl_point]))
@ -3728,7 +3776,7 @@ rl_complete_internal (what_to_do)
some_matches:
/* It seems to me that in all the cases we handle we would like
to ignore duplicate possiblilities. Scan for the text to
to ignore duplicate possibilities. Scan for the text to
insert being identical to the other completions. */
if (rl_ignore_completion_duplicates)
{
@ -3801,11 +3849,40 @@ rl_complete_internal (what_to_do)
our_func == (int (*)())filename_completion_function)
(void)(*rl_ignore_some_completions_function)(matches);
if (matches[0])
/* If we are doing completions on quoted substrings, and any matches
contain any of the completer word break characters, then auto-
matically prepend the substring with a quote character (just
pick the first one from the list of such) if it does not already
begin with a quote string. FIXME: Need to remove any such
automatically inserted quote character when it no longer is
necessary, such as if we change the string we are completing on
and the new set of matches don't require a quoted substring? */
replacement = matches[0];
if (matches[0] != NULL
&& rl_completer_quote_characters != NULL
&& (quote_char == '\0'))
{
for (i = 1; matches[i] != NULL; i++)
{
if (strpbrk (matches[i], rl_completer_word_break_characters))
{
/* Found an embedded word break character in a potential
match, so need to prepend a quote character if we are
replacing the completion string. */
replacement = alloca (strlen (matches[0]) + 2);
quote_char = *rl_completer_quote_characters;
*replacement = quote_char;
strcpy (replacement + 1, matches[0]);
break;
}
}
}
if (replacement)
{
rl_delete_text (start, rl_point);
rl_point = start;
rl_insert_text (matches[0]);
rl_insert_text (replacement);
}
/* If there are more matches, ring the bell to indicate.
@ -3819,10 +3896,15 @@ rl_complete_internal (what_to_do)
}
else
{
char temp_string[2];
char temp_string[16];
int temp_index = 0;
temp_string[0] = delimiter ? delimiter : ' ';
temp_string[1] = '\0';
if (quote_char)
{
temp_string[temp_index++] = quote_char;
}
temp_string[temp_index++] = delimiter ? delimiter : ' ';
temp_string[temp_index++] = '\0';
if (rl_filename_completion_desired)
{
@ -5559,8 +5641,10 @@ rl_named_function (string)
/* The last key bindings file read. */
#ifdef __MSDOS__
static char *last_readline_init_file = "~/inputrc";
/* Don't know what to do, but this is a guess */
static char *last_readline_init_file = "/INPUTRC";
#else
static char *last_readline_init_file = "~/inputrc";
#endif
/* Re-read the current keybindings file. */
@ -6310,6 +6394,27 @@ rl_function_dumper (print_readably)
static char *strindex ();
/* Return pointer to first occurance in STRING1 of any character from STRING2,
or NULL if no occurance found. */
static char *
strpbrk (string1, string2)
char *string1, *string2;
{
register char *scan;
for (; *string1 != '\0'; string1++)
{
for (scan = string2; *scan != '\0'; scan++)
{
if (*string1 == *scan)
{
return (string1);
}
}
}
return (NULL);
}
/* Return non-zero if any members of ARRAY are a substring in STRING. */
static int
substring_member_of_array (string, array)