From 7b76a8e662cf72c153ad3baf4e00ad4bd18bf3aa Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Tue, 22 Feb 2022 20:18:50 +0800 Subject: [PATCH] port conda to engine-q (#160) --- engine-q/virtual_environments/README.md | 45 +++++++++++++++++ engine-q/virtual_environments/conda.nu | 49 +++++++++++++++++++ .../virtual_environments/conda_deactivate.nu | 7 +++ 3 files changed, 101 insertions(+) create mode 100644 engine-q/virtual_environments/README.md create mode 100644 engine-q/virtual_environments/conda.nu create mode 100644 engine-q/virtual_environments/conda_deactivate.nu diff --git a/engine-q/virtual_environments/README.md b/engine-q/virtual_environments/README.md new file mode 100644 index 0000000..01efb44 --- /dev/null +++ b/engine-q/virtual_environments/README.md @@ -0,0 +1,45 @@ +# Virtual environment scripts + +The scripts in this directory activate virtual environments for Conda environments. They follow the pattern described in the [Nushell 0.32 +changelog](https://www.nushell.sh/blog/2021-06-01-nushell_0_32.html#environment-loading-lily-mara): + +``` +$ load-env (activate some-env) +``` + +A custom command (`activate`) creates a table with environment variables and +`load-env` is used to load it into the shell's scope. + +In most cases, deactivation is a matter of restoring the PATH variable to the +state before activating the env and removing any additional variables. There are +no environment-specific elements to this, which is why the same deactivation +script can be used for deactivating any environment of a specific type. For +example, `source conda_deactivate.nu` will deactivate any Conda env, there are +no input parameters. + +## Expected Usage + +1. Source an activation script in your `config.nu`. For example, `conda.nu`. + You'll then have the `conda-env` command available. +2. Create an alias for sourcing the appropriate deactivation script: + `alias conda-deactivate = source /path/to/conda_deactivate.nu` +3. Activate with `load-env (conda-env env-name)`. You might want to define some + shorter aliases for both commands, if typing that every time seems like a + hassle. +4. If you're using [Starship](https://starship.rs/), your prompt should reflect the activated env. +5. When done, deactivate with your alias: `conda-deactivate`. + +Look at the script files to find the exact command name for creating an environment table. + +## `conda.nu` + +Limitations: + +- The "root_prefix" might not actually correspond to the correct path to the Conda envs. You can fix + this for your setup by changing how the root prefix is found in the `conda-env` command. +- Nested envs are not well supported. If you activate a Conda env while another one is + activated, new elements will be appended to the PATH, but the other environment + variables will be overwritten. There's no way to then restore the PATH to the state + it was in before activating the *first* env (at least not with this script directly). +- The prompt is not updated by the script. Consider using [Starship](https://starship.rs/) + with the Python prompt element. diff --git a/engine-q/virtual_environments/conda.nu b/engine-q/virtual_environments/conda.nu new file mode 100644 index 0000000..70e477c --- /dev/null +++ b/engine-q/virtual_environments/conda.nu @@ -0,0 +1,49 @@ +def conda-env [env-name] { + let conda-info = (conda info --envs --json | from json) + let suffix = (if $env-name == "base" {""} else {(["envs" $env-name] | path join)}) + let env-dir = ([$conda-info.root_prefix $suffix] | path join) + let old-path = ($env.PATH | str collect (path-sep)) + let new-path = (if (windows?) { (conda-create-path-windows $env-dir) } else { (conda-create-path-unix $env-dir) }) + let new-env = { + CONDA_DEFAULT_ENV: $env-name + CONDA_PREFIX: $env-dir + CONDA_PROMPT_MODIFIER: $"[($env-name)]" + CONDA_SHLVL: "1" + CONDA_OLD_PATH: $old-path + } + $new-env | merge { $new-path } +} + +def conda-create-path-windows [env-dir] { + # 1. Conda on Windows needs a few additional Path elements + # 2. The path env var on Windows is called Path (not PATH) + let env-path = [ + $env-dir + ([$env-dir "Scripts"] | path join) + ([$env-dir "Library" "mingw-w64"] | path join) + ([$env-dir "Library" "bin"] | path join) + ([$env-dir "Library" "usr" "bin"] | path join) + ] + let new-path = ([$env-path $env.PATH] | flatten | str collect (path-sep)) + { + PATH: $new-path + } +} + +def conda-create-path-unix [env-dir] { + let env-path = [ + ([$env-dir "bin"] | path join) + ] + let new-path = ([$env-path $env.PATH] | flatten | str collect (path-sep)) + { + PATH: $new-path + } +} + +def windows? [] { + (sys).host.name == "Windows" +} + +def path-sep [] { + if (windows?) { ";" } else { ":" } +} diff --git a/engine-q/virtual_environments/conda_deactivate.nu b/engine-q/virtual_environments/conda_deactivate.nu new file mode 100644 index 0000000..f1fcbce --- /dev/null +++ b/engine-q/virtual_environments/conda_deactivate.nu @@ -0,0 +1,7 @@ +let path-name = (if ((sys).host.name == "Windows") { "Path" } else { "PATH" }) +let-env $path-name = $env.CONDA_OLD_PATH +hide CONDA_PROMPT_MODIFIER +hide CONDA_PREFIX +hide CONDA_SHLVL +hide CONDA_DEFAULT_ENV +hide CONDA_OLD_PATH