Skip to content

Commit 243d49b

Browse files
committed
[TASK] Improve progress bar
* Display a progress bar during parsing * Display one progress bar per renderer * Introduce an event once the files have been collected for parsing This gives me progress bars like this after rendering: Parsing: 16/16 [============================] 100% Parsed 16 files in 0.98 seconds Rendering: 16/16 [============================] 100% Output format html: Rendered 16 documents in 0.71 seconds Rendering: 16/16 [============================] 100% Output format interlink: Rendered 16 documents in 0.00 seconds During rendering and during parsing the currently handled file is displayed.
1 parent 9d860d2 commit 243d49b

File tree

7 files changed

+156
-19
lines changed

7 files changed

+156
-19
lines changed

packages/guides-cli/src/Command/Run.php

Lines changed: 87 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@
1313
use Monolog\Logger;
1414
use phpDocumentor\Guides\Cli\Logger\SpyProcessor;
1515
use phpDocumentor\Guides\Compiler\CompilerContext;
16+
use phpDocumentor\Guides\Event\PostCollectFilesForParsingEvent;
17+
use phpDocumentor\Guides\Event\PostParseDocument;
18+
use phpDocumentor\Guides\Event\PostParseProcess;
1619
use phpDocumentor\Guides\Event\PostRenderDocument;
20+
use phpDocumentor\Guides\Event\PostRenderProcess;
21+
use phpDocumentor\Guides\Event\PreParseDocument;
22+
use phpDocumentor\Guides\Event\PreRenderDocument;
23+
use phpDocumentor\Guides\Event\PreRenderProcess;
1724
use phpDocumentor\Guides\Handlers\CompileDocumentsCommand;
1825
use phpDocumentor\Guides\Handlers\ParseDirectoryCommand;
1926
use phpDocumentor\Guides\Handlers\ParseFileCommand;
@@ -39,6 +46,7 @@
3946
use function implode;
4047
use function is_countable;
4148
use function is_dir;
49+
use function microtime;
4250
use function pathinfo;
4351
use function realpath;
4452
use function sprintf;
@@ -117,6 +125,80 @@ public function __construct(
117125
);
118126
}
119127

128+
public function registerProgressBar(ConsoleOutputInterface $output): void
129+
{
130+
$parsingProgressBar = new ProgressBar($output->section());
131+
$parsingProgressBar->setFormat('Parsing: %current%/%max% [%bar%] %percent:3s%% %message%');
132+
$parsingStartTime = microtime(true);
133+
$this->eventDispatcher->addListener(
134+
PostCollectFilesForParsingEvent::class,
135+
static function (PostCollectFilesForParsingEvent $event) use ($parsingProgressBar, &$parsingStartTime): void {
136+
// Each File needs to be first parsed then rendered
137+
$parsingStartTime = microtime(true);
138+
$parsingProgressBar->setMaxSteps(count($event->getFiles()));
139+
},
140+
);
141+
$this->eventDispatcher->addListener(
142+
PreParseDocument::class,
143+
static function (PreParseDocument $event) use ($parsingProgressBar): void {
144+
$parsingProgressBar->setMessage('Parsing file: ' . $event->getFileName());
145+
$parsingProgressBar->display();
146+
},
147+
);
148+
$this->eventDispatcher->addListener(
149+
PostParseDocument::class,
150+
static function (PostParseDocument $event) use ($parsingProgressBar): void {
151+
$parsingProgressBar->advance();
152+
},
153+
);
154+
$this->eventDispatcher->addListener(
155+
PostParseProcess::class,
156+
static function (PostParseProcess $event) use ($parsingProgressBar, $parsingStartTime): void {
157+
$parsingTimeElapsed = microtime(true) - $parsingStartTime;
158+
$parsingProgressBar->setMessage(sprintf(
159+
'Parsed %s files in %.2f seconds',
160+
$parsingProgressBar->getMaxSteps(),
161+
$parsingTimeElapsed,
162+
));
163+
$parsingProgressBar->finish();
164+
},
165+
);
166+
$that = $this;
167+
$this->eventDispatcher->addListener(
168+
PreRenderProcess::class,
169+
static function (PreRenderProcess $event) use ($that, $output): void {
170+
$renderingProgressBar = new ProgressBar($output->section(), count($event->getCommand()->getDocumentArray()));
171+
$renderingProgressBar->setFormat('Rendering: %current%/%max% [%bar%] %percent:3s%% Output format ' . $event->getCommand()->getOutputFormat() . ': %message%');
172+
$renderingStartTime = microtime(true);
173+
$that->eventDispatcher->addListener(
174+
PreRenderDocument::class,
175+
static function (PreRenderDocument $event) use ($renderingProgressBar): void {
176+
$renderingProgressBar->setMessage('Rendering: ' . $event->getCommand()->getFileDestination());
177+
$renderingProgressBar->display();
178+
},
179+
);
180+
$that->eventDispatcher->addListener(
181+
PostRenderDocument::class,
182+
static function (PostRenderDocument $event) use ($renderingProgressBar): void {
183+
$renderingProgressBar->advance();
184+
},
185+
);
186+
$that->eventDispatcher->addListener(
187+
PostRenderProcess::class,
188+
static function (PostRenderProcess $event) use ($renderingProgressBar, $renderingStartTime): void {
189+
$renderingElapsedTime = microtime(true) - $renderingStartTime;
190+
$renderingProgressBar->setMessage(sprintf(
191+
'Rendered %s documents in %.2f seconds',
192+
$renderingProgressBar->getMaxSteps(),
193+
$renderingElapsedTime,
194+
));
195+
$renderingProgressBar->finish();
196+
},
197+
);
198+
},
199+
);
200+
}
201+
120202
private function getSettingsOverridenWithInput(InputInterface $input): ProjectSettings
121203
{
122204
$settings = $this->settingsManager->getProjectSettings();
@@ -200,6 +282,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
200282

201283
$documents = [];
202284

285+
286+
if ($output instanceof ConsoleOutputInterface && $settings->isShowProgressBar()) {
287+
$this->registerProgressBar($output);
288+
}
289+
203290
if ($settings->getInputFile() === '') {
204291
$documents = $this->commandBus->handle(
205292
new ParseDirectoryCommand(
@@ -231,16 +318,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int
231318

232319
$outputFormats = $settings->getOutputFormats();
233320

234-
if ($output instanceof ConsoleOutputInterface && $settings->isShowProgressBar()) {
235-
$progressBar = new ProgressBar($output->section(), count($documents));
236-
$this->eventDispatcher->addListener(
237-
PostRenderDocument::class,
238-
static function (PostRenderDocument $event) use ($progressBar): void {
239-
$progressBar->advance();
240-
},
241-
);
242-
}
243-
244321
foreach ($outputFormats as $format) {
245322
$this->commandBus->handle(
246323
new RenderCommand(
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpDocumentor\Guides\Event;
6+
7+
use phpDocumentor\Guides\Files;
8+
use phpDocumentor\Guides\Handlers\ParseDirectoryCommand;
9+
10+
/**
11+
* This event is called after all files have been collected for parsing
12+
* But before the actual parsing begins.
13+
*
14+
* It can be used to manipulate the files to be parsed.
15+
*/
16+
final class PostCollectFilesForParsingEvent
17+
{
18+
public function __construct(
19+
private readonly ParseDirectoryCommand $command,
20+
private Files $files,
21+
) {
22+
}
23+
24+
public function getCommand(): ParseDirectoryCommand
25+
{
26+
return $this->command;
27+
}
28+
29+
public function getFiles(): Files
30+
{
31+
return $this->files;
32+
}
33+
34+
public function setFiles(Files $files): void
35+
{
36+
$this->files = $files;
37+
}
38+
}

packages/guides/src/Event/PostRenderDocument.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
final class PostRenderDocument
1717
{
1818
/** @param NodeRenderer<DocumentNode> $renderer */
19-
public function __construct(private readonly NodeRenderer $renderer, private readonly RenderDocumentCommand $command)
20-
{
19+
public function __construct(
20+
private readonly NodeRenderer $renderer,
21+
private readonly RenderDocumentCommand $command,
22+
) {
2123
}
2224

2325
/** @return NodeRenderer<DocumentNode> */

packages/guides/src/Event/PreRenderProcess.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ final class PreRenderProcess
1717
{
1818
private bool $exitRendering = false;
1919

20-
public function __construct(private readonly RenderCommand $command)
21-
{
20+
public function __construct(
21+
private readonly RenderCommand $command,
22+
private readonly int $steps = 1,
23+
) {
2224
}
2325

2426
public function getCommand(): RenderCommand
@@ -37,4 +39,9 @@ public function setExitRendering(bool $exitRendering): PreRenderProcess
3739

3840
return $this;
3941
}
42+
43+
public function getSteps(): int
44+
{
45+
return $this->steps;
46+
}
4047
}

packages/guides/src/Files.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
namespace phpDocumentor\Guides;
1515

1616
use ArrayIterator;
17+
use Countable;
1718
use Iterator;
1819
use IteratorAggregate;
1920

21+
use function count;
2022
use function in_array;
2123

2224
/** @implements IteratorAggregate<string> */
23-
final class Files implements IteratorAggregate
25+
final class Files implements IteratorAggregate, Countable
2426
{
2527
/** @var string[] */
2628
private array $files = [];
@@ -39,4 +41,9 @@ public function getIterator(): Iterator
3941
{
4042
return new ArrayIterator($this->files);
4143
}
44+
45+
public function count(): int
46+
{
47+
return count($this->files);
48+
}
4249
}

packages/guides/src/Handlers/ParseDirectoryHandler.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use InvalidArgumentException;
88
use League\Flysystem\FilesystemInterface;
99
use League\Tactician\CommandBus;
10+
use phpDocumentor\Guides\Event\PostCollectFilesForParsingEvent;
1011
use phpDocumentor\Guides\Event\PostParseProcess;
1112
use phpDocumentor\Guides\Event\PreParseProcess;
1213
use phpDocumentor\Guides\FileCollector;
@@ -47,18 +48,23 @@ public function handle(ParseDirectoryCommand $command): array
4748
);
4849

4950
$files = $this->fileCollector->collect($origin, $currentDirectory, $extension);
51+
52+
$postCollectFilesForParsingEvent = $this->eventDispatcher->dispatch(
53+
new PostCollectFilesForParsingEvent($command, $files),
54+
);
55+
assert($postCollectFilesForParsingEvent instanceof PostCollectFilesForParsingEvent);
5056
/** @var DocumentNode[] $documents */
5157
$documents = [];
52-
foreach ($files as $file) {
58+
foreach ($postCollectFilesForParsingEvent->getFiles() as $file) {
5359
$documents[] = $this->commandBus->handle(
5460
new ParseFileCommand($origin, $currentDirectory, $file, $extension, 1, $command->getProjectNode(), $indexName === $file),
5561
);
5662
}
5763

58-
$postParseProcessEvent = $this->eventDispatcher->dispatch(
64+
$postCollectFilesForParsingEvent = $this->eventDispatcher->dispatch(
5965
new PostParseProcess($command, $documents),
6066
);
61-
assert($postParseProcessEvent instanceof PostParseProcess);
67+
assert($postCollectFilesForParsingEvent instanceof PostParseProcess);
6268

6369
return $documents;
6470
}

phpstan-baseline.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ parameters:
3232

3333
-
3434
message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, mixed given\\.$#"
35-
count: 2
35+
count: 1
3636
path: packages/guides-cli/src/Command/Run.php
3737

3838
-

0 commit comments

Comments
 (0)