On 3/15/11 4:44 PM, Chet Ramey wrote:
>> Bash Version: 4.2
>> Patch Level: 7
>> Release Status: release
>>
>> Description:
>> When enter in console "ls $HOME/" and press TAB for
>> completion, then bash add slash for special characters like $ { }
>> When I back to wersion 4.1_p10 then problem is gone. Problem
>> also exists with 4.2_p6 and 4.2_p1 (these veriosn I have checked).
>
> The difference is that bash-4.1 expanded $HOME and left the expansion
> as part of the replacement text. Bash-4.2 tries to leave what the
> user typed alone, but that leads to an inherently ambiguous situation:
> when do you quote the `$' in a filename (or, in this case, a directory
> name)? It could be a shell variable, and it could be a character in
> the filename.
I've attached a patch that applies a heuristic. If the directory name
contains a variable, and bash expands it, it removes the appropriate
characters from the set that causes readline to ask bash to quote the
filename. It's the 90% solution.
It is not perfect: if a character in the filename needs to be quoted,
bash will still quote the `$' in the directory name. It should handle
most of the cases, however.
If you're interested, apply it with `patch -p0' and see whether or not
it works.
Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRU [email protected] http://cnswww.cns.cwru.edu/~chet/
*** ../bash-4.2-patched/bashline.c 2011-01-16 15:32:47.000000000 -0500
--- bashline.c 2011-03-16 17:10:20.000000000 -0400
***************
*** 248,251 ****
--- 250,256 ----
/* )) */
+ static const char *default_filename_quote_characters = "
\t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
+ static char *custom_filename_quote_characters = 0;
+
static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
***************
*** 530,534 ****
/* characters that need to be quoted when appearing in filenames. */
! rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
rl_filename_quoting_function = bash_quote_filename;
--- 535,539 ----
/* characters that need to be quoted when appearing in filenames. */
! rl_filename_quote_characters = default_filename_quote_characters;
rl_filename_quoting_function = bash_quote_filename;
***************
*** 567,570 ****
--- 574,578 ----
rl_directory_rewrite_hook = bash_directory_completion_hook;
rl_ignore_some_completions_function = filename_completion_ignore;
+ rl_filename_quote_characters = default_filename_quote_characters;
}
***************
*** 1280,1283 ****
--- 1288,1293 ----
rl_ignore_some_completions_function = filename_completion_ignore;
+ rl_filename_quote_characters = default_filename_quote_characters;
+
/* Determine if this could be a command word. It is if it appears at
the start of the line (ignoring preceding whitespace), or if it
***************
*** 2703,2720 ****
{
char *local_dirname, *new_dirname, *t;
! int return_value, should_expand_dirname;
WORD_LIST *wl;
struct stat sb;
! return_value = should_expand_dirname = 0;
local_dirname = *dirname;
! if (mbschr (local_dirname, '$'))
! should_expand_dirname = 1;
else
{
t = mbschr (local_dirname, '`');
if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") ==
0)
! should_expand_dirname = 1;
}
--- 2713,2741 ----
{
char *local_dirname, *new_dirname, *t;
! int return_value, should_expand_dirname, nextch, closer;
WORD_LIST *wl;
struct stat sb;
! return_value = should_expand_dirname = nextch = closer = 0;
local_dirname = *dirname;
! if (t = mbschr (local_dirname, '$'))
! {
! should_expand_dirname = '$';
! nextch = t[1];
! /* Deliberately does not handle the deprecated $[...] arithmetic
! expansion syntax */
! if (nextch == '(')
! closer = ')';
! else if (nextch == '{')
! closer = '}';
! else
! nextch = 0;
! }
else
{
t = mbschr (local_dirname, '`');
if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") ==
0)
! should_expand_dirname = '`';
}
***************
*** 2740,2743 ****
--- 2761,2781 ----
dispose_words (wl);
local_dirname = *dirname;
+ /* XXX - change rl_filename_quote_characters here based on
+ should_expand_dirname/nextch/closer. This is the only place
+ custom_filename_quote_characters is modified. */
+ if (rl_filename_quote_characters && *rl_filename_quote_characters)
+ {
+ int i, j, c;
+ i = strlen (default_filename_quote_characters);
+ custom_filename_quote_characters = xrealloc
(custom_filename_quote_characters, i+1);
+ for (i = j = 0; c = default_filename_quote_characters[i]; i++)
+ {
+ if (c == should_expand_dirname || c == nextch || c == closer)
+ continue;
+ custom_filename_quote_characters[j++] = c;
+ }
+ custom_filename_quote_characters[j] = '\0';
+ rl_filename_quote_characters = custom_filename_quote_characters;
+ }
}
else