blob: 5bfdd20ba3bb71c7b34010ce438a732795364164 [file] [log] [blame] [edit]
command -v cargo >/dev/null 2>&1 &&
_cargo()
{
local cur prev words cword
_get_comp_words_by_ref cur prev words cword
COMPREPLY=()
# Skip past - and + options to find the command.
local nwords=${#words[@]}
local cmd_i cmd
for (( cmd_i=1; cmd_i<$nwords; cmd_i++ ));
do
if [[ ! "${words[$cmd_i]}" =~ ^[+-] ]]; then
cmd="${words[$cmd_i]}"
break
fi
done
local vcs='git hg none'
local color='auto always never'
local msg_format='human json'
local opt_help='-h --help'
local opt_verbose='-v --verbose'
local opt_quiet='-q --quiet'
local opt_color='--color'
local opt_common="$opt_help $opt_verbose $opt_quiet $opt_color"
local opt_pkg='-p --package'
local opt_feat='--features --all-features --no-default-features'
local opt_mani='--manifest-path'
local opt_jobs='-j --jobs'
local opt_force='-f --force'
local opt_test='--test --bench'
local opt_lock='--frozen --locked'
local opt___nocmd="$opt_common -V --version --list"
local opt__bench="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test --message-format --target --lib --bin --example --no-run"
local opt__build="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test --message-format --target --lib --bin --example --release"
local opt__check="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test --message-format --target --lib --bin --example --release"
local opt__clean="$opt_common $opt_pkg $opt_mani $opt_lock --target --release"
local opt__doc="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs --message-format --bin --lib --target --open --no-deps --release"
local opt__fetch="$opt_common $opt_mani $opt_lock"
local opt__generate_lockfile="${opt__fetch}"
local opt__git_checkout="$opt_common $opt_lock --reference --url"
local opt__help="$opt_help"
local opt__init="$opt_common $opt_lock --bin --lib --name --vcs"
local opt__install="$opt_common $opt_feat $opt_jobs $opt_lock $opt_force --bin --branch --debug --example --git --list --path --rev --root --tag --vers"
local opt__locate_project="$opt_mani -h --help"
local opt__login="$opt_common $opt_lock --host"
local opt__metadata="$opt_common $opt_feat $opt_mani $opt_lock --format-version --no-deps"
local opt__new="$opt_common $opt_lock --vcs --bin --lib --name"
local opt__owner="$opt_common $opt_lock -a --add -r --remove -l --list --index --token"
local opt__package="$opt_common $opt_mani $opt_lock $opt_jobs --allow-dirty -l --list --no-verify --no-metadata"
local opt__pkgid="${opt__fetch} $opt_pkg"
local opt__publish="$opt_common $opt_mani $opt_lock $opt_jobs --allow-dirty --dry-run --host --token --no-verify"
local opt__read_manifest="$opt_help $opt_verbose $opt_mani $opt_color --no-deps"
local opt__run="$opt_common $opt_feat $opt_mani $opt_lock $opt_jobs --message-format --target --bin --example --release"
local opt__rustc="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test --message-format --profile --target --lib --bin --example --release"
local opt__rustdoc="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test --message-format --target --lib --bin --example --release --open"
local opt__search="$opt_common $opt_lock --host --limit"
local opt__test="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_jobs $opt_test --message-format --all --doc --target --lib --bin --example --no-run --release --no-fail-fast"
local opt__uninstall="$opt_common $opt_lock --bin --root"
local opt__update="$opt_common $opt_pkg $opt_mani $opt_lock --aggressive --precise"
local opt__verify_project="${opt__fetch}"
local opt__version="$opt_help $opt_verbose $opt_color"
local opt__yank="$opt_common $opt_lock --vers --undo --index --token"
if [[ $cmd_i -ge $nwords-1 ]]; then
# Completion before or at the command.
if [[ "$cur" == -* ]]; then
COMPREPLY=( $( compgen -W "${opt___nocmd}" -- "$cur" ) )
elif [[ "$cur" == +* ]]; then
COMPREPLY=( $( compgen -W "$(_toolchains)" -- "$cur" ) )
else
COMPREPLY=( $( compgen -W "$__cargo_commands" -- "$cur" ) )
fi
else
case "${prev}" in
--vcs)
COMPREPLY=( $( compgen -W "$vcs" -- "$cur" ) )
;;
--color)
COMPREPLY=( $( compgen -W "$color" -- "$cur" ) )
;;
--message-format)
COMPREPLY=( $( compgen -W "$msg_format" -- "$cur" ) )
;;
--manifest-path)
_filedir toml
;;
--bin)
COMPREPLY=( $( compgen -W "$(_bin_names)" -- "$cur" ) )
;;
--test)
COMPREPLY=( $( compgen -W "$(_test_names)" -- "$cur" ) )
;;
--bench)
COMPREPLY=( $( compgen -W "$(_benchmark_names)" -- "$cur" ) )
;;
--example)
COMPREPLY=( $( compgen -W "$(_get_examples)" -- "$cur" ) )
;;
--target)
COMPREPLY=( $( compgen -W "$(_get_targets)" -- "$cur" ) )
;;
help)
COMPREPLY=( $( compgen -W "$__cargo_commands" -- "$cur" ) )
;;
*)
local opt_var=opt__${cmd//-/_}
COMPREPLY=( $( compgen -W "${!opt_var}" -- "$cur" ) )
;;
esac
fi
# compopt does not work in bash version 3
return 0
} &&
complete -F _cargo cargo
__cargo_commands=$(cargo --list 2>/dev/null | tail -n +2)
_locate_manifest(){
local manifest=`cargo locate-project 2>/dev/null`
# regexp-replace manifest '\{"root":"|"\}' ''
echo ${manifest:9:${#manifest}-11}
}
# Extracts the values of "name" from the array given in $1 and shows them as
# command line options for completion
_get_names_from_array()
{
local manifest=$(_locate_manifest)
if [[ -z $manifest ]]; then
return 0
fi
local last_line
local -a names
local in_block=false
local block_name=$1
while read line
do
if [[ $last_line == "[[$block_name]]" ]]; then
in_block=true
else
if [[ $last_line =~ .*\[\[.* ]]; then
in_block=false
fi
fi
if [[ $in_block == true ]]; then
if [[ $line =~ .*name.*\= ]]; then
line=${line##*=}
line=${line%%\"}
line=${line##*\"}
names+=($line)
fi
fi
last_line=$line
done < $manifest
echo "${names[@]}"
}
#Gets the bin names from the manifest file
_bin_names()
{
_get_names_from_array "bin"
}
#Gets the test names from the manifest file
_test_names()
{
_get_names_from_array "test"
}
#Gets the bench names from the manifest file
_benchmark_names()
{
_get_names_from_array "bench"
}
_get_examples(){
local files=($(dirname $(_locate_manifest))/examples/*.rs)
local names=("${files[@]##*/}")
local names=("${names[@]%.*}")
# "*" means no examples found
if [[ "${names[@]}" != "*" ]]; then
echo "${names[@]}"
fi
}
_get_targets(){
local CURRENT_PATH
if [ `uname -o` == "Cygwin" -a -f "$PWD"/Cargo.toml ]; then
CURRENT_PATH=$PWD
else
CURRENT_PATH=$(_locate_manifest)
fi
if [[ -z "$CURRENT_PATH" ]]; then
return 1
fi
local TARGETS=()
local FIND_PATHS=( "/" )
local FIND_PATH LINES LINE
while [[ "$CURRENT_PATH" != "/" ]]; do
FIND_PATHS+=( "$CURRENT_PATH" )
CURRENT_PATH=$(dirname $CURRENT_PATH)
done
for FIND_PATH in ${FIND_PATHS[@]}; do
if [[ -f "$FIND_PATH"/.cargo/config ]]; then
LINES=( `grep "$FIND_PATH"/.cargo/config -e "^\[target\."` )
for LINE in ${LINES[@]}; do
TARGETS+=(`sed 's/^\[target\.\(.*\)\]$/\1/' <<< $LINE`)
done
fi
done
echo "${TARGETS[@]}"
}
_toolchains(){
local result=()
local toolchains=$(rustup toolchain list)
local channels="nightly|beta|stable|[0-9]\.[0-9]{1,2}\.[0-9]"
local date="[0-9]{4}-[0-9]{2}-[0-9]{2}"
while read line
do
# Strip " (default)"
line=${line%% *}
if [[ "$line" =~ ^($channels)(-($date))?(-.*) ]]; then
if [[ -z ${BASH_REMATCH[3]} ]]; then
result+=("+${BASH_REMATCH[1]}")
else
# channel-date
result+=("+${BASH_REMATCH[1]}-${BASH_REMATCH[3]}")
fi
result+=("+$line")
else
result+=("+$line")
fi
done <<< "$toolchains"
echo "${result[@]}"
}
# vim:ft=sh