jdx / mise

dev tools, env vars, task runner
https://mise.jdx.dev
MIT License
9.17k stars 248 forks source link

Investigate preexec hook for bash/zsh #1294

Open jdx opened 8 months ago

jdx commented 8 months ago

It might be possible to use rtx activate in scripts if I used preexec instead of precmd in zsh. It looks like this package provides preexec for bash too: https://github.com/rcaloras/bash-preexec

I think I might be able to get rid of the "not_found" handler with this too. rtx could perform the bin check before the command is executed.

Fish probably has a similar hook too

jdx commented 8 months ago

It's unclear to me if preexec actually runs in non-interactive sessions or not, I'll need to experiment. If not, chpwd could work for zsh.

Unfortunately most people use bash for scripts so I'm not sure what solution could be used there.

jdx commented 8 months ago

Possible the biggest benefit here would be not being able to run "scripts" but just for zshrc to be able to use tools. Of course zshrc is a "script" but it's a special kind since it prepares the interactive session and I think users would expect it to work.

joshuataylor commented 8 months ago

I ran into this tonight, there is a slight difference to the way zsh and bash hooks seem to work currently with rtx.

2023.12.40 linux-x64 (460e547 2023-12-28)

zsh has much better support for chpwd, but bash is clunky.

Here's a good example when using bash:

Let's say we have a project at ~/foo/bar:

  1. Create a simple Python project with virtualenv, version of Python doesn't really matter:

.rtx.toml

[tools]
python = {version='3.12', virtualenv='.venv'}
  1. Change trace+debug.
    export RTX_DEBUG=1
    export RTX_LOG_LEVEL=trace

zsh

In zsh (5.9 for me, but should work with whatever), this works correctly:

  1. First, change to the directory so .venv etc is created.
cd ~/foo/bar
  1. Now, in a single line, cd to the parent directory, then delete the .venv directory, then cd back into the bar directory, then echo "hello".

In theory, this should first setup the virtualenv then echo hello.

cd ~/foo && rm -rf bar/.venv && cd bar && echo "hello"

Output (correct):

[DEBUG] ARGS: rtx hook-env -s zsh
[DEBUG] Config {
    Config Files: [
        "~/.config/rtx/config.toml",
    ],
    Installed Plugins: [
        "poetry",
    ],
}
[DEBUG] Toolset:
[DEBUG] ARGS: rtx hook-env -s zsh
[DEBUG] Config {
    Config Files: [
        "~/foo/bar/.rtx.toml",
        "~/.config/rtx/config.toml",
    ],
    Installed Plugins: [
        "poetry",
    ],
}
[DEBUG] Toolset: python@3.11
[INFO] rtx setting up virtualenv at: /home/josh/foo/bar/.venv
[DEBUG] $ ~/.local/share/rtx/installs/python/3.11/bin/python -m venv /home/josh/foo/bar/.venv
hello
[DEBUG] ARGS: rtx hook-env -s zsh
[DEBUG] Config {
    Config Files: [
        "~/foo/bar/.rtx.toml",
        "~/.config/rtx/config.toml",
    ],
    Installed Plugins: [
        "poetry",
    ],
}

bash

  1. But in bash, it seems this is never triggered:
    hello
    [DEBUG] ARGS: rtx hook-env -s bash
    [DEBUG] Config {
    Config Files: [
        "~/foo/bar/.rtx.toml",
        "~/.config/rtx/config.toml",
    ],
    Installed Plugins: [
        "poetry",
    ],
    }
    [DEBUG] Toolset: python@3.11
    [INFO] rtx setting up virtualenv at: /home/josh/foo/bar/.venv
    [DEBUG] $ ~/.local/share/rtx/installs/python/3.11/bin/python -m venv /home/josh/foo/bar/.venv
jdx commented 8 months ago

first, thanks for the writeup, it's helpful to get these kind of user stories. I wonder if chpwd only gets fired on a new prompt display? I would expect that line to work like you did. I'll have to do some experimentation here

https://github.com/jdx/rtx/blob/main/src/shell/zsh.rs#L49-L56

joshuataylor commented 8 months ago

I'll have a play with it, Bash isn't my primary shell but agreed, looks like it only fires on prompt as bash doesn't have that hook.

IMHO, it's outside of the scope of rtx to fix if it's a bash issue, the current way is fine for most usecases.

I'll have more of a dig though.