Skip to content

Commit b4f6757

Browse files
committedOct 6, 2024
feature #57576 [Console] Add finished indicator to ProgressIndicator (LauLaman)
This PR was merged into the 7.2 branch. Discussion ---------- [Console] Add finished indicator to `ProgressIndicator` | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Issues | <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT Add a (configurable) finished indicator to the progress indicator to show that the progress is finished instead of last used indicator value. This will make the output a bit nicer instead of ``` - Process A (4 secs, 8.0 MiB) \ Process B (1 min, 39 secs, 18.0 MiB) - Process C (7 secs, 18.0 MiB) - Process D (48 secs, 20.0 MiB) / Process E (45 secs, 20.0 MiB) ``` The output will look now like this: ``` ✔ Process A (4 secs, 8.0 MiB) ✔ Process B (1 min, 39 secs, 18.0 MiB) ✔ Process C (7 secs, 18.0 MiB) ✔ Process D (48 secs, 20.0 MiB) ✔ Process E (45 secs, 20.0 MiB) ``` Commits ------- b13fffc82e Add finished indicator to ProgressIndicator
2 parents 721a55b + 6f86f8d commit b4f6757

File tree

3 files changed

+56
-4
lines changed

3 files changed

+56
-4
lines changed
 

‎CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* Add `verbosity` argument to `mustRun` process helper method
99
* [BC BREAK] Add silent verbosity (`--silent`/`SHELL_VERBOSITY=-2`) to suppress all output, including errors
1010
* Add `OutputInterface::isSilent()`, `Output::isSilent()`, `OutputStyle::isSilent()` methods
11+
* Add a configurable finished indicator to the progress indicator to show that the progress is finished
1112

1213
7.1
1314
---

‎Helper/ProgressIndicator.php

+20-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ class ProgressIndicator
3636
private ?string $message = null;
3737
private array $indicatorValues;
3838
private int $indicatorCurrent;
39+
private string $finishedIndicatorValue;
3940
private float $indicatorUpdateTime;
4041
private bool $started = false;
42+
private bool $finished = false;
4143

4244
/**
4345
* @var array<string, callable>
@@ -53,17 +55,20 @@ public function __construct(
5355
?string $format = null,
5456
private int $indicatorChangeInterval = 100,
5557
?array $indicatorValues = null,
58+
?string $finishedIndicatorValue = null,
5659
) {
5760
$format ??= $this->determineBestFormat();
5861
$indicatorValues ??= ['-', '\\', '|', '/'];
5962
$indicatorValues = array_values($indicatorValues);
63+
$finishedIndicatorValue ??= '';
6064

6165
if (2 > \count($indicatorValues)) {
6266
throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
6367
}
6468

6569
$this->format = self::getFormatDefinition($format);
6670
$this->indicatorValues = $indicatorValues;
71+
$this->finishedIndicatorValue = $finishedIndicatorValue;
6772
$this->startTime = time();
6873
}
6974

@@ -88,6 +93,7 @@ public function start(string $message): void
8893

8994
$this->message = $message;
9095
$this->started = true;
96+
$this->finished = false;
9197
$this->startTime = time();
9298
$this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
9399
$this->indicatorCurrent = 0;
@@ -122,13 +128,25 @@ public function advance(): void
122128

123129
/**
124130
* Finish the indicator with message.
131+
*
132+
* @param ?string $finishedIndicator
125133
*/
126-
public function finish(string $message): void
134+
public function finish(string $message/* , ?string $finishedIndicator = null */): void
127135
{
136+
$finishedIndicator = 1 < \func_num_args() ? func_get_arg(1) : null;
137+
if (null !== $finishedIndicator && !\is_string($finishedIndicator)) {
138+
throw new \TypeError(\sprintf('Argument 2 passed to "%s()" must be of the type string or null, "%s" given.', __METHOD__, get_debug_type($finishedIndicator)));
139+
}
140+
128141
if (!$this->started) {
129142
throw new LogicException('Progress indicator has not yet been started.');
130143
}
131144

145+
if (null !== $finishedIndicator) {
146+
$this->finishedIndicatorValue = $finishedIndicator;
147+
}
148+
149+
$this->finished = true;
132150
$this->message = $message;
133151
$this->display();
134152
$this->output->writeln('');
@@ -215,7 +233,7 @@ private function getCurrentTimeInMilliseconds(): float
215233
private static function initPlaceholderFormatters(): array
216234
{
217235
return [
218-
'indicator' => fn (self $indicator) => $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)],
236+
'indicator' => fn (self $indicator) => $indicator->finished ? $indicator->finishedIndicatorValue : $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)],
219237
'message' => fn (self $indicator) => $indicator->message,
220238
'elapsed' => fn (self $indicator) => Helper::formatTime(time() - $indicator->startTime, 2),
221239
'memory' => fn () => Helper::formatMemory(memory_get_usage(true)),

‎Tests/Helper/ProgressIndicatorTest.php

+35-2
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ public function testDefaultIndicator()
5454
$this->generateOutput(' \\ Starting...').
5555
$this->generateOutput(' \\ Advancing...').
5656
$this->generateOutput(' | Advancing...').
57-
$this->generateOutput(' | Done...').
57+
$this->generateOutput(' Done...').
5858
\PHP_EOL.
5959
$this->generateOutput(' - Starting Again...').
6060
$this->generateOutput(' \\ Starting Again...').
61-
$this->generateOutput(' \\ Done Again...').
61+
$this->generateOutput(' Done Again...').
6262
\PHP_EOL,
6363
stream_get_contents($output->getStream())
6464
);
@@ -109,6 +109,39 @@ public function testCustomIndicatorValues()
109109
);
110110
}
111111

112+
public function testCustomFinishedIndicatorValue()
113+
{
114+
$bar = new ProgressIndicator($output = $this->getOutputStream(), null, 100, ['a', 'b'], '');
115+
116+
$bar->start('Starting...');
117+
usleep(101000);
118+
$bar->finish('Done');
119+
120+
rewind($output->getStream());
121+
122+
$this->assertSame(
123+
$this->generateOutput(' a Starting...').
124+
$this->generateOutput(' ✅ Done').\PHP_EOL,
125+
stream_get_contents($output->getStream())
126+
);
127+
}
128+
129+
public function testCustomFinishedIndicatorWhenFinishingProcess()
130+
{
131+
$bar = new ProgressIndicator($output = $this->getOutputStream(), null, 100, ['a', 'b']);
132+
133+
$bar->start('Starting...');
134+
$bar->finish('Process failed', '');
135+
136+
rewind($output->getStream());
137+
138+
$this->assertEquals(
139+
$this->generateOutput(' a Starting...').
140+
$this->generateOutput(' ❌ Process failed').\PHP_EOL,
141+
stream_get_contents($output->getStream())
142+
);
143+
}
144+
112145
public function testCannotSetInvalidIndicatorCharacters()
113146
{
114147
$this->expectException(\InvalidArgumentException::class);

0 commit comments

Comments
 (0)
Please sign in to comment.