Feature request: default subcommand
CGamesPlay opened this issue · 5 comments
Hi @sigoden, continuing to love using argc for all of my shell scripts. One pattern that I see coming up sometimes is a desire for a "default subcommand". Basically, I have a script called "backup", and I want it to... perform a backup. But I also want to add subcommands, like "backup verify" or "backup restore". With the current system, I can't do this, because the main command is completely masked by the presence of subcommands.
So the feature request is for the ability to designate a subcommand as a "default" one. Something like this:
#!/usr/bin/env bash
# @cmd
# @default_subcommand
backup() { :; }
# @cmd
restore() { :; }
eval "$(argc --argc-eval "$0" "$@")"
This script could be invoked as argc; argc backup; argc restore
. Now, this behavior would cause ambiguity with positional arguments. For example, if the backup
subcommand accepted arguments, should argc $PARAM
be an error, or invoke argc backup $PARAM
? What if $PARAM
was restore
? So, in order for a subcommand to be eligible as a default subcommand, it cannot accept any positional arguments.
Ideally this feature would also work with nested subcommands in the same way, so e.g. with 3 subcommands backup; backup::incremental; backup::full
I could designate backup::incremental
as the default for the backup
command (which again could be the default subcommand for the overall script).
It would be nice if the shell completion also understood when a command was the default and showed arguments for that subcommand when there wasn't one given.
Thanks again for the consideration. Loving the activity on this project!
use main
function.
# @cmd
backup() { :; }
# @cmd
restore() { :; }
main() {
backup
}
eval "$(argc --argc-eval "$0" "$@")"
# @cmd
backup() { :; }
# @cmd
backup::incremental() { :; }
# @cmd
backup::full() { :; }
backup::main() {
backup::incremental
}
eval "$(argc --argc-eval "$0" "$@")"
Amazing. Works like a charm.
One quirk I found while playing with it is that the main command really only works if it doesn't take arguments/options/flags. If you need any of these, you have to specify the main function as a separate @cmd
. It can still be invoked using the parent command, but you can't pass any parameters to it when you invoke it this way. Example: in the following, argc; argc main --incremental
both work, but argc --incremental
does not.
# @cmd
restore() { :; }
# @cmd
# @option --incremental
main() { :; }
eval "$(argc --argc-eval "$0" "$@")"
It would be nice to be able to use the normal @option/@flag
with the main function without using @cmd
, like this:
# @cmd
restore() { :; }
# @option --incremental
main() { :; }
eval "$(argc --argc-eval "$0" "$@")"
Again, allowing @arg
invites ambiguity, so maybe that one should be disabled.