# shellcheck shell=bash # Bash completion for terractl (terraria-server-manager) # # Installed to /share/bash-completion/completions/terractl, where the # bash-completion package loads it automatically. Also works with 'sudo terractl'. # Instances directory: default, or TERRARIA_BASE from /etc/default/terractl. # The file is parsed rather than sourced, so nothing runs in your shell. _terractl_base() { local base=/var/lib/terraria/instances value if [[ -r /etc/default/terractl ]]; then value=$(sed -n 's/^[[:space:]]*TERRARIA_BASE=//p' /etc/default/terractl | tail -n 1) value=${value%\"}; value=${value#\"}; value=${value%\'}; value=${value#\'} if [[ -n $value ]]; then base=$value; fi fi printf '%s\n' "$base" } # Instance names. Reading the directory needs root or the 'terraria' group; if # it isn't readable, fall back to the terraria@ services systemd knows about. _terractl_instances() { local base conf base=$(_terractl_base) if [[ -r $base && -x $base ]]; then while IFS= read -r conf; do conf=${conf%/instance.conf} printf '%s\n' "${conf##*/}" done < <(compgen -G "$base/*/instance.conf") elif command -v systemctl >/dev/null 2>&1; then systemctl list-units --all --plain --no-legend 'terraria@*.service' 2>/dev/null | sed -n 's/^terraria@\([^ ]*\)\.service.*/\1/p' fi } # Mods installed in an instance (*.tmod files), or enabled ones (enabled.json) _terractl_mods() { local mdir f mdir="$(_terractl_base)/$1/data/Mods" if [[ $2 == enabled ]]; then [[ -r $mdir/enabled.json ]] && grep -o '"[^"]*"' "$mdir/enabled.json" | tr -d '"' else while IFS= read -r f; do f=${f##*/} printf '%s\n' "${f%.tmod}" done < <(compgen -G "$mdir/*.tmod") fi } # Set COMPREPLY to the words matching what's typed so far _terractl_reply() { mapfile -t COMPREPLY < <(compgen -W "$1" -- "$cur") } _terractl() { local cur words cword if declare -F _init_completion >/dev/null 2>&1; then # shellcheck disable=SC2034 # prev is set by _init_completion but not needed here local prev _init_completion || return else cur=${COMP_WORDS[COMP_CWORD]} words=("${COMP_WORDS[@]}") cword=$COMP_CWORD fi local commands="new list attach cmd mods reinstall delete prepare run --help --version" local console="save say playing kick ban motd password time dawn noon dusk midnight settle seed version maxplayers port clear help" if (( cword == 1 )); then _terractl_reply "$commands" return fi local command=${words[1]} case $command in list|help|-h|--help|version|-V|--version) return ;; new) # new [vanilla|tmodloader] [port]: the name is new, so nothing to offer if (( cword == 3 )); then _terractl_reply "vanilla tmodloader"; fi return ;; esac if (( cword == 2 )); then _terractl_reply "$(_terractl_instances)" return fi local instance=${words[2]} case $command in cmd) if (( cword == 3 )); then _terractl_reply "$console"; fi ;; reinstall) if (( cword == 3 )); then _terractl_reply "--clean"; fi ;; delete) _terractl_reply "-y --yes --no-backup" ;; mods) if (( cword == 3 )); then _terractl_reply "list add enable disable remove" return fi case ${words[3]} in add) # .tmod files and folders (e.g. the Windows export folder) if declare -F _filedir >/dev/null 2>&1; then _filedir tmod else compopt -o filenames 2>/dev/null mapfile -t COMPREPLY < <(compgen -d -- "$cur"; compgen -f -X '!*.tmod' -- "$cur") fi ;; enable|remove) _terractl_reply "$(_terractl_mods "$instance" installed)" ;; disable) _terractl_reply "$(_terractl_mods "$instance" enabled)" ;; esac ;; esac } complete -F _terractl terractl