postmodern / chruby

Changes the current Ruby
MIT License
2.87k stars 190 forks source link

Value of $_ overwritten in bash #367

Open HaleTom opened 8 years ago

HaleTom commented 8 years ago

In bash, $_ should be “the last argument of the last command executed”

Instead, this is overwritten:

> @ravi@boxy:~/.dotfiles(master* u+1)$ echo "This argument should be printed"
> This argument should be printed
> @ravi@boxy:~/.dotfiles(master* u+1)$ echo $_
> chruby_auto
> @ravi@boxy:~/.dotfiles(master* u+1)$ 
skull-squadron commented 7 years ago

The before-command hook in bash trap ... DEBUG causes many state changes.

zsh seems to work okay, but not always an option.

Perhaps bash needs shell commands for pushing/popping state (somewhat fine-grained) so that only specified target variables are mutated?

HaleTom commented 7 years ago

$? is fine, It's only $_.

HaleTom commented 7 years ago

I raised this as a question on SO.

It's possible that this is a bash bug, see the zsh example working at: bash: preserve $_ in a DEBUG trap

HaleTom commented 7 years ago

Solution given on SO, I'll make a PR.

skull-squadron commented 7 years ago

The SO answer seems to be incomplete as only the last argument is captured in old_.

bash-4.4$ f() { local old_="$1"; echo "=== $old_ ==="; : "$old_"; }; trap 'f "$_"' DEBUG
bash-4.4$ ls -lart >/dev/null
=== DEBUG ===
bash-4.4$ echo "$_"
=== -lart ===
-lart
bash-4.4$

Although s/1/@/ doesn't help, there might be a solution or there's a bash bug/unhandled edge-case "feature."

HaleTom commented 7 years ago

@steakknife, the bash manual says:

expands to the last argument to the previous command, after expansion

So I assert that the SO answer is correct.