diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index c046f5ec9faff..af4d0b9cca459 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -21,6 +21,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; /** * The QuestionHelper class provides helpers to interact with the user. @@ -157,7 +158,7 @@ private function doAsk(OutputInterface $output, Question $question) $inputStream = $this->inputStream ?: STDIN; $autocomplete = $question->getAutocompleterValues(); - if (null === $autocomplete || !$this->hasSttyAvailable()) { + if (null === $autocomplete || !Terminal::hasSttyAvailable()) { $ret = false; if ($question->isHidden()) { try { @@ -409,7 +410,7 @@ private function getHiddenResponse(OutputInterface $output, $inputStream) return $value; } - if ($this->hasSttyAvailable()) { + if (Terminal::hasSttyAvailable()) { $sttyMode = shell_exec('stty -g'); shell_exec('stty -echo'); @@ -495,20 +496,4 @@ private function getShell() return self::$shell; } - - /** - * Returns whether Stty is available or not. - * - * @return bool - */ - private function hasSttyAvailable() - { - if (null !== self::$stty) { - return self::$stty; - } - - exec('stty 2>&1', $output, $exitcode); - - return self::$stty = 0 === $exitcode; - } } diff --git a/src/Symfony/Component/Console/Terminal.php b/src/Symfony/Component/Console/Terminal.php index 56eb05096442b..53a0f7890b6ff 100644 --- a/src/Symfony/Component/Console/Terminal.php +++ b/src/Symfony/Component/Console/Terminal.php @@ -15,6 +15,7 @@ class Terminal { private static $width; private static $height; + private static $stty; /** * Gets the terminal width. @@ -54,6 +55,22 @@ public function getHeight() return self::$height ?: 50; } + /** + * @internal + * + * @return bool + */ + public static function hasSttyAvailable() + { + if (null !== self::$stty) { + return self::$stty; + } + + exec('stty 2>&1', $output, $exitcode); + + return self::$stty = 0 === $exitcode; + } + private static function initDimensions() { if ('\\' === \DIRECTORY_SEPARATOR) { @@ -62,12 +79,21 @@ private static function initDimensions() // or [w, h] from "wxh" self::$width = (int) $matches[1]; self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (self::hasSttyAvailable()) { + self::initDimensionsUsingStty(); } elseif (null !== $dimensions = self::getConsoleMode()) { // extract [w, h] from "wxh" self::$width = (int) $dimensions[0]; self::$height = (int) $dimensions[1]; } - } elseif ($sttyString = self::getSttyColumns()) { + } else { + self::initDimensionsUsingStty(); + } + } + + private static function initDimensionsUsingStty() + { + if ($sttyString = self::getSttyColumns()) { if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { // extract [w, h] from "rows h; columns w;" self::$width = (int) $matches[2]; diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index d4ac0f4693ae7..fc2589097c301 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -19,6 +19,7 @@ use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; /** * @group tty @@ -167,7 +168,7 @@ public function testAsk() public function testAskWithAutocomplete() { - if (!$this->hasSttyAvailable()) { + if (!Terminal::hasSttyAvailable()) { $this->markTestSkipped('`stty` is required to test autocomplete functionality'); } @@ -200,7 +201,7 @@ public function testAskWithAutocomplete() public function testAskWithAutocompleteWithNonSequentialKeys() { - if (!$this->hasSttyAvailable()) { + if (!Terminal::hasSttyAvailable()) { $this->markTestSkipped('`stty` is required to test autocomplete functionality'); } @@ -219,7 +220,7 @@ public function testAskWithAutocompleteWithNonSequentialKeys() public function testAskWithAutocompleteWithExactMatch() { - if (!$this->hasSttyAvailable()) { + if (!Terminal::hasSttyAvailable()) { $this->markTestSkipped('`stty` is required to test autocomplete functionality'); } @@ -255,7 +256,7 @@ public function getInputs() */ public function testAskWithAutocompleteWithMultiByteCharacter($character) { - if (!$this->hasSttyAvailable()) { + if (!Terminal::hasSttyAvailable()) { $this->markTestSkipped('`stty` is required to test autocomplete functionality'); } @@ -279,7 +280,7 @@ public function testAskWithAutocompleteWithMultiByteCharacter($character) public function testAutocompleteWithTrailingBackslash() { - if (!$this->hasSttyAvailable()) { + if (!Terminal::hasSttyAvailable()) { $this->markTestSkipped('`stty` is required to test autocomplete functionality'); } @@ -672,7 +673,7 @@ public function testLegacyAsk() */ public function testLegacyAskWithAutocomplete() { - if (!$this->hasSttyAvailable()) { + if (!Terminal::hasSttyAvailable()) { $this->markTestSkipped('`stty` is required to test autocomplete functionality'); } @@ -709,7 +710,7 @@ public function testLegacyAskWithAutocomplete() */ public function testLegacyAskWithAutocompleteWithNonSequentialKeys() { - if (!$this->hasSttyAvailable()) { + if (!Terminal::hasSttyAvailable()) { $this->markTestSkipped('`stty` is required to test autocomplete functionality'); } @@ -977,7 +978,7 @@ public function testEmptyChoices() public function testTraversableAutocomplete() { - if (!$this->hasSttyAvailable()) { + if (!Terminal::hasSttyAvailable()) { $this->markTestSkipped('`stty` is required to test autocomplete functionality'); } @@ -1062,13 +1063,6 @@ protected function createInputInterfaceMock($interactive = true) return $mock; } - - private function hasSttyAvailable() - { - exec('stty 2>&1', $output, $exitcode); - - return 0 === $exitcode; - } } class AutocompleteValues implements \IteratorAggregate diff --git a/src/Symfony/Component/Console/Tests/TerminalTest.php b/src/Symfony/Component/Console/Tests/TerminalTest.php index 93b8c44a78158..546d2214c4c46 100644 --- a/src/Symfony/Component/Console/Tests/TerminalTest.php +++ b/src/Symfony/Component/Console/Tests/TerminalTest.php @@ -18,17 +18,31 @@ class TerminalTest extends TestCase { private $colSize; private $lineSize; + private $ansiCon; protected function setUp() { $this->colSize = getenv('COLUMNS'); $this->lineSize = getenv('LINES'); + $this->ansiCon = getenv('ANSICON'); + $this->resetStatics(); } protected function tearDown() { putenv($this->colSize ? 'COLUMNS='.$this->colSize : 'COLUMNS'); putenv($this->lineSize ? 'LINES' : 'LINES='.$this->lineSize); + putenv($this->ansiCon ? 'ANSICON='.$this->ansiCon : 'ANSICON'); + $this->resetStatics(); + } + + private function resetStatics() + { + foreach (['height', 'width', 'stty'] as $name) { + $property = new \ReflectionProperty(Terminal::class, $name); + $property->setAccessible(true); + $property->setValue(null); + } } public function test() @@ -56,4 +70,28 @@ public function test_zero_values() $this->assertSame(0, $terminal->getWidth()); $this->assertSame(0, $terminal->getHeight()); } + + public function testSttyOnWindows() + { + if ('\\' !== \DIRECTORY_SEPARATOR) { + $this->markTestSkipped('Must be on windows'); + } + + $sttyString = exec('(stty -a | grep columns) 2>&1', $output, $exitcode); + if (0 !== $exitcode) { + $this->markTestSkipped('Must have stty support'); + } + + $matches = []; + if (0 === preg_match('/columns.(\d+)/i', $sttyString, $matches)) { + $this->fail('Could not determine existing stty columns'); + } + + putenv('COLUMNS'); + putenv('LINES'); + putenv('ANSICON'); + + $terminal = new Terminal(); + $this->assertSame((int) $matches[1], $terminal->getWidth()); + } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy