On 3/5/14 5:01 PM, Albert Shih wrote:

> If you got a file name begin with "(" the completion didn't work.
> 
> For example if I do
> 
>     mkdir emptydir
>     cd emptydir
>     touch \(\)
>     rm + Tab 
> 
> don't give me anything. 

This is actually a general problem with empty completions (typing TAB at
the end of a line) in general with bash-4.3 and the latest versions of the
bash-completion package.

The problem, as it usually is, is mismatched assumptions.  There was a
change between bash-4.2 and bash-4.3 prompted by this message thread
from 2011 (!):

http://lists.gnu.org/archive/html/bug-bash/2011-10/msg00059.html

The problem, in a nutshell, was that complete and compgen need to act
differently based on how they are invoked: from the command line for
testing, and from within readline's completion engine.  When invoked on
the command line, the arguments are run through the usual word
expansions; when run via the programmable completion code, they are not.
That has implications for quoted words, and the bash-completion package
assumes that the programmable completion code unconditionally dequotes
all words passed to complete and compgen that are supposed to be treated
as filenames (as the bash-4.2 code did).

Here is a message describing what I ultimately put into bash-4.3:

http://lists.gnu.org/archive/html/bug-bash/2011-10/msg00068.html

This works, as far as it goes, but the problem with it is that it missed
this particular case.  When the original word doesn't have quotes (so
readline doesn't find any quotes and doesn't set the flag indicating that),
but the argument passed to compgen has quotes and therefore needs
dequoting, the bash-4.3 code doesn't dequote it.  The bash-4.2 code, since
it dequoted unconditionally, doesn't have this problem.

I've attached a patch that solves the problem with "empty" completions.
It's a start, but it may require more work to capture all of the cases.

(Frankly, I'm disappointed that this slipped through into bash-4.3.  The
change was made back in 2011, and has been in the devel tree since early
2012.  Bash-4.3 testing versions were available for almost a year.)

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.3/pcomplete.c	2013-08-26 15:23:45.000000000 -0400
--- pcomplete.c	2014-03-07 13:12:42.000000000 -0500
***************
*** 184,187 ****
--- 184,188 ----
  COMPSPEC *pcomp_curcs;
  const char *pcomp_curcmd;
+ const char *pcomp_curtxt;
  
  #ifdef DEBUG
***************
*** 754,757 ****
--- 755,767 ----
  	  dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
  	}
+       /* Intended to solve a mismatched assumption by bash-completion.  If
+ 	 the text to be completed is empty, but bash-completion turns it into
+ 	 a quoted string ('') assuming that this code will dequote it before
+ 	 calling readline, do the dequoting. */
+       else if (iscompgen && iscompleting &&
+ 	       pcomp_curtxt && *pcomp_curtxt == 0 &&
+ 	       text && (*text == '\'' || *text == '"') && text[1] == text[0] && text[2] == 0 && 
+ 	       rl_filename_dequoting_function)
+ 	  dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
        else
  	dfn = savestring (text);
***************
*** 1523,1527 ****
  {
    COMPSPEC *cs, *oldcs;
!   const char *oldcmd;
    STRINGLIST *ret;
  
--- 1533,1537 ----
  {
    COMPSPEC *cs, *oldcs;
!   const char *oldcmd, *oldtxt;
    STRINGLIST *ret;
  
***************
*** 1546,1552 ****
--- 1556,1564 ----
    oldcs = pcomp_curcs;
    oldcmd = pcomp_curcmd;
+   oldtxt = pcomp_curtxt;
  
    pcomp_curcs = cs;
    pcomp_curcmd = cmd;
+   pcomp_curtxt = word;
  
    ret = gen_compspec_completions (cs, cmd, word, start, end, foundp);
***************
*** 1554,1557 ****
--- 1566,1570 ----
    pcomp_curcs = oldcs;
    pcomp_curcmd = oldcmd;
+   pcomp_curtxt = oldtxt;
  
    /* We need to conditionally handle setting *retryp here */

Reply via email to