bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: compgen gets confused when trying to complete ambiguous special char


From: Chet Ramey
Subject: Re: compgen gets confused when trying to complete ambiguous special char
Date: Mon, 17 Mar 2008 17:56:49 -0400
User-agent: Thunderbird 2.0.0.12 (Macintosh/20080213)

Mika Fischer wrote:
* Chet Ramey <address@hidden> [2008-03-17 18:47]:
For historical reasons, complete/compgen dequote the filename they're
passed, removing backslash escapes and interpreting embedded quoted
substrings.

Yes. I've run into this problem now several times while trying to fix
the bugs in bash_completion. As far as I can see it's impossible to do
the completion the same way as the built-in completion.

It's probably time to take the dequoting out of compgen when it's not
run from the readline completion code.

When my ${COMP_WORDS[COMP_CWORD]} is STORE\' and I have the following
files in $PWD:
STORE'N'GO
STORE\'N\'GO

Then I have a hard time getting this information to compgen. The only
way I can think of is to do the shell-quoting myself and then let
compgen strip it away again. This is obviously not very nice, certainly
error-prone and maybe even impossible. Do you agree?

It's not really possible.  One of the things that's wrong with the bash
helper function that dequotes filenames for readline is that it doesn't
implement shell quoting rules.

(One of the things bash should do when it does that is to be better
about obeying the shell rules about backslash-escaped characters and
double quotes, but that doesn't matter for this example

Can you elaborate on the differences in case they're the cause of other
strange behaviours?

1.  Backslashes should not be stripped within single quotes.

2.  Backslashes should only be stripped within double quotes if they're
    followed by one of $ ` " \ <newline>

Are you referring to compgen or some function in bash_completion?

The filename dequoting function that's part of the bash readline support.

One possible change is to inhibit filename dequoting when compgen
isn't run via a readline keybinding, but I'm not sure how much of an
effect it will have on the problem, which occurs when completing.  It
will make the behavior when run on the command line closer to what the
completion will do.  This is an easy change; contact me if you're
interested in evaluating it.

Yes, that would be nice. I'm willing to test it.

OK, I attached a patch.

Another possibility would be to provide means to do shell-quoting and
de-quoting from within bash. Or is this possible in a safe and resonably
easy way even now?

There's no reason to do shell quoting from within bash; the following
does the job:

quote()
{
    echo \'${1//\'/\'\\\'\'}\'
}

and its inverse:

dequote()
{
    eval echo "$1"
}

That handles only quote characters; I didn't test it with parameter and
variable expansion, though it should work.

Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                       Live Strong.  No day but today.
Chet Ramey, ITS, CWRU    address@hidden    http://cnswww.cns.cwru.edu/~chet/
*** ../bash-3.2-patched/pcomplete.c     2006-07-27 09:39:02.000000000 -0400
--- pcomplete.c 2008-03-17 14:10:07.000000000 -0400
***************
*** 689,704 ****
        FREE (dfn);
        /* remove backslashes quoting special characters in filenames. */
        if (rl_filename_dequoting_function)
        {
- #if 0
-         qc = (text[0] == '"' || text[0] == '\'') ? text[0] : 0;
- #else
          /* Use rl_completion_quote_character because any single or
             double quotes have been removed by the time TEXT makes it
             here, and we don't want to remove backslashes inside
             quoted strings. */
!         qc = rl_dispatching ? rl_completion_quote_character : 0;
! #endif
!         dfn = (*rl_filename_dequoting_function) ((char *)text, qc);
        }
        else
--- 689,703 ----
        FREE (dfn);
        /* remove backslashes quoting special characters in filenames. */
+ #if 1
+       if (RL_ISSTATE (RL_STATE_COMPLETING) && rl_filename_dequoting_function)
+ #else
        if (rl_filename_dequoting_function)
+ #endif
        {
          /* Use rl_completion_quote_character because any single or
             double quotes have been removed by the time TEXT makes it
             here, and we don't want to remove backslashes inside
             quoted strings. */
!         dfn = (*rl_filename_dequoting_function) ((char *)text, 
rl_completion_quote_character);
        }
        else

reply via email to

[Prev in Thread] Current Thread [Next in Thread]