activateしたmiseを一時的に無効化したい

【mise】mise activateでシェルにmiseを組み込む でシェルにmiseを組み込んだ後、一時的に無効化したい場合がある。mise deactivateは、mise activate済みのシェルセッション内でmiseを無効化するコマンドである。

mise deactivateの基本

mise activate済みのシェルでmise deactivateを実行すると、PATHからmiseのshimsディレクトリが取り除かれ、mise管理下のツールが使えなくなる。

$ which jq
/root/.local/share/mise/installs/jq/1.7.1/jq

$ mise deactivate

$ which jq
jq: not found

再びmise activateを実行すれば元の状態に戻る。

$ eval "$(mise activate bash)"
$ which jq
/root/.local/share/mise/installs/jq/1.7.1/jq

activateしていない状態で実行すると警告になる

mise activateを実行していないシェルでmise deactivateを実行しても、何も変化せず警告が表示されるだけである。

$ mise deactivate
mise WARN  mise is not activated in this shell session. Already deactivated or never activated.

仕組み: mise関数がdeactivateを自動的にevalする

mise activateを実行すると、シェル上のmiseはバイナリへの直接呼び出しではなく、シェル関数として再定義される。type miseで実際の定義を確認できる。

$ type mise
mise is a function
mise ()
{
    local command;
    command="${1:-}";
    ...
    case "$command" in
        deactivate | shell | sh)
            if [[ ! " $* " =~ " --help " ]] && [[ ! " $* " =~ " -h " ]]; then
                eval "$(command "$__MISE_EXE" "$command" "$@")";
                return $?;
            fi
        ;;
    esac;
    command "$__MISE_EXE" "$command" "$@"
}

このシェル関数は、サブコマンドがdeactivate(やshell/sh)の場合だけ、mise本体の出力を自動的にevalする。mise deactivateの実体は、PATHの変更などを行うシェルスクリプトを標準出力に返すコマンドであり、シェル関数がそれをevalすることで、現在のシェルの環境変数を直接書き換えている。mise activateしていないシェルでは、このmise関数が定義されておらずバイナリが直接呼ばれるだけなので、出力がevalされず何も反映されない。

mise deactivateが返すスクリプトには、mise関数自体を解除する処理も含まれている。そのためdeactivateを実行した後はtype miseの結果もバイナリへの直接パスに戻り、シェルはmise activateする前の状態に完全に戻れる。