bash autocompletions
This commit is contained in:
1 parent
47808ffa17
commit
675f5308e6
7 files changed
+157
-5
No files matched your search
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# 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
|
## 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.
|
- 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.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ SYSUSERSDIR := $(PREFIX)/lib/sysusers.d
|
|||||||
TMPFILESDIR := $(PREFIX)/lib/tmpfiles.d
|
TMPFILESDIR := $(PREFIX)/lib/tmpfiles.d
|
||||||
DOCDIR := $(PREFIX)/share/doc/$(NAME)
|
DOCDIR := $(PREFIX)/share/doc/$(NAME)
|
||||||
DATADIR := $(PREFIX)/share/$(NAME)
|
DATADIR := $(PREFIX)/share/$(NAME)
|
||||||
|
COMPLETIONDIR := $(PREFIX)/share/bash-completion/completions
|
||||||
|
|
||||||
# Fill in version and install paths
|
# Fill in version and install paths
|
||||||
SUBST = sed -e 's|@VERSION@|$(VERSION)|g' -e 's|@BINDIR@|$(BINDIR)|g' -e 's|@DOCDIR@|$(DOCDIR)|g'
|
SUBST = sed -e 's|@VERSION@|$(VERSION)|g' -e 's|@BINDIR@|$(BINDIR)|g' -e 's|@DOCDIR@|$(DOCDIR)|g'
|
||||||
@@ -31,9 +32,10 @@ all: check
|
|||||||
|
|
||||||
check:
|
check:
|
||||||
bash -n bin/terractl
|
bash -n bin/terractl
|
||||||
|
bash -n completions/bash/terractl
|
||||||
for f in $(MAINT_SCRIPTS); do sh -n $$f; done
|
for f in $(MAINT_SCRIPTS); do sh -n $$f; done
|
||||||
@if command -v shellcheck >/dev/null; then \
|
@if command -v shellcheck >/dev/null; then \
|
||||||
shellcheck bin/terractl $(MAINT_SCRIPTS); \
|
shellcheck bin/terractl completions/bash/terractl $(MAINT_SCRIPTS); \
|
||||||
else \
|
else \
|
||||||
echo "shellcheck not installed; skipped (apt install shellcheck)"; \
|
echo "shellcheck not installed; skipped (apt install shellcheck)"; \
|
||||||
fi
|
fi
|
||||||
@@ -41,7 +43,7 @@ check:
|
|||||||
install:
|
install:
|
||||||
install -d $(DESTDIR)$(BINDIR) $(DESTDIR)$(UNITDIR) $(DESTDIR)$(SYSUSERSDIR) \
|
install -d $(DESTDIR)$(BINDIR) $(DESTDIR)$(UNITDIR) $(DESTDIR)$(SYSUSERSDIR) \
|
||||||
$(DESTDIR)$(TMPFILESDIR) $(DESTDIR)$(DOCDIR) $(DESTDIR)$(DATADIR) \
|
$(DESTDIR)$(TMPFILESDIR) $(DESTDIR)$(DOCDIR) $(DESTDIR)$(DATADIR) \
|
||||||
$(DESTDIR)$(SYSCONFDIR)/default
|
$(DESTDIR)$(COMPLETIONDIR) $(DESTDIR)$(SYSCONFDIR)/default
|
||||||
$(SUBST) bin/terractl > $(DESTDIR)$(BINDIR)/terractl
|
$(SUBST) bin/terractl > $(DESTDIR)$(BINDIR)/terractl
|
||||||
chmod 755 $(DESTDIR)$(BINDIR)/terractl
|
chmod 755 $(DESTDIR)$(BINDIR)/terractl
|
||||||
$(SUBST) systemd/terraria@.service > $(DESTDIR)$(UNITDIR)/terraria@.service
|
$(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 config/tmpfiles.d/terractl.conf $(DESTDIR)$(TMPFILESDIR)/
|
||||||
install -m 644 docs/guide.md $(DESTDIR)$(DOCDIR)/README.md
|
install -m 644 docs/guide.md $(DESTDIR)$(DOCDIR)/README.md
|
||||||
install -m 644 tools/windows/export-tmod-mods.ps1 $(DESTDIR)$(DATADIR)/
|
install -m 644 tools/windows/export-tmod-mods.ps1 $(DESTDIR)$(DATADIR)/
|
||||||
|
install -m 644 completions/bash/terractl $(DESTDIR)$(COMPLETIONDIR)/terractl
|
||||||
@# Never overwrite local settings
|
@# Never overwrite local settings
|
||||||
@if [ -e $(DESTDIR)$(SYSCONFDIR)/default/terractl ]; then \
|
@if [ -e $(DESTDIR)$(SYSCONFDIR)/default/terractl ]; then \
|
||||||
echo "keeping existing $(DESTDIR)$(SYSCONFDIR)/default/terractl"; \
|
echo "keeping existing $(DESTDIR)$(SYSCONFDIR)/default/terractl"; \
|
||||||
@@ -67,7 +70,8 @@ install:
|
|||||||
uninstall:
|
uninstall:
|
||||||
rm -f $(DESTDIR)$(BINDIR)/terractl \
|
rm -f $(DESTDIR)$(BINDIR)/terractl \
|
||||||
$(DESTDIR)$(UNITDIR)/terraria@.service $(DESTDIR)$(UNITDIR)/terraria@.socket \
|
$(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)
|
rm -rf $(DESTDIR)$(DOCDIR) $(DESTDIR)$(DATADIR)
|
||||||
@if [ -z "$(DESTDIR)" ] && [ -d /run/systemd/system ]; then systemctl daemon-reload; fi
|
@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."
|
@echo "Removed. Kept: $(SYSCONFDIR)/default/terractl, /var/lib/terraria and the terraria user."
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ sudo terractl attach calamity
|
|||||||
- **Safe shutdowns.** Stopping a server saves the world first.
|
- **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.
|
- **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.
|
- **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.
|
- **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.
|
- **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
|
bin/terractl The command-line tool
|
||||||
systemd/ terraria@.service and terraria@.socket
|
systemd/ terraria@.service and terraria@.socket
|
||||||
|
completions/bash/ Bash completion for terractl
|
||||||
config/ /etc/default settings, sysusers.d and tmpfiles.d entries
|
config/ /etc/default settings, sysusers.d and tmpfiles.d entries
|
||||||
packaging/deb/ Debian package metadata and install/remove scripts
|
packaging/deb/ Debian package metadata and install/remove scripts
|
||||||
docs/guide.md Full documentation
|
docs/guide.md Full documentation
|
||||||
|
|||||||
@@ -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
@@ -21,7 +21,8 @@ Run any number of vanilla Terraria and tModLoader dedicated servers on one Linux
|
|||||||
15. [Permissions](#permissions)
|
15. [Permissions](#permissions)
|
||||||
16. [Running by hand for debugging](#running-by-hand-for-debugging)
|
16. [Running by hand for debugging](#running-by-hand-for-debugging)
|
||||||
17. [Troubleshooting](#troubleshooting)
|
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
|
## Command reference
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ Depends: unzip, systemd
|
|||||||
Recommends: curl, libicu76 | libicu74 | libicu72 | libicu70 | libicu-dev
|
Recommends: curl, libicu76 | libicu74 | libicu72 | libicu70 | libicu-dev
|
||||||
Conflicts: terraria-instance
|
Conflicts: terraria-instance
|
||||||
Replaces: terraria-instance
|
Replaces: terraria-instance
|
||||||
|
Suggests: bash-completion
|
||||||
Description: run multiple Terraria and tModLoader dedicated servers with systemd
|
Description: run multiple Terraria and tModLoader dedicated servers with systemd
|
||||||
Provides the terraria@.service template and the terractl command for
|
Provides the terraria@.service template and the terractl command for
|
||||||
running any number of vanilla Terraria and tModLoader dedicated servers, each
|
running any number of vanilla Terraria and tModLoader dedicated servers, each
|
||||||
|
|||||||
Reference in new issue
Block a user