Skip to content

Instantly share code, notes, and snippets.

@zish
Last active December 7, 2023 09:24
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save zish/85dccece461e050077997ff5d7d9c9d4 to your computer and use it in GitHub Desktop.
Save zish/85dccece461e050077997ff5d7d9c9d4 to your computer and use it in GitHub Desktop.
Better Terraform Bash Completion
# Bash Terraform completion
#
# Originally adapted from
# https://gist.github.com/cornfeedhobo/8bc08747ec3add1fc5adb2edb7cd68d3
#
# Author: Jeremy Melanson
#
# Features of this version:
# - Uses built-in bash routines for text processing, instead of external tools
# (awk, sed, grep, ...).
#
# - fixes the retrieval of options from the Terraform executble.
#
# - Optional _init_terraform_completion function, which can enable
# command-completion for multiple Terraform executables.
#
#--- Get options listing from Terraform command.
#
_terraform_completion_get_opts () {
local CMD_EXEC="${1}"
local TF_OPT="${2}"
local IFS=$'\n'
#-- "terraform -help"
if [[ "${TF_OPT}" == "" ]]; then
for O in $(${CMD_EXEC} -help); do
if [[ "${O}" =~ ^\ +([^\ ]+) ]]; then
echo -e "${BASH_REMATCH[1]}"
fi
done
#-- "terraform -help XXXX"
else
for O in $(${CMD_EXEC} -help ${TF_OPT}); do
if [[ "${O}" =~ ^\ +(-[^\ =]+=?) ]]; then
echo -e "${BASH_REMATCH[1]}"
fi
done
fi
}
#--- This function is passed to 'complete' for handling completion.
#
_terraform_completion () {
local cur prev words cword opts
local O_COMP_WORDBREAKS="${COMP_WORDBREAKS}"
export COMP_WORDBREAKS="${COMP_WORDBREAKS//=/}"
_init_completion -s || return
_get_comp_words_by_ref -n : cur prev words cword
COMPREPLY=()
local opts=""
local CMD_EXEC="${COMP_WORDS[0]}"
if [[ ${cword} -eq 1 ]]; then
if [[ ${cur} == -* ]]; then
if [[ ${cur} == -c* ]]; then
compopt -o nospace
local CUR_DIR=${cur//-chdir=/}
opts="$(compgen -P "-chdir=" -d -- ${CUR_DIR})"
opts="${opts:--chdir=}"
else
opts="-chdir= -help -version"
fi
else
opts="$(_terraform_completion_get_opts ${CMD_EXEC})"
fi
elif [[ ${cword} -gt 1 ]]; then
if [[ ${cword} -eq 2 && ${prev} == -help ]]; then
opts="$(_terraform_completion_get_opts ${CMD_EXEC})"
else
if [[ "${NEW_OPT_TYPE}" != "" ]]; then
compopt -o nospace
else
local TF_COMMAND="${words[1]}"
opts="$(_terraform_completion_get_opts ${CMD_EXEC} ${TF_COMMAND})"
fi
fi
fi
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
if [[ "${COMPREPLY[0]}" =~ =$ ]]; then
compopt -o nospace
fi
fi
export COMP_WORDBREAKS="${O_COMP_WORDBREAKS}"
return 0
}
#--- Initialize Bash Command Completion for multiple Terraform executables.
# It searches the PATH for files starting with "terraform", but does not
# contain "-" characters. This avoids adding Completion for third-party
# Terraform provider plugins that exist as a separate executable
# (terraform-provider-XXXX).
#
_init_terraform_completion () {
#-- Regex used when looking for terraform executables.
# Looks for "terraform", or "terraform[anything else that isn't a dash]".
# This enables Command Completion for multiple versions of Terraform,
# if you have them.
#
local TF_EXEC_PREFIX='^terrafor(m[^-]+|m)$'
local ORIG_DIR="${PWD}"
local IFS=':'
for P in ${PATH}; do
if [ -d "${P}" ]; then
cd "${P}"
else
continue
fi
for E in *; do
if [[ "${E}" =~ ${TF_EXEC_PREFIX} ]]; then
complete -F _terraform_completion ${E}
fi
done
done
cd "${ORIG_DIR}"
}
complete -F _terraform_completion terraform
#--- Optionally enable command completion for multiple Terraform executables.
# It currently works with executables in the PATH, that are named similar
# to "terraform_XXXX".
#
# ** If your files are named differently, then you may need to modify the REGEX
# ** in TF_EXEC_PREFIX to suit your needs.
#
# This provides a little simplicity, when working with multiple Terraform versions.
#
# Uncomment this line to enable:
#
_init_terraform_completion
#--- Remove the initialization function. It is only needed once.
unset -f _init_terraform_completion
#--- Include command completion for the optional "tf" command.
complete -F _terraform_completion tf
@jwhitcraft
Copy link

Thanks for this, the only problem that i noticed what that I alias tf to terraform and when when i add that the auto complete it fails when trying to finish the auto complete.

not a huge deal as i was able to get around since i don't use more than one version of terraform, but i thought I would let you know.

@zish
Copy link
Author

zish commented Jul 30, 2018

Hi @jwhitcraft. I noticed this problem happening when trying to use autocomplete after the first "-xxxx" option. I just updated the gist with a working version.
I've also verified that using "tf" works. Just update the value of TF_EXEC_PREFIX to be TF_EXEC_PREFIX="^tf$".

@ProfMoo
Copy link

ProfMoo commented Aug 6, 2020

Thanks! This is great!

Small nit: Typo on line 133.
It is onluy needed once. should be It is only needed once.

@bgmonroe
Copy link

There's an undefined function (_init_completion) at line 44. I've removed from my copy and seems to be fine.

@zish
Copy link
Author

zish commented May 17, 2022

Thanks for pointing it out @ProfMoo

@zish
Copy link
Author

zish commented May 17, 2022

@jwhitcraft Check out complete-alias. I've tested it with this gist, and I was able to get completion for an alias.

@zish
Copy link
Author

zish commented May 17, 2022

@bgmonroe Are you still experiencing this issue? What version of bash-completion is installed?

@bgmonroe
Copy link

No, I've since switched over to zsh, so no longer use the above. Thanks for the follow-up though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment