# Copyright (C) 2012 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause

# bash_completion for conda.
#
# This was initially based on completion support for `fish`, but later extended
# complete options for subcommands and files/dirs/paths as appropriate.
#
# Dynamic option lookup uses a cache that persists for the duration of the shell. If you
# Updates to the conda command options are relatively rare, but there is a small chance
# that this cache will hold incorrect/incomplete values. A restart of your shell will
# fix this.

# If this completion file is 'installed' under
#
#   /etc/bash_completion.d/,
#   /usr/share/bash-completion/completions/, or
#   ~/.local/share/bash-completion/completions/,
#
# rather than being managed via the `conda shell.bash hook`, then this file may
# be sourced before conda is setup.  To support this we allow for a potential
# late initiallization of the CONDA_ROOT and CONDA_SOURCE environment
# variables.


function __comp_conda_ensure_root() {
    if [[ -z "${CONDA_SOURCE-}" && -n "${CONDA_EXE-}" ]] ; then
        if [[ -n "${_CE_CONDA-}" && -n "${WINDIR-}" ]]; then
            CONDA_ROOT=$(\dirname "${CONDA_EXE}")
        else
            CONDA_ROOT=$(\dirname "${CONDA_EXE}")
            CONDA_ROOT=$(\dirname "${CONDA_ROOT}")
        fi
        CONDA_SOURCE=$(
            cat - <<'            EOF' | sed 's/^ *: //g' | ${CONDA_PYTHON_EXE} -
            : from __future__ import print_function
            : import os
            : import conda
            : print(os.path.dirname(conda.__file__))
            EOF
        )
    fi
}

function __comp_conda_commands () {
    for f in $CONDA_SOURCE/cli/main_*.py
    do
        \expr match "$f" '.*_\([a-z]\+\)\.py$'
    done

    for f in $CONDA_ROOT/bin/conda-*
    do
        if test -x "$f" -a ! -d "$f"
        then
            \expr match "$f" '^.*/conda-\(.*\)'
        fi
    done
    echo activate
    echo deactivate
}

function __comp_conda_env_commands() {
    for f in $CONDA_SOURCE/../conda_env/cli/main_*.py
    do
        \expr match "$f" '.*_\([a-z]\+\)\.py$'
    done
}

function __comp_conda_envs() {
    script=$(
        cat - <<'        EOF' | sed 's/^ *: //g'
        : from __future__ import print_function;
        : import json, os, sys;
        : from os.path import isdir, join;
        : print('\n'.join(
        :    d for ed in json.load(sys.stdin)['envs_dirs'] if isdir(ed)
        :    for d in os.listdir(ed) if isdir(join(ed, d))));
        EOF
    )
    conda config --json --show envs_dirs | python -c "$script"
}

function __comp_conda_packages() {
    conda list | awk 'NR > 3 {print $1}'
}

function __comp_conda_cmds_str() {
    # get a list of commands
    \local cmd cmds
    for cmd in $*; do
        case "$cmd" in
            -*) continue ;;
            *) cmds="$cmds $cmd" ;;
        esac
    done
    cmds=${cmds# }
    echo $cmds
}

# cache conda subcommand help lookups for the duration of the shell
unset __comp_conda_cache
declare -A __comp_conda_cache

__comp_conda_ensure_root

_comp_conda()
{
    \local cur prev words cword
    _init_completion || return

    __comp_conda_ensure_root

    \local word_list cmds_str
    if [[ $cur == -* ]]; then
        # get the current list of commands as a string
        cmds_str="$(__comp_conda_cmds_str ${words[*]})"
        if [[ -z ${__comp_conda_cache[$cmds_str]} ]]; then
            # parse the output of command help to get completions
            word_list=$($cmds_str --help 2>&1 | _parse_help -)
            __comp_conda_cache[$cmds_str]=$word_list
        else
            word_list=${__comp_conda_cache[$cmds_str]}
        fi
    else
        case "$prev" in
            conda)
                word_list=$(__comp_conda_commands)
                ;;
            env)
                word_list=$(__comp_conda_env_commands)
                ;;
            activate)
                if [[ $cur == ./* || $cur == /* ]]; then
                    # complete for paths
                    COMPREPLY=( $(compgen -d -- "$cur" ) )
                else
                    word_list=$(__comp_conda_envs)
                fi
                ;;
            remove|uninstall|upgrade|update)
                word_list=$(__comp_conda_packages)
                ;;
            --name|--clone)
                word_list=$(__comp_conda_envs)
                ;;
            --*-file|--file|--which|convert)
                # complete for files
                COMPREPLY=( $(compgen -f -- "$cur" ) )
                ;;
            --*-dir|--*-folder|--subdir|--prefix|--cwd|index)
                # complete for directories
                COMPREPLY=( $(compgen -d -- "$cur" ) )
                ;;
            verify)
                # complete for paths
                COMPREPLY=( $(compgen -fd -- "$cur" ) )
                ;;
        esac
    fi
    if [[ -n $word_list ]]; then
        COMPREPLY=( $(compgen -W '$word_list' -- "$cur" ) )
    fi
} &&
complete -F _comp_conda conda

# vim: ft=sh
