-
Notifications
You must be signed in to change notification settings - Fork 101
Pestle Arguments and Options
Assuming you've created a command
<?php
namespace Pulsestorm\Magento2\Cli\Testbed;
use function Pulsestorm\Pestle\Importer\pestle_import;
pestle_import('Pulsestorm\Pestle\Library\output');
/**
* Test Command
* @command testbed
*/
function pestle_cli($argv)
{
output("Hello World");
}
your next question may be
How do I pass arguments into a pestle command line program.
Things passed to pestle on the command line are split into two categories. Arguments are just that -- arguments to the command
# We're going to use the `runner.php` script in this
# tutorial -- pestle.phar equivalent shown here for
# context
$ php runner.php testbed argument_1 argument_2
$ pestle.phar testbed argument_1 argument_2
If, however, you prepend an argument with two dashes (--
), pestle will consider this an option.
$ php runner.php testbed argument_1 argument_2 --option_1=foo --option_2 foo argument_3
$ pestle.phar testbed argument_1 argument_2 --option_1=foo --option_2 foo argument_3
By default, pestle passes all arguments to the pestle_cli
function as the first parameter, and all options as the second parameter. Pestle passes the parameters as native PHP arrays. For example, the following command
<?php
namespace Pulsestorm\Magento2\Cli\Testbed;
use function Pulsestorm\Pestle\Importer\pestle_import;
pestle_import('Pulsestorm\Pestle\Library\output');
/**
* Test Command
* @command testbed
*/
function pestle_cli($arguments, $options)
{
foreach($arguments as $key=>$value)
{
output($key . '::' . $value);
}
foreach($options as $key=>$value)
{
output($key . '::' . $value);
}
}
Will produce the following output
$ php runner.php testbed argument_1 argument_2 --option_1=foo --option_2 foo argument_3
0::argument_1
1::argument_2
2::argument_3
option_1::foo
option_2::foo
As you can see, arguments are passed as an numerically indexed array, and options as a string-indexed array.
Pestle has a simple function for accepting user input. You can import it from the module library with
pestle_import('Pulsestorm\Pestle\Library\input');
and then use it like this
function pestle_cli($arguments, $options)
{
$ask = input("Enter a value");
output("You entered: " . $ask);
}
Running the following program
<?php
namespace Pulsestorm\Magento2\Cli\Testbed;
use function Pulsestorm\Pestle\Importer\pestle_import;
pestle_import('Pulsestorm\Pestle\Library\output');
pestle_import('Pulsestorm\Pestle\Library\input');
/**
* Test Command
* @command testbed
*/
function pestle_cli($arguments, $options)
{
$ask = input("Enter a value",'default');
output("You entered: " . $ask);
}
will product the following output, with the program pausing for user input.
$ php runner.php testbed
Enter a value (default)] Great!
You entered: Great!
Most other PHP command line frameworks have something similar. However, one of the high level goals for pestle's commands is that all commands be runnable without the need to pause for user input -- i.e., anything that and end user might input should be available as a command option. To help facilitate this, pestle parses the PHP Doc Block at the top of the pestle_cli
function for arguments and options.
You can add an arguments to your program using the @argument
identifier
/**
* Test Command
* @command testbed
* @argument argument_name Please enter a value for argument_name [the default value]
*/
function pestle_cli($arguments, $options)
{
output($arguments['argument_name']);
}
If you run the above program with no arguments, pestle will prompt you for the missing argument
$ php runner.php testbed
Please enter a value for argument_name (the default value)]
However, if you pass in an argument, pestle will run without prompting.
$ php runner.php testbed 'First argument'
First argument
When using the @argument
syntax, pestle will pass in $arguments
as a string indexed PHP array.
output($arguments['argument_name']);
As for the @argument
value itself
* @argument argument_name Please enter a value for argument_name [the default value]
The first bit of text (argument_name
) is the key you want for your argument. The next bit of text is the question pestle uses when asking end-users for a missing argument value. If you include a value inside two brackets ([]
), pestle will use that value for the default.
If you're using @argument
identifiers, pestle will ignore any additional un-configured arguments passed in. Consider the following program
/**
* Test Command
* @command testbed
* @argument argument_name Please enter a value for argument_name [the default value]
*/
function pestle_cli($arguments, $options)
{
foreach($arguments as $key=>$value)
{
output($key . '::' . $value);
}
}
//...
and the output from that program
$ php runner.php testbed first_argument second_argument
argument_name::first_argument
As you can see, pestle ignores the second_argument
. If you want your program to recognize this, you'll need to add a second @argument
.
/**
* Test Command
* @command testbed
* @argument argument_name Please enter a value for argument_name [the default value]
* @argument argument_foo Don't forget the other value [the default value]
*
*/
Run the program with the above doc block, and should see the following
$ php runner.php testbed first_argument second_argument
argument_name::first_argument
argument_foo::second_argument
Pestle features a special callback argument type. Consider the following program.
function exampleOfACallback($arguments, $index)
{
return 'Value of Argument';
}
/**
* Test Command
* @command testbed
* @argument foobar @callback exampleOfACallback
*/
function pestle_cli($arguments, $options)
{
output($arguments['foobar']);
}
Here we've configured a argument named foobar
. Immediately after the argument's name, we've entered the string @callback
. This lets pestle know foobar
is a callback argument. Then, the final string, exampleOfACallback
is a function local to this program's module. Pestle will call the exampleOfACallback
function to get the value for the foobar
argument.
This is a powerful feature, most useful if you want to ask a complex series of questions to determine the value of a single argument in pestle. You can see an example of this in the generate_menu
command.
* @argument parent @callback selectParentMenu
//...
function selectParentMenu($arguments, $index)
{
if(array_key_exists($index, $arguments))
{
return $arguments[$index];
}
$parent = '';
$continue = input('Is this a new top level menu? (Y/N)','N');
if(strToLower($continue) === 'n')
{
$parent = choseMenuFromTop();
}
return $parent;
}
Here we have a @argument
named parent
, configured as a @callback
, with the function selectParentMenu
. In selectParentMenu
, you can see we're using the input
function to ask the user a question, and then take different code paths depending on the answers.
While this feature is powerful, it does introduce the possibility of creating a command that requires user interaction, so use it with caution. One of pestle's goals is all interactive questions in a command should be passable @arguments
. That's why pestle, when it calls the callback, will pass in the entire list of command arguments, as well as the index of the current argument.
function selectParentMenu($arguments, $index)
This allows you, if you wish, to just return the value a user passed in. You can see this with the selectParentMenu
callback above.
function selectParentMenu($arguments, $index)
{
if(array_key_exists($index, $arguments))
{
return $arguments[$index];
}
//...
}