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    c...@case.edu    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

Reply via email to