Giter Club home page Giter Club logo

commando's Introduction

Commando

An Elegant PHP CLI Library

Commando is a PHP command line interface library that beautifies and simplifies writing PHP scripts intended for command line use.

Why?

PHP's $argv magic variable and global $_SERVER['argv'] make me cringe, getopt isn't all that much better, and most other PHP CLI libraries are far too bloated for many cases. Commando gets down to business without a ton of overhead, removes the common boilerplate stuff when it comes to handling CLI input, all while providing a clean and readable interface.

Installation

Commando requires that you are running PHP 8.1 or higher.

Commando is PSR-0 compliant and can be installed using Composer. Add nategood/commando to your composer.json

"require": {
    "nategood/commando": "*"
}

If you're new to Composer...

Currently installing via Composer is the only supported option.

Example

Here is an example of a PHP Commando script that gives a decent tour of Commando's features. Let's say it is in a file called hello.php.

<?php

require_once 'vendor/autoload.php';

$hello_cmd = new Commando\Command();

// Define first option
$hello_cmd->option()
    ->require()
    ->describedAs('A person\'s name');

// Define a flag "-t" a.k.a. "--title"
$hello_cmd->option('t')
    ->aka('title')
    ->describedAs('When set, use this title to address the person')
    ->must(function($title) {
        $titles = array('Mister', 'Mr', 'Misses', 'Mrs', 'Miss', 'Ms');
        return in_array($title, $titles);
    })
    ->map(function($title) {
        $titles = array('Mister' => 'Mr', 'Misses' => 'Mrs', 'Miss' => 'Ms');
        if (array_key_exists($title, $titles))
            $title = $titles[$title];
        return "$title. ";
    });

// Define a boolean flag "-c" aka "--capitalize"
$hello_cmd->option('c')
    ->aka('capitalize')
    ->aka('cap')
    ->describedAs('Always capitalize the words in a name')
    ->boolean();

// Define an incremental flag "-e" aka "--educate"
$hello_cmd->option('e')
    ->aka('educate')
    ->map(function($value) {
        $postfix = array('', 'Jr', 'esq', 'PhD');
        return $postfix[$value] === '' ? '' : " {$postfix[$value]}";
    })
    ->count(4);

$name = $hello_cmd['capitalize'] ? ucwords($hello_cmd[0]) : $hello_cmd[0];

echo "Hello {$hello_cmd['title']}$name{$hello_cmd['educate']}!", PHP_EOL;

Running it:

> php hello.php Nate
Hello, Nate!

> php hello.php --capitalize nate
Hello, Nate!

> php hello.php -c -t Mr 'nate good'
Hello, Mr. Nate Good!

> php hello.php -ceet Mr 'nate good'
Hello, Mr. Nate Good esq!

Things to note:

  • Commando implements ArrayAccess so it acts much like an array when you want to retrieve values for it
  • For "anonymous" (i.e. not a named flag) arguments, we access them based on their numeric index
  • We can access option values in an array via a flags name OR its alias
  • We can use closures to perform validation and map operations right as part of our option definition

Baked in Help

Commando has automatic --help support built in. Calling your script with this flag will print out a pretty help page based on your option definitions and Commando settings. If you define an option with the alias of 'help', it will override this built in support.

help screenshot

Error Messaging

By default, Commando will catch Exceptions that occur during the parsing process. Instead, Commando prints a formatted, user-friendly error message to standard error and exits with a code of 1. If you wish to have Commando throw Exceptions in these cases, call the doNotTrapErrors method on your Command instance.

error screenshot

Command Methods

These options work on the "command" level.

useDefaultHelp (bool help)

The default behavior of Commando is to provide a --help option that spits out a useful help page generated off of your option definitions. Disable this feature by calling useDefaultHelp(false)

setHelp (string help)

Text to prepend to the help page. Use this to describe the command at a high level and maybe some examples usages of the command.

printHelp()

Print the default help for the command. Useful if you want to output help if no arguments are passed.

beepOnError (bool beep=true)

When an error occurs, print character to make the terminal "beep".

getOptions

Return an array of Options for each options provided to the command.

getFlags

Return an array of Options for only the flags provided to the command.

getArguments

Return an array of Options for only the arguments provided to the command. The order of the array is the same as the order of the arguments.

getFlagValues

Return associative array of values for arguments provided to the command. E.g. array('f' => 'value1').

getArgumentValues

Return array of values for arguments provided to the command. E.g. array('value1', 'value2').

Command Option Definition Methods

These options work on the "option" level, even though they are chained to a Command instance

option (mixed $name = null)

Aliases: o

Define a new option. When name is set, the option will be a named "flag" option. Can be a short form option (e.g. f for option -f) or long form (e.g. foo for option --foo). When no name is defined, the option is an anonymous argument and is referenced in the future by its position.

flag (string $name)

Same as option except that it can only be used to define "flag" type options (a.k.a. those options that must be specified with a -flag on the command line).

argument ()

Same as option except that it can only be used to define "argument" type options (a.k.a those options that are specified WITHOUT a -flag on the command line).

alias (string $alias)

Aliases: a, aka

Add an alias for a named option. This method can be called multiple times to add multiple aliases.

description (string $description)

Aliases: d, describe, describedAs

Text to describe this option. This text will be used to build the "help" page and as such, it is end user facing.

require (bool $require)

Aliases: r, required

Require that this flag is specified

needs (string|array $options)

Aliases: none

Require that other $options be set for this option to be used.

must (Closure $rule)

Aliases: N/A

Define a rule to validate input against. Takes function that accepts a string $value and returns a boolean as to whether or not $value is valid.

map (Closure $map)

Aliases: cast, castTo

Perform a map operation on the value for this option. Takes function that accepts a string $value and return mixed (you can map to whatever you wish).

reduce (Closure $reducer [, mixed $seed])

Aliases: list, each, every

Execute an accumulator/reducer function on every instance of the option in the command. Takes an accumulator function, and returns mixed (you can return any value). If you also supply a map for the option the map will execute on every value before it is passed to the accumulator function. If $seed value is supplied, this will be used as the default value.

Signature: function(mixed $accumulated, mixed $value) : mixed

  • $accumulated: null|Option::default|mixed (the last value returned from the function, the option default value, or null.)
  • $value: mixed (the value that comes after the option. if map is supplied, the value returned from the map function.)
  • return: mixed (anything you want. The last value returned becomes the value of the Option after parsing.)

referToAs (string $name)

Aliases: title, referredToAs

Add a name to refer to an argument option by. Makes the help docs a little cleaner for anonymous "argument" options.

boolean ()

Aliases: N/A

Specifices that the flag is a boolean type flag.

increment (int $max)

Aliases: i, count, repeats, repeatable

Specifies that the flag is a counter type flag. The value of the flag will be incremented up to the value of $max for each time the flag is used in the command. Options that are set to increment or boolean types can be grouped together.

default (mixed $defaultValue)

Aliases: defaultsTo

If the value is not specified, default to $defaultValue.

In the case of boolean() type flags, when the flag is present, the value of this option the negation of $defaultValue. That is to say, if you have a flag -b with a default of true, when -b is present as a command line flag, the value of the option will be false.

file ()

Aliases: expectsFile

The value specified for this option must be a valid file path. When used relative paths will be converted into fully quantify file paths and globbing is also optionally supported. See the file.php example.

boolean ()

Aliases: N/A

Specifices that the flag is a boolean type flag.

default (mixed $defaultValue)

Aliases: defaultsTo

If the value is not specified, default to $defaultValue.

In the case of boolean() type flags, when the flag is present, the value of this option the negation of $defaultValue. That is to say, if you have a flag -b with a default of true, when -b is present as a command line flag, the value of the option will be false.

file ()

Aliases: expectsFile

The value specified for this option must be a valid file path. When used relative paths will be converted into fully quatified file paths and globbing is also optionally supported. See the file.php example.

Contributing

Commando highly encourages sending in pull requests. When submitting a pull request please:

  • All pull requests should target the dev branch (not master)
  • Make sure your code follows the coding standards laid out in PSR-1 and PSR-2
  • Make sure you add appropriate test coverage for your changes
  • Run all unit tests in the test directory via phpunit ./tests
  • Include commenting where appropriate and add a descriptive pull request message

Inspiration

Released under MIT license.

Change Log

v1.0.1

  • Add support for negative numbers not to be misinterpreted as bad options.

v1.0.0

  • Dropping support for anything before PHP 8.1

v0.4.0

  • Dropping support for 5.4 and 5.5, bumping minor version number
  • PR #93 FEATURE Add reducer option
  • PR #95 FIX Remove tput call on Windows OS
  • PR #101 FIX Only evaluate 'needs' constraints of an option if that option is actually used
  • PR #76 FIX Fix non-empty getArgumentValues array when using anonymous args

v0.3.0

  • Dropped PHP 5.3

v0.2.9

  • PR #63 FEATURE incremental flags
  • PR #60 MINOR getDescription method

v0.2.8

  • Bug fix for #34

v0.2.7

  • getOptions added (along with some better documentation)

v0.2.6

  • Adds support for "needs" to define dependencies between options (thanks @enygma) PR #31
  • Fixes issue with long-argument-names Issue #30

v0.2.5

  • Fixed up default values for boolean options, automatically default boolean options to false (unlikely, but potentially breaking change) PR #19

v0.2.4

  • Added ability to define default values for options

v0.2.3

  • Improved Help Formatting PR #12

v0.2.2

  • Bug fix for printing double help PR #10

v0.2.1

  • Adds support for requiring options to be valid file paths or globs
  • Returns a fully qualified file path name (e.g. converts relative paths)
  • Returns an array of file paths in the case of globbing
  • See the file.php example in the examples directory

v0.2.0

The primary goal of this update was to better delineate between flag options and argument options. In Commando, flags are options that we define that require a name when they are being specified on the command line. Arguments are options that are not named in this way. In the example below, '-f' and '--long' are described as "flags" type options in Commando terms with the values 'value1' and 'value2' respectively, whereas value3, value4, and value5 are described as "argument" type options.

php command.php -f value1 --long value2 value3 value4 value5
  • Added Command::getArguments() to return an array of Option that are of the "argument" type (see argumentsVsFlags.php example)
  • Added Command::getFlags() to return an array of Option that are of the "flag" type (see argumentsVsFlags.php example)
  • Added Command::getArgumentValues() to return an array of all the values for "arguments"
  • Added Command::getFlagValues() to return an array of all values for "flags"
  • Command now implements Iterator interface and will iterator over all options, starting with arguments and continuing with flags in alphabetical order
  • Can now define options with Command::flag($name) and Command::argument(), in addition to Command::option($name)
  • Added ability to add a "title" to refer to arguments by, making the help docs a little cleaner (run help.php example)
  • Cleaned up the generated help docs
  • Bug fix for additional colorized red line when an error is displayed

v0.1.4

  • Bug fix for options values with multiple words

v0.1.3

  • Beep support added to Terminal
  • Commando::beepOnError() added

v0.1.2

  • Terminal updated to use tput correctly

commando's People

Contributors

13leaf avatar abreksa4 avatar alexander-perez avatar basuke avatar bitdeli-chef avatar dudemullet avatar erusev avatar garyrogers avatar inquam avatar jalle19 avatar mackenza avatar michielroding avatar nategood avatar neovance avatar omnicolor avatar orthographic-pedant avatar robinkanters avatar rougin avatar thomaswunderlich avatar unstoppablecarl avatar volnix avatar zhaofengli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

commando's Issues

New release

Can you make a new release for the latest fixes?

--help, SORT_NATURAL constant, requires PHP 5.4

/**

around line 589, Command.php, the code should be changed to:
// sort($keys, SORT_NATURAL);
natsort($keys);

"SORT_NATURAL" constant was added in PHP 5.4. While you are trying to support 5.3.

Without this change, PHP5.3 gives errors/warnings.

getOptions() method missing?

readme.md contains decriptions about getOptions() method, but I cannot find it in the source code. How can I get all registered options from Command's subclass ? ( This method could be very useful for customizing help message )

How do I determine when a flag is actually passed into the cmd session?

I know I must be missing something here, but what is the actual process of determining when a predefined flag is passed into the script endpoint? I've resorted to writing my own function to parse the $_SERVER['argc'] array.

Pretty sure the library is supposed to be taking care of this for me already, right?

Documentation could use a little updating

  • "Command Option Definition Methods" section is missing the boolean() option
  • Documentation has no mention at all of default() option, or examples of it

Great library, though! Just discovered it and am working to figure it out fully!

Long parameter with dash

How can I create params with dash in it?
I tried this: (new Command)->option('reset-list')->boolean() then I call my script this:

$ php test.php --reset-list
ERROR: Unknown option, reset, specified 

The help shows the param correctly:

$ php test.php --help
 test.php                                                                                                                                                                                                    


--help
     Show the help page for this command.


--reset-list

Get all remaining items

If i've configured argument parsing for x and y, in scenarios below what is the best way to retrieve all tokens after the last parsed argument?

script.php -x arg1 -y arg2 everything else that's here
script.php -x arg1 everything else that's here

I can achieve a variable containing everything else that's here but only if I enclose it in quotes. Any way to do this without quotes?

getValue() not working

echo $command['n] successfully returns what's passed as -n, but $command->getOption('n')->getValue() returns nothing

Closures vs callable

I was wondering if there was a particular reason why you're type hinting to \Closure instead of the less restrictive \Callable?

Autoparsing on get option causes later option rules not to trip

Given this script:

$cmd = new \Commando\Command();

// Define an option
$cmd->option("t");

// If that option is a certain value, then define another option (this causes autoparsing)
if ($cmd['t'] == 'something') {
    // do something, like perhaps define other options
}

// Now define a required option. Because we've already parsed the options, the rules
// for this option won't cause an error when really they should.
$cmd->option("e")
    ->required()
    ->must(function($t) {
        return preg_match("/^[^0-9]+$/", $t);
    }); 


// Try to echo the required 'e' option. Script should not get to this point, but does,
// and also doesn't throw an error here.
echo $cmd['e'];

Expected Behavior

  • With option 'e' not given: should show an error and stop execution when required called on option 'e'.
  • With option 'e' given, but not matching regexp: should show an error and stop execution when must called on option 'e'.
  • With option 'e' given and correct, should echo the value of option 'e'.

Actual Behavior

Does not show any errors at all, and outputs any value given for option 'e'.

tputs is sometimes tput

I just checked on two systems: Ubuntu 10.04.4 LTS and Mac OS X 10.7.4 Lion: tputs is not installed, but instead uses tput. I think this might be a change in the ncurses library? Use of tputs

No support for --option=value

A lot of commands use this syntax, not sure how standard it is, but I think supporting it would help prevent confusion.

Help doesn't short circuit

Probably related to #75, the --help option doesn't short circuit unless you're accessing an option via the array access interface.

option->map() is not called on default value

for example, if I call $command->option("foo")->default() and then followed by another map() call, the closure passed to map() is not called on the default value. Is this intentional (design?) or this is a bug?

let me know if you need further information

--help "Could not find the specified path"

--help command gives me Could not find the specified path.

PHP code:

<?php

require_once 'vendor/autoload.php';

use Commando\Command;

// command config
$cmd = new Command;
$cmd
    ->setHelp('This is a great command it.  It can be used by calling `run <argument>`.')
    ->option()->referToAs('the first arg')->describeAs('run takes an optional single argument. e.g. run argument0')
    ->option('a')->description("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.")
    ->option('b')->boolean()->describeAs("A boolean option.")
    ->option('c')->aka('foo')->describeAs("Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt.")->required();

Output:

C:\Users\MYUSER\Desktop\myscript>php index.php --help
Could not find the specified path.
Could not find the specified path.
Could not find the specified path.
Could not find the specified path.
Could not find the specified path.
Could not find the specified path.
Could not find the specified path.
 index.php

This is a great command it.  It can be used by calling `run <argument>`.

the first arg
     run takes an optional single argument. e.g. run argument0


-a <argument>
     Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
     tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
     veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
     commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
     velit esse cillum dolore eu fugiat nulla pariatur.


-b
     A boolean option.


-c/--foo <argument>
     Required. Excepteur sint occaecat cupidatat non proident, sunt in culpa
     qui officia deserunt.


--help
     Show the help page for this command.

composer.json:

{
    "name": "my/my",
    "description": "my",
    "require": {
        "nategood/commando": "^0.2.9"
    },
    "authors": [
        {
            "name": "me",
            "email": "[email protected]"
        }
    ]
}

I am on Windows

Feture Request: conflictsWith (oppositive than needs)

Let's have

$cmd->flag('a')->boolean();
$cmd->flag('b')->boolean()->conflictsWith('c');
$cmd->flag('c')->boolean();

to get the following result:
PASS: (no args), -a, -b, -c, -ab, -ac
FAIL: -bc, -abc

(Please use thumb to +1 instead reply unless you are adding additional information.)

any more complex examples?

I am trying to figure out how to properly write my commands. All the examples are essentially linear main() PHP programs. I am trying to figure out if that is a good practice or whether I should be making a class to define my options and such to make it more OOP.

Just wondering if anyone has opinions or examples I could see?

New version

Can you make a new version so we have the latest fixes in a stable build?

Impossible to read filename or '-'

It's very common for a file processing script to either take the filename OR '-' to get data from stdin.
With this library I cannot do this:

php convert.php input.log
php convert.php - < input.log

Whenever I pass "-" it says

ERROR: Unable to parse option -: Invalid syntax

My definition was like:

  $cmd->option()
    ->require()
    ->describedAs('Input log file or `-` to read from stdin');

and value reading part was as simple as:

  $filename = $cmd[0];

Errors do not bubble up...

try {
  throw new \Exception('Expect to see error caught');
} catch (\Throwable $t) {
  var_dump($t->getMessage());
}

But in your library...

$cmd = CMD::getInstance()->doNotTrapErrors();
try {
  $cmd->option('r')
    ->require()
    ->aka('run')
    ->describedAs('When set, use this title to address the person');
} catch (\Throwable $t) {
  var_dump('caught');
}

Never gets to that statement var_dump('caught');

Instead it just dumps out the error and dies...

PHP Fatal error:  Uncaught Exception: Required option r must be specified in /var/www/nano/vendor/nategood/commando/src/Commando/Command.php:466
Stack trace:
#0 /var/www/nano/vendor/nategood/commando/src/Commando/Command.php(164): Commando\Command->parse()
#1 [internal function]: Commando\Command->__destruct()
#2 {main}
  thrown in /var/www/nano/vendor/nategood/commando/src/Commando/Command.php on line 466

Fatal error: Uncaught Exception: Required option r must be specified in /var/www/nano/vendor/nategood/commando/src/Commando/Command.php on line 466

Exception: Required option r must be specified in /var/www/nano/vendor/nategood/commando/src/Commando/Command.php on line 466

Call Stack:
    0.0237     585528   1. Commando\Command->__destruct() /var/www/nano/vendor/nategood/commando/src/Commando/Command.php:0
    0.0237     585528   2. Commando\Command->parse() /var/www/nano/vendor/nategood/commando/src/Commando/Command.php:164
    0.0239     589064   3. Commando\Command->error() /var/www/nano/vendor/nategood/commando/src/Commando/Command.php:498

Too add:

   public function run(){
      if (!$this->parsed) {
          $this->parse();
      }
    }

    public function __destruct()
    {
        if (!$this->parsed) {
            $this->parse();
        }
    }

Created an identical function run(), when called (in sequence) the error is now caught properly. Is the a PHP issue whereby thrown \Exception after destruct? No idea...

try {
  $cmd = CMD::getInstance()->doNotTrapErrors();
  $cmd->option('r')
    ->require()
    ->aka('run')
    ->describedAs('When set, use this title to address the person')
    ->run();
} catch (\Throwable $t) {
  var_dump('now gets here when run() is used');
}

Fixed in #69

Feature request: create new `transform` method that both maps and validates values

Instead of Issue #86, perhaps it makes more sense to implement a transform method that handles both validation and value mapping.

I have certain options that accept simple json strings as values, for example. These will require both a transformation from string to php array, and also certain object-specific validations.

To handle this well, I'll need the ability to deliver fine-grained error messages and also the ability to parse the value only once, rather than parsing the value for validation, then parsing again for mapping.

Here's how I see this working:

$cmd->option("t")
    ->require()
    ->transform(function($val) {
        $val = json_decode($val, true);
        if (!$val) {
            throw new OptionValidationException("You must provide a valid json-encoded object for option 't'");
        }

        $errors = [];
        if (empty($val['prop1']) || !is_string($val['prop1'])) {
            $errors[] = "`prop1` of option 't' must be a string";
        }
        if (empty($val['prop2']) || !preg_match("/^[a-fA-F0-9-]{32,36}$/", $val['prop2'])) {
            $errors[] = "`prop2` of option 't' must be a valid GUID or UUID"
        }

        if (!empty($errors)) {
            $e = new OptionValidationException("");
            $e->setOptionValidationErrors($errors);
            throw $e;
        }

        if (empty($val['prop3'])) {
            $val['prop3'] = 0;
        } elseif (!is_int($val['prop3'])) {
            $val['prop3'] = (int)$val['prop3'];
        }

        // Return the transformed value for the option
        return $val;
    });

Hyphenated names fail

If you have an option/flag with a hyphen in the middle of its name, Commando accepts it but only parses the received argument's name up to the hyphen.

Example:

<?php
$cmd = new Commando\Command();

$cmd->option('basicarg');
$cmd->option('hyphen-arg');

var_dump($cmd['basicarg']);
var_dump($cmd['hyphen-arg']);

Calls:

$ php script.php --basicarg hello
string(5) "hello"
NULL

$ php script.php --hyphen-arg hello
ERROR: Unknown option, hyphen, specified 

The main sample is not work

Subj. I copy sample and run it:

php /srv/bitrix/batches/user_generation.php --title=Mister
ERROR: Invalid value, , for option t

The problem in must method:

->must(function($title) {
        var_dump($title); // *always null*
        $titles = array('Mister', 'Mr', 'Misses', 'Mrs', 'Miss', 'Ms');
        return in_array($title, $titles);
    })

PHP 5.6.32 (cli) (built: Oct 25 2017 07:00:59)

"Needs" behaviour

Needs behaves a bit strangely and should interact with "requires" but doesn't. It's actually acting as a defacto "requires". Even if a "needed" command isn't "required" Commando will still throw an exception if it is specified as needed by an unused argument.

E.g

$cmd
->option("a");

$cmd->option("b")
    ->needs("c")

$cmd->option("c");

The following command should run:

filename.php --a --b --c

Only this should fail

filename.php --a --b

But this also (incorrectly) fails:

filename.php --a

In the last one the "needs" clause says that "b needs c" even though c isn't a required argument and b wasn't even specified.

The fix in my local branch is to replace the current "needs" block in Command.php with the following:

    // See if our options have what they require
            foreach ($keyvals as $key => $value) {
                $option = $this->getOption($key);
                if(!is_null($option->getValue()) || $option->isRequired()){
                    $needs = $option->hasNeeds($this->options);
                    if ($needs !== true) {
                        throw new \InvalidArgumentException(
                            'Option "'.$option->getName().'" does not have required option(s): '.implode(', ', $needs)
                        );
                    }
                }
            }

But I'd like to know if the current behaviour of "needs" also acting as a defacto "requires" is actually the desired behaviour before I upload it and submit a pull request.

Windows – Color not working

Hi

Using windows environment
try to use --help, got this errors, just right before filename appeared=

The system cannot find the path specified.
The system cannot find the path specified.
The system cannot find the path specified.

Yes, 3 in a row.

Thanks

Option repetition (mostly for verbosity 'levels') ?

Is there a clean way to implement this using the existing code? Or would it need to be a new feature?

Think ssh -v[vvvvvv...] (incrementing levels of verbosity if the option is repeated)

Note that with ssh, it functions the same with: ssh -v -v -v -v example.com and ssh -vvvv example.com

I don't recall ever seeing this type of "option repetition" used with anything other than verbosity levels, and I'm not sure if that's even a GNU utility psuedo-standard, or if it's just specific to ssh and a few other oddball utilities, but it is handy. I'd actually like to use that for a project I'm building, using your Commando library that wraps around ssh, and would like to provide the same -v[vvv...] functionality if possible. Ideas?

I love your work on this by the way -- great library.

Grouping Requirements

I know you can require single commands, eg:

$command->option('t')->require(true);
$command->option('b')->require(true);

Is it possible to do something like this:

$command->option('t')->requireOr('b');
$command->option('b')->requireOr('t');

$command->option('t')->requireAndOr('b');
$command->option('b')->requireAndOr('t');

deployment of CLI

I am in the process of writing a CLI for a framework/ORM (see my comments in #20 for more details).

One thing I am wondering about is how the completed CLI is intended to be deployed. This is, perhaps, not really an issue per se but GitHub only allows issues and no true discussions so here goes...heh).

So assuming my CLI is part of a Composer package for framework (or vice verse, I could make the framework a dependency of my CLI package). I don't think it's good practice to run PHP directly from the vendor folder and the CLI will need the context of the app being developed (environment, etc).

I notice that most frameworks have the base/core in one repository and then have a skeleton or bootstrap repository from which the actual app is built from. Is that the best way to deploy a CLI using Commando?

Any thoughts?

Undefined constant SORT_NATURAL on PHP 5.3

When printing the '--help' on PHP 5.3, the following notice and warning occures:

PHP Notice: Use of undefined constant SORT_NATURAL - assumed 'SORT_NATURAL' in Command.php on line 589

PHP Warning: sort() expects parameter 2 to be long, string given in Command.php on line 589

--help doesn't work

When executing the examples/help.php example, if the last line ($cmd->printHelp();) is removed, the help message doesn't work, even if the script is called with the --help flag.

->file() option with dynamic default must come last?

I want to set the default value for a ->file() option based on the value of another option. This appears to work only if the ->file() option is the last one defined. Examples:

#!/usr/bin/env php
<?php

require_once 'vendor/autoload.php';

$cmd = new Commando\Command();

$cmd->option()
    ->require()
    ->describedAs('Output directory.');

$cmd->option('t')
    ->aka('type')
    ->describedAs('Type of thing to process.');

// Hard-coded value for default() works.
$cmd->option('c')
    ->aka('connfigfile')
    ->describedAs('The config file to use.')
    ->file()
    ->default('configs/foo.yml');

$cmd->option('n')
    ->aka('number')
    ->describedAs('The number of things to process.');

Running ./file_test.php -n 10 -t foo /tmp does not produce an error. But if set the default value of the ->file() option based on the value of another option:

#!/usr/bin/env php
<?php

require_once 'vendor/autoload.php';

$cmd = new Commando\Command();

$cmd->option()
    ->require()
    ->describedAs('Output directory.');

$cmd->option('t')
    ->aka('type')
    ->describedAs('Type of thing to process.');

// Dynamically generated value for default() produces error.
$cmd->option('c')
    ->aka('connfigfile')
    ->describedAs('The config file to use.')
    ->file()
    ->default('configs/' . $cmd['type'] . '.yml');

// Now this option is not recognized.
$cmd->option('n')
    ->aka('number')
    ->describedAs('The number of things to process.');

running ./file_test.php -n 10 -t foo /tmp produces ERROR: Unknown option, n, specified.

However, if the ->file() option is the last option defined, its default value can be dynamically generated:

#!/usr/bin/env php
<?php

require_once 'vendor/autoload.php';

$cmd = new Commando\Command();

$cmd->option()
    ->require()
    ->describedAs('Output directory.');

$cmd->option('t')
    ->aka('type')
    ->describedAs('Type of thing to process.');

$cmd->option('n')
    ->aka('number')
    ->describedAs('The number of things to process.');

// Dynamically generated value for default() works.
$cmd->option('c')
    ->aka('connfigfile')
    ->describedAs('The config file to use.')
    ->file()
    ->default('configs/' . $cmd['type'] . '.yml');

Running ./file_test.php -n 10 -t foo /tmp does not produce an error.

Is this expected behavior, or am I missing something obvious?

Multiple valued option - how to?

I want to declare an option which could be invoked several times, e.g.:

--option value1 --option value2 --option value3

This is similar to what tar have for files exclusion, .e.g

$ tar --exclude='./folder' --exclude='./upload/folder2' -zcvf /backup/filename.tgz .

I cannot find a way how to do this, or I'm missing something?

Needs() method looking at the wrong thing?

Either the needs method isn't working, or my understanding of what it's supposed to do isn't working.

Say you've got a script with two options: -t and -e. If you use -t, you must include -e with a value. According to the documentation, needs('e') on the -t option would require the -e option to be set. However, that doesn't seem to be the case.

For example:
<?php
require_once 'vendor/autoload.php';

$cmd = new Commando\Command();
$cmd->option('e');
$cmd->option('t')
    ->boolean()
    ->needs('e');

var_dump($cmd['e']);
var_dump($cmd['t']);

It appears that when it's checking to see if the -e option is set, it actually is just checking to see if there is a -e option defined (src/Commando/Option.php: 305) not that it has been passed in by the user.

I'm willing to fix the issue if this isn't how the method is intended to behave.

Value of option argument not getting set

Value isn't getting set when passing a argument to a option

use Commando\Command;

$tokens = array('status');
$cmd = new Command($tokens);
$cmd->setHelp('This tool is for managing status from the cli. It takes no arguments just options that take arguments')
    ->option()->describe('status take a optional single action argument. e.g. status {create|view|update}')
    ->option('m')->aka('message')->describe('This is message you wish to use with create or update. wrap in double quotes or vim will be used');
var_dump($cmd->getOption('m'));
var_dump($cmd['message']);exit;
08:43:49 baldr:[~/cvs/status-cli/bin] $ php status.php create -m 'this is a test'
object(Commando\Option)#10 (9) {
  ["name":"Commando\Option":private]=>
  string(1) "m"
  ["aliases":"Commando\Option":private]=>
  array(1) {
    [0]=>
    string(7) "message"
  }
  ["value":"Commando\Option":private]=>
  NULL
  ["description":"Commando\Option":private]=>
  string(96) "This is message you wish to use with create or update. wrap in double quotes or vim will be used"
  ["required":"Commando\Option":private]=>
  bool(false)
  ["boolean":"Commando\Option":private]=>
  bool(false)
  ["type":"Commando\Option":private]=>
  int(1)
  ["rule":"Commando\Option":private]=>
  NULL
  ["map":"Commando\Option":private]=>
  NULL
}
NULL

Error when value is null

When the value assigned to the key is NULL, an exception is thrown: 'Unable to parse option XX Expected an argument'. Instead of returning an exception, I consider the set of values from the 'default' for the option.

So, if it has a default value this is considered, otherwise consider the $val value itself.

Please add phpDoc at Command for IDE auto completion

add like this method at Commando/Command

Thanks

Use multiple inputs for options

Is it possible to access/use options with multiple words as input?

somecommand.php --countries usa gb fr

I tried it, but $hello_cmd['countries'] returns just the first (in this case usa).

Missing ext-mbstring dependency in composer.json

Just noticed this on a machine where I hadn't installed mbstring yet. I got this error:

Fatal error: Call to undefined function Commando\mb_strlen() in /path/to/vendor/nategood/commando/src/Commando/Option.php on line 38

So your composer.json should probably include "ext-mbstring": "*" as a required runtime dependency.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.