Bash-4.2 distribution sources and documentation
This commit is contained in:
parent
30d188c293
commit
495aee441b
341 changed files with 108751 additions and 36060 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/* complete.c -- filename completion for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2011 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.
|
||||
|
|
@ -119,9 +119,11 @@ static char **remove_duplicate_matches PARAMS((char **));
|
|||
static void insert_match PARAMS((char *, int, int, char *));
|
||||
static int append_to_match PARAMS((char *, int, int, int));
|
||||
static void insert_all_matches PARAMS((char **, int, char *));
|
||||
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 complete_get_screenwidth PARAMS((void));
|
||||
|
||||
static char *make_quoted_replacement PARAMS((char *, int, char *));
|
||||
|
||||
|
|
@ -157,10 +159,14 @@ int _rl_print_completions_horizontally;
|
|||
#if defined (__MSDOS__) && !defined (__DJGPP__)
|
||||
int _rl_completion_case_fold = 1;
|
||||
#else
|
||||
int _rl_completion_case_fold;
|
||||
int _rl_completion_case_fold = 0;
|
||||
#endif
|
||||
|
||||
/* If non-zero, don't match hidden files (filenames beginning with a `.' on
|
||||
/* Non-zero means that `-' and `_' are equivalent when comparing filenames
|
||||
for completion. */
|
||||
int _rl_completion_case_map = 0;
|
||||
|
||||
/* If zero, don't match hidden files (filenames beginning with a `.' on
|
||||
Unix) when doing filename completion. */
|
||||
int _rl_match_hidden_files = 1;
|
||||
|
||||
|
|
@ -170,6 +176,10 @@ int _rl_match_hidden_files = 1;
|
|||
display prefix replaced with an ellipsis. */
|
||||
int _rl_completion_prefix_display_length = 0;
|
||||
|
||||
/* The readline-private number of screen columns to use when displaying
|
||||
matches. If < 0 or > _rl_screenwidth, it is ignored. */
|
||||
int _rl_completion_columns = -1;
|
||||
|
||||
/* Global variables available to applications using readline. */
|
||||
|
||||
#if defined (VISIBLE_STATS)
|
||||
|
|
@ -185,6 +195,10 @@ int rl_visible_stats = 0;
|
|||
after the `e' in `Makefile' won't result in `Makefilefile'. */
|
||||
int _rl_skip_completed_text = 0;
|
||||
|
||||
/* If non-zero, menu completion displays the common prefix first in the
|
||||
cycle of possible completions instead of the last. */
|
||||
int _rl_menu_complete_prefix_first = 0;
|
||||
|
||||
/* If non-zero, then this is the address of a function to call when
|
||||
completing on a directory name. The function is called with
|
||||
the address of a string (the current directory name) as an arg. */
|
||||
|
|
@ -467,6 +481,14 @@ get_y_or_n (for_pager)
|
|||
{
|
||||
int c;
|
||||
|
||||
/* For now, disable pager in callback mode, until we later convert to state
|
||||
driven functions. Have to wait until next major version to add new
|
||||
state definition, since it will change value of RL_STATE_DONE. */
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
for (;;)
|
||||
{
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
|
|
@ -829,7 +851,7 @@ print_filename (to_print, full_pathname, prefix_bytes)
|
|||
if (path_isdir (new_full_pathname))
|
||||
extension_char = '/';
|
||||
|
||||
free (new_full_pathname);
|
||||
xfree (new_full_pathname);
|
||||
to_print[-1] = c;
|
||||
}
|
||||
else
|
||||
|
|
@ -844,7 +866,7 @@ print_filename (to_print, full_pathname, prefix_bytes)
|
|||
extension_char = '/';
|
||||
}
|
||||
|
||||
free (s);
|
||||
xfree (s);
|
||||
if (extension_char)
|
||||
{
|
||||
putc (extension_char, rl_outstream);
|
||||
|
|
@ -1081,7 +1103,7 @@ remove_duplicate_matches (matches)
|
|||
{
|
||||
if (strcmp (matches[i], matches[i + 1]) == 0)
|
||||
{
|
||||
free (matches[i]);
|
||||
xfree (matches[i]);
|
||||
matches[i] = (char *)&dead_slot;
|
||||
}
|
||||
else
|
||||
|
|
@ -1099,7 +1121,7 @@ remove_duplicate_matches (matches)
|
|||
temp_array[j] = (char *)NULL;
|
||||
|
||||
if (matches[0] != (char *)&dead_slot)
|
||||
free (matches[0]);
|
||||
xfree (matches[0]);
|
||||
|
||||
/* Place the lowest common denominator back in [0]. */
|
||||
temp_array[0] = lowest_common;
|
||||
|
|
@ -1109,7 +1131,7 @@ remove_duplicate_matches (matches)
|
|||
insert. */
|
||||
if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0)
|
||||
{
|
||||
free (temp_array[1]);
|
||||
xfree (temp_array[1]);
|
||||
temp_array[1] = (char *)NULL;
|
||||
}
|
||||
return (temp_array);
|
||||
|
|
@ -1288,7 +1310,7 @@ postprocess_matches (matchesp, matching_filenames)
|
|||
if (rl_ignore_completion_duplicates)
|
||||
{
|
||||
temp_matches = remove_duplicate_matches (matches);
|
||||
free (matches);
|
||||
xfree (matches);
|
||||
matches = temp_matches;
|
||||
}
|
||||
|
||||
|
|
@ -1325,6 +1347,23 @@ postprocess_matches (matchesp, matching_filenames)
|
|||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
complete_get_screenwidth ()
|
||||
{
|
||||
int cols;
|
||||
char *envcols;
|
||||
|
||||
cols = _rl_completion_columns;
|
||||
if (cols >= 0 && cols <= _rl_screenwidth)
|
||||
return cols;
|
||||
envcols = getenv ("COLUMNS");
|
||||
if (envcols && *envcols)
|
||||
cols = atoi (envcols);
|
||||
if (cols >= 0 && cols <= _rl_screenwidth)
|
||||
return cols;
|
||||
return _rl_screenwidth;
|
||||
}
|
||||
|
||||
/* A convenience function for displaying a list of strings in
|
||||
columnar format on readline's output stream. MATCHES is the list
|
||||
of strings, in argv format, LEN is the number of strings in MATCHES,
|
||||
|
|
@ -1334,7 +1373,7 @@ rl_display_match_list (matches, len, max)
|
|||
char **matches;
|
||||
int len, max;
|
||||
{
|
||||
int count, limit, printed_len, lines;
|
||||
int count, limit, printed_len, lines, cols;
|
||||
int i, j, k, l, common_length, sind;
|
||||
char *temp, *t;
|
||||
|
||||
|
|
@ -1355,12 +1394,17 @@ rl_display_match_list (matches, len, max)
|
|||
}
|
||||
|
||||
/* How many items of MAX length can we fit in the screen window? */
|
||||
cols = complete_get_screenwidth ();
|
||||
max += 2;
|
||||
limit = _rl_screenwidth / max;
|
||||
if (limit != 1 && (limit * max == _rl_screenwidth))
|
||||
limit = cols / max;
|
||||
if (limit != 1 && (limit * max == cols))
|
||||
limit--;
|
||||
|
||||
/* Avoid a possible floating exception. If max > _rl_screenwidth,
|
||||
/* If cols == 0, limit will end up -1 */
|
||||
if (cols < _rl_screenwidth && limit < 0)
|
||||
limit = 1;
|
||||
|
||||
/* Avoid a possible floating exception. If max > cols,
|
||||
limit will be 0 and a divide-by-zero fault will result. */
|
||||
if (limit == 0)
|
||||
limit = 1;
|
||||
|
|
@ -1608,7 +1652,7 @@ insert_match (match, start, mtype, qc)
|
|||
else
|
||||
_rl_replace_text (replacement, start, end);
|
||||
if (replacement != match)
|
||||
free (replacement);
|
||||
xfree (replacement);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1675,7 +1719,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
|
|||
if (rl_point == rl_end && temp_string_index)
|
||||
rl_insert_text (temp_string);
|
||||
}
|
||||
free (filename);
|
||||
xfree (filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1711,7 +1755,7 @@ insert_all_matches (matches, point, qc)
|
|||
rl_insert_text (rp);
|
||||
rl_insert_text (" ");
|
||||
if (rp != matches[i])
|
||||
free (rp);
|
||||
xfree (rp);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1720,7 +1764,7 @@ insert_all_matches (matches, point, qc)
|
|||
rl_insert_text (rp);
|
||||
rl_insert_text (" ");
|
||||
if (rp != matches[0])
|
||||
free (rp);
|
||||
xfree (rp);
|
||||
}
|
||||
rl_end_undo_group ();
|
||||
}
|
||||
|
|
@ -1735,8 +1779,8 @@ _rl_free_match_list (matches)
|
|||
return;
|
||||
|
||||
for (i = 0; matches[i]; i++)
|
||||
free (matches[i]);
|
||||
free (matches);
|
||||
xfree (matches[i]);
|
||||
xfree (matches);
|
||||
}
|
||||
|
||||
/* Complete the word at or before point.
|
||||
|
|
@ -1757,6 +1801,9 @@ rl_complete_internal (what_to_do)
|
|||
int start, end, delimiter, found_quote, i, nontrivial_lcd;
|
||||
char *text, *saved_line_buffer;
|
||||
char quote_char;
|
||||
#if 1
|
||||
int tlen, mlen;
|
||||
#endif
|
||||
|
||||
RL_SETSTATE(RL_STATE_COMPLETING);
|
||||
|
||||
|
|
@ -1784,7 +1831,11 @@ rl_complete_internal (what_to_do)
|
|||
/* nontrivial_lcd is set if the common prefix adds something to the word
|
||||
being completed. */
|
||||
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
|
||||
free (text);
|
||||
#if 1
|
||||
if (what_to_do == '!' || what_to_do == '@')
|
||||
tlen = strlen (text);
|
||||
#endif
|
||||
xfree (text);
|
||||
|
||||
if (matches == 0)
|
||||
{
|
||||
|
|
@ -1817,8 +1868,25 @@ rl_complete_internal (what_to_do)
|
|||
case '!':
|
||||
case '@':
|
||||
/* Insert the first match with proper quoting. */
|
||||
#if 0
|
||||
if (*matches[0])
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
#else
|
||||
if (what_to_do == TAB)
|
||||
{
|
||||
if (*matches[0])
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
}
|
||||
else if (*matches[0] && matches[1] == 0)
|
||||
/* should we perform the check only if there are multiple matches? */
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
else if (*matches[0]) /* what_to_do != TAB && multiple matches */
|
||||
{
|
||||
mlen = *matches[0] ? strlen (matches[0]) : 0;
|
||||
if (mlen >= tlen)
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If there are more matches, ring the bell to indicate.
|
||||
If we are in vi mode, Posix.2 says to not ring the bell.
|
||||
|
|
@ -1872,7 +1940,7 @@ rl_complete_internal (what_to_do)
|
|||
if (saved_line_buffer)
|
||||
{
|
||||
completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0;
|
||||
free (saved_line_buffer);
|
||||
xfree (saved_line_buffer);
|
||||
}
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
|
|
@ -1939,7 +2007,7 @@ rl_completion_matches (text, entry_function)
|
|||
compute_lcd_of_matches (match_list, matches, text);
|
||||
else /* There were no matches. */
|
||||
{
|
||||
free (match_list);
|
||||
xfree (match_list);
|
||||
match_list = (char **)NULL;
|
||||
}
|
||||
return (match_list);
|
||||
|
|
@ -2005,6 +2073,62 @@ rl_username_completion_function (text, state)
|
|||
#endif /* !__WIN32__ && !__OPENNT */
|
||||
}
|
||||
|
||||
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
|
||||
(FILENAME_LEN). If _rl_completion_case_fold is set, compare without
|
||||
regard to the alphabetic case of characters. CONVFN is the possibly-
|
||||
converted directory entry; FILENAME is what the user typed. */
|
||||
static int
|
||||
complete_fncmp (convfn, convlen, filename, filename_len)
|
||||
const char *convfn;
|
||||
int convlen;
|
||||
const char *filename;
|
||||
int filename_len;
|
||||
{
|
||||
register char *s1, *s2;
|
||||
int d, len;
|
||||
|
||||
/* Otherwise, if these match up to the length of filename, then
|
||||
it is a match. */
|
||||
if (_rl_completion_case_fold && _rl_completion_case_map)
|
||||
{
|
||||
/* Case-insensitive comparison treating _ and - as equivalent */
|
||||
if (filename_len == 0)
|
||||
return 1;
|
||||
if (convlen < filename_len)
|
||||
return 0;
|
||||
s1 = (char *)convfn;
|
||||
s2 = (char *)filename;
|
||||
len = filename_len;
|
||||
do
|
||||
{
|
||||
d = _rl_to_lower (*s1) - _rl_to_lower (*s2);
|
||||
/* *s1 == [-_] && *s2 == [-_] */
|
||||
if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
d = 0;
|
||||
if (d != 0)
|
||||
return 0;
|
||||
s1++; s2++; /* already checked convlen >= filename_len */
|
||||
}
|
||||
while (--len != 0);
|
||||
return 1;
|
||||
}
|
||||
else if (_rl_completion_case_fold)
|
||||
{
|
||||
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
|
||||
(convlen >= filename_len) &&
|
||||
(_rl_strnicmp (filename, convfn, filename_len) == 0))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((convfn[0] == filename[0]) &&
|
||||
(convlen >= filename_len) &&
|
||||
(strncmp (filename, convfn, filename_len) == 0))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Okay, now we write the entry_function for filename completion. In the
|
||||
general case. Note that completion in the shell is a little different
|
||||
because of all the pathnames that must be followed when looking up the
|
||||
|
|
@ -2071,32 +2195,41 @@ rl_filename_completion_function (text, state)
|
|||
|
||||
/* We aren't done yet. We also support the "~user" syntax. */
|
||||
|
||||
/* Save the version of the directory that the user typed. */
|
||||
users_dirname = savestring (dirname);
|
||||
/* Save the version of the directory that the user typed, dequoting
|
||||
it if necessary. */
|
||||
if (rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
users_dirname = (*rl_filename_dequoting_function) (dirname, rl_completion_quote_character);
|
||||
else
|
||||
users_dirname = savestring (dirname);
|
||||
|
||||
if (*dirname == '~')
|
||||
{
|
||||
temp = tilde_expand (dirname);
|
||||
free (dirname);
|
||||
xfree (dirname);
|
||||
dirname = temp;
|
||||
}
|
||||
|
||||
/* We have saved the possibly-dequoted version of the directory name
|
||||
the user typed. Now transform the directory name we're going to
|
||||
pass to opendir(2). The directory rewrite hook modifies only the
|
||||
directory name; the directory completion hook modifies both the
|
||||
directory name passed to opendir(2) and the version the user
|
||||
typed. Both the directory completion and rewrite hooks should perform
|
||||
any necessary dequoting. The hook functions return 1 if they modify
|
||||
the directory name argument. If either hook returns 0, it should
|
||||
not modify the directory name pointer passed as an argument. */
|
||||
if (rl_directory_rewrite_hook)
|
||||
(*rl_directory_rewrite_hook) (&dirname);
|
||||
|
||||
/* The directory completion hook should perform any necessary
|
||||
dequoting. */
|
||||
if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
|
||||
else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
|
||||
{
|
||||
free (users_dirname);
|
||||
xfree (users_dirname);
|
||||
users_dirname = savestring (dirname);
|
||||
}
|
||||
else if (rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
{
|
||||
/* delete single and double quotes */
|
||||
temp = (*rl_filename_dequoting_function) (users_dirname, rl_completion_quote_character);
|
||||
free (users_dirname);
|
||||
users_dirname = temp;
|
||||
xfree (dirname);
|
||||
dirname = savestring (users_dirname);
|
||||
}
|
||||
directory = opendir (dirname);
|
||||
|
||||
|
|
@ -2105,7 +2238,7 @@ rl_filename_completion_function (text, state)
|
|||
{
|
||||
/* delete single and double quotes */
|
||||
temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character);
|
||||
free (filename);
|
||||
xfree (filename);
|
||||
filename = temp;
|
||||
}
|
||||
filename_len = strlen (filename);
|
||||
|
|
@ -2147,22 +2280,8 @@ rl_filename_completion_function (text, state)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, if these match up to the length of filename, then
|
||||
it is a match. */
|
||||
if (_rl_completion_case_fold)
|
||||
{
|
||||
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
|
||||
(convlen >= filename_len) &&
|
||||
(_rl_strnicmp (filename, convfn, filename_len) == 0))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((convfn[0] == filename[0]) &&
|
||||
(convlen >= filename_len) &&
|
||||
(strncmp (filename, convfn, filename_len) == 0))
|
||||
break;
|
||||
}
|
||||
if (complete_fncmp (convfn, convlen, filename, filename_len))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2175,17 +2294,17 @@ rl_filename_completion_function (text, state)
|
|||
}
|
||||
if (dirname)
|
||||
{
|
||||
free (dirname);
|
||||
xfree (dirname);
|
||||
dirname = (char *)NULL;
|
||||
}
|
||||
if (filename)
|
||||
{
|
||||
free (filename);
|
||||
xfree (filename);
|
||||
filename = (char *)NULL;
|
||||
}
|
||||
if (users_dirname)
|
||||
{
|
||||
free (users_dirname);
|
||||
xfree (users_dirname);
|
||||
users_dirname = (char *)NULL;
|
||||
}
|
||||
|
||||
|
|
@ -2225,7 +2344,7 @@ rl_filename_completion_function (text, state)
|
|||
temp = savestring (convfn);
|
||||
|
||||
if (convfn != dentry)
|
||||
free (convfn);
|
||||
xfree (convfn);
|
||||
|
||||
return (temp);
|
||||
}
|
||||
|
|
@ -2304,14 +2423,14 @@ rl_old_menu_complete (count, invoking_key)
|
|||
|
||||
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
FREE (orig_text);
|
||||
orig_text = (char *)0;
|
||||
completion_changed_buffer = 0;
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
return (0);
|
||||
completion_changed_buffer = 0;
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
return (0);
|
||||
}
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
|
|
@ -2340,7 +2459,10 @@ rl_old_menu_complete (count, invoking_key)
|
|||
|
||||
match_list_index += count;
|
||||
if (match_list_index < 0)
|
||||
match_list_index += match_list_size;
|
||||
{
|
||||
while (match_list_index < 0)
|
||||
match_list_index += match_list_size;
|
||||
}
|
||||
else
|
||||
match_list_index %= match_list_size;
|
||||
|
||||
|
|
@ -2375,7 +2497,7 @@ rl_menu_complete (count, ignore)
|
|||
static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */
|
||||
static int orig_start, orig_end;
|
||||
static char quote_char;
|
||||
static int delimiter;
|
||||
static int delimiter, cstate;
|
||||
|
||||
/* The first time through, we generate the list of matches and set things
|
||||
up to insert them. */
|
||||
|
|
@ -2428,14 +2550,14 @@ rl_menu_complete (count, ignore)
|
|||
|
||||
if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
matches = (char **)0;
|
||||
FREE (orig_text);
|
||||
orig_text = (char *)0;
|
||||
completion_changed_buffer = 0;
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
return (0);
|
||||
completion_changed_buffer = 0;
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
return (0);
|
||||
}
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_COMPLETING);
|
||||
|
|
@ -2483,6 +2605,11 @@ rl_menu_complete (count, ignore)
|
|||
full_completion = 1;
|
||||
return (0);
|
||||
}
|
||||
else if (_rl_menu_complete_prefix_first && match_list_size > 1)
|
||||
{
|
||||
rl_ding ();
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have the list of matches. Replace the text between
|
||||
|
|
@ -2500,7 +2627,10 @@ rl_menu_complete (count, ignore)
|
|||
|
||||
match_list_index += count;
|
||||
if (match_list_index < 0)
|
||||
match_list_index += match_list_size;
|
||||
{
|
||||
while (match_list_index < 0)
|
||||
match_list_index += match_list_size;
|
||||
}
|
||||
else
|
||||
match_list_index %= match_list_size;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue