[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Completion of ENV variables seems to be broken - leading slash (or e
From: |
Guillaume Outters |
Subject: |
Re: Completion of ENV variables seems to be broken - leading slash (or even more) is added |
Date: |
Thu, 09 Dec 2021 09:41:32 +0100 |
User-agent: |
Roundcube Webmail/0.8.5 |
Le 2011-03-31 21:47, Chet Ramey a écrit:
On 3/15/11 4:44 PM, Chet Ramey wrote:
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.
I may have a partial solution: not a silver bullet, but making the "90%
solution" go to 95%.
=== Idea ===
The idea behind: the part that the user typed is considered well formed
(sufficently to return matches),
so try to preserve it, and do quote only the completion's additions.
=== Implementation ===
The implementation (attached) of this idea is still imperfect,
because to identify the user-typed part, I simply compare the first
match to the input;
this works in the example's simple case:
as bash completion knows NOT to direxpand, the $HOME from the input is
included in the returned matches,
and so is considered to be preserved; the quoting happens later, on
spaces.
This happens to work on unclosed quotes too (ls "$HOME/sp<TAB>),
because readline starts matching AFTER the quote, so both input and
results start with $HOME/sp (without quote).
=== Limitations ===
This DOES NOT work when 1. user-typed part is fully quoted (ls
"$HOME/space cowboys"/<TAB>),
because readline then passes the quote to the completion function (thus
making input and matches diverge),
nor (theorically) when 2. a space precedes a var (ls $HOME/space\
cowboys/$SUBDIR/f<TAB>),
because the input backslash will be detected as first difference, where
to start quoting.
Thus, due to 1., my proposed patch will not resolve Pedro's case in
https://lists.gnu.org/archive/html/bug-bash/2021-06/msg00131.html
However, a workaround (without direxpand) can be to not close the
quote:
i='a b'
ls "$i/<TAB> # Instead of ls "$i"/
(which btw seems to work without my patch).
=== Going further ===
Maybe readline could go further to resolve 1. (and reach a "97%
solution"?)
by handling specially when, in a closed quote string to complete, the
quote character appears at first and last chars
(or forelast if the last one is a directory separator): then skip the
closing char to handle the string as an unclosed quote.
This would make "$i"/<TAB> work.
To test: "$i/part"/unquoted/"requoted/hey"/<TAB>: how will the middle "
be handled?
=== Optionality ===
The patch can easily be deactivated (shopt?):
it works by computing a common prefix length and passing it to
make_quoted_replacement,
to tell it where to start replacing.
So by forcing a common prefix length of 0, we're back on the current
behavior.
(by the way, this is how the patch itself falls back when it is
confused by the quote_char having changed)
=== History ===
Yes, you read 2011, not 2021!
Sorry for digging up this 10-years-old subject (archeology fun!), from:
https://lists.gnu.org/archive/html/bug-bash/2011-03/msg00235.html
but it seems it has never been resolved,
only circumvented by direxpanding which breaks the beauty of bash
knowing how to preserve a $.
https://lists.gnu.org/archive/html/bug-bash/2015-08/msg00181.html
https://askubuntu.com/questions/70750/how-to-get-bash-to-stop-escaping-during-tab-completion
(and I happen to get the problem every day)
I'm sending this to bug-readline, because it seems to be solvable by
targeting readline only,
but bash would be the first "client" for it (reports are found in
bug-bash),
and in fact I tested it and built the patch on bash's integrated
lib/readline.
=== Tests ===
t=/tmp/btest ; i="$t/space cowboys" ; mkdir -p $t/solid "$i/con"
"$i/contents" "$i/other" "$i/con/solid" "$i/con/space cowboys"
# Each test block lists:
# Typed sequence
Actual result with current bash + readline
Result with current bash + patched readline
# echo $t/<tab>
echo $t/s
echo $t/s
# echo $t/so<tab>
echo $t/solid/
echo $t/solid/
#echo $t/sp<tab>
echo \$t/space cowboys/ # \$ incorrect
echo $t/space cowboys/
# echo $t/space cowboys/<tab>
echo \$t/space cowboys/ # \$ incorrect
echo $t/space cowboys/
#echo "$t/sp<tab>
echo "\$t/space cowboys/" # \$ incorrect, \ unnecessary.
echo "$t/space cowboys"/
# /!\ Note there's still a problem when quotes are closed:
# echo "$t/space cowboys"/<tab>
echo \$t/space cowboys/ # \$ incorrect
echo \$t/space cowboys/ # Incorrect too
# In forelast case the unclosed " made insert_match pass only the
unquoted subpart (starting at $t), which matched with the results.
# In the current case insert_match passes the whole string including
quotes (starting at "$t), thus match ("$t) and replacement ($t) did not
match.
# This is the same as
https://lists.gnu.org/archive/html/bug-bash/2021-06/msg00131.html
# This could perhaps be handled by passing longest_prefix() the
quote_char, so that it accepts comparing "$t" with $t when quote_char is
"
# (like compare_match does).
# Or forcing callers *NOT* to dequote their matches (by temporarily
inhibiting rl_filename_dequoting_function, mapping it to a function that
# removes quotes but not backslashes?).
# /!\ Note that I did *NOT* regress-test against a litteral $ in a
filename.
--
Guillaume
readline.non-intrusive-completion-quoting.8.1.patch
Description: Text Data
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: Completion of ENV variables seems to be broken - leading slash (or even more) is added,
Guillaume Outters <=