merged branch jmikola/double-dash (PR #3624)

Commits
-------

4d4ef24 [Console] Stop parsing options after encountering "--" token

Discussion
----------

[Console] Stop parsing options after encountering "--" token

This enables support for arguments with leading dashes (e.g. "-1"), as supported by getopt in other languages.

[![Build Status](https://secure.travis-ci.org/jmikola/symfony.png?branch=double-dash)](http://travis-ci.org/jmikola/symfony)

The test suite currently fails due to 7a54fe41ca. ArgvInputTest passes, and these changes don't appear to break anything else.

![](http://media.giantbomb.com/uploads/2/27528/1061704-mario_kart_double_dash___title_screen_super.jpg)

Aside: This got me thinking about how one would pass an option value of "-1". I suppose for input options with `VALUE_OPTIONAL`, it would be ambiguous if "-1" followed; however, `VALUE_REQUIRED` should probably require that the next token is captured as the option value. In my tests, a required option value with a leading dash was interpreted as another option. The workaround for all of this is to use the space-less syntax (e.g. `-f=-1`).

---------------------------------------------------------------------------

by fabpot at 2012-03-17T08:43:15Z

AFAIK, the `--` should disable both option and argument parsing, no?

---------------------------------------------------------------------------

by jmikola at 2012-03-18T02:13:51Z

If that were the case, what would be the point of using `--` at all? :)

 * http://wiki.bash-hackers.org/dict/terms/end_of_options
 * http://perldoc.perl.org/Getopt/Long.html#Mixing-command-line-option-with-other-arguments
This commit is contained in:
Fabien Potencier 2012-03-19 00:28:49 +01:00
commit 645d09c984
3 changed files with 24 additions and 2 deletions

View File

@ -168,6 +168,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
* made the defaults (helper set, commands, input definition) in Application more easily customizable
* added support for the shell even if readline is not available
* added support for process isolation in Symfony shell via `--process-isolation` switch
* added support for `--`, which disables options parsing after that point (tokens will be parsed as arguments)
### ClassLoader

View File

@ -75,11 +75,14 @@ class ArgvInput extends Input
*/
protected function parse()
{
$parseOptions = true;
$this->parsed = $this->tokens;
while (null !== $token = array_shift($this->parsed)) {
if (0 === strpos($token, '--')) {
if ($parseOptions && '--' == $token) {
$parseOptions = false;
} elseif ($parseOptions && 0 === strpos($token, '--')) {
$this->parseLongOption($token);
} elseif ('-' === $token[0]) {
} elseif ($parseOptions && '-' === $token[0]) {
$this->parseShortOption($token);
} else {
$this->parseArgument($token);

View File

@ -151,6 +151,24 @@ class ArgvInputTest extends \PHPUnit_Framework_TestCase
$input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name=baz'));
$input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY))));
$this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions());
try {
$input = new ArgvInput(array('cli.php', '-1'));
$input->bind(new InputDefinition(array(new InputArgument('number'))));
$this->fail('->parse() throws a \RuntimeException if an unknown option is passed');
} catch (\Exception $e) {
$this->assertInstanceOf('\RuntimeException', $e, '->parse() parses arguments with leading dashes as options without having encountered a double-dash sequence');
$this->assertEquals('The "-1" option does not exist.', $e->getMessage(), '->parse() parses arguments with leading dashes as options without having encountered a double-dash sequence');
}
$input = new ArgvInput(array('cli.php', '--', '-1'));
$input->bind(new InputDefinition(array(new InputArgument('number'))));
$this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence');
$input = new ArgvInput(array('cli.php', '-f', 'bar', '--', '-1'));
$input->bind(new InputDefinition(array(new InputArgument('number'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL))));
$this->assertEquals(array('foo' => 'bar'), $input->getOptions(), '->parse() parses arguments with leading dashes as options before having encountered a double-dash sequence');
$this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence');
}
public function testGetFirstArgument()