Skip to content

Commit 1cdf158

Browse files
authored
feat(console): support negative arguments (#660)
1 parent 13631ad commit 1cdf158

File tree

3 files changed

+71
-6
lines changed

3 files changed

+71
-6
lines changed

src/Tempest/Console/src/Input/ConsoleInputArgument.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace Tempest\Console\Input;
66

7+
use function Tempest\Support\str;
8+
79
final class ConsoleInputArgument
810
{
911
public function __construct(
@@ -56,23 +58,28 @@ public function matches(string $name): bool
5658
*/
5759
private static function parseNamedArgument(string $argument): array
5860
{
59-
preg_match('/--(?<name>[\w]+)((?<hasValue>=)\"?(?<value>(.*?))(\"|$))?/', $argument, $matches);
61+
preg_match('/--(?<name>[\w-]+)((?<hasValue>=)\"?(?<value>(.*?))(\"|$))?/', $argument, $matches);
6062

61-
$name = $matches['name'] ?? null;
63+
$name = str($matches['name'] ?? null)->kebab()->toString();
64+
$normalizedName = str($matches['name'] ?? null)->kebab()->replaceStart('no-', '')->toString();
65+
$isNegative = str($matches['name'] ?? null)->kebab()->startsWith('no-');
6266
$hasValue = $matches['hasValue'] ?? null;
6367
$value = $matches['value'] ?? null;
6468

6569
if (! $hasValue) {
66-
return [$name, true];
70+
return [$normalizedName, $isNegative ? false : true];
6771
}
6872

6973
$value = match ($value) {
70-
'true' => true,
71-
'false' => false,
74+
'true' => $isNegative ? false : true,
75+
'false' => $isNegative ? true : false,
7276
'' => null,
7377
default => $value,
7478
};
7579

76-
return [$name, $value];
80+
return [
81+
is_bool($value) ? $normalizedName : $name,
82+
$value,
83+
];
7784
}
7885
}

tests/Integration/Console/ConsoleArgumentBagTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Tests\Tempest\Integration\Console;
66

7+
use PHPUnit\Framework\Attributes\TestWith;
78
use Tempest\Console\Input\ConsoleArgumentBag;
89
use Tempest\Console\Input\ConsoleArgumentDefinition;
910
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
@@ -107,4 +108,34 @@ public function test_array_with_one_element_to_command(): void
107108
->call('array_input --input=a')
108109
->assertContains('["a"]');
109110
}
111+
112+
#[TestWith(['foo', false])]
113+
#[TestWith(['bar', true])]
114+
#[TestWith(['baz', false])]
115+
#[TestWith(['qux', true])]
116+
#[TestWith(['bux', true])]
117+
public function test_negative_input(string $name, bool $expected): void
118+
{
119+
$argv = [
120+
'tempest',
121+
'test',
122+
'--no-foo',
123+
'--qux',
124+
'--bux=true',
125+
'--no-bar=false',
126+
'--baz=false',
127+
];
128+
129+
$bag = new ConsoleArgumentBag($argv);
130+
131+
$definition = new ConsoleArgumentDefinition(
132+
name: $name,
133+
type: 'bool',
134+
default: null,
135+
hasDefault: false,
136+
position: 0,
137+
);
138+
139+
$this->assertSame($expected, $bag->findFor($definition)->value);
140+
}
110141
}

tests/Integration/Console/Input/ConsoleInputArgumentTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,32 @@ public function test_parse_named_arguments(): void
3131

3232
$input = ConsoleInputArgument::fromString('--flag="abc"');
3333
$this->assertSame('abc', $input->value);
34+
35+
$input = ConsoleInputArgument::fromString('--foo-bar="baz"');
36+
$this->assertSame('foo-bar', $input->name);
37+
$this->assertSame('baz', $input->value);
38+
39+
$input = ConsoleInputArgument::fromString('--fooBar');
40+
$this->assertSame('foo-bar', $input->name);
41+
42+
$input = ConsoleInputArgument::fromString('--noFooBar');
43+
$this->assertSame('foo-bar', $input->name);
44+
$this->assertSame(false, $input->value);
45+
46+
$input = ConsoleInputArgument::fromString('--no-interaction');
47+
$this->assertSame('interaction', $input->name);
48+
$this->assertSame(false, $input->value);
49+
50+
$input = ConsoleInputArgument::fromString('--no-interaction=true');
51+
$this->assertSame('interaction', $input->name);
52+
$this->assertSame(false, $input->value);
53+
54+
$input = ConsoleInputArgument::fromString('--no-interaction=false');
55+
$this->assertSame('interaction', $input->name);
56+
$this->assertSame(true, $input->value);
57+
58+
$input = ConsoleInputArgument::fromString('--no-foo=baz');
59+
$this->assertSame('no-foo', $input->name);
60+
$this->assertSame('baz', $input->value);
3461
}
3562
}

0 commit comments

Comments
 (0)