chruby
chruby copied to clipboard
.ruby-version auto-switch ignored within subshells
I'm not sure if this is the same as / similar to #168, but subshells appear to not use auto-switching.
~$ cd /tmp
/tmp$ chruby
* ruby-2.0.0-p353
ruby-2.1.0
/tmp$ mkdir foo; echo 2.0.0-p353 > foo/.ruby-version
/tmp$ mkdir bar; echo 2.1.0 > bar/.ruby-version
/tmp$ cd foo/
/tmp/foo$ chruby
* ruby-2.0.0-p353 # correct
ruby-2.1.0
/tmp/foo$ cd ../bar/
/tmp/bar$ chruby
ruby-2.0.0-p353
* ruby-2.1.0 # correct
/tmp/bar$ (cd ../foo && chruby)
ruby-2.0.0-p353
* ruby-2.1.0 # wrong
$ bash --version
GNU bash, version 3.2.51(1)-release (x86_64-apple-darwin13)
Copyright (C) 2007 Free Software Foundation, Inc.
OS X 10.9, chruby 0.3.8.
from man bash
:
set [--abefhkmnptuvxBCEHPT] [-o option-name] [arg ...] set [+abefhkmnptuvxBCEHPT] [+o option-name] [arg ...]
... -T If set, any traps on DEBUG and RETURN are inherited by shell functions, command substitutions, and commands executed in a subshell environment. The DEBUG and RETURN traps are nor- mally not inherited in such cases.
I would try set -T
around: https://github.com/postmodern/chruby/blob/master/share/chruby/auto.sh#L30
Any objections to enabling set -T
by default?
I was going to say no objections, but I just tried this and it's messing with my PS1 for some reason.
Narrowed down the problem: I have a DEBUG
trap in my .bashrc
as per #227. So the end of my auto.sh
is actually:
function chruby_trap() {
[[ "$BASH_COMMAND" != "$PROMPT_COMMAND" ]] && chruby_auto
}
if [[ -n "$ZSH_VERSION" ]]; then
if [[ ! "$preexec_functions" == *chruby_auto* ]]; then
preexec_functions+=("chruby_auto")
fi
elif [[ -n "$BASH_VERSION" ]]; then
set -T
trap chruby_trap DEBUG
fi
This is almost identical to the existing auto.sh
provided by chruby but I expose chruby_trap
. Then my .bashrc
uses this to reset colouring:
# Reset color for command output and call chruby's trap function
trap 'echo -ne "\033[0m" && chruby_trap' DEBUG
Since my PS1
uses __git_ps1
PS1="some stuff \$(__git_ps1 '::%s') other stuff"
the set -T
forces echo -ne
to fire since now the DEBUG
trap is inherited. The end result being that a PS1
of
PS1="abcdefghijklmnop\$(__git_ps1 '::%s')1234567890"
will cause a new terminal to appear as
1234567890[k]lmnop
where [k]
indicates the cursor is over the k
character, and typing will type over the klmnop
portion.
So basically:
-
__git_ps1
inPS1
with other colour codes. - Existing
DEBUG
trap outside of chruby which inserts\033[0m
to reset colouring for stdout. - Inheriting trap causes existing
DEBUG
to fire when__git_ps1
is executed.
I suppose an argument is that this is simply not something chruby
can work around and my desire to have certain colouring in my PS1
+ reset colouring for output through echo -ne "\033[0m"
in a DEBUG
trap, but it would be nice to have them coexist.
I suppose there might be a way to call set +T
and then set -T
around my PS1
to bypass it for the __git_ps1
call?
you could try to use a wrapper that checks what function is called and do reset color only in some cases, or ignoring the __git_ps1
function:
[[ " ${FUNCNAME[*]} " == *" __git_ps1 "* ]]
@mpapis that's awesome, thanks!
I'm :+1: on set -T
, even before I had that workaround, since I don't think this will apply to many people.
set -T
seems to only fix Bash. I have a test in my fork's branch that fails for zsh:
SHELL=`which bash` ./test/runner
>>> Running tests under /bin/bash in interactive-mode ...
>>> Running ./test/chruby_auto_test.sh ...
[...]
test_chruby_auto_within_subshells
[...]
Ran 13 tests.
OK
SHELL=`which zsh` ./test/runner
>>> Running tests under /usr/bin/zsh in interactive-mode ...
>>> Running ./test/chruby_auto_test.sh ...
[...]
test_chruby_auto_within_subshells
ASSERT:did not switch Ruby when subshell entered versioned directory expected:</home/travis/build/aprescott/chruby/test/rubies/ruby-1.9.3-p429> but was:<>
[...]
Ran 13 tests.
FAILED (failures=1)
I don't know zsh enough to get this passing, but if someone lets me know then I can update my branch and PR a fix for this bug.
that might be unsetopt localtraps
try:
if [[ -n "${ZSH_VERSION:-}" ]]
then unsetopt localtraps
else set -T
fi
an important point about Zsh is that it has to be run in top scope, not in a function that gets called from shell
After doing some testing, the trap DEBUG
and preexec_functions
hook are being inherited by the sub-shell.
bash
$ trap -p DEBUG
trap -- '[[ "$BASH_COMMAND" != "$PROMPT_COMMAND" ]] && chruby_auto' DEBUG
$ (trap -p DEBUG)
trap -- '[[ "$BASH_COMMAND" != "$PROMPT_COMMAND" ]] && chruby_auto' DEBUG
zsh
% eval 'echo ${preexec_functions[@]}'
chruby_auto
% (eval 'echo ${preexec_functions[@]}')
chruby_auto
I believe the reason why the chruby_auto function isn't working, is because the sub-shell command is being treated as one single command, not individual commands which chruby_auto runs before.
FWIW adding set -T
before line 30 in auto.sh
fixed my non-functioning auto-switching problem.