Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit afed2f8

Browse filesBrowse files
committed
feature #19012 [Console] progress bar fix (TomasVotruba, fabpot)
This PR was merged into the 3.2-dev branch. Discussion ---------- [Console] progress bar fix | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #13019 | License | MIT | Doc PR | - This is #16490 where I've simplified the code as much as possible and added a test for the bug we're trying to fix. The main change is the renaming of the `TerminalDimensionsProvider` to just `Terminal`. The new class can probably be useful to add more about the terminal. Commits ------- 2f81247 switched to use COLUMNS and LINES env vars to change terminal dimensions bf7a5c5 fixed logic a589635 deprecated some Console Application methods 8f206c8 fixed CS, simplified code b030c24 [Console] ProgressBar - adjust to the window width (static)
2 parents 40f4c57 + 2f81247 commit afed2f8
Copy full SHA for afed2f8

File tree

Expand file treeCollapse file tree

7 files changed

+288
-137
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+288
-137
lines changed

‎src/Symfony/Component/Console/Application.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Application.php
+21-83Lines changed: 21 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,19 @@ class Application
6565
private $definition;
6666
private $helperSet;
6767
private $dispatcher;
68-
private $terminalDimensions;
68+
private $terminal;
6969
private $defaultCommand;
7070
private $singleCommand;
7171

7272
/**
73-
* Constructor.
74-
*
7573
* @param string $name The name of the application
7674
* @param string $version The version of the application
7775
*/
7876
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
7977
{
8078
$this->name = $name;
8179
$this->version = $version;
80+
$this->terminal = new Terminal();
8281
$this->defaultCommand = 'list';
8382
$this->helperSet = $this->getDefaultHelperSet();
8483
$this->definition = $this->getDefaultInputDefinition();
@@ -625,7 +624,7 @@ public function renderException(\Exception $e, OutputInterface $output)
625624

626625
$len = $this->stringWidth($title);
627626

628-
$width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
627+
$width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX;
629628
// HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327
630629
if (defined('HHVM_VERSION') && $width > 1 << 31) {
631630
$width = 1 << 31;
@@ -689,60 +688,42 @@ public function renderException(\Exception $e, OutputInterface $output)
689688
* Tries to figure out the terminal width in which this application runs.
690689
*
691690
* @return int|null
691+
*
692+
* @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
692693
*/
693694
protected function getTerminalWidth()
694695
{
695-
$dimensions = $this->getTerminalDimensions();
696+
@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);
696697

697-
return $dimensions[0];
698+
return $this->terminal->getWidth();
698699
}
699700

700701
/**
701702
* Tries to figure out the terminal height in which this application runs.
702703
*
703704
* @return int|null
705+
*
706+
* @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
704707
*/
705708
protected function getTerminalHeight()
706709
{
707-
$dimensions = $this->getTerminalDimensions();
710+
@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);
708711

709-
return $dimensions[1];
712+
return $this->terminal->getHeight();
710713
}
711714

712715
/**
713716
* Tries to figure out the terminal dimensions based on the current environment.
714717
*
715718
* @return array Array containing width and height
719+
*
720+
* @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead.
716721
*/
717722
public function getTerminalDimensions()
718723
{
719-
if ($this->terminalDimensions) {
720-
return $this->terminalDimensions;
721-
}
724+
@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);
722725

723-
if ('\\' === DIRECTORY_SEPARATOR) {
724-
// extract [w, H] from "wxh (WxH)"
725-
if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
726-
return array((int) $matches[1], (int) $matches[2]);
727-
}
728-
// extract [w, h] from "wxh"
729-
if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
730-
return array((int) $matches[1], (int) $matches[2]);
731-
}
732-
}
733-
734-
if ($sttyString = $this->getSttyColumns()) {
735-
// extract [w, h] from "rows h; columns w;"
736-
if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
737-
return array((int) $matches[2], (int) $matches[1]);
738-
}
739-
// extract [w, h] from "; h rows; w columns"
740-
if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
741-
return array((int) $matches[2], (int) $matches[1]);
742-
}
743-
}
744-
745-
return array(null, null);
726+
return array($this->terminal->getWidth(), $this->terminal->getHeight());
746727
}
747728

748729
/**
@@ -754,10 +735,15 @@ public function getTerminalDimensions()
754735
* @param int $height The height
755736
*
756737
* @return Application The current application
738+
*
739+
* @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead.
757740
*/
758741
public function setTerminalDimensions($width, $height)
759742
{
760-
$this->terminalDimensions = array($width, $height);
743+
@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);
744+
745+
putenv('COLUMNS='.$width);
746+
putenv('LINES='.$height);
761747

762748
return $this;
763749
}
@@ -927,54 +913,6 @@ protected function getDefaultHelperSet()
927913
));
928914
}
929915

930-
/**
931-
* Runs and parses stty -a if it's available, suppressing any error output.
932-
*
933-
* @return string
934-
*/
935-
private function getSttyColumns()
936-
{
937-
if (!function_exists('proc_open')) {
938-
return;
939-
}
940-
941-
$descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
942-
$process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
943-
if (is_resource($process)) {
944-
$info = stream_get_contents($pipes[1]);
945-
fclose($pipes[1]);
946-
fclose($pipes[2]);
947-
proc_close($process);
948-
949-
return $info;
950-
}
951-
}
952-
953-
/**
954-
* Runs and parses mode CON if it's available, suppressing any error output.
955-
*
956-
* @return string <width>x<height> or null if it could not be parsed
957-
*/
958-
private function getConsoleMode()
959-
{
960-
if (!function_exists('proc_open')) {
961-
return;
962-
}
963-
964-
$descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
965-
$process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
966-
if (is_resource($process)) {
967-
$info = stream_get_contents($pipes[1]);
968-
fclose($pipes[1]);
969-
fclose($pipes[2]);
970-
proc_close($process);
971-
972-
if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
973-
return $matches[2].'x'.$matches[1];
974-
}
975-
}
976-
}
977-
978916
/**
979917
* Returns abbreviated suggestions in string format.
980918
*

‎src/Symfony/Component/Console/Helper/ProgressBar.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Helper/ProgressBar.php
+39-18Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\Console\Output\ConsoleOutputInterface;
1515
use Symfony\Component\Console\Output\OutputInterface;
1616
use Symfony\Component\Console\Exception\LogicException;
17+
use Symfony\Component\Console\Terminal;
1718

1819
/**
1920
* The ProgressBar provides helpers to display progress output.
@@ -44,13 +45,12 @@ class ProgressBar
4445
private $formatLineCount;
4546
private $messages = array();
4647
private $overwrite = true;
48+
private $terminal;
4749

4850
private static $formatters;
4951
private static $formats;
5052

5153
/**
52-
* Constructor.
53-
*
5454
* @param OutputInterface $output An OutputInterface instance
5555
* @param int $max Maximum steps (0 if unknown)
5656
*/
@@ -62,6 +62,7 @@ public function __construct(OutputInterface $output, $max = 0)
6262

6363
$this->output = $output;
6464
$this->setMaxSteps($max);
65+
$this->terminal = new Terminal();
6566

6667
if (!$this->output->isDecorated()) {
6768
// disable overwrite when output does not support ANSI codes.
@@ -217,7 +218,7 @@ public function getProgressPercent()
217218
*/
218219
public function setBarWidth($size)
219220
{
220-
$this->barWidth = (int) $size;
221+
$this->barWidth = max(1, (int) $size);
221222
}
222223

223224
/**
@@ -412,21 +413,7 @@ public function display()
412413
$this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
413414
}
414415

415-
$this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) {
416-
if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) {
417-
$text = call_user_func($formatter, $this, $this->output);
418-
} elseif (isset($this->messages[$matches[1]])) {
419-
$text = $this->messages[$matches[1]];
420-
} else {
421-
return $matches[0];
422-
}
423-
424-
if (isset($matches[2])) {
425-
$text = sprintf('%'.$matches[2], $text);
426-
}
427-
428-
return $text;
429-
}, $this->format));
416+
$this->overwrite($this->buildLine());
430417
}
431418

432419
/**
@@ -592,4 +579,38 @@ private static function initFormats()
592579
'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
593580
);
594581
}
582+
583+
/**
584+
* @return string
585+
*/
586+
private function buildLine()
587+
{
588+
$regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i";
589+
$callback = function ($matches) {
590+
if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) {
591+
$text = call_user_func($formatter, $this, $this->output);
592+
} elseif (isset($this->messages[$matches[1]])) {
593+
$text = $this->messages[$matches[1]];
594+
} else {
595+
return $matches[0];
596+
}
597+
598+
if (isset($matches[2])) {
599+
$text = sprintf('%'.$matches[2], $text);
600+
}
601+
602+
return $text;
603+
};
604+
$line = preg_replace_callback($regex, $callback, $this->format);
605+
606+
$lineLength = Helper::strlenWithoutDecoration($this->output->getFormatter(), $line);
607+
$terminalWidth = $this->terminal->getWidth();
608+
if ($lineLength <= $terminalWidth) {
609+
return $line;
610+
}
611+
612+
$this->setBarWidth($this->barWidth - $lineLength + $terminalWidth);
613+
614+
return preg_replace_callback($regex, $callback, $this->format);
615+
}
595616
}

‎src/Symfony/Component/Console/Style/SymfonyStyle.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Style/SymfonyStyle.php
+3-10Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Component\Console\Style;
1313

14-
use Symfony\Component\Console\Application;
1514
use Symfony\Component\Console\Exception\RuntimeException;
1615
use Symfony\Component\Console\Formatter\OutputFormatter;
1716
use Symfony\Component\Console\Helper\Helper;
@@ -25,6 +24,7 @@
2524
use Symfony\Component\Console\Question\ChoiceQuestion;
2625
use Symfony\Component\Console\Question\ConfirmationQuestion;
2726
use Symfony\Component\Console\Question\Question;
27+
use Symfony\Component\Console\Terminal;
2828

2929
/**
3030
* Output decorator helpers for the Symfony Style Guide.
@@ -50,7 +50,8 @@ public function __construct(InputInterface $input, OutputInterface $output)
5050
$this->input = $input;
5151
$this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
5252
// Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
53-
$this->lineLength = min($this->getTerminalWidth() - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
53+
$width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH;
54+
$this->lineLength = min($width - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
5455

5556
parent::__construct($output);
5657
}
@@ -401,14 +402,6 @@ private function getProgressBar()
401402
return $this->progressBar;
402403
}
403404

404-
private function getTerminalWidth()
405-
{
406-
$application = new Application();
407-
$dimensions = $application->getTerminalDimensions();
408-
409-
return $dimensions[0] ?: self::MAX_LINE_LENGTH;
410-
}
411-
412405
private function autoPrependBlock()
413406
{
414407
$chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.