postmodern/chruby

Use precmd_functions instead of preexec_functions

sobrinho opened this issue · 5 comments

Description

preexec_functions does not run early enough for chruby work soon enough for RPS1.

Another way of fixing is calling chruby_auto on ~/.zshrc but precmd_functions seems more appropriate. Maybe?

Steps To Reproduce

Steps to reproduce the bug:

  1. Use ZSH
  2. Create .ruby-version with any version
  3. export RPS1="%F{240}host %F{255}%m %F{240}pwd %F{255}%1~ %F{240}vcs %F{255}\${vcs_info_msg_0_:-ッ} %F{240}ruby %F{255}\$(chruby_prompt_info || echo ッ) %F{240}node %F{255}\$(node -v || echo "ッ")"
  4. Open a new tab in that directory

Expected Behavior

Screen Shot 2021-09-15 at 13 55 26

Actual Behavior

Screen Shot 2021-09-15 at 13 54 17

Environment

$ bash --version # if applicable
...
$ zsh --version # if applicable
zsh 5.8 (x86_64-apple-darwin20.0)
$ chruby --version
chruby: 0.3.9
$ ruby --version
...
$ gem --version
...
$ gem env
...

Long ago chruby used to use precmd_functions (issue #40), but those do not execute when in non-interactive mode (ex: zsh -c "cd path/to/file && ruby ..."). Thus I switched to preexec_functions which will execute in both interactive and non-interactive sessions. 9293422

Maybe we should detect non-interactive mode and fallback to using preexec_functions, otherwise use precmd_functions?

Looks like a good approach!

While that I'm calling chruby_auto on .zshrc and it is working as expected, maybe we could call chruby_auto when sourcing the auto file to avoid the machinery?

@sobrinho note that chruby_auto also has to catch multiple cds in non-interactive mode (as well as when a .ruby-version file is created by the previous command), such as when running a shell script under zsh from a cron job.

Also, we should make sure that any changes to chruby_auto zsh support do not introduce deviations in how chruby_auto behaves under bash.

svoop commented

@postmodern Here's another use case.

I've tripped over this issue as well trying to add the current Ruby version to the iTerm status bar:

Screenshot 2021-12-28 at 16 31 13

In case someone is interested in how to do this:

  1. Install iTerm shell integration
  2. Add the following to ~/.zshrc to get the version over to iTerm:
    iterm2_print_user_vars() { iterm2_set_user_var ruby_version "$RUBY_VERSION" }
  3. Add a status bar component of type "Interpolated String" with string value \(user.ruby_version).

Currently, cding into a directory which switches the Ruby won't update the status bar until the next command (preexec), but it works fine when using precmd instead. I guess, a solution along the lines of what you suggested above would do the trick.

I'm adding a call to chruby_auto in my zsh prompt precmd(). Downside is I think I'm now running chruby_auto again when I execute a command as well so it will run twice generally.

Agree that a good solution would be to use precmd for interactive and prexec for non.

I'm generally only running bash in scripts - does Bash also have the same problem?