nategood / commando

An Elegant CLI Library for PHP
MIT License
798 stars 80 forks source link

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

Open mjordan opened 8 years ago

mjordan commented 8 years ago

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?

NeoVance commented 8 years ago

When you access the command values it actually parses the argument list, and sets the values for every option. At this time there is a flag preventing it from re-parsing after the first run. If your "c" option is not last than it is causing the argument list to be parsed before you create the rest of your options and define their features.

there may be a viable option to work around this, but I don't know if there is any plan to implement it.