mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-08-09 11:40:30 +02:00
Bash-5.3-alpha release
This commit is contained in:
+179
-170
@@ -1,6 +1,6 @@
|
||||
/* complete.c -- filename completion for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2024 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.
|
||||
@@ -77,11 +77,7 @@ extern int errno;
|
||||
# include "colors.h"
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef int QSFUNC (const void *, const void *);
|
||||
#else
|
||||
typedef int QSFUNC ();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LSTAT
|
||||
# define LSTAT lstat
|
||||
@@ -250,11 +246,24 @@ rl_icppfunc_t *rl_filename_stat_hook = (rl_icppfunc_t *)NULL;
|
||||
either return its first argument (if no conversion takes place) or
|
||||
newly-allocated memory. This can, for instance, convert filenames
|
||||
between character sets for comparison against what's typed at the
|
||||
keyboard. The returned value is what is added to the list of
|
||||
matches. The second argument is the length of the filename to be
|
||||
converted. */
|
||||
keyboard (after its potential modification by rl_completion_rewrite_hook).
|
||||
The returned value is what is added to the list of matches.
|
||||
The second argument is the length of the filename to be converted. */
|
||||
rl_dequote_func_t *rl_filename_rewrite_hook = (rl_dequote_func_t *)NULL;
|
||||
|
||||
/* If non-zero, this is the address of a function to call before
|
||||
comparing the filename portion of a word to be completed with directory
|
||||
entries from the filesystem. This takes the address of the partial word
|
||||
to be completed, after any rl_filename_dequoting_function has been applied.
|
||||
The function should either return its first argument (if no conversion
|
||||
takes place) or newly-allocated memory. This can, for instance, convert
|
||||
the filename portion of the completion word to a character set suitable
|
||||
for comparison against directory entries read from the filesystem (after
|
||||
their potential modification by rl_filename_rewrite_hook).
|
||||
The returned value is what is added to the list of matches.
|
||||
The second argument is the length of the filename to be converted. */
|
||||
rl_dequote_func_t *rl_completion_rewrite_hook = (rl_dequote_func_t *)NULL;
|
||||
|
||||
/* Non-zero means readline completion functions perform tilde expansion. */
|
||||
int rl_complete_with_tilde_expansion = 0;
|
||||
|
||||
@@ -340,6 +349,15 @@ int rl_filename_completion_desired = 0;
|
||||
entry finder function. */
|
||||
int rl_filename_quoting_desired = 1;
|
||||
|
||||
/* Non-zero means we should apply filename-type quoting to all completions
|
||||
even if we are not otherwise treating the matches as filenames. This is
|
||||
ALWAYS zero on entry, and can only be changed within a completion entry
|
||||
finder function. */
|
||||
int rl_full_quoting_desired = 0;
|
||||
|
||||
#define QUOTING_DESIRED() \
|
||||
(rl_full_quoting_desired || (rl_filename_completion_desired && rl_filename_quoting_desired))
|
||||
|
||||
/* 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.
|
||||
@@ -455,6 +473,7 @@ rl_complete (int ignore, int invoking_key)
|
||||
int
|
||||
rl_possible_completions (int ignore, int invoking_key)
|
||||
{
|
||||
last_completion_failed = 0;
|
||||
rl_completion_invoking_key = invoking_key;
|
||||
return (rl_complete_internal ('?'));
|
||||
}
|
||||
@@ -484,6 +503,32 @@ rl_completion_mode (rl_command_func_t *cfunc)
|
||||
return TAB;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* */
|
||||
/* Completion signal handling and cleanup */
|
||||
/* */
|
||||
/********************************************/
|
||||
|
||||
/* State to clean up and free if completion is interrupted by a signal. */
|
||||
typedef struct {
|
||||
char **matches;
|
||||
char *saved_line;
|
||||
} complete_sigcleanarg_t;
|
||||
|
||||
static void
|
||||
_rl_complete_sigcleanup (int sig, void *ptr)
|
||||
{
|
||||
complete_sigcleanarg_t *arg;
|
||||
|
||||
if (sig == SIGINT) /* XXX - for now */
|
||||
{
|
||||
arg = ptr;
|
||||
_rl_free_match_list (arg->matches);
|
||||
FREE (arg->saved_line);
|
||||
_rl_complete_display_matches_interrupt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************/
|
||||
/* */
|
||||
/* Completion utility functions */
|
||||
@@ -498,16 +543,6 @@ _rl_reset_completion_state (void)
|
||||
rl_completion_quote_character = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_complete_sigcleanup (int sig, void *ptr)
|
||||
{
|
||||
if (sig == SIGINT) /* XXX - for now */
|
||||
{
|
||||
_rl_free_match_list ((char **)ptr);
|
||||
_rl_complete_display_matches_interrupt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set default values for readline word completion. These are the variables
|
||||
that application completion functions can change or inspect. */
|
||||
static void
|
||||
@@ -516,6 +551,7 @@ set_completion_defaults (int what_to_do)
|
||||
/* Only the completion entry function can change these. */
|
||||
rl_filename_completion_desired = 0;
|
||||
rl_filename_quoting_desired = 1;
|
||||
rl_full_quoting_desired = 0;
|
||||
rl_completion_type = what_to_do;
|
||||
rl_completion_suppress_append = rl_completion_suppress_quote = 0;
|
||||
rl_completion_append_character = ' ';
|
||||
@@ -1319,6 +1355,7 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
|
||||
int low; /* Count of max-matched characters. */
|
||||
int lx;
|
||||
char *dtext; /* dequoted TEXT, if needed */
|
||||
size_t len1, len2;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
int v;
|
||||
size_t v1, v2;
|
||||
@@ -1345,6 +1382,9 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
|
||||
memset (&ps2, 0, sizeof (mbstate_t));
|
||||
}
|
||||
#endif
|
||||
len1 = strlen (match_list[i]);
|
||||
len2 = strlen (match_list[i + 1]);
|
||||
|
||||
for (si = 0; (c1 = match_list[i][si]) && (c2 = match_list[i + 1][si]); si++)
|
||||
{
|
||||
if (_rl_completion_case_fold)
|
||||
@@ -1355,8 +1395,8 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
v1 = MBRTOWC (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
|
||||
v2 = MBRTOWC (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
|
||||
v1 = MBRTOWC (&wc1, match_list[i]+si, len1 - si, &ps1);
|
||||
v2 = MBRTOWC (&wc2, match_list[i+1]+si, len2 - si, &ps2);
|
||||
if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
|
||||
{
|
||||
if (c1 != c2) /* do byte comparison */
|
||||
@@ -1412,10 +1452,8 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
|
||||
check against the list of matches
|
||||
FI */
|
||||
dtext = (char *)NULL;
|
||||
if (rl_filename_completion_desired &&
|
||||
rl_filename_dequoting_function &&
|
||||
rl_completion_found_quote &&
|
||||
rl_filename_quoting_desired)
|
||||
if (QUOTING_DESIRED() && rl_completion_found_quote &&
|
||||
rl_filename_dequoting_function)
|
||||
{
|
||||
dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
|
||||
text = dtext;
|
||||
@@ -1630,7 +1668,7 @@ rl_display_match_list (char **matches, int len, int max)
|
||||
if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
|
||||
{
|
||||
lines = _rl_internal_pager (lines);
|
||||
if (lines < 0)
|
||||
if (lines < 0 || _rl_complete_display_matches_interrupt)
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1658,7 +1696,7 @@ rl_display_match_list (char **matches, int len, int max)
|
||||
if (_rl_page_completions && lines >= _rl_screenheight - 1)
|
||||
{
|
||||
lines = _rl_internal_pager (lines);
|
||||
if (lines < 0)
|
||||
if (lines < 0 || _rl_complete_display_matches_interrupt)
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1745,7 +1783,9 @@ display_matches (char **matches)
|
||||
}
|
||||
}
|
||||
|
||||
rl_display_match_list (matches, len, max);
|
||||
/* We rely on the caller to set MATCHES to 0 when this returns. */
|
||||
if (_rl_complete_display_matches_interrupt == 0)
|
||||
rl_display_match_list (matches, len, max);
|
||||
|
||||
rl_forced_update_display ();
|
||||
rl_display_fixed = 1;
|
||||
@@ -1768,9 +1808,7 @@ make_quoted_replacement (char *match, int mtype, char *qc)
|
||||
matches don't require a quoted substring. */
|
||||
replacement = match;
|
||||
|
||||
should_quote = match && rl_completer_quote_characters &&
|
||||
rl_filename_completion_desired &&
|
||||
rl_filename_quoting_desired;
|
||||
should_quote = match && rl_completer_quote_characters && QUOTING_DESIRED();
|
||||
|
||||
if (should_quote)
|
||||
should_quote = should_quote && (!qc || !*qc ||
|
||||
@@ -1784,6 +1822,11 @@ make_quoted_replacement (char *match, int mtype, char *qc)
|
||||
should_quote = rl_filename_quote_characters
|
||||
? (_rl_strpbrk (match, rl_filename_quote_characters) != 0)
|
||||
: 0;
|
||||
/* If we saw a quote in the original word, but readline thinks the
|
||||
match doesn't need to be quoted, and the application has a filename
|
||||
quoting function, give the application a chance to quote it if
|
||||
needed so we don't second-guess the user. */
|
||||
should_quote |= *qc == 0 && rl_completion_found_quote && mtype != NO_MATCH && rl_filename_quoting_function;
|
||||
|
||||
do_replace = should_quote ? mtype : NO_MATCH;
|
||||
/* Quote the replacement, since we found an embedded
|
||||
@@ -1791,6 +1834,7 @@ make_quoted_replacement (char *match, int mtype, char *qc)
|
||||
if (do_replace != NO_MATCH && rl_filename_quoting_function)
|
||||
replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
|
||||
}
|
||||
|
||||
return (replacement);
|
||||
}
|
||||
|
||||
@@ -1976,8 +2020,7 @@ 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)
|
||||
if (QUOTING_DESIRED() && rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
{
|
||||
temp = (*rl_filename_dequoting_function) (text, rl_completion_quote_character);
|
||||
r = strcmp (temp, match);
|
||||
@@ -2001,10 +2044,11 @@ rl_complete_internal (int what_to_do)
|
||||
{
|
||||
char **matches;
|
||||
rl_compentry_func_t *our_func;
|
||||
int start, end, delimiter, found_quote, i, nontrivial_lcd;
|
||||
int start, end, delimiter, found_quote, i, nontrivial_lcd, do_display;
|
||||
char *text, *saved_line_buffer;
|
||||
char quote_char;
|
||||
int tlen, mlen, saved_last_completion_failed;
|
||||
complete_sigcleanarg_t cleanarg; /* state to clean up on signal */
|
||||
|
||||
RL_SETSTATE(RL_STATE_COMPLETING);
|
||||
|
||||
@@ -2031,9 +2075,24 @@ rl_complete_internal (int what_to_do)
|
||||
|
||||
text = rl_copy_text (start, end);
|
||||
matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
|
||||
/* If TEXT contains quote characters, it will be dequoted as part of
|
||||
generating the matches, and the matches will not contain any quote
|
||||
characters. We need to dequote TEXT before performing the comparison.
|
||||
Since compare_match performs the dequoting, and we only want to do it
|
||||
once, we don't call compare_matches after dequoting TEXT; we call
|
||||
strcmp directly. */
|
||||
/* nontrivial_lcd is set if the common prefix adds something to the word
|
||||
being completed. */
|
||||
nontrivial_lcd = matches && compare_match (text, matches[0]) != 0;
|
||||
if (QUOTING_DESIRED() && rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
{
|
||||
char *t;
|
||||
t = (*rl_filename_dequoting_function) (text, rl_completion_quote_character);
|
||||
xfree (text);
|
||||
text = t;
|
||||
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
|
||||
}
|
||||
else
|
||||
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
|
||||
if (what_to_do == '!' || what_to_do == '@')
|
||||
tlen = strlen (text);
|
||||
xfree (text);
|
||||
@@ -2068,6 +2127,8 @@ rl_complete_internal (int what_to_do)
|
||||
if (matches && matches[0] && *matches[0])
|
||||
last_completion_failed = 0;
|
||||
|
||||
do_display = 0;
|
||||
|
||||
switch (what_to_do)
|
||||
{
|
||||
case TAB:
|
||||
@@ -2101,13 +2162,13 @@ rl_complete_internal (int what_to_do)
|
||||
{
|
||||
if (what_to_do == '!')
|
||||
{
|
||||
display_matches (matches);
|
||||
do_display = 1;
|
||||
break;
|
||||
}
|
||||
else if (what_to_do == '@')
|
||||
{
|
||||
if (nontrivial_lcd == 0)
|
||||
display_matches (matches);
|
||||
do_display = 1;
|
||||
break;
|
||||
}
|
||||
else if (rl_editing_mode != vi_mode)
|
||||
@@ -2131,23 +2192,11 @@ rl_complete_internal (int what_to_do)
|
||||
append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rl_completion_display_matches_hook == 0)
|
||||
{
|
||||
_rl_sigcleanup = _rl_complete_sigcleanup;
|
||||
_rl_sigcleanarg = matches;
|
||||
_rl_complete_display_matches_interrupt = 0;
|
||||
}
|
||||
display_matches (matches);
|
||||
if (_rl_complete_display_matches_interrupt)
|
||||
{
|
||||
matches = 0; /* already freed by rl_complete_sigcleanup */
|
||||
_rl_complete_display_matches_interrupt = 0;
|
||||
if (rl_signal_event_hook)
|
||||
(*rl_signal_event_hook) (); /* XXX */
|
||||
}
|
||||
_rl_sigcleanup = 0;
|
||||
_rl_sigcleanarg = 0;
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
case '%': /* used by menu_complete */
|
||||
case '|': /* add this for unconditional display */
|
||||
do_display = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2160,6 +2209,34 @@ rl_complete_internal (int what_to_do)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If we need to display the match list, set up to clean it up on receipt of
|
||||
a signal and do it here. If the application has registered a function to
|
||||
display the matches, let it do the work. */
|
||||
if (do_display)
|
||||
{
|
||||
if (rl_completion_display_matches_hook == 0)
|
||||
{
|
||||
_rl_sigcleanup = _rl_complete_sigcleanup;
|
||||
cleanarg.matches = matches;
|
||||
cleanarg.saved_line = saved_line_buffer;
|
||||
_rl_sigcleanarg = &cleanarg;
|
||||
_rl_complete_display_matches_interrupt = 0;
|
||||
}
|
||||
|
||||
display_matches (matches);
|
||||
|
||||
if (_rl_complete_display_matches_interrupt)
|
||||
{
|
||||
matches = 0; /* Both already freed by _rl_complete_sigcleanup */
|
||||
saved_line_buffer = 0;
|
||||
_rl_complete_display_matches_interrupt = 0;
|
||||
if (rl_signal_event_hook)
|
||||
(*rl_signal_event_hook) ();
|
||||
}
|
||||
_rl_sigcleanup = 0;
|
||||
_rl_sigcleanarg = 0;
|
||||
}
|
||||
|
||||
_rl_free_match_list (matches);
|
||||
|
||||
/* Check to see if the line has changed through all of this manipulation. */
|
||||
@@ -2200,7 +2277,7 @@ rl_completion_matches (const char *text, rl_compentry_func_t *entry_function)
|
||||
register int i;
|
||||
|
||||
/* Number of slots in match_list. */
|
||||
int match_list_size;
|
||||
size_t match_list_size;
|
||||
|
||||
/* The list of matches. */
|
||||
char **match_list;
|
||||
@@ -2265,9 +2342,9 @@ rl_completion_matches (const char *text, rl_compentry_func_t *entry_function)
|
||||
char *
|
||||
rl_username_completion_function (const char *text, int state)
|
||||
{
|
||||
#if defined (__WIN32__) || defined (__OPENNT)
|
||||
#if defined (_WIN32) || defined (__OPENNT) || !defined (HAVE_GETPWENT)
|
||||
return (char *)NULL;
|
||||
#else /* !__WIN32__ && !__OPENNT) */
|
||||
#else /* !_WIN32 && !__OPENNT) && HAVE_GETPWENT */
|
||||
static char *username = (char *)NULL;
|
||||
static struct passwd *entry;
|
||||
static int namelen, first_char, first_char_loc;
|
||||
@@ -2282,25 +2359,19 @@ rl_username_completion_function (const char *text, int state)
|
||||
|
||||
username = savestring (&text[first_char_loc]);
|
||||
namelen = strlen (username);
|
||||
#if defined (HAVE_GETPWENT)
|
||||
setpwent ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (HAVE_GETPWENT)
|
||||
while (entry = getpwent ())
|
||||
{
|
||||
/* Null usernames should result in all users as possible completions. */
|
||||
if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (entry == 0)
|
||||
{
|
||||
#if defined (HAVE_GETPWENT)
|
||||
endpwent ();
|
||||
#endif
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else
|
||||
@@ -2316,7 +2387,7 @@ rl_username_completion_function (const char *text, int state)
|
||||
|
||||
return (value);
|
||||
}
|
||||
#endif /* !__WIN32__ && !__OPENNT */
|
||||
#endif /* !_WIN32 && !__OPENNT && HAVE_GETPWENT */
|
||||
}
|
||||
|
||||
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
|
||||
@@ -2327,18 +2398,7 @@ rl_username_completion_function (const char *text, int state)
|
||||
static int
|
||||
complete_fncmp (const char *convfn, int convlen, const char *filename, int filename_len)
|
||||
{
|
||||
register char *s1, *s2;
|
||||
int d, len;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
size_t v1, v2;
|
||||
mbstate_t ps1, ps2;
|
||||
WCHAR_T wc1, wc2;
|
||||
#endif
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (&ps1, 0, sizeof (mbstate_t));
|
||||
memset (&ps2, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
size_t len;
|
||||
|
||||
if (filename_len == 0)
|
||||
return 1;
|
||||
@@ -2346,100 +2406,26 @@ complete_fncmp (const char *convfn, int convlen, const char *filename, int filen
|
||||
return 0;
|
||||
|
||||
len = filename_len;
|
||||
s1 = (char *)convfn;
|
||||
s2 = (char *)filename;
|
||||
|
||||
/* Otherwise, if these match up to the length of filename, then
|
||||
it is a match. */
|
||||
if (_rl_completion_case_fold && _rl_completion_case_map)
|
||||
if (_rl_completion_case_fold)
|
||||
{
|
||||
/* Case-insensitive comparison treating _ and - as equivalent */
|
||||
/* Case-insensitive comparison treating _ and - as equivalent if
|
||||
_rl_completion_case_map is non-zero */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
v1 = MBRTOWC (&wc1, s1, convlen, &ps1);
|
||||
v2 = MBRTOWC (&wc2, s2, filename_len, &ps2);
|
||||
if (v1 == 0 && v2 == 0)
|
||||
return 1;
|
||||
else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
|
||||
{
|
||||
if (*s1 != *s2) /* do byte comparison */
|
||||
return 0;
|
||||
else if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
return 0;
|
||||
s1++; s2++; len--;
|
||||
continue;
|
||||
}
|
||||
wc1 = towlower (wc1);
|
||||
wc2 = towlower (wc2);
|
||||
s1 += v1;
|
||||
s2 += v1;
|
||||
len -= v1;
|
||||
if ((wc1 == L'-' || wc1 == L'_') && (wc2 == L'-' || wc2 == L'_'))
|
||||
continue;
|
||||
if (wc1 != wc2)
|
||||
return 0;
|
||||
}
|
||||
while (len != 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
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 defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
v1 = MBRTOWC (&wc1, s1, convlen, &ps1);
|
||||
v2 = MBRTOWC (&wc2, s2, filename_len, &ps2);
|
||||
if (v1 == 0 && v2 == 0)
|
||||
return 1;
|
||||
else if (MB_INVALIDCH (v1) || MB_INVALIDCH (v2))
|
||||
{
|
||||
if (*s1 != *s2) /* do byte comparison */
|
||||
return 0;
|
||||
s1++; s2++; len--;
|
||||
continue;
|
||||
}
|
||||
wc1 = towlower (wc1);
|
||||
wc2 = towlower (wc2);
|
||||
if (wc1 != wc2)
|
||||
return 0;
|
||||
s1 += v1;
|
||||
s2 += v1;
|
||||
len -= v1;
|
||||
}
|
||||
while (len != 0);
|
||||
return 1;
|
||||
}
|
||||
return (_rl_mb_strcaseeqn (convfn, convlen, filename, filename_len, len, _rl_completion_case_map));
|
||||
else
|
||||
#endif
|
||||
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
|
||||
(convlen >= filename_len) &&
|
||||
(_rl_strnicmp (filename, convfn, filename_len) == 0))
|
||||
return 1;
|
||||
(convlen >= filename_len))
|
||||
return (_rl_strcaseeqn (convfn, filename, len, _rl_completion_case_map));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX - add new _rl_mb_streqn function (like mbsncmp) instead of
|
||||
relying on byte equivalence? */
|
||||
if ((convfn[0] == filename[0]) &&
|
||||
(convlen >= filename_len) &&
|
||||
(strncmp (filename, convfn, filename_len) == 0))
|
||||
@@ -2461,7 +2447,8 @@ rl_filename_completion_function (const char *text, int state)
|
||||
static char *users_dirname = (char *)NULL;
|
||||
static int filename_len;
|
||||
char *temp, *dentry, *convfn;
|
||||
int dirlen, dentlen, convlen;
|
||||
size_t dirlen;
|
||||
int dentlen, convlen;
|
||||
int tilde_dirname;
|
||||
struct dirent *entry;
|
||||
|
||||
@@ -2526,7 +2513,8 @@ rl_filename_completion_function (const char *text, int state)
|
||||
temp = tilde_expand (dirname);
|
||||
xfree (dirname);
|
||||
dirname = temp;
|
||||
tilde_dirname = 1;
|
||||
if (*dirname != '~')
|
||||
tilde_dirname = 1; /* indicate successful tilde expansion */
|
||||
}
|
||||
|
||||
/* We have saved the possibly-dequoted version of the directory name
|
||||
@@ -2545,11 +2533,16 @@ rl_filename_completion_function (const char *text, int state)
|
||||
xfree (users_dirname);
|
||||
users_dirname = savestring (dirname);
|
||||
}
|
||||
else if (tilde_dirname == 0 && rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
else if (rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
{
|
||||
/* delete single and double quotes */
|
||||
/* We already ran users_dirname through the dequoting function.
|
||||
If tilde_dirname == 1, we successfully performed tilde expansion
|
||||
on dirname. Now we need to reconcile those results. We either
|
||||
just copy the already-dequoted users_dirname or tilde expand it
|
||||
if we tilde-expanded dirname. */
|
||||
temp = tilde_dirname ? tilde_expand (users_dirname) : savestring (users_dirname);
|
||||
xfree (dirname);
|
||||
dirname = savestring (users_dirname);
|
||||
dirname = temp;
|
||||
}
|
||||
directory = opendir (dirname);
|
||||
|
||||
@@ -2564,6 +2557,18 @@ rl_filename_completion_function (const char *text, int state)
|
||||
}
|
||||
filename_len = strlen (filename);
|
||||
|
||||
/* Normalize the filename if the application has set a rewrite hook. */
|
||||
if (*filename && rl_completion_rewrite_hook)
|
||||
{
|
||||
temp = (*rl_completion_rewrite_hook) (filename, filename_len);
|
||||
if (temp != filename)
|
||||
{
|
||||
xfree (filename);
|
||||
filename = temp;
|
||||
filename_len = strlen (filename);
|
||||
}
|
||||
}
|
||||
|
||||
rl_filename_completion_desired = 1;
|
||||
}
|
||||
|
||||
@@ -2576,6 +2581,7 @@ rl_filename_completion_function (const char *text, int state)
|
||||
/* Now that we have some state, we can read the directory. */
|
||||
|
||||
entry = (struct dirent *)NULL;
|
||||
convfn = dentry = 0;
|
||||
while (directory && (entry = readdir (directory)))
|
||||
{
|
||||
convfn = dentry = entry->d_name;
|
||||
@@ -2593,17 +2599,20 @@ rl_filename_completion_function (const char *text, int state)
|
||||
if (filename_len == 0)
|
||||
{
|
||||
if (_rl_match_hidden_files == 0 && HIDDEN_FILE (convfn))
|
||||
continue;
|
||||
{
|
||||
if (convfn != dentry)
|
||||
xfree (convfn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (convfn[0] != '.' ||
|
||||
(convfn[1] && (convfn[1] != '.' || convfn[2])))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (complete_fncmp (convfn, convlen, filename, filename_len))
|
||||
break;
|
||||
}
|
||||
else if (complete_fncmp (convfn, convlen, filename, filename_len))
|
||||
break;
|
||||
else if (convfn != dentry)
|
||||
xfree (convfn);
|
||||
}
|
||||
|
||||
if (entry == 0)
|
||||
@@ -2825,7 +2834,7 @@ rl_menu_complete (int count, int 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, cstate;
|
||||
static int delimiter;
|
||||
|
||||
/* The first time through, we generate the list of matches and set things
|
||||
up to insert them. */
|
||||
@@ -2921,7 +2930,7 @@ rl_menu_complete (int count, int ignore)
|
||||
if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items)
|
||||
{
|
||||
rl_ding ();
|
||||
FREE (matches);
|
||||
_rl_free_match_list (matches);
|
||||
matches = (char **)0;
|
||||
full_completion = 1;
|
||||
return (0);
|
||||
|
||||
Reference in New Issue
Block a user