#compdef -default-

# argcomplete global completion loader for zsh and bash
# Copyright 2012-2023, Andrey Kislyuk and argcomplete contributors.
# Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info.

# Note: both the leading underscore in the name of this file and the first line (compdef) are required by zsh

# In zsh, this file is autoloaded and used as the default completer (_default).
# There are many other special contexts we don't want to override
# (as would be the case with `#compdef -P *`).
# https://zsh.sourceforge.io/Doc/Release/Completion-System.html

# Copy of __expand_tilde_by_ref from bash-completion
# ZSH implementation added
__python_argcomplete_expand_tilde_by_ref () {
    if [ -n "${ZSH_VERSION-}" ]; then
        if [ "${(P)1[1]}" = "~" ]; then
            eval $1="${(P)1/#\~/$HOME}";
        fi
    else
        if [ "${!1:0:1}" = "~" ]; then
            if [ "${!1}" != "${!1//\/}" ]; then
                eval $1="${!1/%\/*}"/'${!1#*/}';
            else
                eval $1="${!1}";
            fi;
        fi
    fi
}

# Run something, muting output or redirecting it to the debug stream
# depending on the value of _ARC_DEBUG.
# If ARGCOMPLETE_USE_TEMPFILES is set, use tempfiles for IPC.
__python_argcomplete_run() {
    if [[ -z "${ARGCOMPLETE_USE_TEMPFILES-}" ]]; then
        __python_argcomplete_run_inner "$@"
        return
    fi
    local tmpfile="$(mktemp)"
    _ARGCOMPLETE_STDOUT_FILENAME="$tmpfile" __python_argcomplete_run_inner "$@"
    local code=$?
    cat "$tmpfile"
    rm "$tmpfile"
    return $code
}

__python_argcomplete_run_inner() {
    if [[ -z "${_ARC_DEBUG-}" ]]; then
        "$@" 8>&1 9>&2 1>/dev/null 2>&1 </dev/null
    else
        "$@" 8>&1 9>&2 1>&9 2>&1 </dev/null
    fi
}

__python_argcomplete_upshift_bash_rematch() {
    if [[ -z "${ZSH_VERSION-}" ]]; then
        _BASH_REMATCH=( "" "${BASH_REMATCH[@]}" )
    else
        _BASH_REMATCH=( "${BASH_REMATCH[@]}" )
    fi
}

# This function scans the beginning of an executable file provided as the first
# argument ($1) for certain indicators, specified by the second argument ($2),
# or the "target". There are three possible targets: "interpreter",
# "magic_string", and "easy_install". If the target is "interpreter", the
# function matches the interpreter line, alongside any optional interpreter
# arguments. If the target is "magic_string", a match is attempted for the
# "PYTHON_ARGCOMPLETE_OK" magic string, indicating that the file should be run
# to get completions. If the target is "easy_install", the function matches either
# "PBR Generated" or any of the "EASY-INSTALL" scripts (either SCRIPT,
# ENTRY-SCRIPT, or DEV-SCRIPT). In all cases, only the first kilobyte of
# the file is searched. The regex matches are returned in BASH_REMATCH,
# indexed starting at 1, regardless of the shell in use.
__python_argcomplete_scan_head() {
    local file="$1"
    local target="$2"

    local REPLY
    if [[ -n "${ZSH_VERSION-}" ]]; then
        read -r -k 1024 -u 0 < "$file";
    else
        read -r -N 1024 < "$file"
    fi

    # Since ZSH does not support a -n option, we
    # trim all characters after the first line in both shells
    if [[ "$target" = "interpreter" ]]; then
        read -r <<< "$REPLY"
    fi

    local regex

    case "$target" in
            magic_string) regex='PYTHON_ARGCOMPLETE_OK' ;;
            easy_install) regex="(PBR Generated)|(EASY-INSTALL-(SCRIPT|ENTRY-SCRIPT|DEV-SCRIPT))" ;;
            asdf) regex="asdf exec " ;;
            interpreter) regex='^#!(.*)$' ;;
    esac

    local ret=""
    if [[ "$REPLY" =~ $regex ]]; then
        ret=1
    fi

    __python_argcomplete_upshift_bash_rematch

    [[ -n $ret ]]
}

__python_argcomplete_scan_head_noerr() {
    __python_argcomplete_scan_head "$@" 2>/dev/null
}

__python_argcomplete_which() {
    if [[ -n "${ZSH_VERSION-}" ]]; then
        whence -p "$@"
    else
        type -P "$@"
    fi
}

_python_argcomplete_global() {

    if [[ -n "${ZSH_VERSION-}" ]]; then
        # Store result of a regex match in the
        # BASH_REMATCH variable rather than MATCH
        setopt local_options BASH_REMATCH
    fi

    # 1-based version of BASH_REMATCH. Modifying BASH_REMATCH
    # directly causes older versions of Bash to exit
    local _BASH_REMATCH="";

    local executable=""

    # req_argv contains the arguments to the completion
    # indexed from 1 (regardless of the shell.) In Bash,
    # the zeroth index is empty
    local req_argv=()

    if [[ -z "${ZSH_VERSION-}" ]]; then
        executable=$1
        req_argv=( "" "${COMP_WORDS[@]:1}" )
        __python_argcomplete_expand_tilde_by_ref executable
    else
        executable="${words[1]}"
        __python_argcomplete_expand_tilde_by_ref executable
        req_argv=( "${words[@]:1}" )
    fi

    local ARGCOMPLETE=0
    if [[ "$executable" == python* ]] || [[ "$executable" == pypy* ]]; then
        if [[ "${req_argv[1]}" == -m ]]; then
            if __python_argcomplete_run "$executable" -m argcomplete._check_module "${req_argv[2]}"; then
                ARGCOMPLETE=3
            else
                return
            fi
        fi
        if [[ $ARGCOMPLETE == 0 ]]; then
            local potential_path="${req_argv[1]}"
            __python_argcomplete_expand_tilde_by_ref potential_path
            if [[ -f "$potential_path" ]] && __python_argcomplete_scan_head_noerr "$potential_path" magic_string; then
                req_argv[1]="$potential_path" # not expanded in __python_argcomplete_run
                ARGCOMPLETE=2
            else
                return
            fi
        fi
    elif __python_argcomplete_which "$executable" >/dev/null 2>&1; then
        local SCRIPT_NAME=$(__python_argcomplete_which "$executable")
        __python_argcomplete_scan_head_noerr "$SCRIPT_NAME" interpreter
        if (__python_argcomplete_which pyenv && [[ "$SCRIPT_NAME" = $(pyenv root)/shims/* ]]) >/dev/null 2>&1; then
            local SCRIPT_NAME=$(pyenv which "$executable")
        fi
        if (__python_argcomplete_which asdf && __python_argcomplete_scan_head_noerr "$SCRIPT_NAME" asdf) >/dev/null 2>&1; then
            local SCRIPT_NAME=$(asdf which "$executable")
        fi
        if __python_argcomplete_scan_head_noerr "$SCRIPT_NAME" magic_string; then
            ARGCOMPLETE=1
        elif __python_argcomplete_scan_head_noerr "$SCRIPT_NAME" interpreter; then
            __python_argcomplete_upshift_bash_rematch
            local interpreter="${_BASH_REMATCH[2]}"

            if [[ -n "${ZSH_VERSION-}" ]]; then
                interpreter=($=interpreter)
            else
                interpreter=($interpreter)
            fi

            if (__python_argcomplete_scan_head_noerr "$SCRIPT_NAME" easy_install \
                && "${interpreter[@]}" "$(__python_argcomplete_which python-argcomplete-check-easy-install-script)" "$SCRIPT_NAME") >/dev/null 2>&1; then
                ARGCOMPLETE=1
            elif ([[ "${interpreter[@]}" == *python* ]] || [[ "${interpreter[@]}" == *pypy* ]])\
                && __python_argcomplete_run "${interpreter[@]}" -m argcomplete._check_console_script "$SCRIPT_NAME"; then
                ARGCOMPLETE=1
            fi
        fi
    fi

    if [[ $ARGCOMPLETE != 0 ]]; then
        local IFS=$'\013'
        if [[ -n "${ZSH_VERSION-}" ]]; then
            local completions
            completions=($(IFS="$IFS" \
                COMP_LINE="$BUFFER" \
                COMP_POINT="$CURSOR" \
                _ARGCOMPLETE=$ARGCOMPLETE \
                _ARGCOMPLETE_SHELL="zsh" \
                _ARGCOMPLETE_SUPPRESS_SPACE=1 \
                __python_argcomplete_run "$executable" "${(@)req_argv[1, ${ARGCOMPLETE}-1]}"))
            local nosort=()
            local nospace=()
            if is-at-least 5.8; then
                nosort=(-o nosort)
            fi
            if [[ "${completions-}" =~ ([^\\\\]): && "${BASH_REMATCH[2]}" =~ [=/:] ]]; then
                nospace=(-S '')
            fi
            _describe "$executable" completions "${nosort[@]}" "${nospace[@]}"
        else
            COMPREPLY=($(IFS="$IFS" \
                COMP_LINE="$COMP_LINE" \
                COMP_POINT="$COMP_POINT" \
                COMP_TYPE="$COMP_TYPE" \
                _ARGCOMPLETE_COMP_WORDBREAKS="$COMP_WORDBREAKS" \
                _ARGCOMPLETE=$ARGCOMPLETE \
                _ARGCOMPLETE_SHELL="bash" \
                _ARGCOMPLETE_SUPPRESS_SPACE=1 \
                __python_argcomplete_run "$executable" "${req_argv[@]:1:${ARGCOMPLETE}-1}"))
            if [[ $? != 0 ]]; then
                unset COMPREPLY
            elif [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then
                compopt -o nospace
            fi
        fi
    elif [[ -n "${ZSH_VERSION-}" ]]; then
        _default
    else
        type -t _completion_loader | grep -q 'function' && _completion_loader "$@"
    fi
}
if [[ -z "${ZSH_VERSION-}" ]]; then
    complete -o default -o bashdefault -D -F _python_argcomplete_global
else
    # -Uz is recommended for the use of functions supplied with the zsh distribution.
    # https://unix.stackexchange.com/a/214306
    autoload -Uz is-at-least
    # If this is being implicitly loaded because we placed it on fpath,
    # the comment at the top of this file causes zsh to invoke this script directly,
    # so we must explicitly call the global completion function.
    # Note $service should only ever be -default- because the comment at the top
    # registers this script as the default completer (#compdef -default-).
    if [[ $service == -default- ]]; then
        _python_argcomplete_global
    fi
    # If this has been executed directly (e.g. `eval "$(activate-global-python-argcomplete --dest=-)"`)
    # we need to explicitly call compdef to register the completion function.
    # If we have been implicitly loaded, we still call compdef as a slight optimisation
    # (there is no need to execute any top-level code more than once).
    compdef _python_argcomplete_global -default-
fi
