Skip to content

Instantly share code, notes, and snippets.

@eparis
Created June 1, 2015 17:18
Show Gist options
  • Save eparis/2380a2daa7ff6c0b52a6 to your computer and use it in GitHub Desktop.
Save eparis/2380a2daa7ff6c0b52a6 to your computer and use it in GitHub Desktop.
etcdctl bash completions
#!/bin/bash
__debug()
{
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
fi
}
__index_of_word()
{
local w word=$1
shift
index=0
for w in "$@"; do
[[ $w = "$word" ]] && return
index=$((index+1))
done
index=-1
}
__contains_word()
{
local w word=$1; shift
for w in "$@"; do
[[ $w = "$word" ]] && return
done
return 1
}
__handle_reply()
{
__debug "${FUNCNAME}"
case $cur in
-*)
compopt -o nospace
local allflags
if [ ${#must_have_one_flag[@]} -ne 0 ]; then
allflags=("${must_have_one_flag[@]}")
else
allflags=("${flags[*]} ${two_word_flags[*]}")
fi
COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") )
[[ $COMPREPLY == *= ]] || compopt +o nospace
return 0;
;;
esac
# check if we are handling a flag with special work handling
local index
__index_of_word "${prev}" "${flags_with_completion[@]}"
if [[ ${index} -ge 0 ]]; then
${flags_completion[${index}]}
return
fi
# we are parsing a flag and don't have a special handler, no completion
if [[ ${cur} != "${words[cword]}" ]]; then
return
fi
local completions
if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then
completions=("${must_have_one_flag[@]}")
elif [[ ${#must_have_one_noun[@]} -ne 0 ]]; then
completions=("${must_have_one_noun[@]}")
else
completions=("${commands[@]}")
fi
COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") )
if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
declare -F __custom_func >/dev/null && __custom_func
fi
}
# The arguments should be in the form "ext1|ext2|extn"
__handle_filename_extension_flag()
{
local ext="$1"
_filedir "@(${ext})"
}
__handle_flag()
{
__debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
# if a command required a flag, and we found it, unset must_have_one_flag()
local flagname=${words[c]}
# if the word contained an =
if [[ ${words[c]} == *"="* ]]; then
flagname=${flagname%=*} # strip everything after the =
flagname="${flagname}=" # but put the = back
fi
__debug "${FUNCNAME}: looking for ${flagname}"
if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then
must_have_one_flag=()
fi
# skip the argument to a two word flag
if __contains_word "${words[c]}" "${two_word_flags[@]}"; then
c=$((c+1))
# if we are looking for a flags value, don't show commands
if [[ $c -eq $cword ]]; then
commands=()
fi
fi
# skip the flag itself
c=$((c+1))
}
__handle_noun()
{
__debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
must_have_one_noun=()
fi
nouns+=("${words[c]}")
c=$((c+1))
}
__handle_command()
{
__debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
local next_command
if [[ -n ${last_command} ]]; then
next_command="_${last_command}_${words[c]}"
else
next_command="_${words[c]}"
fi
c=$((c+1))
__debug "${FUNCNAME}: looking for ${next_command}"
declare -F $next_command >/dev/null && $next_command
}
__handle_word()
{
if [[ $c -ge $cword ]]; then
__handle_reply
return
fi
__debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
if [[ "${words[c]}" == -* ]]; then
__handle_flag
elif __contains_word "${words[c]}" "${commands[@]}"; then
__handle_command
else
__handle_noun
fi
__handle_word
}
__etcdctl_get_path()
{
compopt +o nospace
local etcdctl_out
if etcdctl_out=$(etcdctl ls "${dir}" 2>/dev/null); then
COMPREPLY=( $( compgen -W "${etcdctl_out[*]}" -- "${cur}" ) )
echo "dir=${dir} comp=${COMPREPLY[@]}" >> /tmp/debug
if [[ ${#COMPREPLY[@]} -gt 0 ]]; then
compopt -o nospace
return 0
fi
fi
return 1
}
__etcdctl_complete_path()
{
if [[ ${#nouns[@]} -gt 0 ]]; then
return 1
fi
local dir
dir="${cur}"
echo -n "one: " >> /tmp/debug
__etcdctl_get_path && return
echo -n "two: " >> /tmp/debug
dir=$(dirname ${cur} 2>/dev/null)
__etcdctl_get_path && return
}
__custom_func() {
case ${last_command} in
etcdctl_ls | etcdctl_get | etcdctl_set | etcdctl_rm | etcdctl_rmdir )
__etcdctl_complete_path
return
;;
*)
;;
esac
}
_etcdctl_backup()
{
last_command="etcdctl_backup"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--backup-dir=")
flags+=("--data-dir=")
flags+=("--help")
flags+=("-h")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_cluster-health()
{
last_command="etcdctl_cluster-health"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_mk()
{
last_command="etcdctl_mk"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
flags+=("--ttl=")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_mkdir()
{
last_command="etcdctl_mkdir"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
flags+=("--ttl=")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_rm()
{
last_command="etcdctl_rm"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--dir")
flags+=("--help")
flags+=("-h")
flags+=("--recursive")
flags+=("--with-index=")
flags+=("--with-value=")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_rmdir()
{
last_command="etcdctl_rmdir"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_get()
{
last_command="etcdctl_get"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
flags+=("--sort")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_ls()
{
last_command="etcdctl_ls"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
flags+=("--p")
flags+=("--recursive")
flags+=("--sort")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_set()
{
last_command="etcdctl_set"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
flags+=("--swap-with-index=")
flags+=("--swap-with-value=")
flags+=("--ttl=")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_setdir()
{
last_command="etcdctl_setdir"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
flags+=("--ttl=")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_update()
{
last_command="etcdctl_update"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
flags+=("--ttl=")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_updatedir()
{
last_command="etcdctl_updatedir"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
flags+=("--ttl=")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_watch()
{
last_command="etcdctl_watch"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--after-index=")
flags+=("--forever")
flags+=("--help")
flags+=("-h")
flags+=("--recursive")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_exec-watch()
{
last_command="etcdctl_exec-watch"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--after-index=")
flags+=("--help")
flags+=("-h")
flags+=("--recursive")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_member_list()
{
last_command="etcdctl_member_list"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_member_add()
{
last_command="etcdctl_member_add"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_member_remove()
{
last_command="etcdctl_member_remove"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_member()
{
last_command="etcdctl_member"
commands=()
commands+=("list")
commands+=("add")
commands+=("remove")
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_import()
{
last_command="etcdctl_import"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--c=")
flags+=("--help")
flags+=("-h")
flags+=("--snap=")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_genbash()
{
last_command="etcdctl_genbash"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
flags+=("--outfile=")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl_help()
{
last_command="etcdctl_help"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--help")
flags+=("-h")
must_have_one_flag=()
must_have_one_noun=()
}
_etcdctl()
{
last_command="etcdctl"
commands=()
commands+=("backup")
commands+=("cluster-health")
commands+=("mk")
commands+=("mkdir")
commands+=("rm")
commands+=("rmdir")
commands+=("get")
commands+=("ls")
commands+=("set")
commands+=("setdir")
commands+=("update")
commands+=("updatedir")
commands+=("watch")
commands+=("exec-watch")
commands+=("member")
commands+=("import")
commands+=("genbash")
commands+=("help")
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
flags+=("--ca-file=")
flags+=("--cert-file=")
flags+=("--debug")
flags+=("--help")
flags+=("-h")
flags+=("--key-file=")
flags+=("--no-sync")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--peers=")
two_word_flags+=("-C")
must_have_one_flag=()
must_have_one_noun=()
}
__start_etcdctl()
{
local cur prev words cword
_init_completion -s || return
local c=0
local flags=()
local two_word_flags=()
local flags_with_completion=()
local flags_completion=()
local commands=("etcdctl")
local must_have_one_flag=()
local must_have_one_noun=()
local last_command
local nouns=()
__handle_word
}
complete -F __start_etcdctl etcdctl
# ex: ts=4 sw=4 et filetype=sh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment