From b553dd95cddc12708566c19f5705e5a2fe9e83da Mon Sep 17 00:00:00 2001 From: Maximilian Beckers Date: Mon, 9 Oct 2023 13:19:22 +0200 Subject: [PATCH] [Console] Add Placeholders to ProgressBar for exactly times --- .../Component/Console/Helper/Helper.php | 51 +++++++++++------- .../Component/Console/Helper/ProgressBar.php | 6 +-- .../Console/Helper/ProgressIndicator.php | 2 +- .../Console/Tests/Helper/HelperTest.php | 52 ++++++++++--------- .../Console/Tests/Helper/ProgressBarTest.php | 12 +++++ 5 files changed, 74 insertions(+), 49 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/Helper.php b/src/Symfony/Component/Console/Helper/Helper.php index 3631b30f692ab..c4b3df72e4ca1 100644 --- a/src/Symfony/Component/Console/Helper/Helper.php +++ b/src/Symfony/Component/Console/Helper/Helper.php @@ -94,33 +94,44 @@ public static function substr(?string $string, int $from, int $length = null): s /** * @return string */ - public static function formatTime(int|float $secs) + public static function formatTime(int|float $secs, int $precision = 1) { + $secs = (int) floor($secs); + + if (0 === $secs) { + return '< 1 sec'; + } + static $timeFormats = [ - [0, '< 1 sec'], - [1, '1 sec'], - [2, 'secs', 1], - [60, '1 min'], - [120, 'mins', 60], - [3600, '1 hr'], - [7200, 'hrs', 3600], - [86400, '1 day'], - [172800, 'days', 86400], + [1, '1 sec', 'secs'], + [60, '1 min', 'mins'], + [3600, '1 hr', 'hrs'], + [86400, '1 day', 'days'], ]; + $times = []; foreach ($timeFormats as $index => $format) { - if ($secs >= $format[0]) { - if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0]) - || $index == \count($timeFormats) - 1 - ) { - if (2 == \count($format)) { - return $format[1]; - } - - return floor($secs / $format[2]).' '.$format[1]; - } + $seconds = isset($timeFormats[$index + 1]) ? $secs % $timeFormats[$index + 1][0] : $secs; + + if (isset($times[$index - $precision])) { + unset($times[$index - $precision]); + } + + if (0 === $seconds) { + continue; } + + $unitCount = ($seconds / $format[0]); + $times[$index] = 1 === $unitCount ? $format[1] : $unitCount.' '.$format[2]; + + if ($secs === $seconds) { + break; + } + + $secs -= $seconds; } + + return implode(', ', array_reverse($times)); } /** diff --git a/src/Symfony/Component/Console/Helper/ProgressBar.php b/src/Symfony/Component/Console/Helper/ProgressBar.php index 1a6fdf5fb31f7..64389c4a2d285 100644 --- a/src/Symfony/Component/Console/Helper/ProgressBar.php +++ b/src/Symfony/Component/Console/Helper/ProgressBar.php @@ -540,20 +540,20 @@ private static function initPlaceholderFormatters(): array return $display; }, - 'elapsed' => fn (self $bar) => Helper::formatTime(time() - $bar->getStartTime()), + 'elapsed' => fn (self $bar) => Helper::formatTime(time() - $bar->getStartTime(), 2), 'remaining' => function (self $bar) { if (!$bar->getMaxSteps()) { throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); } - return Helper::formatTime($bar->getRemaining()); + return Helper::formatTime($bar->getRemaining(), 2); }, 'estimated' => function (self $bar) { if (!$bar->getMaxSteps()) { throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); } - return Helper::formatTime($bar->getEstimated()); + return Helper::formatTime($bar->getEstimated(), 2); }, 'memory' => fn (self $bar) => Helper::formatMemory(memory_get_usage(true)), 'current' => fn (self $bar) => str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT), diff --git a/src/Symfony/Component/Console/Helper/ProgressIndicator.php b/src/Symfony/Component/Console/Helper/ProgressIndicator.php index 84dbef950c6b1..79d47643efad5 100644 --- a/src/Symfony/Component/Console/Helper/ProgressIndicator.php +++ b/src/Symfony/Component/Console/Helper/ProgressIndicator.php @@ -228,7 +228,7 @@ private static function initPlaceholderFormatters(): array return [ 'indicator' => fn (self $indicator) => $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)], 'message' => fn (self $indicator) => $indicator->message, - 'elapsed' => fn (self $indicator) => Helper::formatTime(time() - $indicator->startTime), + 'elapsed' => fn (self $indicator) => Helper::formatTime(time() - $indicator->startTime, 2), 'memory' => fn () => Helper::formatMemory(memory_get_usage(true)), ]; } diff --git a/src/Symfony/Component/Console/Tests/Helper/HelperTest.php b/src/Symfony/Component/Console/Tests/Helper/HelperTest.php index 9f59aa2ff1a76..0a0c2fa48b22c 100644 --- a/src/Symfony/Component/Console/Tests/Helper/HelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/HelperTest.php @@ -20,26 +20,31 @@ class HelperTest extends TestCase public static function formatTimeProvider() { return [ - [0, '< 1 sec'], - [1, '1 sec'], - [2, '2 secs'], - [59, '59 secs'], - [60, '1 min'], - [61, '1 min'], - [119, '1 min'], - [120, '2 mins'], - [121, '2 mins'], - [3599, '59 mins'], - [3600, '1 hr'], - [7199, '1 hr'], - [7200, '2 hrs'], - [7201, '2 hrs'], - [86399, '23 hrs'], - [86400, '1 day'], - [86401, '1 day'], - [172799, '1 day'], - [172800, '2 days'], - [172801, '2 days'], + [0, '< 1 sec', 1], + [0.95, '< 1 sec', 1], + [1, '1 sec', 1], + [2, '2 secs', 2], + [59, '59 secs', 1], + [59.21, '59 secs', 1], + [60, '1 min', 2], + [61, '1 min, 1 sec', 2], + [119, '1 min, 59 secs', 2], + [120, '2 mins', 2], + [121, '2 mins, 1 sec', 2], + [3599, '59 mins, 59 secs', 2], + [3600, '1 hr', 2], + [7199, '1 hr, 59 mins', 2], + [7200, '2 hrs', 2], + [7201, '2 hrs', 2], + [86399, '23 hrs, 59 mins', 2], + [86399, '23 hrs, 59 mins, 59 secs', 3], + [86400, '1 day', 2], + [86401, '1 day', 2], + [172799, '1 day, 23 hrs', 2], + [172799, '1 day, 23 hrs, 59 mins, 59 secs', 4], + [172800, '2 days', 2], + [172801, '2 days', 2], + [172801, '2 days, 1 sec', 4], ]; } @@ -55,13 +60,10 @@ public static function decoratedTextProvider() /** * @dataProvider formatTimeProvider - * - * @param int $secs - * @param string $expectedFormat */ - public function testFormatTime($secs, $expectedFormat) + public function testFormatTime(int|float $secs, string $expectedFormat, int $precision) { - $this->assertEquals($expectedFormat, Helper::formatTime($secs)); + $this->assertEquals($expectedFormat, Helper::formatTime($secs, $precision)); } /** diff --git a/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php b/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php index 18644503b5f2f..4dff078ae72dd 100644 --- a/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php @@ -1005,6 +1005,18 @@ public function testSetFormat() ); } + public function testSetFormatWithTimes() + { + $bar = new ProgressBar($output = $this->getOutputStream(), 15, 0); + $bar->setFormat('%current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%/%remaining:-6s%'); + $bar->start(); + rewind($output->getStream()); + $this->assertEquals( + ' 0/15 [>---------------------------] 0% < 1 sec/< 1 sec/< 1 sec', + stream_get_contents($output->getStream()) + ); + } + public function testUnicode() { $bar = new ProgressBar($output = $this->getOutputStream(), 10, 0);