Skip to content

Commit e06dd63

Browse files
authored
refactor(console): improve console output consistency (#1102)
1 parent 0d93283 commit e06dd63

39 files changed

+235
-146
lines changed

src/Tempest/Console/src/Actions/ExecuteConsoleCommand.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use Tempest\Container\Container;
1515
use Throwable;
1616

17+
use function Tempest\Support\Arr\wrap;
18+
1719
final readonly class ExecuteConsoleCommand
1820
{
1921
public function __construct(
@@ -39,6 +41,16 @@ public function __invoke(string|array $command, string|array $arguments = []): E
3941
));
4042
}
4143

44+
public function withoutArgumentBag(): self
45+
{
46+
$bag = new ConsoleArgumentBag([
47+
$this->argumentBag->getBinaryPath(),
48+
$this->argumentBag->getCommandName(),
49+
]);
50+
51+
return new self($this->container, $this->consoleConfig, $bag, $this->resolveConsoleCommand);
52+
}
53+
4254
private function getCallable(array $commandMiddleware): ConsoleMiddlewareCallable
4355
{
4456
$callable = new ConsoleMiddlewareCallable(function (Invocation $invocation) {
@@ -77,9 +89,10 @@ private function resolveConsoleCommand(string|array $commandName): ?ConsoleComma
7789
}
7890

7991
/** @return array{string,array} */
80-
private function resolveCommandAndArguments(string|array $command, array $arguments = []): array
92+
private function resolveCommandAndArguments(string|array $command, string|array $arguments = []): array
8193
{
8294
$commandName = $command;
95+
$arguments = wrap($arguments);
8396

8497
if (is_array($command)) {
8598
$commandName = $command[0] ?? '';

src/Tempest/Console/src/Commands/MakeCommandCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function __invoke(
3838
],
3939
);
4040

41-
$this->console->success(sprintf('File successfully created at <em>%s</em>.', $targetPath));
41+
$this->console->writeln();
42+
$this->console->success(sprintf('File successfully created at <file="%s"/>.', $targetPath));
4243
}
4344
}

src/Tempest/Console/src/Commands/MakeGeneratorCommandCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function __invoke(
3838
],
3939
);
4040

41-
$this->console->success(sprintf('File successfully created at <em>%s</em>.', $targetPath));
41+
$this->console->writeln();
42+
$this->console->success(sprintf('File successfully created at <file="%s"/>.', $targetPath));
4243
}
4344
}

src/Tempest/Console/src/Commands/MakeMiddlewareCommand.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public function __invoke(
4141
shouldOverride: $shouldOverride,
4242
);
4343

44+
$this->console->writeln();
4445
$this->console->success(sprintf('Middleware successfully created at <file="%s"/>.', $targetPath));
4546
}
4647

src/Tempest/Console/src/Components/InteractiveComponentRenderer.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,7 @@ private function resolveHandlers(InteractiveConsoleComponent $component): array
226226
*/
227227
private function validate(mixed $value, array $validation): ?Rule
228228
{
229-
$validator = new Validator();
230-
231-
try {
232-
$validator->validateValue($value, $validation);
233-
} catch (InvalidValueException $invalidValueException) {
234-
return $invalidValueException->failingRules[0];
235-
}
236-
237-
return null;
229+
return new Validator()->validateValue($value, $validation)[0] ?? null;
238230
}
239231

240232
public function isComponentSupported(Console $console, InteractiveConsoleComponent $component): bool

src/Tempest/Console/src/Components/Renderers/MessageRenderer.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public function render(string $contents, ?string $title = null): string
2323
->implode("\n");
2424

2525
return str()
26-
->append("\n")
2726
->append("<style='fg-{$this->color} bold'>{$title}</style> <style='dim fg-{$this->color}'>//</style>")
2827
->append("<style='fg-{$this->color}'>{$lines}</style>")
2928
->toString();

src/Tempest/Console/src/Components/Renderers/RendersInput.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ trait RendersInput
1717

1818
public const int MARGIN_TOP = 1;
1919

20+
public const int MARGIN_BOTTOM = 0;
21+
2022
private ImmutableString $frame;
2123

2224
private Terminal $terminal;
@@ -54,10 +56,10 @@ private function prepareRender(Terminal $terminal, ComponentState $state): self
5456
private function finishRender(): string
5557
{
5658
if ($this->state->isFinished() && $this->frame->endsWith("\n")) {
57-
$this->frame = $this->frame->replaceEnd("\n", '');
59+
$this->frame = $this->frame->stripEnd("\n");
5860
}
5961

60-
return $this->frame->toString();
62+
return $this->frame->append(str_repeat("\n", self::MARGIN_BOTTOM))->toString();
6163
}
6264

6365
private function truncate(?string $string = null, int $maxLineOffset = 0): string

src/Tempest/Console/src/Components/Renderers/TextInputRenderer.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Tempest\Console\Components\TextBuffer;
99
use Tempest\Console\Point;
1010
use Tempest\Console\Terminal\Terminal;
11+
use Tempest\Support\Str\ImmutableString;
1112

1213
use function Tempest\Support\str;
1314

@@ -42,7 +43,8 @@ public function render(
4243
$lines = str($buffer->text ?: ($placeholder ?: ''))
4344
->explode("\n")
4445
->flatMap(fn (string $line) => str($line)->chunk($this->maxLineCharacters)->toArray())
45-
->map(static fn (string $line) => str($line)->replaceEnd("\n", ' '));
46+
->map(static fn (string $line) => str($line)->replaceEnd("\n", ' '))
47+
->filter(fn (ImmutableString $line) => $line->isNotEmpty());
4648

4749
// calculates scroll offset based on cursor position
4850
$this->scrollOffset = $this->calculateScrollOffset($lines, $this->maximumLines, $buffer->getRelativeCursorPosition($this->maxLineCharacters)->y);
@@ -51,7 +53,7 @@ public function render(
5153
$displayLines = $lines->slice($this->scrollOffset, $this->state->isFinished() ? 1 : $this->maximumLines);
5254

5355
// if there is nothing to display after the component is done, show "no input"
54-
if ($this->state->isFinished() && $lines->count() === 0) {
56+
if ($this->state->isFinished() && $lines->isEmpty()) {
5557
$this->line($this->style('italic dim', 'No input.'))->newLine();
5658
}
5759

src/Tempest/Console/src/Exceptions/ConsoleErrorHandler.php

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use Tempest\Highlight\Highlighter;
1616
use Throwable;
1717

18+
use function Tempest\Support\str;
19+
1820
final readonly class ConsoleErrorHandler implements ErrorHandler
1921
{
2022
public function __construct(
@@ -36,9 +38,9 @@ public function handleException(Throwable $throwable): void
3638
condition: $throwable->getMessage(),
3739
callback: fn (Console $console) => $console->error($throwable->getMessage()),
3840
)
39-
->writeln($this->getSnippet($throwable->getFile(), $throwable->getLine()))
4041
->writeln()
41-
->writeln('<u>' . $throwable->getFile() . ':' . $throwable->getLine() . '</u>')
42+
->writeln('In ' . $this->formatFileWithLine($throwable->getFile() . ':' . $throwable->getLine()))
43+
->writeln($this->getSnippet($throwable->getFile(), $throwable->getLine()))
4244
->writeln();
4345

4446
if ($this->argumentBag->get('-v') !== null) {
@@ -48,12 +50,11 @@ public function handleException(Throwable $throwable): void
4850

4951
$this->console->writeln();
5052
} else {
51-
$firstLine = $throwable->getTrace()[0];
52-
5353
$this->console
54-
->writeln('<style="fg-blue bold">#0</style> ' . $this->formatTrace($firstLine))
54+
->writeln('<style="fg-blue bold">#0</style> ' . $this->formatTrace($throwable->getTrace()[0]))
55+
->writeln('<style="fg-blue bold">#1</style> ' . $this->formatTrace($throwable->getTrace()[1]))
5556
->writeln()
56-
->writeln('<em>-v</em> show more')
57+
->writeln(' <style="dim">Run with -v to show more.</style>')
5758
->writeln();
5859
}
5960

@@ -75,10 +76,13 @@ public function handleError(int $errNo, string $errstr, string $errFile, int $er
7576
private function getSnippet(string $file, int $lineNumber): string
7677
{
7778
$highlighter = $this->highlighter->withGutter();
78-
$code = Escape::terminal($highlighter->parse(file_get_contents($file), 'php'));
79+
$code = Escape::terminal($highlighter->parse(file_get_contents($file), language: 'php'));
7980
$lines = explode(PHP_EOL, $code);
8081

81-
$lines[$lineNumber - 1] = $lines[$lineNumber - 1] . ' <style="fg-red"><</style>';
82+
$lines[$lineNumber - 1] = str($lines[$lineNumber - 1])
83+
->replaceRegex('/^\d+/', fn (array $match) => "<style='fg-red'>{$match[0]}</style>")
84+
->append(' <style="fg-red"><<<</style>')
85+
->toString();
8286

8387
$excerptSize = 5;
8488
$start = max(0, ($lineNumber - $excerptSize) - 2);
@@ -87,16 +91,30 @@ private function getSnippet(string $file, int $lineNumber): string
8791
return PHP_EOL . implode(PHP_EOL, $lines);
8892
}
8993

90-
private function formatTrace(mixed $trace): string
94+
private function formatFileWithLine(string $file): string
95+
{
96+
[$file, $line] = explode(':', $file);
97+
$directory = dirname($file);
98+
$filename = basename($file);
99+
100+
return sprintf('<style="fg-gray">%s/</style>%s<style="dim">:</style>%s', $directory, $filename, $line);
101+
}
102+
103+
private function formatTrace(array $trace): string
91104
{
92105
if (isset($trace['file'])) {
93-
return '<u>' . $trace['file'] . ':' . $trace['line'] . '</u>';
106+
return $this->formatFileWithLine($trace['file'] . ':' . $trace['line']);
94107
}
95108

96109
if (isset($trace['class'])) {
97-
return $trace['class'] . $trace['type'] . $trace['function'];
110+
return sprintf(
111+
"%s<style='dim'>%s</style>%s<style='dim'>()</style>",
112+
$trace['class'],
113+
$trace['type'],
114+
$trace['function'],
115+
);
98116
}
99117

100-
return $trace['function'] . '()';
118+
return sprintf("%s<style='dim'>()</style>", $trace['function']);
101119
}
102120
}

src/Tempest/Console/src/Exceptions/InterruptException.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ final class InterruptException extends ConsoleException
1010
{
1111
public function render(Console $console): void
1212
{
13+
$console->writeln();
1314
$console->error('Interrupted by user.');
1415
}
1516
}

0 commit comments

Comments
 (0)