diff --git a/src/Ulrichsg/Getopt.php b/src/Ulrichsg/Getopt.php index fb0668feea0e8b6e72e045a0f36a4e01f7c7f80b..e3b4051b0c23bad87bed54ac5a9bc54043b30246 100644 --- a/src/Ulrichsg/Getopt.php +++ b/src/Ulrichsg/Getopt.php @@ -76,7 +76,7 @@ class Getopt { $arguments = $argv; $this->scriptName = array_shift($arguments); // $argv[0] is the script's name } elseif (is_string($arguments)) { - $this->scriptName = $_SERVER['PHP_SELF']; + $this->scriptName = $_SERVER['PHP_SELF']; $arguments = explode(' ', $arguments); } @@ -113,8 +113,21 @@ class Getopt { $option = mb_substr($arg, 1); if (mb_strlen($option) > 1) { // multiple options strung together - foreach ($this->mb_str_split($option, 1) as $ch) { - $this->addOption($ch, null, false); + $options = $this->mb_str_split($option, 1); + foreach ($options as $j => $ch) { + if ($j < count($options) - 1 + || !( + $i < $num_args - 1 + && mb_substr($arguments[$i + 1], 0, 1) != '-' + && $this->optionHasArgument($ch, false) + ) + ) { + $this->addOption($ch, null, false); + } else { // e.g. `ls -sw 100` + $value = $arguments[$i + 1]; + ++$i; + $this->addOption($ch, $value, false); + } } } else { if ($i < $num_args - 1 @@ -296,7 +309,7 @@ class Getopt { . "Getopt::NO_ARGUMENT, Getopt::OPTIONAL_ARGUMENT and Getopt::REQUIRED_ARGUMENT"); } if (!isset($option[3])) { - $option[3] = ""; // description + $option[3] = ""; // description } } return $options; @@ -409,7 +422,7 @@ class Getopt { /** * @param string $str string to split - * @param int $l + * @param int $l * * @return string * @internal diff --git a/test/Ulrichsg/GetoptTest.php b/test/Ulrichsg/GetoptTest.php index f9111ea55a00164ba57c07acfd9a0573eec8449e..c3901b350e4d2c86f2ee89df5d44a37d81c4eb89 100644 --- a/test/Ulrichsg/GetoptTest.php +++ b/test/Ulrichsg/GetoptTest.php @@ -145,6 +145,19 @@ class GetoptTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('value', $getopt->getOption('a')); } + public function testParseCollapsedShortOptionsRequiredArgumentMissing() { + $this->setExpectedException('UnexpectedValueException'); + $getopt = new Getopt('ab:'); + $getopt->parse('-ab'); + } + + public function testParseCollapsedShortOptionsWithArgument() { + $getopt = new Getopt('ab:'); + $getopt->parse('-ab value'); + $this->assertEquals(1, $getopt->getOption('a')); + $this->assertEquals('value', $getopt->getOption('b')); + } + public function testParseNoArgumentOptionAndOperand() { $getopt = new Getopt('a'); $getopt->parse('-a b'); @@ -257,7 +270,7 @@ class GetoptTest extends \PHPUnit_Framework_TestCase { array('a', 'alpha', Getopt::NO_ARGUMENT, 'Short and long options with no argument'), array(null, 'beta', Getopt::OPTIONAL_ARGUMENT, 'Long option only with an optional argument'), array('c', null, Getopt::REQUIRED_ARGUMENT, 'Short option only with a mandatory argument') - )); + )); $getopt->parse(''); $script = $_SERVER['PHP_SELF']; @@ -277,7 +290,7 @@ class GetoptTest extends \PHPUnit_Framework_TestCase { array('a', 'alpha', Getopt::NO_ARGUMENT), array(null, 'beta', Getopt::OPTIONAL_ARGUMENT), array('c', null, Getopt::REQUIRED_ARGUMENT) - )); + )); $getopt->parse(''); $script = $_SERVER['PHP_SELF'];