Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conda documentation #633

Closed
TeaDrinkingProgrammer opened this issue Oct 13, 2023 · 3 comments
Closed

Conda documentation #633

TeaDrinkingProgrammer opened this issue Oct 13, 2023 · 3 comments
Labels
documentation Improvements or additions to documentation question Further information is requested

Comments

@TeaDrinkingProgrammer
Copy link
Contributor

TeaDrinkingProgrammer commented Oct 13, 2023

I am just starting out with Nushell and I love the speed of it and its functional approach to doing things. I am setting up the conda plugin and I have two (newby) questions:

  1. Why are there two Conda scripts? On the surface they are very similar.
  2. It is not immediately clear to me how to enable these scripts by default. The nu_conda script says to "put it in the modules folder in the config folder" but if I put the file in ~/.config/nushell/modules, nothing happens. I looked in the env.nu file and found that putting it in the scripts folder enables me to enable it using use nu_conda.nu, but I would like it to always be on.

Update: I got it working by putting the following in the config, put it is a hardcoded path and feels like a hack

use ~/.config/nushell/scripts/nu_conda.nu
@amtoine amtoine added documentation Improvements or additions to documentation question Further information is requested labels Oct 14, 2023
@TeaDrinkingProgrammer
Copy link
Contributor Author

TeaDrinkingProgrammer commented Oct 14, 2023

Another Update: I couldn't get the nu_conda script to work, but I did get the conda script to work. I have updated the conda.nu script to also work with mamba, which should make the nu_conda script redundant. The main difference is the export-env block at the start, which is pretty much copied from the nu_conda script. I also added a clearer error message for when the command doesn't work and made the base environment a default parameter instead of a nullcheck.

export-env {
    $env.CONDA_INFO = (
        if not (which mamba | is-empty) {
            (mamba info --envs --json | from json)
        } else if not (which conda | is-empty) {
            (conda info --envs --json | from json)
        } else {
            null
        }
    )

    $env.CONDA_ENVS = (
        if not (which mamba | is-empty) {
            (mamba info --envs)
        } else if not (which conda | is-empty) {
            (conda info --envs)
        } else {
            null
        }
    )
}

# Activate conda environment
export def-env activate [
    env_name: string@'nu-complete conda envs' = "base" # name of the environment
] {
    let conda_info = $env.CONDA_INFO
    if ($conda_info == null) {
        print "Error: No Conda or Mamba install could be found in the environment. Please install either and add them to the environment. See: https://www.nushell.sh/book/environment.html for more info"
        return
    }

    let env_dir = if $env_name != "base" {
        if ($env_name | path exists) and (($env_name | path expand) in $conda_info.envs ) {
            ($env_name | path expand)
        } else {
            ((check-if-env-exists $env_name $conda_info) | into string)
        }
    } else {
        $conda_info.root_prefix
    }

    let old_path = (system-path | str join (char esep))

    let new_path = if (windows?) {
        conda-create-path-windows $env_dir
    } else {
        conda-create-path-unix $env_dir
    }

    let virtual_prompt = $'[($env_name)] '

    let new_env = ({
        CONDA_DEFAULT_ENV: $env_name
        CONDA_PREFIX: $env_dir
        CONDA_PROMPT_MODIFIER: $virtual_prompt
        CONDA_SHLVL: "1"
        CONDA_OLD_PATH: $old_path
    } | merge $new_path)

    let new_env = if not (has-env CONDA_NO_PROMPT) {
        let old_prompt_command = if (has-env CONDA_OLD_PROMPT_COMMAND) {
            $env.CONDA_OLD_PROMPT_COMMAND
        } else {
            if (has-env 'PROMPT_COMMAND') {
                $env.PROMPT_COMMAND
            } else {
                ''
            }
        }


        let new_prompt = if (has-env 'PROMPT_COMMAND') {
            if 'closure' in ($old_prompt_command | describe) {
                {|| $'($virtual_prompt)(do $old_prompt_command)' }
            } else {
                {|| $'($virtual_prompt)($old_prompt_command)' }
            }
        } else {
            {|| $'($virtual_prompt)' }
        }

        $new_env | merge {
            CONDA_OLD_PROMPT_COMMAND: $old_prompt_command
            PROMPT_COMMAND: $new_prompt
        }
    } else {
        $new_env | merge { CONDA_OLD_PROMPT_COMMAND: null }
    }


    load-env $new_env
}

# Deactivate currently active conda environment
export def-env deactivate [] {
    let path_name = if "PATH" in $env { "PATH" } else { "Path" }
    $env.$path_name = $env.CONDA_OLD_PATH

    hide-env CONDA_PROMPT_MODIFIER
    hide-env CONDA_PREFIX
    hide-env CONDA_SHLVL
    hide-env CONDA_DEFAULT_ENV
    hide-env CONDA_OLD_PATH

    $env.PROMPT_COMMAND = (
        if $env.CONDA_OLD_PROMPT_COMMAND == null {
            $env.PROMPT_COMMAND
        } else {
            $env.CONDA_OLD_PROMPT_COMMAND
        }
    )
    hide-env CONDA_OLD_PROMPT_COMMAND
}

def check-if-env-exists [ env_name: string, conda_info: record ] {
    let env_dirs = (
        $conda_info.envs_dirs |
        each { || path join $env_name }
    )

    let en = ($env_dirs | each {|en| $conda_info.envs | where $it == $en } | where ($it | length) == 1 | flatten)
    if ($en | length) > 1 {
        error make --unspanned {msg: $"You have enviroments in multiple locations: ($en)"}
    }
    if ($en | length) == 0 {
        error make --unspanned {msg: $"Could not find given environment: ($env_name)"}
    }
    $en.0
}

def 'nu-complete conda envs' [] {
    $env.CONDA_ENVS
    | lines
    | where not ($it | str starts-with '#')
    | where not ($it | is-empty)
    | each {|entry| $entry | split row ' ' | get 0 }
}

def conda-create-path-windows [env_dir: path] {
    # Conda on Windows needs a few additional Path elements
    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 (system-path)]
        | flatten
        | str join (char esep))

    { Path: $new_path }
}

def conda-create-path-unix [env_dir: path] {
    let env_path = [
        ([$env_dir "bin"] | path join)
    ]

    let new_path = ([$env_path $env.PATH]
        | flatten
        | str join (char esep))

    { PATH: $new_path }
}

def windows? [] {
    ((sys).host.name | str downcase) == "windows"
}

def system-path [] {
    if "PATH" in $env { $env.PATH } else { $env.Path }
}

def has-env [name: string] {
    $name in $env
}

@Tiggax
Copy link
Contributor

Tiggax commented Nov 14, 2023

  1. Why are there two Conda scripts? On the surface they are very similar.

conda.nu script is older and nu_conda.nu was made to be faster than the vanilla implementation (see) as it loads the conda essentials into the nushell environments, while conda.nu re-runs the commands multiple times.
There aren't many differences, but in short:
conda.nu takes longer to load, but has more completions,
nu_conda.nu is faster, but you don't have as many auto-completions that are in conda.nu.

2. It is not immediately clear to me how to enable these scripts by default. The nu_conda script says to "put it in the modules folder in the config folder" but if I put the file in ~/.config/nushell/modules, nothing happens. I looked in the env.nu file and found that putting it in the scripts folder enables me to enable it using use nu_conda.nu, but I would like it to always be on.

The readme assumes that the user know some things about the workings of nushell. Mainly:

If you have any questions, feel free to ask, but I would recommended asking in the discord as people are more active there 😄

Footnotes

  1. In your case you need to add ~/.config/nushell/scripts to your $env.NU_LIB_DIR, so that nu knows from what directory you want to load the modules. After they are loaded, you can always call them, or automatically run them by adding use <module.nu> in your env.nu or config.nu.

@TeaDrinkingProgrammer
Copy link
Contributor Author

Thank you for all the help! I finally found the time to make a pull-request for the script: #694

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants