Add Workflows to PhutilArgumentParser
Summary:
Provides a way to build commands that operate in several modes, like "git" and "arc" do.
Basically, we add a new parseWorkflows(workflows) method to PhutilArgumentParser. It works like this:
$args = new PhutilArgumentParser($argv); $args->parsePartial(/* global options */); // Optional, for options all workflows accept. $workflow = $args->parseWorkflows( array( /* ... */ ));
You provide a list of PhutilArgumentWorkflow objects to parseWorkflows(). There are two ways to write those objects:
- Lightweight: Instantiate and configure a PhutilArgumentWorkflow to put options and behavior in the script.
- Heavyweight: Extend PhutilArgumentWorkflow to put all the options and behavior in a class.
The intent is to provide a balance between making this useful for scripting (so you can have a self-contained script that still uses workflows) and for building larger CLI tools like arc.
To build a lightweight workflow, do this:
$workflow = id(new PhutilArgumentWorkflow()) ->setName('example') ->setSynopsis('...') ->setArguments( array( /* Takes specs just like parse() and parsePartial(). */ ));
To build a heavyweight workflow, do this:
class ExampleWorkflow extends PhutilArgumentWorkflow { protected function didConstruct() { $this->setName('...'); $this->setSynopsis('...'); } public function isExecutable() { return true; } public function execute(PhutilArgumentParser $args) { /* do things when user types "./script.php example" */ return 0; } }
With lightweight workflows (which return false from isExecutable()), parseWorkflows() will return the workflow the user selected.
With heavyweight workflows (which return true from isExecutable()), parseWorkflows() will run the workflow and exit with an appropriate status code.
A builtin PhutilHelpArgumentWorkflow allows you to make "script.php help [workflow]" work easily.
I also wrote a simple "calculator" example that should be a good reference.
Test Plan: I've converted phd, but want to test/doc/unit test this more thoroughly.
Reviewers: davidreuss, btrahan, vrana, jungejason
Reviewed By: davidreuss
CC: aran, epriestley
Maniphest Tasks: T345
Differential Revision: https://secure.phabricator.com/D1640