Closed devkev closed 1 year ago
This is not an issue specific to bash-completion. I think the general solution is just to save the value of $_
to another variable in PROMPT_COMMAND
and restore it just before running the command. E.g.,
# bashrc
PROMPT_COMMAND=$'_devkev_save_lastarg=$_\n'$PROMPT_COMMAND
bind -x '"\xC0\1":: "$_devkev_save_lastarg"'
bind '"\xC0\2": accept-line'
bind '"\r": "\xC0\1\xC0\2"'
In this way, you do not have to care about anything about $_
in the programmable completions, bind -x
functions, etc.
Thanks! That's an excellent workaround for this problem, that I would never have thought of (and only barely understand). Closing this out.
Describe the bug
As per the bash manpage, the
$_
bash variable:This can be useful for referring to the final arg of the previous command, without having to re-type it, and without having to muck around editing history lines. See for example the repro below.
Unfortunately, invoking bash-completion (ie. by pressing Tab) causes simple commands to be run, which causes the value of
$_
to be overwritten. This manifests as commands which fail - or more usually, succeed but with highly unexpected (and potentially dangerous) results - if tab completion has been used on the input line, but work just fine otherwise. See the repro below.To reproduce
See https://asciinema.org/a/cHIfI9Fv6k4TLRt5JtywxShlN . This shows first the expected behaviour (with plain bash completion), and then the behaviour with bash-completion loaded.
Repro:
Expected behavior
As above - the value of
$_
should be unaffected by bash-completion invocations.Versions (please complete the following information)
echo "$BASH_VERSION"
: 5.1.16(1)-release(IFS=.; echo "${BASH_COMPLETION_VERSINFO[*]}")
: 2 11Additional context
I've encountered a similar problem before when using a DEBUG trap to show the current command in my terminal title bar. In that case the simple and easy solution was to deliberately pass an ignored final arg of
"$_"
to the function, ie.I expect something similar can be done in this case. Changing every
_filedir
call to_filedir "$_"
(and similarly for every other function call / command) seems exceptionally painful. A more general solution might be to adjust every "entry point function" (eg._longopt
,_service
, etc) so that the first thing is does islocal last="$_"
, and the last thing it does is: "$last"
(though early returns make this "last thing" a pain, and_longopt
alone has 7 of them). However, I'm not sure if there's a strategy which can make this work easily for any/every possible entry function. It would be nice ifcomplete -F
could somehow pass extra args to the function (or even set vars), but this seems impossible. So the least bad possibility is probably doing something like:And perhaps a wrapper function around the
complete
builtin could automatically define and inject such a shim whenevercomplete -F
is used (ugh).