239 lines
8.4 KiB
Plaintext
239 lines
8.4 KiB
Plaintext
#compdef -P *
|
|
|
|
# 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
|
|
|
|
# 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
|
|
else
|
|
"$@" 8>&1 9>&2 1>&9 2>&1
|
|
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"
|
|
|
|
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
|
|
if [[ "$service" != "-default-" ]]; then
|
|
# TODO: this may not be sufficient - see https://zsh.sourceforge.io/Doc/Release/Completion-System.html
|
|
# May need to call _complete with avoid-completer=_python-argcomplete or something like that
|
|
_default
|
|
return
|
|
fi
|
|
executable="${words[1]}"
|
|
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 __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]}"))
|
|
_describe "$executable" completions
|
|
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
|
|
compdef _python_argcomplete_global -P '*'
|
|
fi
|