Skip to content

argparse

Compare
Choose a tag to compare
@p-ranav p-ranav released this 21 Sep 04:24
· 203 commits to master since this release

Subcommands

Many programs split up their functionality into a number of sub-commands, for example, the git program can invoke sub-commands like git checkout, git add, and git commit. Splitting up functionality this way can be a particularly good idea when a program performs several different functions which require different kinds of command-line arguments. ArgumentParser now supports the creation of such sub-commands with add_subparser().

#include <argparse/argparse.hpp>

int main(int argc, char *argv[]) {
  argparse::ArgumentParser program("git");

  // git add subparser
  argparse::ArgumentParser add_command("add");
  add_command.add_argument("files")
    .help("Files to add content from. Fileglobs (e.g.  *.c) can be given to add all matching files.")
    .remaining();

  // git commit subparser
  argparse::ArgumentParser commit_command("commit");
  commit_command.add_argument("-a", "--all")
    .help("Tell the command to automatically stage files that have been modified and deleted.")
    .default_value(false)
    .implicit_value(true);

  commit_command.add_argument("-m", "--message")
    .help("Use the given <msg> as the commit message.");

  // git cat-file subparser
  argparse::ArgumentParser catfile_command("cat-file");
  catfile_command.add_argument("-t")
    .help("Instead of the content, show the object type identified by <object>.");

  catfile_command.add_argument("-p")
    .help("Pretty-print the contents of <object> based on its type.");

  // git submodule subparser
  argparse::ArgumentParser submodule_command("submodule");
  argparse::ArgumentParser submodule_update_command("update");
  submodule_update_command.add_argument("--init")
    .default_value(false)
    .implicit_value(true);
  submodule_update_command.add_argument("--recursive")
    .default_value(false)
    .implicit_value(true);
  submodule_command.add_subparser(submodule_update_command);

  // Add the subcommands to the parent parser
  program.add_subparser(add_command);
  program.add_subparser(commit_command);
  program.add_subparser(catfile_command);
  program.add_subparser(submodule_command);

  // Parse args
  try {
    program.parse_args(argc, argv);
  }
  catch (const std::runtime_error& err) {
    std::cerr << err.what() << std::endl;
    std::cerr << program;
    std::exit(1);
  }

  // Use arguments
}
foo@bar:/home/dev/$ ./git --help
Usage: git [options] <command> [<args>]

Optional arguments:
-h --help    	shows help message and exits [default: false]
-v --version 	prints version information and exits [default: false]

Subcommands:
add          	Add file contents to the index
cat-file     	Provide content or type and size information for repository objects
commit       	Record changes to the repository
submodule    	Initialize, update or inspect submodules

foo@bar:/home/dev/$ ./git add --help
Usage: git add [options] files 

Add file contents to the index

Positional arguments:
files        	Files to add content from. Fileglobs (e.g.  *.c) can be given to add all matching files.

Optional arguments:
-h --help    	shows help message and exits [default: false]
-v --version 	prints version information and exits [default: false]

foo@bar:/home/dev/$ ./git submodule --help
Usage: git submodule [options] <command> [<args>]

Initialize, update or inspect submodules

Optional arguments:
-h --help    	shows help message and exits [default: false]
-v --version 	prints version information and exits [default: false]

Subcommands:
update       	Update the registered submodules to match what the superproject expects

When a help message is requested from a subparser, only the help for that particular parser will be printed. The help message will not include parent parser or sibling parser messages.

Additionally, every parser has a .is_subcommand_used("<command_name>") member function to check if a subcommand was used.

You can find relevant unit tests here.