diff --git a/src/mako/cli/output/components/Progress.php b/src/mako/cli/output/components/Progress.php index 7c695b34d..e8a104f0c 100644 --- a/src/mako/cli/output/components/Progress.php +++ b/src/mako/cli/output/components/Progress.php @@ -38,6 +38,14 @@ public function __construct( } } + /** + * Destructor. + */ + public function __destruct() + { + $this->output->restoreCursor(); + } + /** * Draws the progressbar. */ @@ -47,6 +55,10 @@ public function draw(): void return; } + if ($this->progress === 0) { + $this->output->hideCursor(); + } + $this->baseDraw(); } @@ -60,5 +72,9 @@ public function advance(): void } $this->baseAdvance(); + + if ($this->progress === $this->itemCount) { + $this->output->showCursor(); + } } } diff --git a/tests/unit/cli/output/components/ProgressTest.php b/tests/unit/cli/output/components/ProgressTest.php index 67cf8a83c..a3829959b 100644 --- a/tests/unit/cli/output/components/ProgressTest.php +++ b/tests/unit/cli/output/components/ProgressTest.php @@ -26,6 +26,8 @@ public function testProgressWithZeroItems(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('write')->never(); $progressBar = new Progress($output, 0); @@ -41,6 +43,10 @@ public function testBasicProgress(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('showCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('write')->once()->with("\r00/10 ──────────────────── 0% "); $output->shouldReceive('write')->once()->with("\r01/10 ██────────────────── 10% "); $output->shouldReceive('write')->once()->with("\r02/10 ████──────────────── 20% "); @@ -76,6 +82,10 @@ public function testProgressWithCustomWidth(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('showCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('write')->once()->with("\r00/10 ──────────────────────────────────────── 0% "); $output->shouldReceive('write')->once()->with("\r01/10 ████──────────────────────────────────── 10% "); $output->shouldReceive('write')->once()->with("\r02/10 ████████──────────────────────────────── 20% "); @@ -111,6 +121,10 @@ public function testProgressWithCustomTemplates(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('showCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('write')->once()->with("\r00/10 -------------------- 0% "); $output->shouldReceive('write')->once()->with("\r01/10 ==------------------ 10% "); $output->shouldReceive('write')->once()->with("\r02/10 ====---------------- 20% "); @@ -146,6 +160,10 @@ public function testProgressWithDescription(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('showCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('write')->once()->with("\rProcessing files: 00/10 ──────────────────── 0% "); $output->shouldReceive('write')->once()->with("\rProcessing files: 01/10 ██────────────────── 10% "); $output->shouldReceive('write')->once()->with("\rProcessing files: 02/10 ████──────────────── 20% "); @@ -181,6 +199,10 @@ public function testProgressWith100ItemsAndDefaultMinTimeBetweenRedraw(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('showCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('write')->times(102); $progressBar = new class ($output, 100) extends Progress { @@ -207,6 +229,9 @@ public function testProgressTimeBetweenRedraw(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('write')->times(3); $progressBar = new Progress($output, 100, minTimeBetweenRedraw: 0.5); @@ -230,6 +255,10 @@ public function testProgressWith100ItemsAndCustomMinTimeBetweenRedraw(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('showCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('write'); $progressBar = new class ($output, 100, minTimeBetweenRedraw: 1) extends Progress { @@ -267,6 +296,9 @@ public function testRemoveIncomplete(): void /** @var \Mockery\MockInterface|Output $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('clearLines')->once()->with(1); $output->shouldReceive('write')->once()->with("\r00/10 ──────────────────── 0% "); @@ -286,6 +318,10 @@ public function testRemoveComplete(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('showCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('clearLines')->once()->with(2); $output->shouldReceive('write')->once()->with("\r00/10 ──────────────────── 0% "); @@ -327,6 +363,10 @@ public function testProgressPast100Percent(): void /** @var \mako\cli\output\Output|\Mockery\MockInterface $output */ $output = Mockery::mock(Output::class); + $output->shouldReceive('hideCursor')->once(); + $output->shouldReceive('showCursor')->once(); + $output->shouldReceive('restoreCursor'); // Destructor + $output->shouldReceive('write')->times(12); $progressBar = new class ($output, 10) extends Progress {