From 2f812470052c7145451f5f12523d6cc744787a8a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 10 Jun 2016 08:21:21 +0200 Subject: [PATCH] switched to use COLUMNS and LINES env vars to change terminal dimensions --- src/Symfony/Component/Console/Application.php | 30 ++---- .../Component/Console/Helper/ProgressBar.php | 14 --- src/Symfony/Component/Console/Terminal.php | 96 +++++++------------ .../Console/Tests/ApplicationTest.php | 12 ++- .../Console/Tests/Helper/ProgressBarTest.php | 34 +++++-- .../Component/Console/Tests/TerminalTest.php | 10 +- 6 files changed, 84 insertions(+), 112 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 313ba3f50e..71f0d9a950 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -684,26 +684,16 @@ class Application } } - /** - * Returns the current terminal. - * - * @return Terminal - */ - public function getTerminal() - { - return $this->terminal; - } - /** * Tries to figure out the terminal width in which this application runs. * * @return int|null * - * @deprecated since version 3.2, to be removed in 4.0. Use the getTerminal() method instead. + * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. */ protected function getTerminalWidth() { - @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Use getTerminal() instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); + @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); return $this->terminal->getWidth(); } @@ -713,11 +703,11 @@ class Application * * @return int|null * - * @deprecated since version 3.2, to be removed in 4.0. Use the getTerminal() method instead. + * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. */ protected function getTerminalHeight() { - @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Use getTerminal() instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); + @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); return $this->terminal->getHeight(); } @@ -727,11 +717,11 @@ class Application * * @return array Array containing width and height * - * @deprecated since version 3.2, to be removed in 4.0. Use the getTerminal() method instead. + * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. */ public function getTerminalDimensions() { - @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Use getTerminal() instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); + @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); return array($this->terminal->getWidth(), $this->terminal->getHeight()); } @@ -746,14 +736,14 @@ class Application * * @return Application The current application * - * @deprecated since version 3.2, to be removed in 4.0. Use the getTerminal() method instead. + * @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead. */ public function setTerminalDimensions($width, $height) { - @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Use getTerminal() instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); + @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); - $this->terminal->setWidth($width); - $this->terminal->setHeight($height); + putenv('COLUMNS='.$width); + putenv('LINES='.$height); return $this; } diff --git a/src/Symfony/Component/Console/Helper/ProgressBar.php b/src/Symfony/Component/Console/Helper/ProgressBar.php index 305094c99e..896cbf5eff 100644 --- a/src/Symfony/Component/Console/Helper/ProgressBar.php +++ b/src/Symfony/Component/Console/Helper/ProgressBar.php @@ -436,20 +436,6 @@ class ProgressBar $this->overwrite(''); } - /** - * Gets the terminal. - * - * Can be useful to force terminal dimensions for functional tests. - * - * @return Terminal - * - * @internal - */ - public function getTerminal() - { - return $this->terminal; - } - /** * Sets the progress bar format. * diff --git a/src/Symfony/Component/Console/Terminal.php b/src/Symfony/Component/Console/Terminal.php index ef2d8e44b8..4a6c30b8a0 100644 --- a/src/Symfony/Component/Console/Terminal.php +++ b/src/Symfony/Component/Console/Terminal.php @@ -13,8 +13,8 @@ namespace Symfony\Component\Console; class Terminal { - private $width; - private $height; + private static $width; + private static $height; /** * Gets the terminal width. @@ -23,21 +23,15 @@ class Terminal */ public function getWidth() { - if (null === $this->width) { - $this->initDimensions(); + if ($width = trim(getenv('COLUMNS'))) { + return (int) $width; } - return $this->width; - } + if (null === self::$width) { + self::initDimensions(); + } - /** - * Sets the terminal width. - * - * @param int $width - */ - public function setWidth($width) - { - $this->width = $width; + return self::$width; } /** @@ -47,59 +41,41 @@ class Terminal */ public function getHeight() { - if (null === $this->height) { - $this->initDimensions(); + if ($height = trim(getenv('LINES'))) { + return (int) $height; } - return $this->height; - } - - /** - * Sets the terminal height. - * - * @param int $height - */ - public function setHeight($height) - { - $this->height = $height; - } - - private function initDimensions() - { - if (null !== $this->width && null !== $this->height) { - return; + if (null === self::$height) { + self::initDimensions(); } - $width = $height = null; - if ($this->isWindowsEnvironment()) { - if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) { + return self::$height; + } + + private static function initDimensions() + { + if ('\\' === DIRECTORY_SEPARATOR) { + if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) { // extract [w, H] from "wxh (WxH)" - $width = (int) $matches[1]; - $height = (int) $matches[2]; - } elseif (null != $dimensions = $this->getConsoleMode()) { + // or [w, h] from "wxh" + self::$width = (int) $matches[1]; + self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (null != $dimensions = self::getConsoleMode()) { // extract [w, h] from "wxh" - $width = $dimensions[0]; - $height = $dimensions[1]; + self::$width = (int) $dimensions[0]; + self::$height = (int) $dimensions[1]; } - } elseif ($sttyString = $this->getSttyColumns()) { + } elseif ($sttyString = self::getSttyColumns()) { if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { // extract [w, h] from "rows h; columns w;" - $width = (int) $matches[1]; - $height = (int) $matches[2]; + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { // extract [w, h] from "; h rows; w columns" - $width = (int) $matches[2]; - $heighth = (int) $matches[1]; + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; } } - - if (null === $this->width) { - $this->width = $width; - } - - if (null === $this->height) { - $this->height = $height; - } } /** @@ -107,7 +83,7 @@ class Terminal * * @return array|null An array composed of the width and the height or null if it could not be parsed */ - private function getConsoleMode() + private static function getConsoleMode() { if (!function_exists('proc_open')) { return; @@ -135,7 +111,7 @@ class Terminal * * @return string */ - private function getSttyColumns() + private static function getSttyColumns() { if (!function_exists('proc_open')) { return; @@ -156,12 +132,4 @@ class Terminal return $info; } } - - /** - * @return bool - */ - private function isWindowsEnvironment() - { - return '\\' === DIRECTORY_SEPARATOR; - } } diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index ac3549f00a..60ab13dacc 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -478,7 +478,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase { $application = new Application(); $application->setAutoExit(false); - $application->getTerminal()->setWidth(120); + putenv('COLUMNS=120'); $tester = new ApplicationTester($application); $application->setCatchExceptions(true); @@ -514,7 +514,7 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase { $application = new Application(); $application->setAutoExit(false); - $application->getTerminal()->setWidth(120); + putenv('COLUMNS=120'); $tester = new ApplicationTester($application); $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); @@ -544,18 +544,19 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $application = new Application(); $application->setAutoExit(false); - $application->getTerminal()->setWidth(32); + putenv('COLUMNS=32'); $tester = new ApplicationTester($application); $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); + putenv('COLUMNS=120'); } public function testRenderExceptionWithDoubleWidthCharacters() { $application = new Application(); $application->setAutoExit(false); - $application->getTerminal()->setWidth(120); + putenv('COLUMNS=120'); $application->register('foo')->setCode(function () { throw new \Exception('エラーメッセージ'); }); @@ -569,13 +570,14 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $application = new Application(); $application->setAutoExit(false); - $application->getTerminal()->setWidth(32); + putenv('COLUMNS=32'); $application->register('foo')->setCode(function () { throw new \Exception('コマンドの実行中にエラーが発生しました。'); }); $tester = new ApplicationTester($application); $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); + putenv('COLUMNS=120'); } public function testRun() diff --git a/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php b/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php index e0a7fa889a..96bfc6e4b4 100644 --- a/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php @@ -522,9 +522,10 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase $output = $this->getOutputStream(); $bar = new ProgressBar($output); - $bar->getTerminal()->setWidth(12); + putenv('COLUMNS=12'); $bar->start(); $bar->advance(); + putenv('COLUMNS=120'); rewind($output->getStream()); $this->assertEquals( @@ -577,6 +578,8 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase public function testAnsiColorsAndEmojis() { + putenv('COLUMNS=156'); + $bar = new ProgressBar($output = $this->getOutputStream(), 15); ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) { static $i = 0; @@ -592,10 +595,6 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase $bar->setMessage('Starting the demo... fingers crossed', 'title'); $bar->start(); - $bar->setMessage('Looks good to me...', 'title'); - $bar->advance(4); - $bar->setMessage('Thanks, bye', 'title'); - $bar->finish(); rewind($output->getStream()); $this->assertEquals( @@ -603,12 +602,32 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase " \033[44;37m Starting the demo... fingers crossed \033[0m\n". ' 0/15 '.$progress.str_repeat($empty, 26)." 0%\n". " \xf0\x9f\x8f\x81 < 1 sec \033[44;37m 0 B \033[0m" - ). + ), + stream_get_contents($output->getStream()) + ); + ftruncate($output->getStream(), 0); + rewind($output->getStream()); + + $bar->setMessage('Looks good to me...', 'title'); + $bar->advance(4); + + rewind($output->getStream()); + $this->assertEquals( $this->generateOutput( " \033[44;37m Looks good to me... \033[0m\n". ' 4/15 '.str_repeat($done, 7).$progress.str_repeat($empty, 19)." 26%\n". " \xf0\x9f\x8f\x81 < 1 sec \033[41;37m 97 KiB \033[0m" - ). + ), + stream_get_contents($output->getStream()) + ); + ftruncate($output->getStream(), 0); + rewind($output->getStream()); + + $bar->setMessage('Thanks, bye', 'title'); + $bar->finish(); + + rewind($output->getStream()); + $this->assertEquals( $this->generateOutput( " \033[44;37m Thanks, bye \033[0m\n". ' 15/15 '.str_repeat($done, 28)." 100%\n". @@ -616,6 +635,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase ), stream_get_contents($output->getStream()) ); + putenv('COLUMNS=120'); } public function testSetFormat() diff --git a/src/Symfony/Component/Console/Tests/TerminalTest.php b/src/Symfony/Component/Console/Tests/TerminalTest.php index edbb8a079c..f13102244e 100644 --- a/src/Symfony/Component/Console/Tests/TerminalTest.php +++ b/src/Symfony/Component/Console/Tests/TerminalTest.php @@ -17,10 +17,16 @@ class TerminalTest extends \PHPUnit_Framework_TestCase { public function test() { + putenv('COLUMNS=100'); + putenv('LINES=50'); $terminal = new Terminal(); - $terminal->setWidth(100); - $terminal->setHeight(50); $this->assertSame(100, $terminal->getWidth()); $this->assertSame(50, $terminal->getHeight()); + + putenv('COLUMNS=120'); + putenv('LINES=60'); + $terminal = new Terminal(); + $this->assertSame(120, $terminal->getWidth()); + $this->assertSame(60, $terminal->getHeight()); } }