Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 64011bf

Browse files
support for partially typed commands (e.g. c:c) and added verbose mode
1 parent d16d233 commit 64011bf

13 files changed

+436
-79
lines changed

‎bin/console‎

Lines changed: 0 additions & 25 deletions
This file was deleted.

‎examples/commands.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@
2828
// $container = $kernel->getContainer();
2929
// $app = $container->get(CommandRunner::class);
3030

31-
$app = new CommandRunner([
31+
$runner = new CommandRunner([
3232
new FooCommand(),
3333
]);
34-
$exitCode = $app->run(new CommandParser(), new Output());
34+
$exitCode = $runner->run(new CommandParser(), new Output());
3535
exit($exitCode);
3636

3737

‎src/Command/HelpCommand.php‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66

77
use PhpDevCommunity\Console\InputInterface;
8+
use PhpDevCommunity\Console\Option\CommandOption;
89
use PhpDevCommunity\Console\Output;
910
use PhpDevCommunity\Console\OutputInterface;
1011

@@ -44,6 +45,22 @@ public function execute(InputInterface $input, OutputInterface $output): void
4445
$commands[$command->getName()] = $command->getDescription();
4546
}
4647
$io->listKeyValues($commands, true);
48+
49+
$io->writeColor('Options:', 'yellow');
50+
$io->write(PHP_EOL);
51+
$options = [];
52+
foreach ([new CommandOption('help', 'h', 'Display this help message.', true), new CommandOption('verbose', 'v', 'Enable verbose output', true)] as $option) {
53+
$name = sprintf('--%s', $option->getName());
54+
if ($option->getShortcut() !== null) {
55+
$name = sprintf('-%s, --%s', $option->getShortcut(), $option->getName());
56+
}
57+
58+
if (!$option->isFlag()) {
59+
$name = sprintf('%s=VALUE', $name);
60+
}
61+
$options[$name] = $option->getDescription();
62+
}
63+
$io->listKeyValues($options, true);
4764
}
4865

4966
/**

‎src/CommandRunner.php‎

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use InvalidArgumentException;
66
use PhpDevCommunity\Console\Command\CommandInterface;
77
use PhpDevCommunity\Console\Command\HelpCommand;
8+
use PhpDevCommunity\Console\Option\CommandOption;
89
use PhpDevCommunity\Console\Output\ConsoleOutput;
910
use Throwable;
1011
use const PHP_EOL;
@@ -13,6 +14,9 @@ final class CommandRunner
1314
{
1415
const CLI_ERROR = 1;
1516
const CLI_SUCCESS = 0;
17+
public const CLI_COMMAND_NOT_FOUND = 10; // Aucune commande trouvée
18+
public const CLI_INVALID_ARGUMENTS = 11; // Arguments invalides
19+
public const CLI_AMBIGUOUS_COMMAND = 12; // Plusieurs correspondances possibles
1620

1721
/**
1822
* @var CommandInterface[]
@@ -58,7 +62,7 @@ public function run(CommandParser $commandParser, OutputInterface $output): int
5862
}
5963

6064
if (empty($commands)) {
61-
throw new InvalidArgumentException(sprintf('Command "%s" is not defined.', $commandParser->getCommandName()));
65+
throw new InvalidArgumentException(sprintf('Command "%s" is not defined.', $commandParser->getCommandName()), self::CLI_COMMAND_NOT_FOUND);
6266
}
6367

6468
if (count($commands) > 1) {
@@ -69,7 +73,7 @@ public function run(CommandParser $commandParser, OutputInterface $output): int
6973
$consoleOutput = new ConsoleOutput($output);
7074
$consoleOutput->error(sprintf('Command "%s" is ambiguous.', $commandParser->getCommandName()));
7175
$consoleOutput->listKeyValues($names, true);
72-
return self::CLI_ERROR;
76+
return self::CLI_AMBIGUOUS_COMMAND;
7377
}
7478

7579
$command = $commands[0];
@@ -84,16 +88,32 @@ public function run(CommandParser $commandParser, OutputInterface $output): int
8488

8589
} catch (Throwable $e) {
8690
(new ConsoleOutput($output))->error($e->getMessage());
87-
return self::CLI_ERROR;
91+
return in_array($e->getCode(), [self::CLI_COMMAND_NOT_FOUND, self::CLI_INVALID_ARGUMENTS]) ? $e->getCode() : self::CLI_ERROR;
8892
}
8993

9094
}
9195

9296
private function execute(CommandInterface $command, CommandParser $commandParser, OutputInterface $output)
9397
{
9498
$argvOptions = [];
95-
9699
$options = $command->getOptions();
100+
$forbidden = ['help', 'h', 'verbose', 'v'];
101+
foreach ($options as $option) {
102+
$name = $option->getName();
103+
$shortcut = $option->getShortcut();
104+
if (in_array($name, $forbidden, true) || ($shortcut !== null && in_array($shortcut, $forbidden, true))) {
105+
$invalid = in_array($name, $forbidden, true) ? $name : $shortcut;
106+
throw new \InvalidArgumentException(
107+
sprintf(
108+
'The option "%s" is reserved and cannot be used with the "%s" command.',
109+
$invalid,
110+
$command->getName()
111+
)
112+
);
113+
}
114+
}
115+
116+
$options[] = new CommandOption('verbose', 'v', 'Enable verbose output', true);
97117
foreach ($options as $option) {
98118
if ($option->isFlag()) {
99119
$argvOptions["--{$option->getName()}"] = false;
@@ -135,7 +155,20 @@ private function execute(CommandInterface $command, CommandParser $commandParser
135155
throw new InvalidArgumentException(sprintf('Too many arguments for command "%s". Expected %d, got %d.', $command->getName(), count($arguments), count($commandParser->getArguments())));
136156
}
137157

138-
$command->execute(new Input($commandParser->getCommandName(), $argvOptions, $argv), $output);
158+
$startTime = microtime(true);
159+
$input = new Input($commandParser->getCommandName(), $argvOptions, $argv);
160+
$command->execute($input, $output);
161+
$endTime = microtime(true);
162+
$peakMemoryBytes = memory_get_peak_usage(true);
163+
$peakMemoryMB = round($peakMemoryBytes / 1024 / 1024, 2);
164+
$duration = round($endTime - $startTime, 2);
165+
if ($input->getOptionValue('verbose')) {
166+
$output->writeln(sprintf(
167+
'Execution time: %.2fs; Peak memory usage: %.2f MB',
168+
$duration,
169+
$peakMemoryMB
170+
));
171+
}
139172
}
140173

141174
private function showCommandHelp(CommandInterface $selectedCommand, OutputInterface $output): void
@@ -171,8 +204,18 @@ private function showCommandHelp(CommandInterface $selectedCommand, OutputInterf
171204
$consoleOutput->listKeyValues($options, true);
172205
}
173206

174-
private static function stringStartsWith(string $haystack, string $needle): bool
207+
private static function stringStartsWith(string $command, string $input): bool
175208
{
176-
return substr($haystack, 0, strlen($needle)) === $needle;
209+
$commandParts = explode(':', $command);
210+
$inputParts = explode(':', $input);
211+
foreach ($inputParts as $i => $inPart) {
212+
$cmdPart = $commandParts[$i] ?? null;
213+
214+
if ($cmdPart === null || strpos($cmdPart, $inPart) !== 0) {
215+
return false;
216+
}
217+
}
218+
219+
return true;
177220
}
178221
}

‎tests/Command/CacheClearCommand.php‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Test\PhpDevCommunity\Console\Command;
4+
5+
use PhpDevCommunity\Console\Command\CommandInterface;
6+
use PhpDevCommunity\Console\InputInterface;
7+
use PhpDevCommunity\Console\OutputInterface;
8+
9+
class CacheClearCommand implements CommandInterface
10+
{
11+
public function getName(): string
12+
{
13+
return 'cache:clear';
14+
}
15+
16+
public function getDescription(): string
17+
{
18+
return 'TEST : Clear cache';
19+
}
20+
21+
public function getOptions(): array
22+
{
23+
return [
24+
];
25+
}
26+
27+
public function getArguments(): array
28+
{
29+
return [
30+
];
31+
}
32+
33+
public function execute(InputInterface $input, OutputInterface $output): void
34+
{
35+
$output->write('Test OK : Clear cache');
36+
}
37+
}

‎tests/Command/FooCommand.php‎

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,44 @@
1-
<?php
2-
3-
namespace Test\PhpDevCommunity\Console\Command;
4-
5-
use PhpDevCommunity\Console\Argument\CommandArgument;
6-
use PhpDevCommunity\Console\Command\CommandInterface;
7-
use PhpDevCommunity\Console\InputInterface;
8-
use PhpDevCommunity\Console\Option\CommandOption;
9-
use PhpDevCommunity\Console\OutputInterface;
10-
11-
class FooCommand implements CommandInterface
12-
{
13-
public function getName(): string
14-
{
15-
return 'foo';
16-
}
17-
18-
public function getDescription(): string
19-
{
20-
return 'Performs the foo operation with optional parameters.';
21-
}
22-
23-
public function getOptions(): array
24-
{
25-
return [
26-
new CommandOption('verbose', 'v', 'Enable verbose output', true),
27-
new CommandOption('output', 'o', 'Specify output file', false)
28-
];
29-
}
30-
31-
public function getArguments(): array
32-
{
33-
return [
34-
new CommandArgument('input', false, 'none', 'The input file for the foo operation')
35-
];
36-
}
37-
38-
public function execute(InputInterface $input, OutputInterface $output): void
39-
{
40-
41-
$output->writeln('Test OK');
42-
$output->writeln('ARGUMENTS: ' . json_encode($input->getArguments()));
43-
$output->writeln('OPTIONS: ' . json_encode($input->getOptions()));
44-
}
45-
}
1+
<?php
2+
3+
namespace Test\PhpDevCommunity\Console\Command;
4+
5+
use PhpDevCommunity\Console\Argument\CommandArgument;
6+
use PhpDevCommunity\Console\Command\CommandInterface;
7+
use PhpDevCommunity\Console\InputInterface;
8+
use PhpDevCommunity\Console\Option\CommandOption;
9+
use PhpDevCommunity\Console\OutputInterface;
10+
11+
class FooCommand implements CommandInterface
12+
{
13+
public function getName(): string
14+
{
15+
return 'foo';
16+
}
17+
18+
public function getDescription(): string
19+
{
20+
return 'Performs the foo operation with optional parameters.';
21+
}
22+
23+
public function getOptions(): array
24+
{
25+
return [
26+
new CommandOption('verbose', 'v', 'Enable verbose output', true),
27+
new CommandOption('output', 'o', 'Specify output file', false)
28+
];
29+
}
30+
31+
public function getArguments(): array
32+
{
33+
return [
34+
new CommandArgument('input', false, 'none', 'The input file for the foo operation')
35+
];
36+
}
37+
38+
public function execute(InputInterface $input, OutputInterface $output): void
39+
{
40+
$output->writeln('Test OK');
41+
$output->writeln('ARGUMENTS: ' . json_encode($input->getArguments()));
42+
$output->writeln('OPTIONS: ' . json_encode($input->getOptions()));
43+
}
44+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Test\PhpDevCommunity\Console\Command;
4+
5+
use PhpDevCommunity\Console\Argument\CommandArgument;
6+
use PhpDevCommunity\Console\Command\CommandInterface;
7+
use PhpDevCommunity\Console\InputInterface;
8+
use PhpDevCommunity\Console\Option\CommandOption;
9+
use PhpDevCommunity\Console\OutputInterface;
10+
11+
class MakeControllerCommand implements CommandInterface
12+
{
13+
public function getName(): string
14+
{
15+
return 'make:controller';
16+
}
17+
18+
public function getDescription(): string
19+
{
20+
return 'TEST : Make a new controller';
21+
}
22+
23+
public function getOptions(): array
24+
{
25+
return [
26+
];
27+
}
28+
29+
public function getArguments(): array
30+
{
31+
return [
32+
];
33+
}
34+
35+
public function execute(InputInterface $input, OutputInterface $output): void
36+
{
37+
$output->write('Test OK : Make a new controller');
38+
}
39+
}

‎tests/Command/MakeEntityCommand.php‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Test\PhpDevCommunity\Console\Command;
4+
5+
use PhpDevCommunity\Console\Command\CommandInterface;
6+
use PhpDevCommunity\Console\InputInterface;
7+
use PhpDevCommunity\Console\OutputInterface;
8+
9+
class MakeEntityCommand implements CommandInterface
10+
{
11+
public function getName(): string
12+
{
13+
return 'make:controller';
14+
}
15+
16+
public function getDescription(): string
17+
{
18+
return 'TEST : Make a new Entity';
19+
}
20+
21+
public function getOptions(): array
22+
{
23+
return [
24+
];
25+
}
26+
27+
public function getArguments(): array
28+
{
29+
return [
30+
];
31+
}
32+
33+
public function execute(InputInterface $input, OutputInterface $output): void
34+
{
35+
$output->write('Test OK : Make a new entity');
36+
}
37+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /