mirror of
https://github.com/sheumann/hush.git
synced 2024-10-12 01:24:10 +00:00
lineedit: fix tab-completion of filenames with spaces
Using ash in busybox git version dea28e1e
, tab completion doesn't seem
to work properly for filenames that have special characters (such as
spaces) in them. For example, with filenames "foo bar" and "foo zap",
typing "ls fo<TAB>" correctly expands to "ls foo\ ", but then
continuing to type "b<TAB>" will produce "ls foo\ bbar", which is not
correct (the 'b' is duplicated).
Signed-off-by: Mike Shal <marfey@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
7c6ed78aaa
commit
f3763033e4
@ -584,6 +584,12 @@ static void input_forward(void)
|
||||
|
||||
#if ENABLE_FEATURE_TAB_COMPLETION
|
||||
|
||||
//FIXME:
|
||||
//needs to be more clever: currently it thinks that "foo\ b<TAB>
|
||||
//matches the file named "foo bar", which is untrue.
|
||||
//Also, perhaps "foo b<TAB> needs to complete to "foo bar" <cursor>,
|
||||
//not "foo bar <cursor>...
|
||||
|
||||
static void free_tab_completion_data(void)
|
||||
{
|
||||
if (matches) {
|
||||
@ -1015,13 +1021,18 @@ static void showfiles(void)
|
||||
}
|
||||
}
|
||||
|
||||
static char *add_quote_for_spec_chars(char *found)
|
||||
static const char *is_special_char(char c)
|
||||
{
|
||||
return strchr(" `\"#$%^&*()=+{}[]:;'|\\<>", c);
|
||||
}
|
||||
|
||||
static char *quote_special_chars(char *found)
|
||||
{
|
||||
int l = 0;
|
||||
char *s = xzalloc((strlen(found) + 1) * 2);
|
||||
|
||||
while (*found) {
|
||||
if (strchr(" `\"#$%^&*()=+{}[]:;'|\\<>", *found))
|
||||
if (is_special_char(*found))
|
||||
s[l++] = '\\';
|
||||
s[l++] = *found++;
|
||||
}
|
||||
@ -1085,19 +1096,30 @@ static NOINLINE void input_tab(smallint *lastWasTab)
|
||||
free_tab_completion_data();
|
||||
|
||||
# if ENABLE_FEATURE_USERNAME_COMPLETION
|
||||
/* If the word starts with `~' and there is no slash in the word,
|
||||
/* If the word starts with ~ and there is no slash in the word,
|
||||
* then try completing this word as a username. */
|
||||
if (state->flags & USERNAME_COMPLETION)
|
||||
if (match_buf[0] == '~' && strchr(match_buf, '/') == NULL)
|
||||
match_pfx_len = complete_username(match_buf);
|
||||
# endif
|
||||
/* Try to match a command in $PATH, or a directory, or a file */
|
||||
/* If complete_username() did not match,
|
||||
* try to match a command in $PATH, or a directory, or a file */
|
||||
if (!matches)
|
||||
match_pfx_len = complete_cmd_dir_file(match_buf, find_type);
|
||||
|
||||
/* Account for backslashes which will be inserted
|
||||
* by quote_special_chars() later */
|
||||
{
|
||||
const char *e = match_buf + strlen(match_buf);
|
||||
const char *s = e - match_pfx_len;
|
||||
while (s < e)
|
||||
if (is_special_char(*s++))
|
||||
match_pfx_len++;
|
||||
}
|
||||
|
||||
/* Remove duplicates */
|
||||
if (matches) {
|
||||
unsigned i;
|
||||
unsigned n = 0;
|
||||
unsigned i, n = 0;
|
||||
qsort_string_vector(matches, num_matches);
|
||||
for (i = 0; i < num_matches - 1; ++i) {
|
||||
//if (matches[i] && matches[i+1]) { /* paranoia */
|
||||
@ -1112,6 +1134,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
|
||||
matches[n++] = matches[i];
|
||||
num_matches = n;
|
||||
}
|
||||
|
||||
/* Did we find exactly one match? */
|
||||
if (num_matches != 1) { /* no */
|
||||
char *cp;
|
||||
@ -1133,7 +1156,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
|
||||
goto ret; /* no */
|
||||
}
|
||||
*cp = '\0';
|
||||
cp = add_quote_for_spec_chars(chosen_match);
|
||||
cp = quote_special_chars(chosen_match);
|
||||
free(chosen_match);
|
||||
chosen_match = cp;
|
||||
len_found = strlen(chosen_match);
|
||||
@ -1141,7 +1164,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
|
||||
/* Next <tab> is not a double-tab */
|
||||
*lastWasTab = 0;
|
||||
|
||||
chosen_match = add_quote_for_spec_chars(matches[0]);
|
||||
chosen_match = quote_special_chars(matches[0]);
|
||||
len_found = strlen(chosen_match);
|
||||
if (chosen_match[len_found-1] != '/') {
|
||||
chosen_match[len_found] = ' ';
|
||||
|
Loading…
Reference in New Issue
Block a user