Skip to content

Commit 0f5defa

Browse files
committed
exec()
1 parent 6b5df7a commit 0f5defa

File tree

2 files changed

+79
-64
lines changed

2 files changed

+79
-64
lines changed

src/SimpleConsole.php

Lines changed: 72 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,6 @@ protected function configure(): void
111111
//
112112
}
113113

114-
public function setBoolMapping(array $boolMapping): SimpleConsole
115-
{
116-
$this->boolMapping = $boolMapping;
117-
118-
return $this;
119-
}
120-
121114
protected function doExecute(): int|bool
122115
{
123116
return 0;
@@ -127,6 +120,7 @@ public function execute(?array $argv = null, ?\Closure $main = null): int
127120
{
128121
$argv = $argv ?? $_SERVER['argv'];
129122
$main ??= $this->doExecute(...);
123+
$main->bindTo($this);
130124

131125
try {
132126
if (!$this->disableDefaultParameters) {
@@ -139,13 +133,10 @@ public function execute(?array $argv = null, ?\Closure $main = null): int
139133
$this->params = $this->parser->parse($argv);
140134

141135
if (!$this->disableDefaultParameters) {
142-
if ($v = $this->get('verbosity')) {
143-
$this->verbosity = $v;
144-
}
136+
$this->verbosity = (int) $this->get('verbosity');
145137

146138
if ($this->get('help')) {
147139
$this->showHelp();
148-
149140
return static::SUCCESS;
150141
}
151142
}
@@ -158,7 +149,7 @@ public function execute(?array $argv = null, ?\Closure $main = null): int
158149
$exitCode = 255;
159150
}
160151

161-
return $exitCode;
152+
return (int) $exitCode;
162153
} catch (\Throwable $e) {
163154
return $this->handleException($e);
164155
}
@@ -171,43 +162,24 @@ protected function help(): string
171162

172163
public function showHelp(): void
173164
{
174-
$help = ParameterDescriptor::describe($this->parser, 'command', $this->help());
175-
176-
$this->writeln($help);
165+
$this->writeln(ParameterDescriptor::describe($this->parser, 'command', $this->help()));
177166
}
178167

179-
public function write(string $message): static
168+
public function write(string $message, bool $err = false): static
180169
{
181-
fwrite($this->stdout, $message);
182-
170+
fwrite($err ? $this->stderr : $this->stdout, $message);
183171
return $this;
184172
}
185173

186-
public function writeln(string $message = ''): static
174+
public function writeln(string $message = '', bool $err = false): static
187175
{
188-
$this->write($message . "\n");
189-
176+
$this->write($message . "\n", $err);
190177
return $this;
191178
}
192179

193-
public function newLine(int $lines = 1): static
180+
public function newLine(int $lines = 1, bool $err = false): static
194181
{
195-
$this->write(str_repeat("\n", $lines));
196-
197-
return $this;
198-
}
199-
200-
public function writeErr(string $message): static
201-
{
202-
fwrite($this->stderr, $message);
203-
204-
return $this;
205-
}
206-
207-
public function writelnErr(string $message = ''): static
208-
{
209-
$this->writeErr($message . "\n");
210-
182+
$this->write(str_repeat("\n", $lines), $err);
211183
return $this;
212184
}
213185

@@ -247,21 +219,67 @@ public function mapBoolean($in): bool|null
247219
return null;
248220
}
249221

222+
public function exec(string $cmd, ?\Closure $output = null): int
223+
{
224+
$this->writeln('>> ' . $cmd);
225+
226+
$descriptorspec = [
227+
0 => ["pipe", "r"], // stdin
228+
1 => ["pipe", "w"], // stdout
229+
2 => ["pipe", "w"] // stderr
230+
];
231+
232+
if ($process = proc_open($cmd, $descriptorspec, $pipes)) {
233+
while (($out = fgets($pipes[1])) || $err = fgets($pipes[2])) {
234+
if (isset($out[0])) {
235+
if ($output) {
236+
$output($out, false);
237+
} else {
238+
$this->write($out, false);
239+
}
240+
}
241+
242+
if (isset($err[0])) {
243+
if ($output) {
244+
$output($err, true);
245+
} else {
246+
$this->write($err, true);
247+
}
248+
}
249+
}
250+
251+
return proc_close($process);
252+
}
253+
254+
return 255;
255+
}
256+
257+
public function mustExec(string $cmd, ?\Closure $output = null): int
258+
{
259+
$result = $this->exec($cmd, $output);
260+
261+
if ($result !== 0) {
262+
throw new \RuntimeException('Command "' . $cmd . '" failed with code ' . $result);
263+
}
264+
265+
return $result;
266+
}
267+
250268
protected function handleException(\Throwable $e): int
251269
{
252270
$v = $this->verbosity;
253271

254272
if ($e instanceof InvalidParameterException) {
255-
$this->writelnErr('[Warning] ' . $e->getMessage())
256-
->writelnErr()
257-
->writelnErr('HELP');
273+
$this->writeln('[Warning] ' . $e->getMessage(), true)
274+
->newLine(err: true)
275+
->writeln('HELP', true);
258276
} else {
259-
$this->writelnErr('[Error] ' . $e->getMessage());
277+
$this->writeln('[Error] ' . $e->getMessage(), true);
260278
}
261279

262280
if ($v > 0) {
263-
$this->writelnErr('[Backtrace]:')
264-
->writeErr($e->getTraceAsString());
281+
$this->writeln('[Backtrace]:', true)
282+
->writeln($e->getTraceAsString(), true);
265283
}
266284

267285
$code = $e->getCode();
@@ -344,7 +362,7 @@ public function addParameter(
344362

345363
foreach ($name as $n) {
346364
if (!str_starts_with($n, '-')) {
347-
throw new \RuntimeException('Argument name cannot contains "|" sign.');
365+
throw new \InvalidArgumentException('Argument name cannot contains "|" sign.');
348366
}
349367
}
350368
}
@@ -353,7 +371,7 @@ public function addParameter(
353371

354372
foreach ((array) $parameter->name as $n) {
355373
if (in_array($n, $this->existsNames, true)) {
356-
throw new \RuntimeException('Duplicate parameter name "' . $n . '"');
374+
throw new \InvalidArgumentException('Duplicate parameter name "' . $n . '"');
357375
}
358376
}
359377

@@ -506,11 +524,7 @@ private function parseLongOption(string $token): void
506524

507525
private function parseArgument(string $token): void
508526
{
509-
$c = $this->currentArgument;
510-
511-
$arg = $this->getArgumentByIndex($c);
512-
513-
if ($arg) {
527+
if ($arg = $this->getArgumentByIndex($this->currentArgument)) {
514528
$this->values[$arg->primaryName] = $arg->isArray ? [$token] : $token;
515529
} elseif (($last = $this->getLastArgument()) && $last->isArray) {
516530
$this->values[$last->primaryName][] = $token;
@@ -544,9 +558,8 @@ public function setOptionValue(string $name, mixed $value = null): void
544558
throw new InvalidParameterException('Option "' . $option->primaryName . '" does not accept value.');
545559
}
546560

561+
// Try get option value from next token
547562
if (\in_array($value, ['', null], true) && $option->acceptValue && \count($this->tokens)) {
548-
// if option accepts an optional or mandatory argument
549-
// let's see if there is one provided
550563
$next = array_shift($this->tokens);
551564

552565
if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, ['', null], true)) {
@@ -678,33 +691,33 @@ public function __construct(
678691
if (is_array($this->name)) {
679692
foreach ($this->name as $i => $n) {
680693
if (!str_starts_with($n, '--') && strlen($n) > 2) {
681-
throw new InvalidParameterException('Invalid option name "' . $n . '"');
694+
throw new \InvalidArgumentException('Invalid option name "' . $n . '"');
682695
}
683696

684697
$this->name[$i] = ltrim($n, '-');
685698
}
686699
}
687700

688701
if ($this->isArray && !is_array($this->defaultValue)) {
689-
throw new InvalidParameterException("Default value of \"{$this->primaryName}\" must be an array.");
702+
throw new \InvalidArgumentException("Default value of \"{$this->primaryName}\" must be an array.");
690703
}
691704

692705
if ($this->isArg) {
693706
if ($this->negatable) {
694-
throw new InvalidParameterException(
707+
throw new \InvalidArgumentException(
695708
"Argument \"{$this->primaryName}\" cannot be negatable."
696709
);
697710
}
698711
} else {
699712
if ($this->negatable && $this->required) {
700-
throw new InvalidParameterException(
713+
throw new \InvalidArgumentException(
701714
"Negatable option \"{$this->primaryName}\" cannot be required."
702715
);
703716
}
704717
}
705718

706719
if ($this->required && $this->default !== null) {
707-
throw new InvalidParameterException(
720+
throw new \InvalidArgumentException(
708721
"Default value of \"{$this->primaryName}\" cannot be set when required is true."
709722
);
710723
}
@@ -749,6 +762,7 @@ public function validate(mixed $value): void
749762
"Invalid value type for \"{$this->primaryName}\". Expected int."
750763
);
751764
}
765+
break;
752766
case ParameterType::FLOAT:
753767
if (!is_numeric($value) || ((string) (float) $value) !== $value) {
754768
throw new InvalidParameterException(
@@ -992,6 +1006,5 @@ enum ParameterType
9921006

9931007
class InvalidParameterException extends \RuntimeException
9941008
{
995-
//
9961009
}
9971010
}

test/test.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
include_once __DIR__ . '/../vendor/autoload.php';
66

7-
$command = new \Symfony\Component\Console\Command\Command();
8-
$command->addOption(
9-
'foo',
10-
'f',
11-
\Symfony\Component\Console\Input\InputOption::VALUE_NEGATABLE
7+
$app = new \Asika\SimpleConsole\SimpleConsole();
8+
$app->execute(
9+
main: function () use ($app) {
10+
$app->mustExec(
11+
'ls sddfsg',
12+
);
13+
}
1214
);

0 commit comments

Comments
 (0)