bash autocompletions

This commit is contained in:
adam committed 2026-09-28 17:18:41 +00:00
1 parent 47808ffa17
commit 675f5308e6
7 files changed
+157 -5

No files matched your search

+8
View File
@@ -1,5 +1,13 @@
# Changelog
## 2.1.0 - 2026-09-28
- Bash completion for `terractl`: commands, instance names, `new` types, console commands for `cmd`, `reinstall`/`delete` options, and `mods` actions and mod names. Installed to `share/bash-completion/completions/terractl` by both `make install` and the package.
## 2.0.1 - 2026-09-28
- Fixed ShellCheck warnings that made `make check` (and therefore `make deb`) fail when ShellCheck is installed: simplified the development-copy check in `--version` (SC2140), and marked the intentional unquoted unit list in `prerm` (SC2086).
## 2.0.0 - 2026-09-28
- Renamed the command from `terraria-instance` to `terractl`, and the package from `terraria-instance` to `terraria-server-manager`. The new package replaces the old one automatically; see "Upgrading from the terraria-instance package" in the guide.
+7 -3
View File
@@ -17,6 +17,7 @@ SYSUSERSDIR := $(PREFIX)/lib/sysusers.d
TMPFILESDIR := $(PREFIX)/lib/tmpfiles.d
DOCDIR := $(PREFIX)/share/doc/$(NAME)
DATADIR := $(PREFIX)/share/$(NAME)
COMPLETIONDIR := $(PREFIX)/share/bash-completion/completions
# Fill in version and install paths
SUBST = sed -e 's|@VERSION@|$(VERSION)|g' -e 's|@BINDIR@|$(BINDIR)|g' -e 's|@DOCDIR@|$(DOCDIR)|g'
@@ -31,9 +32,10 @@ all: check
check:
bash -n bin/terractl
bash -n completions/bash/terractl
for f in $(MAINT_SCRIPTS); do sh -n $$f; done
@if command -v shellcheck >/dev/null; then \
shellcheck bin/terractl $(MAINT_SCRIPTS); \
shellcheck bin/terractl completions/bash/terractl $(MAINT_SCRIPTS); \
else \
echo "shellcheck not installed; skipped (apt install shellcheck)"; \
fi
@@ -41,7 +43,7 @@ check:
install:
install -d $(DESTDIR)$(BINDIR) $(DESTDIR)$(UNITDIR) $(DESTDIR)$(SYSUSERSDIR) \
$(DESTDIR)$(TMPFILESDIR) $(DESTDIR)$(DOCDIR) $(DESTDIR)$(DATADIR) \
$(DESTDIR)$(SYSCONFDIR)/default
$(DESTDIR)$(COMPLETIONDIR) $(DESTDIR)$(SYSCONFDIR)/default
$(SUBST) bin/terractl > $(DESTDIR)$(BINDIR)/terractl
chmod 755 $(DESTDIR)$(BINDIR)/terractl
$(SUBST) systemd/terraria@.service > $(DESTDIR)$(UNITDIR)/terraria@.service
@@ -50,6 +52,7 @@ install:
install -m 644 config/tmpfiles.d/terractl.conf $(DESTDIR)$(TMPFILESDIR)/
install -m 644 docs/guide.md $(DESTDIR)$(DOCDIR)/README.md
install -m 644 tools/windows/export-tmod-mods.ps1 $(DESTDIR)$(DATADIR)/
install -m 644 completions/bash/terractl $(DESTDIR)$(COMPLETIONDIR)/terractl
@# Never overwrite local settings
@if [ -e $(DESTDIR)$(SYSCONFDIR)/default/terractl ]; then \
echo "keeping existing $(DESTDIR)$(SYSCONFDIR)/default/terractl"; \
@@ -67,7 +70,8 @@ install:
uninstall:
rm -f $(DESTDIR)$(BINDIR)/terractl \
$(DESTDIR)$(UNITDIR)/terraria@.service $(DESTDIR)$(UNITDIR)/terraria@.socket \
$(DESTDIR)$(SYSUSERSDIR)/terractl.conf $(DESTDIR)$(TMPFILESDIR)/terractl.conf
$(DESTDIR)$(SYSUSERSDIR)/terractl.conf $(DESTDIR)$(TMPFILESDIR)/terractl.conf \
$(DESTDIR)$(COMPLETIONDIR)/terractl
rm -rf $(DESTDIR)$(DOCDIR) $(DESTDIR)$(DATADIR)
@if [ -z "$(DESTDIR)" ] && [ -d /run/systemd/system ]; then systemctl daemon-reload; fi
@echo "Removed. Kept: $(SYSCONFDIR)/default/terractl, /var/lib/terraria and the terraria user."
+2
View File
@@ -17,6 +17,7 @@ sudo terractl attach calamity
- **Safe shutdowns.** Stopping a server saves the world first.
- **A live console.** `terractl attach` shows the server's output and lets you type commands into it.
- **Mod management.** `terractl mods` installs, enables and removes mods, with correct file ownership.
- **Tab completion** for commands, instance names, mods and console commands.
- **Hardened.** Servers run as an unprivileged `terraria` user and can only write to their own data.
- **Helper for Windows.** A PowerShell script exports your enabled tModLoader mods for the server.
@@ -48,6 +49,7 @@ See [docs/guide.md](docs/guide.md). It covers installation, creating instances,
```
bin/terractl The command-line tool
systemd/ terraria@.service and terraria@.socket
completions/bash/ Bash completion for terractl
config/ /etc/default settings, sysusers.d and tmpfiles.d entries
packaging/deb/ Debian package metadata and install/remove scripts
docs/guide.md Full documentation
+1 -1
View File
@@ -1 +1 @@
2.0.0
2.1.0
+119
View File
@@ -0,0 +1,119 @@
# shellcheck shell=bash
# Bash completion for terractl (terraria-server-manager)
#
# Installed to <prefix>/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 <new name> [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
+19 -1
View File
@@ -21,7 +21,8 @@ Run any number of vanilla Terraria and tModLoader dedicated servers on one Linux
15. [Permissions](#permissions)
16. [Running by hand for debugging](#running-by-hand-for-debugging)
17. [Troubleshooting](#troubleshooting)
18. [Command reference](#command-reference)
18. [Tab completion](#tab-completion)
19. [Command reference](#command-reference)
---
@@ -669,6 +670,23 @@ It was generated before the mods were added. Delete the world files in `data/Wor
---
## Tab completion
`terractl` comes with bash completion. Press Tab to complete:
- command names;
- instance names;
- `vanilla`/`tmodloader` for `new`;
- common server console commands for `cmd` (`save`, `say`, `playing`, `kick`...);
- the options of `reinstall` and `delete`;
- `mods` actions. For `mods add` it completes `.tmod` files and folders; for `mods enable` and `mods remove`, the installed mods; for `mods disable`, the enabled ones.
It works with `sudo terractl` too. It needs the `bash-completion` package, which most Debian and Ubuntu systems already have (`sudo apt install bash-completion`). It takes effect in new terminal sessions.
Completion runs as *you*, even when you type `sudo`. Instance and mod names therefore only complete if you can read `/var/lib/terraria`, which means being root or a member of the `terraria` group (see [Permissions](#permissions)). Otherwise, it falls back to the names of servers systemd currently knows about, and mod names don't complete.
---
## Command reference
```
+1
View File
@@ -9,6 +9,7 @@ Depends: unzip, systemd
Recommends: curl, libicu76 | libicu74 | libicu72 | libicu70 | libicu-dev
Conflicts: terraria-instance
Replaces: terraria-instance
Suggests: bash-completion
Description: run multiple Terraria and tModLoader dedicated servers with systemd
Provides the terraria@.service template and the terractl command for
running any number of vanilla Terraria and tModLoader dedicated servers, each