[Top][All Lists]

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

Re: Oddities when tab-completing filenames containing backticks

From: Chet Ramey
Subject: Re: Oddities when tab-completing filenames containing backticks
Date: Sat, 24 Oct 2009 16:17:00 -0400
User-agent: Thunderbird (Macintosh/20090812)

address@hidden wrote:
> 2009/10/16 Chet Ramey <address@hidden>:
>> You need to remember that readline understands the characters in
>> rl_completer_quote_characters as those which, in pairs, delimit quoted
>> substrings in the line.  It performs completion (allowing the application
>> to take first crack, of course) on the substring, using the text after
>> the open quote.
> Then it is a bug in readline that it is incapable of
> properly handling nested quotes.

Not really, but I can fix it in bash, and I will change bash-4.1 so it
doesn't try to perform command substitution completion when completing
text beginning with a backquote inside a single-quoted string.

>> The other thing to keep in mind is that readline doesn't look past point
>> when performing completion -- it only considers characters from the
>> beginning of the line or a quote character up to point.
> If it considered characters from the beginning of the line,
> then there would be no issue.  The backtick is inside an
> open single quote, and the backtick is *not* a special
> character under that circumstance -- it's no more special
> to Bash than the letter "j" inside an open single quote.

Thank you, I'm familiar with the syntax.  I think you missed the point,
though:  Readline doesn't check characters after point when deciding
the word to complete.

>>> Repeat-By:
>>>    1) '`<tab>      This causes all commands available on the system to be
>>>                    listed such as `awk `bash etc., even though it's inside
>>>                    single quotes.
>> Readline does completion on substrings; it passes ` to the bash completion
>> code, which performs command completion.
> Again, a backtick is no more of a special character than the
> letter "a" inside an open single quote.  This is incorrect
> behaviour.

This one I can fix inside bash.  Readline makes the appropriate information
available to the calling application.

>>>    2) '`text<tab>  This completes the filename, but it does not insert a
>>>                    trailing single quote as tab-completion would usually do.
>> Bash receives "`text"
> What do you mean by that?  Didn't you say Bash is sending
> that to readline?

No.  Readline allows the calling application to perform application-
specific completion before it performs filename completion.  When it
does so, in this case, it considers the text after the single quote
and sends it to the application for completion.

>> does command completion on `text'
> How would it do completion on something that isn't there?

I'm not sure you understood when I meant.  When bash-4.0 receives "`text"
for possible completion from readline, it decides (however incorrectly)
that it should perform command completion, and does so on "text".

>> and suppresses the append of the close quote,
>> since it's usually wrong in this case.
> What appended closing quote, there is none?

Ummm...correct.  I just said bash suppressed the closing quote when it
thinks it's performing command completion inside backquotes.  There's
usually more of the command to come, and most of the time the user will
just erase any closing backquote or single quote.

> If you go:
>    # ls '/usr/bin/mpg3<tab>
> You get the following:
>    # ls '/usr/bin/mpg321'
> But if you have a file called /tmp/`rubble.txt and go:
>    # ls '/tmp/`rub<tab>
> Then you get:
>    # ls '/tmp/`rubble.txt
> No closing single quote.

Right again.  Since bash decided that it could perform command completion,
it suppressed the closing quote.  When bash is fixed to not attempt
command completion when inside a single-quoted string, it will insert the
single quote after performing filename completion.

>>>    3) '`dir<tab>   This completes the directory name and adds the trailing
>>>                    forward slash, but not the trailing single quote.
>> Again, appending the trailing single quote without the trailing ` is
>> generally going to be wrong.
> Please explain yourself.  

I did above.  When bash performs command completion inside a command
substitution, it suppresses the appending of the closing quote.

>>>    4) 'text`<tab>  This completes the filename and closes the single quote
>>>                    as expected.
>> Interesting.  I don't get this behavior.
> This behaviour makes snese, because it is the correct
> behaviour.  The other behaviour above is the incorrect
> behaviour.  A backtick is *not* special to Bash from
> inside single quotes.

I get the behavior you do when there is an existing file whose name
starts with "text`".  There wasn't any indication of the existing file
in your original message.  If there isn't such a file, bash doesn't
attempt command completion, but doesn't successfully complete anything,

>>>    5) '`text<tab>' When using tab-completion inside single quotes on a
>>>                    filename beginning with a backtick, then it completes
>>>                    the filename and adds an additional closing single quote,
>>>                    e.g. '`filename.txt''
>> Also interesting.  I get normal command completion without any closing
>> quote appended.
> Are you following my example exactly? 

The steps you provide are not the same as the example above.  If the
substring to be completed begins with a backquote, as above (but not as
in your following example, where it begins with "/tmp"), bash attempts
command completion, even when within single quotes.

When I use a filename that doesn't begin with a backquote, I get the
doubled single quote you see.  I will have to see if I can fix it in
readline.  The problem is that, as I stated above, readline doesn't
look at the characters beyond point when deciding how to complete the
filename.  In this case, that means that readline decides it needs to
insert "'/tmp/`example.txt'", but notices that the existing text in
rl_line_buffer already has a single quote, so it skips over the single
quote at the beginning of the replacement text.  It doesn't pay
attention to the corresponding single quote after point.  Maybe it will
be enough to check the character at point: if it's the same quote
character, readline can skip over the quote at the end of the replacement

> Step 1:
>    touch '/tmp/`example.txt'<enter>

>>>    6) '`dir<tab>'  When using tab-completion inside single quotes on a
>>>                    directory name beginning with a backtick, then it
>>>                    completes the directory name and adds an additional
>>>                    closing single quote after the directory name and before
>>>                    the forward slash, e.g. '`directory'/'
>> I don't see this behavior either.
> Steps to reproduce:

Again, the text above doesn't match the text used in your example.  I
think the same change as for item 5 will work for this, though, since
the decision on the closing quote is made before the decision whether
or not to append the `/', you will probably get "'/tmp/`directory'/",
which may be a minor annoyance.

``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRU    address@hidden    http://cnswww.cns.cwru.edu/~chet/

reply via email to

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