diff --git a/README.md b/README.md index 881aacc..66753c1 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,10 @@ You can also run these remotely without a separate `ssh` login step: ssh nik-gpu "~/ba_dailies.sh mailbox" ``` +### Tab completion + +`setup.sh` installs bash tab-completion for the phase argument (`~/ba_dailies.sh sto` -> `story_sweep`) automatically: it copies `completions/ba_dailies.bash` to `~/.ba_dailies_completion.bash` and adds a `source` line to `~/.bashrc` (skipped if already present, so re-running `setup.sh` doesn't duplicate it). Open a new shell (or `source ~/.bashrc`) on `nik-gpu` to pick it up. The completion list is queried live from `ba_daily.py --list-commands` rather than duplicated in the completion script, so it can't drift when a task is added or renamed. + Exit code `0` means the script ran to completion without a Python exception — it does **not** by itself guarantee the in-game action succeeded. `mailbox`, `cafe`, and `stamina` all log what they actually detected and did (or why they safely aborted), so check the log output, not just the exit code. ## How to watch/verify it diff --git a/ba_daily.py b/ba_daily.py index f3bdb91..5eb70b4 100644 --- a/ba_daily.py +++ b/ba_daily.py @@ -24,6 +24,14 @@ DEFAULT_ORDER = ["mailbox", "cafe", "stamina"] def main(argv): args = argv[1:] + if args and args[0] == "--list-commands": + # Machine-readable command list for shell completion (see + # completions/ba_dailies.bash) -- kept as a thin read of TASKS + # itself so the completion list can never drift from what's + # actually dispatchable. + print(" ".join(TASKS.keys())) + return 0 + if not args: for name in DEFAULT_ORDER: TASKS[name](driver, config) @@ -33,6 +41,7 @@ def main(argv): command = args[0] if command not in TASKS: print(f"Unknown phase: {command}", file=sys.stderr) + print(f"Valid phases: {' '.join(TASKS.keys())}", file=sys.stderr) return 1 TASKS[command](driver, config) diff --git a/completions/ba_dailies.bash b/completions/ba_dailies.bash new file mode 100644 index 0000000..d679cc2 --- /dev/null +++ b/completions/ba_dailies.bash @@ -0,0 +1,30 @@ +# Bash tab-completion for ba_dailies.sh's subcommand argument. +# +# Installed automatically by setup.sh (copied to +# ~/.ba_dailies_completion.bash and sourced from ~/.bashrc) -- not meant to +# be sourced manually from the repo checkout, since it shells out to the +# deployed ~/ba_dailies.sh, not this file's own location. +# +# The command list is queried from ba_daily.py itself (--list-commands) +# rather than duplicated here, so it can never drift from the real TASKS +# dict when a task is added, renamed, or removed. + +_ba_dailies_completions() { + local cur + cur="${COMP_WORDS[COMP_CWORD]}" + + # Only the first argument is a phase name; ba_dailies.sh doesn't take + # any further positional args today. + if [ "$COMP_CWORD" -ne 1 ]; then + return 0 + fi + + local commands + commands="$("$HOME/ba_dailies.sh" --list-commands 2>/dev/null)" + COMPREPLY=($(compgen -W "$commands" -- "$cur")) +} + +# Registered under every literal form CLAUDE.md documents running this as. +complete -F _ba_dailies_completions ba_dailies.sh +complete -F _ba_dailies_completions ./ba_dailies.sh +complete -F _ba_dailies_completions ~/ba_dailies.sh diff --git a/setup.sh b/setup.sh index d082b04..7c57306 100755 --- a/setup.sh +++ b/setup.sh @@ -59,6 +59,17 @@ cp ba_daily.py "$HOME/ba_daily.py" rm -rf "$HOME/ba_auto" cp -r ba_auto "$HOME/ba_auto" +echo "== Installing tab completion ==" +cp completions/ba_dailies.bash "$HOME/.ba_dailies_completion.bash" +COMPLETION_LINE='source "$HOME/.ba_dailies_completion.bash"' +if [ -f "$HOME/.bashrc" ] && ! grep -qF ".ba_dailies_completion.bash" "$HOME/.bashrc"; then + printf '\n# Added by ba-auto-daily setup.sh\n%s\n' "$COMPLETION_LINE" >> "$HOME/.bashrc" + echo "Added source line to ~/.bashrc" +else + echo "~/.bashrc already sources it (or doesn't exist) -- left untouched" +fi +echo "Run 'source ~/.bashrc' or open a new shell to pick up completion" + echo "== Done ==" echo "Run with: ~/ba_dailies.sh [mailbox|cafe|stamina|story_sweep|shop_common|shop_tactical|lesson]" echo "(requires the game already running, window titled 'BlueArchive')"