瀏覽代碼

[Console] Wrap exception messages to the terminal width to avoid ugly output

Jordi Boggiano 13 年之前
父節點
當前提交
595cc11251

+ 28 - 3
src/Symfony/Component/Console/Application.php

@@ -733,13 +733,16 @@ class Application
         do {
             $title = sprintf('  [%s]  ', get_class($e));
             $len = $strlen($title);
+            $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
             $lines = array();
             foreach (preg_split("{\r?\n}", $e->getMessage()) as $line) {
-                $lines[] = sprintf('  %s  ', $line);
-                $len = max($strlen($line) + 4, $len);
+                foreach (str_split($line, $width - 4) as $line) {
+                    $lines[] = sprintf('  %s  ', $line);
+                    $len = max($strlen($line) + 4, $len);
+                }
             }
 
-            $messages = array(str_repeat(' ', $len), $title.str_repeat(' ', $len - $strlen($title)));
+            $messages = array(str_repeat(' ', $len), $title.str_repeat(' ', max(0, $len - $strlen($title))));
 
             foreach ($lines as $line) {
                 $messages[] = $line.str_repeat(' ', $len - $strlen($line));
@@ -786,6 +789,28 @@ class Application
         }
     }
 
+    protected function getTerminalWidth()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD') && $ansicon = getenv('ANSICON')) {
+            return preg_replace('{^(\d+)x.*$}', '$1', $ansicon);
+        }
+
+        if (preg_match("{rows.(\d+);.columns.(\d+);}i", exec('stty -a | grep columns'), $match)) {
+            return $match[1];
+        }
+    }
+
+    protected function getTerminalHeight()
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD') && $ansicon = getenv('ANSICON')) {
+            return preg_replace('{^\d+x\d+ \(\d+x(\d+)\)$}', '$1', trim($ansicon));
+        }
+
+        if (preg_match("{rows.(\d+);.columns.(\d+);}i", exec('stty -a | grep columns'), $match)) {
+            return $match[2];
+        }
+    }
+
     /**
      * Gets the name of the command based on input.
      *

+ 9 - 0
tests/Symfony/Tests/Component/Console/ApplicationTest.php

@@ -255,6 +255,15 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
         $tester->run(array('command' => 'foo3:bar'), array('decorated' => false));
         $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $this->normalize($tester->getDisplay()), '->renderException() renders a pretty exceptions with previous exceptions');
 
+        $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
+        $application->setAutoExit(false);
+        $application->expects($this->any())
+            ->method('getTerminalWidth')
+            ->will($this->returnValue(32));
+        $tester = new ApplicationTester($application);
+
+        $tester->run(array('command' => 'foo'), array('decorated' => false));
+        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $this->normalize($tester->getDisplay()), '->renderException() wraps messages when they are bigger than the terminal');
     }
 
     public function testRun()

+ 9 - 0
tests/Symfony/Tests/Component/Console/Fixtures/application_renderexception4.txt

@@ -0,0 +1,9 @@
+
+
+                               
+  [InvalidArgumentException]   
+  Command "foo" is not define  
+  d.                           
+                               
+
+