Skip to content

Commit 88ca168

Browse files
committed
Merge branch 'cli-improvements'
2 parents da37a22 + 831b3f4 commit 88ca168

File tree

1 file changed

+32
-18
lines changed

1 file changed

+32
-18
lines changed

src/Cli/CliCommand.php

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Lkrms\Cli;
44

55
use Lkrms\Cli\Catalog\CliHelpSectionName;
6-
use Lkrms\Cli\Catalog\CliHelpType;
76
use Lkrms\Cli\Catalog\CliOptionValueType;
87
use Lkrms\Cli\Catalog\CliOptionVisibility;
98
use Lkrms\Cli\Contract\ICliApplication;
@@ -801,26 +800,28 @@ function (string $key, $value) use (&$argValues, &$saved, &$option) {
801800
}
802801
};
803802
$merged = [];
803+
$positional = [];
804804

805805
for ($i = 0; $i < count($args); $i++) {
806806
$arg = $args[$i];
807807
$short = false;
808808
$saved = false;
809809
if (preg_match('/^-([a-z0-9_])(.*)/i', $arg, $matches)) {
810810
$name = $matches[1];
811-
$value = $matches[2] ?: null;
811+
$value = $matches[2] === '' ? null : $matches[2];
812812
$short = true;
813813
} elseif (preg_match('/^--([a-z0-9_][-a-z0-9_]+)(?:=(.*))?$/i', $arg, $matches, PREG_UNMATCHED_AS_NULL)) {
814814
$name = $matches[1];
815815
$value = $matches[2];
816-
} else {
817-
if ($arg === '--') {
818-
$i++;
819-
} elseif (($arg[0] ?? null) === '-') {
820-
$this->optionError(sprintf("invalid argument '%s'", $arg));
821-
continue;
822-
}
816+
} elseif ($arg === '--') {
817+
$i++;
823818
break;
819+
} elseif ($arg === '-' || ($arg[0] ?? null) !== '-') {
820+
$positional[] = $arg;
821+
continue;
822+
} else {
823+
$this->optionError(sprintf("invalid argument '%s'", $arg));
824+
continue;
824825
}
825826

826827
$option = $this->OptionsByName[$name] ?? null;
@@ -839,7 +840,7 @@ function (string $key, $value) use (&$argValues, &$saved, &$option) {
839840
$valueIsDefault = false;
840841
if ($option->IsFlag) {
841842
// Handle multiple short flags per argument, e.g. `cp -rv`
842-
if ($short && $value) {
843+
if ($short && $value !== null) {
843844
$args[$i] = "-$value";
844845
$i--;
845846
}
@@ -867,17 +868,23 @@ function (string $key, $value) use (&$argValues, &$saved, &$option) {
867868
}
868869

869870
if ($option->MultipleAllowed && !$option->IsFlag) {
870-
// Interpret "--option=" as "clear previous --option values"
871+
// Interpret the first use of "--opt=" as "clear default or
872+
// previous values" without changing the meaning of "--opt ''"
871873
if ($option->ValueRequired && $value === '') {
872-
$merged[$key] = [];
873-
$argValues[$key] = [];
874-
continue;
874+
if ($args[$i] === '' || ($merged[$key] ?? null) === []) {
875+
$value = [''];
876+
} else {
877+
$merged[$key] = [];
878+
$argValues[$key] = [];
879+
continue;
880+
}
881+
} else {
882+
$value = $option->maybeSplitValue($value);
875883
}
876884
// Use $value to extend $option->DefaultValue if:
877885
// - $option->DefaultValue wasn't just assigned to $value
878886
// - extension of default values is enabled, and
879887
// - this is $option's first appearance in $args
880-
$value = $option->maybeSplitValue($value);
881888
$saveArgValue($key, $value);
882889
if (!$valueIsDefault &&
883890
($option->KeepDefault || $option->KeepEnv) &&
@@ -894,6 +901,11 @@ function (string $key, $value) use (&$argValues, &$saved, &$option) {
894901
}
895902
}
896903

904+
// Splice $positional into $args to ensure $nextArgumentIndex is correct
905+
if ($positional) {
906+
$i -= count($positional);
907+
array_splice($args, $i, count($positional), $positional);
908+
}
897909
$pending = count($this->PositionalOptions);
898910
foreach ($this->PositionalOptions as $option) {
899911
if (!($i < count($args))) {
@@ -1129,7 +1141,8 @@ final protected function getEffectiveArgument(
11291141
$value = $this->OptionValues[$option->Key] ?? null;
11301142
}
11311143

1132-
if ($value === null || $value === [] || $value === false || $value === 0) {
1144+
if ($value === null || $value === false || $value === 0 ||
1145+
($value === [] && $option->ValueRequired)) {
11331146
return null;
11341147
}
11351148

@@ -1144,14 +1157,15 @@ final protected function getEffectiveArgument(
11441157
if (is_array($value)) {
11451158
$value = implode(',', $value);
11461159
}
1147-
if ($shellEscape && is_string($value)) {
1160+
if ($shellEscape && is_string($value) &&
1161+
($value !== '' || $option->IsPositional)) {
11481162
$value = Convert::toShellArg($value);
11491163
}
11501164

11511165
return $option->IsPositional
11521166
? $value
11531167
: ($option->Long
1154-
? "--{$option->Long}" . (is_string($value) ? "=$value" : '')
1168+
? "--{$option->Long}" . (is_string($value) && ($value !== '' || $option->ValueRequired) ? "=$value" : '')
11551169
: "-{$option->Short}" . $value);
11561170
}
11571171

0 commit comments

Comments
 (0)