From c6d8252fd90db984ded753861bc71bc936b3f0a2 Mon Sep 17 00:00:00 2001 From: brendt Date: Wed, 29 May 2024 14:20:21 +0200 Subject: [PATCH] Add support for array values --- src/HasConsole.php | 123 +++++++++++++++++++++++++++ src/Input/ConsoleArgumentBag.php | 8 +- src/Input/ConsoleInputArgument.php | 15 ++++ src/Testing/ConsoleTester.php | 5 ++ tests/ConsoleArgumentBagTest.php | 26 +++++- tests/Fixtures/ArrayInputCommand.php | 19 +++++ 6 files changed, 190 insertions(+), 6 deletions(-) create mode 100644 src/HasConsole.php create mode 100644 tests/Fixtures/ArrayInputCommand.php diff --git a/src/HasConsole.php b/src/HasConsole.php new file mode 100644 index 0000000..03efb74 --- /dev/null +++ b/src/HasConsole.php @@ -0,0 +1,123 @@ +console->readln(); + } + + public function read(int $bytes): string + { + return $this->console->read($bytes); + } + + public function write(string $contents): self + { + $this->console->write($contents); + + return $this; + } + + public function writeln(string $line = ''): self + { + $this->console->writeln($line); + + return $this; + } + + /** + * @param string $question + * @param array|null $options + * @param mixed|null $default + * @param bool $multiple + * @param bool $asList + * @param \Tempest\Validation\Rule[] $validation + * @return string|array + */ + public function ask( + string $question, + ?array $options = null, + mixed $default = null, + bool $multiple = false, + bool $asList = false, + array $validation = [], + ): string|array { + return $this->console->ask( + question: $question, + options: $options, + default: $default, + multiple: $multiple, + asList: $asList, + validation: $validation, + ); + } + + public function confirm(string $question, bool $default = false): bool + { + return $this->console->confirm( + question: $question, + default: $default, + ); + } + + public function password(string $label = 'Password', bool $confirm = false): string + { + return $this->console->password( + label: $label, + confirm: $confirm, + ); + } + + public function progressBar(iterable $data, Closure $handler): array + { + return $this->console->progressBar( + data: $data, + handler: $handler, + ); + } + + /** + * @param string $label + * @param Closure(string $search): array $search + * @return mixed + */ + public function search(string $label, Closure $search): mixed + { + return $this->console->search( + label: $label, + search: $search, + ); + } + + public function info(string $line): self + { + $this->console->info($line); + + return $this; + } + + public function error(string $line): self + { + $this->console->error($line); + + return $this; + } + + public function success(string $line): self + { + $this->console->success($line); + + return $this; + } +} diff --git a/src/Input/ConsoleArgumentBag.php b/src/Input/ConsoleArgumentBag.php index 7080eef..887238b 100644 --- a/src/Input/ConsoleArgumentBag.php +++ b/src/Input/ConsoleArgumentBag.php @@ -34,7 +34,7 @@ public function __construct(array $arguments) $this->path = [$cli, $commandName]; - foreach (array_values($arguments) as $position => $argument) { + foreach ($arguments as $argument) { if (str_starts_with($argument, '-') && ! str_starts_with($argument, '--')) { $flags = str_split($argument); unset($flags[0]); @@ -42,8 +42,6 @@ public function __construct(array $arguments) foreach ($flags as $flag) { $arguments[] = "-{$flag}"; } - - unset($arguments[$position]); } } @@ -107,7 +105,9 @@ public function findFor(ConsoleArgumentDefinition $argumentDefinition): ?Console public function add(ConsoleInputArgument $argument): self { - $this->arguments[] = $argument; + $key = $argument->name ?? $argument->position; + + $this->arguments[$key] = $argument->merge($this->arguments[$key] ?? null); return $this; } diff --git a/src/Input/ConsoleInputArgument.php b/src/Input/ConsoleInputArgument.php index 2070816..0c64b50 100644 --- a/src/Input/ConsoleInputArgument.php +++ b/src/Input/ConsoleInputArgument.php @@ -4,6 +4,8 @@ namespace Tempest\Console\Input; +use Tempest\Support\ArrayHelper; + final class ConsoleInputArgument { public function __construct( @@ -70,4 +72,17 @@ private static function parseNamedArgument(string $argument): array return [$key, $value]; } + + public function merge(?ConsoleInputArgument $other): self + { + $clone = clone $this; + + if ($other === null) { + return $clone; + } + + $clone->value = array_values([...ArrayHelper::wrap($other->value), ...ArrayHelper::wrap($this->value)]); + + return $clone; + } } diff --git a/src/Testing/ConsoleTester.php b/src/Testing/ConsoleTester.php index 5351e0b..fd34f07 100644 --- a/src/Testing/ConsoleTester.php +++ b/src/Testing/ConsoleTester.php @@ -147,6 +147,11 @@ public function useInteractiveTerminal(): self return $this; } + public function assertSee(string $text): self + { + return $this->assertContains($text); + } + public function assertContains(string $text): self { Assert::assertStringContainsString( diff --git a/tests/ConsoleArgumentBagTest.php b/tests/ConsoleArgumentBagTest.php index 99af60a..e9756e2 100644 --- a/tests/ConsoleArgumentBagTest.php +++ b/tests/ConsoleArgumentBagTest.php @@ -31,12 +31,12 @@ public function test_argument_bag_works(): void $this->assertSame(0, $firstArg->position); $this->assertNull($firstArg->name); - $forceFlag = $bag->all()[1]; + $forceFlag = $bag->all()['force']; $this->assertSame(true, $forceFlag->value); $this->assertSame(null, $forceFlag->position); $this->assertSame('force', $forceFlag->name); - $timesFlag = $bag->all()[2]; + $timesFlag = $bag->all()['times']; $this->assertSame('2', $timesFlag->value); $this->assertSame(null, $timesFlag->position); $this->assertSame('times', $timesFlag->name); @@ -69,4 +69,26 @@ public function test_short_flags_are_mapped_to_parameters_directly(): void ->call('flags:short -ab') ->assertContains('ok'); } + + public function test_array_input(): void + { + $argv = [ + 'tempest', + 'test', + '--input=a', + '--input=b', + '--input=c', + ]; + + $bag = new ConsoleArgumentBag($argv); + + $this->assertSame(['a', 'b', 'c'], $bag->get('input')->value); + } + + public function test_array_input_to_command(): void + { + $this->console + ->call('array_input --input=a --input=b') + ->assertContains('["a","b"]'); + } } diff --git a/tests/Fixtures/ArrayInputCommand.php b/tests/Fixtures/ArrayInputCommand.php new file mode 100644 index 0000000..e800c15 --- /dev/null +++ b/tests/Fixtures/ArrayInputCommand.php @@ -0,0 +1,19 @@ +writeln(json_encode($input)); + } +}