From 25eae26ddb818e925754cbc3b665208aecc8be54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Wed, 13 Mar 2019 14:50:19 +0100 Subject: [PATCH 01/17] Add WordWrapper console helper --- .../Component/Console/Helper/WordWrapper.php | 280 ++++++++++++++++++ .../Helper/WordWrapper/input/lipsum.txt | 5 + .../WordWrapper/input/lipsum_with_tags.txt | 5 + .../lipsum_with_tags_and_custom_break.txt | 5 + .../Helper/WordWrapper/input/utf120.txt | 1 + .../WordWrapper/input/with_long_words.txt | 9 + .../Helper/WordWrapper/output/lipsum.txt | 24 ++ .../WordWrapper/output/lipsum_with_tags.txt | 24 ++ .../lipsum_with_tags_and_custom_break.txt | 24 ++ .../Helper/WordWrapper/output/utf120.txt | 1 + .../output/with_long_words_with_cut_all.txt | 28 ++ .../with_long_words_with_default_cut.txt | 19 ++ .../output/with_long_words_without_cut.txt | 16 + .../Console/Tests/Helper/WordWrapperTest.php | 155 ++++++++++ 14 files changed, 596 insertions(+) create mode 100644 src/Symfony/Component/Console/Helper/WordWrapper.php create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags_and_custom_break.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/utf120.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/with_long_words.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags_and_custom_break.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/utf120.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_with_cut_all.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_with_default_cut.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_without_cut.txt create mode 100644 src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php diff --git a/src/Symfony/Component/Console/Helper/WordWrapper.php b/src/Symfony/Component/Console/Helper/WordWrapper.php new file mode 100644 index 0000000000000..b9a2d27544b2d --- /dev/null +++ b/src/Symfony/Component/Console/Helper/WordWrapper.php @@ -0,0 +1,280 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +/** + * @author Krisztián Ferenczi + */ +class WordWrapper +{ + const DEFAULT_WIDTH = 120; + const DEFAULT_BREAK = PHP_EOL; + const DEFAULT_LONG_WORDS_CUT_LIMIT = 5; + const DEFAULT_CUT = self::CUT_LONG_WORDS; + + const CUT_DISABLE = 0; + const CUT_LONG_WORDS = 1; + const CUT_WORDS = 3; // Cut long words too + const CUT_URLS = 4; + const CUT_ALL = 7; + + const TAG_REGEX = '[a-z][a-z0-9,_=;-]*+'; + + protected static $instance; + + /** + * We collect the new lines into this array. + * + * @var array + */ + protected $newLines; + + /** + * The current line "words". + * + * @var array + */ + protected $newLineTokens; + + /** + * The current line "real" length, without the formatter "tags" and the spaces! + * + * @var int + */ + protected $currentLength; + + protected static function getInstance() + { + if (!self::$instance) { + self::$instance = new self(); + } + + return self::$instance; + } + + public static function wrap($string, $width = self::DEFAULT_WIDTH, $break = self::DEFAULT_BREAK, $cutOptions = self::DEFAULT_CUT) + { + $wrapper = self::getInstance(); + + return $wrapper->wordwrap($string, $width, $break, $cutOptions); + } + + /** + * @param string $string The text + * @param bool $cutLongWords How the function handles the too long words that is longer then a line. It ignores + * this settings if the word is an URL! + * + * @return string + */ + public function wordwrap($string, $width = self::DEFAULT_WIDTH, $break = self::DEFAULT_BREAK, $cutOptions = self::DEFAULT_CUT) + { + if ($width <= 0) { + throw new \InvalidArgumentException('You have to set more than 0 width!'); + } + if (0 == mb_strlen($break)) { + throw new \InvalidArgumentException('You have to use existing end of the line character or string!'); + } + $this->reset(); + $lines = explode($break, $string); + foreach ($lines as $n => $line) { + // Token can be a word + foreach (explode(' ', $line) as $token) { + $virtualTokenLength = $this->getVirtualTokenLength($token); + $lineLength = $this->getCurrentLineLength(); + if ($lineLength + $virtualTokenLength < $width) { + $this->addTokenToLine($token, $virtualTokenLength); + } else { + $this->handleLineEnding($token, $virtualTokenLength, $width, $cutOptions); + } + } + $this->closeLine(); + } + + return $this->finish($break); + } + + protected function handleLineEnding($token, $virtualTokenLength, $width, $cutOptions) + { + switch (true) { + // Token is an URL and we don't want to cut it + case $this->tokenIsAnUrl($token) && !$this->hasCutOption(self::CUT_URLS, $cutOptions): + $this->closeLine(); + $this->addTokenToLine($token, $virtualTokenLength); + break; + // We cut everything + case $this->hasCutOption(self::CUT_WORDS, $cutOptions): + $freeSpace = $width - $this->getCurrentLineLength() - 1; + $this->sliceToken($token, $freeSpace, $width); + break; + // We want to cut the long words + case $virtualTokenLength > $width && $this->hasCutOption(self::CUT_LONG_WORDS, $cutOptions): + $freeSpace = $width - $this->getCurrentLineLength() - 1; + // A little prettifying + if ($freeSpace < 5 && $width > 10) { + $this->closeLine(); + $freeSpace = $width; + } + $this->sliceToken($token, $freeSpace, $width); + break; + // Other situation... + default: + $this->closeLine(); + $this->addTokenToLine($token, $virtualTokenLength); + break; + } + } + + /** + * Close a line. + */ + protected function closeLine() + { + if (\count($this->newLineTokens)) { + $this->newLines[] = implode(' ', $this->newLineTokens); + $this->newLineTokens = array(); + $this->currentLength = 0; + } + } + + /** + * Register a token with setted length. + * + * @param string $token + * @param int $virtualTokenLength + */ + protected function addTokenToLine($token, $virtualTokenLength) + { + $this->newLineTokens[] = $token; + $this->currentLength += $virtualTokenLength; + } + + /** + * Close everything and build the formatted text. + * + * @return string + */ + protected function finish($break) + { + $this->closeLine(); + + return implode($break, $this->newLines); + } + + /** + * Reset the array containers. + */ + protected function reset() + { + $this->newLineTokens = array(); + $this->newLines = array(); + } + + /** + * How long the current line is: currentLength + number of spaces (token numbers - 1). + * + * @return int + */ + protected function getCurrentLineLength() + { + return $this->currentLength + \count($this->newLineTokens) - 1; + } + + /** + * Virtual token length = length without "formatter tags". Eg: + * - lorem --> 5 + * - lorem --> 5. + * + * @param $token + * + * @return int + */ + protected function getVirtualTokenLength($token) + { + $virtualTokenLength = mb_strlen($token); + if (false !== strpos($token, '<')) { + $untaggedToken = $this->pregReplaceTags('', $token); + $virtualTokenLength = mb_strlen($untaggedToken); + } + + return $virtualTokenLength; + } + + protected function tokenIsAnUrl($token) + { + return false !== mb_strpos($token, 'http://') || false !== mb_strpos($token, 'https://'); + } + + protected function sliceToken($token, $freeChars, $width) + { + // We try to finds "formatter tags": + // verylongwordwithtags --> verylongword withtags + $tokenBlocks = explode(' ', $this->pregReplaceTags(' \\0 ', $token)); + $slicedToken = ''; + $slicedTokenVirtualLength = 0; + foreach ($tokenBlocks as $block) { + while ($block) { + if ($freeChars <= 0) { + if ('' != $slicedToken) { + $this->addTokenToLine($slicedToken, $slicedTokenVirtualLength); + } + $this->closeLine(); + $slicedToken = ''; + $slicedTokenVirtualLength = 0; + $freeChars = $width; + } + list($partial, $block, $blockLength) = $this->sliceTokenBlock($block, $freeChars); + $freeChars -= $blockLength; + $slicedTokenVirtualLength += $blockLength; + $slicedToken .= $partial; + } + } + $this->addTokenToLine($slicedToken, $slicedTokenVirtualLength); + } + + /** + * It handles the long word "blocks". + * + * @param $tokenBlock + * @param $freeChars + * + * @return array [$token, $block, $blockLength] + */ + protected function sliceTokenBlock($tokenBlock, $freeChars) + { + if ('<' == $tokenBlock[0] && '>' == mb_substr($tokenBlock, -1)) { + return array($tokenBlock, '', 0); + } + $blockLength = mb_strlen($tokenBlock); + if ($blockLength <= $freeChars) { + return array($tokenBlock, '', $blockLength); + } + + return array( + mb_substr($tokenBlock, 0, $freeChars), + mb_substr($tokenBlock, $freeChars), + $freeChars, + ); + } + + protected function hasCutOption($option, $cutOptions) + { + return ($cutOptions & $option) === $option; + } + + protected function pregReplaceTags($replacement, $string) + { + return preg_replace( + sprintf('{<((%1$s)|/(%1$s)?)>}', self::TAG_REGEX), + $replacement, + $string + ); + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum.txt new file mode 100644 index 0000000000000..1af6faf7b8865 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum.txt @@ -0,0 +1,5 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ex in dolor mollis aliquet. Maecenas pharetra massa ipsum, id tincidunt velit tincidunt et. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas dignissim augue non risus bibendum, id volutpat elit varius. Phasellus a aliquam elit. Integer sem ipsum, posuere vel mauris et, lobortis tempor urna. Morbi in metus lobortis, iaculis nulla id, dapibus dolor. Donec cursus, justo a finibus faucibus, enim sapien venenatis tortor, id pretium felis dolor ut nunc. Integer viverra feugiat dolor, in ornare lacus porta ac. Cras at arcu quam. Proin fringilla vestibulum magna ut feugiat. Sed at tempor tellus. Aliquam erat volutpat. Aliquam erat volutpat. Fusce efficitur arcu efficitur nibh varius, quis tempor enim imperdiet. Sed sagittis purus non urna imperdiet blandit. + +Aliquam a bibendum diam, nec semper ipsum. Donec magna felis, molestie in nulla ut, cursus luctus nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla lobortis nulla mi. Fusce a libero nec lorem aliquet molestie. Praesent sem diam, ultricies et posuere eu, blandit at lacus. Proin eleifend nisi id neque porta tincidunt. Quisque tempus purus sit amet erat posuere hendrerit. Proin vitae nisi eros. In hac habitasse platea dictumst. Ut ut metus eu diam aliquam feugiat. Pellentesque leo urna, efficitur ac velit quis, tempor molestie odio. Cras vitae cursus leo. + +Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie erat viverra ut. Vestibulum nisl ex, cursus quis magna id, pulvinar condimentum sem. Nunc ac orci volutpat turpis luctus tempor. Phasellus non ultrices est. Proin quis risus ut risus interdum pellentesque. Vestibulum lobortis, est in accumsan porttitor, nunc neque vulputate ipsum, vel varius metus orci condimentum magna. Duis vulputate leo et mi interdum sollicitudin. Suspendisse malesuada sagittis urna ac mattis. Cras vel nisi eu enim interdum maximus in mollis augue. In faucibus vestibulum lectus at pharetra. Maecenas maximus massa ac massa ornare, sit amet blandit lacus ultricies. Suspendisse tristique pellentesque velit, a finibus libero pellentesque vel. Quisque pellentesque ornare tincidunt. diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags.txt new file mode 100644 index 0000000000000..5aee3ac84129d --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags.txt @@ -0,0 +1,5 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ex in dolor mollis aliquet. Maecenas pharetra massa ipsum, id tincidunt velit tincidunt et. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas dignissim augue non risus bibendum, id volutpat elit varius. Phasellus a aliquam elit. Integer sem ipsum, posuere vel mauris et, lobortis tempor urna. Morbi in metus lobortis, iaculis nulla id, dapibus dolor. Donec cursus, justo a finibus faucibus, enim sapien venenatis tortor, id pretium felis dolor ut nunc. Integer viverra feugiat dolor, in ornare lacus porta ac. Cras at arcu quam. Proin fringilla vestibulum magna ut feugiat. Sed at tempor tellus. Aliquam erat volutpat. Aliquam erat volutpat. Fusce efficitur arcu efficitur nibh varius, quis tempor enim imperdiet. Sed sagittis purus non urna imperdiet blandit. + +Aliquam a bibendum diam, nec semper ipsum. Donec magna felis, molestie in nulla ut, cursus luctus nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla lobortis nulla mi. Fusce a libero nec lorem aliquet molestie. Praesent sem diam, ultricies et posuere eu, blandit at lacus. Proin eleifend nisi id neque porta tincidunt. Quisque tempus purus sit amet erat posuere hendrerit. Proin vitae nisi eros. In hac habitasse platea dictumst. Ut ut metus eu diam aliquam feugiat. Pellentesque leo urna, efficitur ac velit quis, tempor molestie odio. Cras vitae cursus leo. + +Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie erat viverra ut. Vestibulum nisl ex, cursus quis magna id, pulvinar condimentum sem. Nunc ac orci volutpat turpis luctus tempor. Phasellus non ultrices est. Proin quis risus ut risus interdum pellentesque. Vestibulum lobortis, est in accumsan porttitor, nunc neque vulputate ipsum, vel varius metus orci condimentum magna. Duis vulputate leo et mi interdum sollicitudin. Suspendisse malesuada sagittis urna ac mattis. Cras vel nisi eu enim interdum maximus in mollis augue. In faucibus vestibulum lectus at pharetra. Maecenas maximus massa ac massa ornare, sit amet blandit lacus ultricies. Suspendisse tristique pellentesque velit, a finibus libero pellentesque vel. Quisque pellentesque ornare tincidunt. diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags_and_custom_break.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags_and_custom_break.txt new file mode 100644 index 0000000000000..5483823fb8c05 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags_and_custom_break.txt @@ -0,0 +1,5 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ex in dolor mollis aliquet. Maecenas pharetra massa ipsum, id tincidunt velit tincidunt et. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas dignissim augue non risus bibendum, id volutpat elit varius. Phasellus a aliquam elit. Integer sem ipsum, posuere vel mauris et, lobortis tempor urna. Morbi in metus lobortis, iaculis nulla id, dapibus dolor. Donec cursus, justo a finibus faucibus, enim sapien venenatis tortor, id pretium felis dolor ut nunc. Integer viverra feugiat dolor, in ornare lacus porta ac. Cras at arcu quam. Proin fringilla vestibulum magna ut feugiat. Sed at tempor tellus. Aliquam erat volutpat. Aliquam erat volutpat. Fusce efficitur arcu efficitur nibh varius, quis tempor enim imperdiet. Sed sagittis purus non urna imperdiet blandit.__break__ +__break__ +Aliquam a bibendum diam, nec semper ipsum. Donec magna felis, molestie in nulla ut, cursus luctus nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla lobortis nulla mi. Fusce a libero nec lorem aliquet molestie. Praesent sem diam, ultricies et posuere eu, blandit at lacus. Proin eleifend nisi id neque porta tincidunt. Quisque tempus purus sit amet erat posuere hendrerit. Proin vitae nisi eros. In hac habitasse platea dictumst. Ut ut metus eu diam aliquam feugiat. Pellentesque leo urna, efficitur ac velit quis, tempor molestie odio. Cras vitae cursus leo.__break__ +__break__ +Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie erat viverra ut. Vestibulum nisl ex, cursus quis magna id, pulvinar condimentum sem. Nunc ac orci volutpat turpis luctus tempor. Phasellus non ultrices est. Proin quis risus ut risus interdum pellentesque. Vestibulum lobortis, est in accumsan porttitor, nunc neque vulputate ipsum, vel varius metus orci condimentum magna. Duis vulputate leo et mi interdum sollicitudin. Suspendisse malesuada sagittis urna ac mattis. Cras vel nisi eu enim interdum maximus in mollis augue. In faucibus vestibulum lectus at pharetra. Maecenas maximus massa ac massa ornare, sit amet blandit lacus ultricies. Suspendisse tristique pellentesque velit, a finibus libero pellentesque vel. Quisque pellentesque ornare tincidunt.__break__ diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/utf120.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/utf120.txt new file mode 100644 index 0000000000000..1ade5947f9316 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/utf120.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ex in dolor mollis aliquet. UTF8:öüóőúéáűíÖÜÓŐÚÉÁŰÍ diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/with_long_words.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/with_long_words.txt new file mode 100644 index 0000000000000..932b7b722b642 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/with_long_words.txt @@ -0,0 +1,9 @@ +Lorem ipsum dolor sit amet: https://www.google.com/search?safe=off&ei=5jSGXIGbGofCkwWcpLGIBA&q=Lorem+ipsum+dolor+sit+amet%2C+consectetur+adipiscing+elit.&oq=Lorem+ipsum+dolor+sit+amet%2C+consectetur+adipiscing+elit.&gs_l=psy-ab.3..0j0i22i30l9.24765.24765..26089...0.0..0.98.98.1......0....2j1..gws-wiz.......0i71.RLWmD-mYSAY Lorem ipsum dolor + +Test longer than 5 chars in the end: +Simple long word: thisisaverylongwordthisisaverylongwordthisisaverylongword + +Test less than 5 chars in the end: +Simple long word.........: thisisaverylongwordthisisaverylongwordthisisaverylongword + +Long word with "tags": thisisaverylongwordthisisaverylongwordthisisaverylongword diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum.txt new file mode 100644 index 0000000000000..b4d91795ca115 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum.txt @@ -0,0 +1,24 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ex in dolor mollis aliquet. Maecenas pharetra massa +ipsum, id tincidunt velit tincidunt et. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac +turpis egestas. Maecenas dignissim augue non risus bibendum, id volutpat elit varius. Phasellus a aliquam elit. Integer +sem ipsum, posuere vel mauris et, lobortis tempor urna. Morbi in metus lobortis, iaculis nulla id, dapibus dolor. Donec +cursus, justo a finibus faucibus, enim sapien venenatis tortor, id pretium felis dolor ut nunc. Integer viverra feugiat +dolor, in ornare lacus porta ac. Cras at arcu quam. Proin fringilla vestibulum magna ut feugiat. Sed at tempor tellus. +Aliquam erat volutpat. Aliquam erat volutpat. Fusce efficitur arcu efficitur nibh varius, quis tempor enim imperdiet. +Sed sagittis purus non urna imperdiet blandit. + +Aliquam a bibendum diam, nec semper ipsum. Donec magna felis, molestie in nulla ut, cursus luctus nisl. Lorem ipsum +dolor sit amet, consectetur adipiscing elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla +lobortis nulla mi. Fusce a libero nec lorem aliquet molestie. Praesent sem diam, ultricies et posuere eu, blandit at +lacus. Proin eleifend nisi id neque porta tincidunt. Quisque tempus purus sit amet erat posuere hendrerit. Proin vitae +nisi eros. In hac habitasse platea dictumst. Ut ut metus eu diam aliquam feugiat. Pellentesque leo urna, efficitur ac +velit quis, tempor molestie odio. Cras vitae cursus leo. + +Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie +erat viverra ut. Vestibulum nisl ex, cursus quis magna id, pulvinar condimentum sem. Nunc ac orci volutpat turpis luctus +tempor. Phasellus non ultrices est. Proin quis risus ut risus interdum pellentesque. Vestibulum lobortis, est in +accumsan porttitor, nunc neque vulputate ipsum, vel varius metus orci condimentum magna. Duis vulputate leo et mi +interdum sollicitudin. Suspendisse malesuada sagittis urna ac mattis. Cras vel nisi eu enim interdum maximus in mollis +augue. In faucibus vestibulum lectus at pharetra. Maecenas maximus massa ac massa ornare, sit amet blandit lacus +ultricies. Suspendisse tristique pellentesque velit, a finibus libero pellentesque vel. Quisque pellentesque ornare +tincidunt. diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags.txt new file mode 100644 index 0000000000000..bd9d865f1f0b0 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags.txt @@ -0,0 +1,24 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ex in dolor mollis aliquet. Maecenas pharetra massa +ipsum, id tincidunt velit tincidunt et. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac +turpis egestas. Maecenas dignissim augue non risus bibendum, id volutpat elit varius. Phasellus a aliquam elit. Integer +sem ipsum, posuere vel mauris et, lobortis tempor urna. Morbi in metus lobortis, iaculis nulla id, dapibus dolor. Donec +cursus, justo a finibus faucibus, enim sapien venenatis tortor, id pretium felis dolor ut nunc. Integer viverra feugiat +dolor, in ornare lacus porta ac. Cras at arcu quam. Proin fringilla vestibulum magna ut feugiat. Sed at tempor tellus. +Aliquam erat volutpat. Aliquam erat volutpat. Fusce efficitur arcu efficitur nibh varius, quis tempor enim imperdiet. +Sed sagittis purus non urna imperdiet blandit. + +Aliquam a bibendum diam, nec semper ipsum. Donec magna felis, molestie in nulla ut, cursus luctus nisl. Lorem ipsum +dolor sit amet, consectetur adipiscing elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla +lobortis nulla mi. Fusce a libero nec lorem aliquet molestie. Praesent sem diam, ultricies et posuere eu, blandit at +lacus. Proin eleifend nisi id neque porta tincidunt. Quisque tempus purus sit amet erat posuere hendrerit. Proin vitae +nisi eros. In hac habitasse platea dictumst. Ut ut metus eu diam aliquam feugiat. Pellentesque leo urna, efficitur ac +velit quis, tempor molestie odio. Cras vitae cursus leo. + +Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie +erat viverra ut. Vestibulum nisl ex, cursus quis magna id, pulvinar condimentum sem. Nunc ac orci volutpat turpis luctus +tempor. Phasellus non ultrices est. Proin quis risus ut risus interdum pellentesque. Vestibulum lobortis, est in +accumsan porttitor, nunc neque vulputate ipsum, vel varius metus orci condimentum magna. Duis vulputate leo et mi +interdum sollicitudin. Suspendisse malesuada sagittis urna ac mattis. Cras vel nisi eu enim interdum maximus in mollis +augue. In faucibus vestibulum lectus at pharetra. Maecenas maximus massa ac massa ornare, sit amet blandit lacus +ultricies. Suspendisse tristique pellentesque velit, a finibus libero pellentesque vel. Quisque pellentesque ornare +tincidunt. diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags_and_custom_break.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags_and_custom_break.txt new file mode 100644 index 0000000000000..3a88148ee732e --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags_and_custom_break.txt @@ -0,0 +1,24 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ex in dolor mollis aliquet. Maecenas pharetra massa__break__ +ipsum, id tincidunt velit tincidunt et. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac__break__ +turpis egestas. Maecenas dignissim augue non risus bibendum, id volutpat elit varius. Phasellus a aliquam elit. Integer__break__ +sem ipsum, posuere vel mauris et, lobortis tempor urna. Morbi in metus lobortis, iaculis nulla id, dapibus dolor. Donec__break__ +cursus, justo a finibus faucibus, enim sapien venenatis tortor, id pretium felis dolor ut nunc. Integer viverra feugiat__break__ +dolor, in ornare lacus porta ac. Cras at arcu quam. Proin fringilla vestibulum magna ut feugiat. Sed at tempor tellus.__break__ +Aliquam erat volutpat. Aliquam erat volutpat. Fusce efficitur arcu efficitur nibh varius, quis tempor enim imperdiet.__break__ +Sed sagittis purus non urna imperdiet blandit.__break__ +__break__ +Aliquam a bibendum diam, nec semper ipsum. Donec magna felis, molestie in nulla ut, cursus luctus nisl. Lorem ipsum__break__ +dolor sit amet, consectetur adipiscing elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla__break__ +lobortis nulla mi. Fusce a libero nec lorem aliquet molestie. Praesent sem diam, ultricies et posuere eu, blandit at__break__ +lacus. Proin eleifend nisi id neque porta tincidunt. Quisque tempus purus sit amet erat posuere hendrerit. Proin vitae__break__ +nisi eros. In hac habitasse platea dictumst. Ut ut metus eu diam aliquam feugiat. Pellentesque leo urna, efficitur ac__break__ +velit quis, tempor molestie odio. Cras vitae cursus leo.__break__ +__break__ +Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie__break__ +erat viverra ut. Vestibulum nisl ex, cursus quis magna id, pulvinar condimentum sem. Nunc ac orci volutpat turpis luctus__break__ +tempor. Phasellus non ultrices est. Proin quis risus ut risus interdum pellentesque. Vestibulum lobortis, est in__break__ +accumsan porttitor, nunc neque vulputate ipsum, vel varius metus orci condimentum magna. Duis vulputate leo et mi__break__ +interdum sollicitudin. Suspendisse malesuada sagittis urna ac mattis. Cras vel nisi eu enim interdum maximus in mollis__break__ +augue. In faucibus vestibulum lectus at pharetra. Maecenas maximus massa ac massa ornare, sit amet blandit lacus__break__ +ultricies. Suspendisse tristique pellentesque velit, a finibus libero pellentesque vel. Quisque pellentesque ornare__break__ +tincidunt.__break__ diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/utf120.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/utf120.txt new file mode 100644 index 0000000000000..1ade5947f9316 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/utf120.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ex in dolor mollis aliquet. UTF8:öüóőúéáűíÖÜÓŐÚÉÁŰÍ diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_with_cut_all.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_with_cut_all.txt new file mode 100644 index 0000000000000..e8b33f2ed76fa --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_with_cut_all.txt @@ -0,0 +1,28 @@ +Lorem ipsum dolor sit amet: ht +tps://www.google.com/search?sa +fe=off&ei=5jSGXIGbGofCkwWcpLGI +BA&q=Lorem+ipsum+dolor+sit+ame +t%2C+consectetur+adipiscing+el +it.&oq=Lorem+ipsum+dolor+sit+a +met%2C+consectetur+adipiscing+ +elit.&gs_l=psy-ab.3..0j0i22i30 +l9.24765.24765..26089...0.0..0 +.98.98.1......0....2j1..gws-wi +z.......0i71.RLWmD-mYSAY Lorem +ipsum dolor + +Test longer than 5 chars in th +e end: +Simple long word: thisisaveryl +ongwordthisisaverylongwordthis +isaverylongword + +Test less than 5 chars in the +end: +Simple long word.........: thi +sisaverylongwordthisisaverylon +gwordthisisaverylongword + +Long word with "tags": thisisa +verylongwordthisisaverylongwor +dthisisaverylongword diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_with_default_cut.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_with_default_cut.txt new file mode 100644 index 0000000000000..e61ed58982943 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_with_default_cut.txt @@ -0,0 +1,19 @@ +Lorem ipsum dolor sit amet: +https://www.google.com/search?safe=off&ei=5jSGXIGbGofCkwWcpLGIBA&q=Lorem+ipsum+dolor+sit+amet%2C+consectetur+adipiscing+elit.&oq=Lorem+ipsum+dolor+sit+amet%2C+consectetur+adipiscing+elit.&gs_l=psy-ab.3..0j0i22i30l9.24765.24765..26089...0.0..0.98.98.1......0....2j1..gws-wiz.......0i71.RLWmD-mYSAY +Lorem ipsum dolor + +Test longer than 5 chars in +the end: +Simple long word: thisisaveryl +ongwordthisisaverylongwordthis +isaverylongword + +Test less than 5 chars in the +end: +Simple long word.........: +thisisaverylongwordthisisavery +longwordthisisaverylongword + +Long word with "tags": thisisa +verylongwordthisisaverylongwor +dthisisaverylongword diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_without_cut.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_without_cut.txt new file mode 100644 index 0000000000000..0a7c617b4f490 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/with_long_words_without_cut.txt @@ -0,0 +1,16 @@ +Lorem ipsum dolor sit amet: +https://www.google.com/search?safe=off&ei=5jSGXIGbGofCkwWcpLGIBA&q=Lorem+ipsum+dolor+sit+amet%2C+consectetur+adipiscing+elit.&oq=Lorem+ipsum+dolor+sit+amet%2C+consectetur+adipiscing+elit.&gs_l=psy-ab.3..0j0i22i30l9.24765.24765..26089...0.0..0.98.98.1......0....2j1..gws-wiz.......0i71.RLWmD-mYSAY +Lorem ipsum dolor + +Test longer than 5 chars in +the end: +Simple long word: +thisisaverylongwordthisisaverylongwordthisisaverylongword + +Test less than 5 chars in the +end: +Simple long word.........: +thisisaverylongwordthisisaverylongwordthisisaverylongword + +Long word with "tags": +thisisaverylongwordthisisaverylongwordthisisaverylongword diff --git a/src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php b/src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php new file mode 100644 index 0000000000000..011c32161e17a --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php @@ -0,0 +1,155 @@ + + */ +class WordWrapperTest extends TestCase +{ + /** + * @param int $width + * @param string $break + * + * @dataProvider dpTestConstructorExceptions + * + * @expectedException \InvalidArgumentException + */ + public function testConstructorExceptions($width, $break) + { + $wordWrapper = new WordWrapper(); + $wordWrapper->wordwrap('test', $width, $break); + } + + public function dpTestConstructorExceptions() + { + return array( + array(0, PHP_EOL), + array(-1, PHP_EOL), + array(0, ''), + array(1, ''), + ); + } + + /** + * @param string $input + * @param int $width + * @param string $break + * @param int $cutOptions + * @param string $output + * + * @dataProvider dpWordwrap + */ + public function testWordwrap($input, $width, $break, $cutOptions, $output) + { + $wordWrapper = new WordWrapper(); + $response = $wordWrapper->wordwrap($this->getInputContents($input), $width, $break, $cutOptions); + + $this->assertEquals($this->getOutputContents($output), $response); + } + + /** + * Maybe in the future it should behave differently from wordwrap() function that is why it same the other now. + * + * @param string $input + * @param int $width + * @param string $break + * @param int $cutOptions + * @param string $output + * + * @dataProvider dpWordwrap + */ + public function testStaticWrap($input, $width, $break, $cutOptions, $output) + { + $response = WordWrapper::wrap($this->getInputContents($input), $width, $break, $cutOptions); + + $this->assertEquals($this->getOutputContents($output), $response); + } + + public function dpWordwrap() + { + $baseBreak = "\n"; + $customBreak = "__break__\n"; + + return array( + // Check empty + array('', 120, $baseBreak, true, ''), + array($baseBreak, 120, $baseBreak, true, $baseBreak), + // Check limit and UTF-8 + array( + 'utf120.txt', + 120, + $baseBreak, + WordWrapper::DEFAULT_CUT, + 'utf120.txt', + ), + // Check simple text + array( + 'lipsum.txt', + 120, + $baseBreak, + WordWrapper::DEFAULT_CUT, + 'lipsum.txt', + ), + // Check colored text + array( + 'lipsum_with_tags.txt', + 120, + $baseBreak, + WordWrapper::DEFAULT_CUT, + 'lipsum_with_tags.txt', + ), + // Check custom break + array( + 'lipsum_with_tags_and_custom_break.txt', + 120, + $customBreak, + WordWrapper::DEFAULT_CUT, + 'lipsum_with_tags_and_custom_break.txt', + ), + // Check long words + array( + 'with_long_words.txt', + 30, + $baseBreak, + WordWrapper::DEFAULT_CUT, + 'with_long_words_with_default_cut.txt', + ), + array( + 'with_long_words.txt', + 30, + $baseBreak, + WordWrapper::CUT_DISABLE, + 'with_long_words_without_cut.txt', + ), + array( + 'with_long_words.txt', + 30, + $baseBreak, + WordWrapper::CUT_ALL, + 'with_long_words_with_cut_all.txt', + ), + ); + } + + protected function getInputContents($filenameOrText) + { + $file = __DIR__ . '/../Fixtures/Helper/WordWrapper/input/' .$filenameOrText; + + return file_exists($file) && is_file($file) + ? file_get_contents($file) + : $filenameOrText; + } + + protected function getOutputContents($filenameOrText) + { + $file = __DIR__ . '/../Fixtures/Helper/WordWrapper/output/' .$filenameOrText; + + return file_exists($file) && is_file($file) + ? file_get_contents($file) + : $filenameOrText; + } +} From 39934bc6f7fe765f50ad8f561890a8006d60e784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Wed, 13 Mar 2019 14:55:36 +0100 Subject: [PATCH 02/17] PHP CS fix --- .../Component/Console/Helper/WordWrapper.php | 14 ++--- .../Console/Tests/Helper/WordWrapperTest.php | 52 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/WordWrapper.php b/src/Symfony/Component/Console/Helper/WordWrapper.php index b9a2d27544b2d..111672bcd4fce 100644 --- a/src/Symfony/Component/Console/Helper/WordWrapper.php +++ b/src/Symfony/Component/Console/Helper/WordWrapper.php @@ -139,7 +139,7 @@ protected function closeLine() { if (\count($this->newLineTokens)) { $this->newLines[] = implode(' ', $this->newLineTokens); - $this->newLineTokens = array(); + $this->newLineTokens = []; $this->currentLength = 0; } } @@ -173,8 +173,8 @@ protected function finish($break) */ protected function reset() { - $this->newLineTokens = array(); - $this->newLines = array(); + $this->newLineTokens = []; + $this->newLines = []; } /** @@ -250,18 +250,18 @@ protected function sliceToken($token, $freeChars, $width) protected function sliceTokenBlock($tokenBlock, $freeChars) { if ('<' == $tokenBlock[0] && '>' == mb_substr($tokenBlock, -1)) { - return array($tokenBlock, '', 0); + return [$tokenBlock, '', 0]; } $blockLength = mb_strlen($tokenBlock); if ($blockLength <= $freeChars) { - return array($tokenBlock, '', $blockLength); + return [$tokenBlock, '', $blockLength]; } - return array( + return [ mb_substr($tokenBlock, 0, $freeChars), mb_substr($tokenBlock, $freeChars), $freeChars, - ); + ]; } protected function hasCutOption($option, $cutOptions) diff --git a/src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php b/src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php index 011c32161e17a..761b53ee7cf3c 100644 --- a/src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php @@ -26,12 +26,12 @@ public function testConstructorExceptions($width, $break) public function dpTestConstructorExceptions() { - return array( - array(0, PHP_EOL), - array(-1, PHP_EOL), - array(0, ''), - array(1, ''), - ); + return [ + [0, PHP_EOL], + [-1, PHP_EOL], + [0, ''], + [1, ''], + ]; } /** @@ -74,70 +74,70 @@ public function dpWordwrap() $baseBreak = "\n"; $customBreak = "__break__\n"; - return array( + return [ // Check empty - array('', 120, $baseBreak, true, ''), - array($baseBreak, 120, $baseBreak, true, $baseBreak), + ['', 120, $baseBreak, true, ''], + [$baseBreak, 120, $baseBreak, true, $baseBreak], // Check limit and UTF-8 - array( + [ 'utf120.txt', 120, $baseBreak, WordWrapper::DEFAULT_CUT, 'utf120.txt', - ), + ], // Check simple text - array( + [ 'lipsum.txt', 120, $baseBreak, WordWrapper::DEFAULT_CUT, 'lipsum.txt', - ), + ], // Check colored text - array( + [ 'lipsum_with_tags.txt', 120, $baseBreak, WordWrapper::DEFAULT_CUT, 'lipsum_with_tags.txt', - ), + ], // Check custom break - array( + [ 'lipsum_with_tags_and_custom_break.txt', 120, $customBreak, WordWrapper::DEFAULT_CUT, 'lipsum_with_tags_and_custom_break.txt', - ), + ], // Check long words - array( + [ 'with_long_words.txt', 30, $baseBreak, WordWrapper::DEFAULT_CUT, 'with_long_words_with_default_cut.txt', - ), - array( + ], + [ 'with_long_words.txt', 30, $baseBreak, WordWrapper::CUT_DISABLE, 'with_long_words_without_cut.txt', - ), - array( + ], + [ 'with_long_words.txt', 30, $baseBreak, WordWrapper::CUT_ALL, 'with_long_words_with_cut_all.txt', - ), - ); + ], + ]; } protected function getInputContents($filenameOrText) { - $file = __DIR__ . '/../Fixtures/Helper/WordWrapper/input/' .$filenameOrText; + $file = __DIR__.'/../Fixtures/Helper/WordWrapper/input/'.$filenameOrText; return file_exists($file) && is_file($file) ? file_get_contents($file) @@ -146,7 +146,7 @@ protected function getInputContents($filenameOrText) protected function getOutputContents($filenameOrText) { - $file = __DIR__ . '/../Fixtures/Helper/WordWrapper/output/' .$filenameOrText; + $file = __DIR__.'/../Fixtures/Helper/WordWrapper/output/'.$filenameOrText; return file_exists($file) && is_file($file) ? file_get_contents($file) From 3726148267f2ca56c09b37f2256cb85fb138ef9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Wed, 13 Mar 2019 17:19:02 +0100 Subject: [PATCH 03/17] Code upgrade for PHP7.1 + Add some documentations --- ...{WordWrapper.php => PrettyWordWrapper.php} | 90 +++++++++++++++---- ...pperTest.php => PrettyWordWrapperTest.php} | 22 ++--- 2 files changed, 82 insertions(+), 30 deletions(-) rename src/Symfony/Component/Console/Helper/{WordWrapper.php => PrettyWordWrapper.php} (71%) rename src/Symfony/Component/Console/Tests/Helper/{WordWrapperTest.php => PrettyWordWrapperTest.php} (86%) diff --git a/src/Symfony/Component/Console/Helper/WordWrapper.php b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php similarity index 71% rename from src/Symfony/Component/Console/Helper/WordWrapper.php rename to src/Symfony/Component/Console/Helper/PrettyWordWrapper.php index 111672bcd4fce..fbfacbd963a16 100644 --- a/src/Symfony/Component/Console/Helper/WordWrapper.php +++ b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php @@ -15,11 +15,12 @@ */ class WordWrapper { + // Defaults const DEFAULT_WIDTH = 120; const DEFAULT_BREAK = PHP_EOL; - const DEFAULT_LONG_WORDS_CUT_LIMIT = 5; const DEFAULT_CUT = self::CUT_LONG_WORDS; + // Cut options const CUT_DISABLE = 0; const CUT_LONG_WORDS = 1; const CUT_WORDS = 3; // Cut long words too @@ -60,7 +61,15 @@ protected static function getInstance() return self::$instance; } - public static function wrap($string, $width = self::DEFAULT_WIDTH, $break = self::DEFAULT_BREAK, $cutOptions = self::DEFAULT_CUT) + /** + * @param string $string The text + * @param int $width Character width of one line + * @param string $break The line breaking character(s) + * @param int $cutOptions You can mix your needs with CUT_* constants + * + * @return string + */ + public static function wrap(string $string, int $width = self::DEFAULT_WIDTH, string $break = self::DEFAULT_BREAK, int $cutOptions = self::DEFAULT_CUT): string { $wrapper = self::getInstance(); @@ -68,13 +77,14 @@ public static function wrap($string, $width = self::DEFAULT_WIDTH, $break = self } /** - * @param string $string The text - * @param bool $cutLongWords How the function handles the too long words that is longer then a line. It ignores - * this settings if the word is an URL! + * @param string $string The text + * @param int $width Character width of one line + * @param string $break The line breaking character(s) + * @param int $cutOptions You can mix your needs with CUT_* constants * * @return string */ - public function wordwrap($string, $width = self::DEFAULT_WIDTH, $break = self::DEFAULT_BREAK, $cutOptions = self::DEFAULT_CUT) + public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, string $break = self::DEFAULT_BREAK, int $cutOptions = self::DEFAULT_CUT): string { if ($width <= 0) { throw new \InvalidArgumentException('You have to set more than 0 width!'); @@ -101,7 +111,15 @@ public function wordwrap($string, $width = self::DEFAULT_WIDTH, $break = self::D return $this->finish($break); } - protected function handleLineEnding($token, $virtualTokenLength, $width, $cutOptions) + /** + * This function handles what what does + * + * @param string $token + * @param int $virtualTokenLength + * @param int $width + * @param int $cutOptions + */ + protected function handleLineEnding(string $token, int $virtualTokenLength, int $width, int $cutOptions) { switch (true) { // Token is an URL and we don't want to cut it @@ -145,12 +163,12 @@ protected function closeLine() } /** - * Register a token with setted length. + * Register a token with set length. * * @param string $token * @param int $virtualTokenLength */ - protected function addTokenToLine($token, $virtualTokenLength) + protected function addTokenToLine(string $token, int $virtualTokenLength) { $this->newLineTokens[] = $token; $this->currentLength += $virtualTokenLength; @@ -159,9 +177,11 @@ protected function addTokenToLine($token, $virtualTokenLength) /** * Close everything and build the formatted text. * + * @param string $break + * * @return string */ - protected function finish($break) + protected function finish(string $break) { $this->closeLine(); @@ -192,11 +212,11 @@ protected function getCurrentLineLength() * - lorem --> 5 * - lorem --> 5. * - * @param $token + * @param string $token * * @return int */ - protected function getVirtualTokenLength($token) + protected function getVirtualTokenLength(string $token): int { $virtualTokenLength = mb_strlen($token); if (false !== strpos($token, '<')) { @@ -207,12 +227,17 @@ protected function getVirtualTokenLength($token) return $virtualTokenLength; } - protected function tokenIsAnUrl($token) + /** + * @param string $token + * + * @return bool + */ + protected function tokenIsAnUrl(string $token): bool { return false !== mb_strpos($token, 'http://') || false !== mb_strpos($token, 'https://'); } - protected function sliceToken($token, $freeChars, $width) + protected function sliceToken(string $token, int $freeChars, int $width) { // We try to finds "formatter tags": // verylongwordwithtags --> verylongword withtags @@ -242,12 +267,12 @@ protected function sliceToken($token, $freeChars, $width) /** * It handles the long word "blocks". * - * @param $tokenBlock - * @param $freeChars + * @param string $tokenBlock + * @param int $freeChars * * @return array [$token, $block, $blockLength] */ - protected function sliceTokenBlock($tokenBlock, $freeChars) + protected function sliceTokenBlock(string $tokenBlock, int $freeChars): array { if ('<' == $tokenBlock[0] && '>' == mb_substr($tokenBlock, -1)) { return [$tokenBlock, '', 0]; @@ -264,12 +289,39 @@ protected function sliceTokenBlock($tokenBlock, $freeChars) ]; } - protected function hasCutOption($option, $cutOptions) + /** + * It checks the cut option is set. See the CUT_* constants. + * + * @param int $option + * @param int $cutOptions + * + * @return bool + */ + protected function hasCutOption(int $option, int $cutOptions): bool { return ($cutOptions & $option) === $option; } - protected function pregReplaceTags($replacement, $string) + /** + * It replaces all tags to something different. If you want to use original tags, use the `\\0` placeholder: + * + * Eg: + * $replacement = 'STARTTAG>\\0 and + * \\1: comment and /comment or / (!: the close tag could be ``) + * \\2: comment or '' (if the close tag is ``) + * + * @param string $replacement + * @param string $string + * + * @return string + */ + protected function pregReplaceTags(string $replacement, string $string): string { return preg_replace( sprintf('{<((%1$s)|/(%1$s)?)>}', self::TAG_REGEX), diff --git a/src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php b/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php similarity index 86% rename from src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php rename to src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php index 761b53ee7cf3c..a5276b811800c 100644 --- a/src/Symfony/Component/Console/Tests/Helper/WordWrapperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php @@ -3,7 +3,7 @@ namespace Symfony\Component\Console\Tests\Helper; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\WordWrapper; +use Symfony\Component\Console\Helper\PrettyWordWrapper; /** * @author Krisztián Ferenczi @@ -20,7 +20,7 @@ class WordWrapperTest extends TestCase */ public function testConstructorExceptions($width, $break) { - $wordWrapper = new WordWrapper(); + $wordWrapper = new PrettyWordWrapper(); $wordWrapper->wordwrap('test', $width, $break); } @@ -45,7 +45,7 @@ public function dpTestConstructorExceptions() */ public function testWordwrap($input, $width, $break, $cutOptions, $output) { - $wordWrapper = new WordWrapper(); + $wordWrapper = new PrettyWordWrapper(); $response = $wordWrapper->wordwrap($this->getInputContents($input), $width, $break, $cutOptions); $this->assertEquals($this->getOutputContents($output), $response); @@ -64,7 +64,7 @@ public function testWordwrap($input, $width, $break, $cutOptions, $output) */ public function testStaticWrap($input, $width, $break, $cutOptions, $output) { - $response = WordWrapper::wrap($this->getInputContents($input), $width, $break, $cutOptions); + $response = PrettyWordWrapper::wrap($this->getInputContents($input), $width, $break, $cutOptions); $this->assertEquals($this->getOutputContents($output), $response); } @@ -83,7 +83,7 @@ public function dpWordwrap() 'utf120.txt', 120, $baseBreak, - WordWrapper::DEFAULT_CUT, + PrettyWordWrapper::DEFAULT_CUT, 'utf120.txt', ], // Check simple text @@ -91,7 +91,7 @@ public function dpWordwrap() 'lipsum.txt', 120, $baseBreak, - WordWrapper::DEFAULT_CUT, + PrettyWordWrapper::DEFAULT_CUT, 'lipsum.txt', ], // Check colored text @@ -99,7 +99,7 @@ public function dpWordwrap() 'lipsum_with_tags.txt', 120, $baseBreak, - WordWrapper::DEFAULT_CUT, + PrettyWordWrapper::DEFAULT_CUT, 'lipsum_with_tags.txt', ], // Check custom break @@ -107,7 +107,7 @@ public function dpWordwrap() 'lipsum_with_tags_and_custom_break.txt', 120, $customBreak, - WordWrapper::DEFAULT_CUT, + PrettyWordWrapper::DEFAULT_CUT, 'lipsum_with_tags_and_custom_break.txt', ], // Check long words @@ -115,21 +115,21 @@ public function dpWordwrap() 'with_long_words.txt', 30, $baseBreak, - WordWrapper::DEFAULT_CUT, + PrettyWordWrapper::DEFAULT_CUT, 'with_long_words_with_default_cut.txt', ], [ 'with_long_words.txt', 30, $baseBreak, - WordWrapper::CUT_DISABLE, + PrettyWordWrapper::CUT_DISABLE, 'with_long_words_without_cut.txt', ], [ 'with_long_words.txt', 30, $baseBreak, - WordWrapper::CUT_ALL, + PrettyWordWrapper::CUT_ALL, 'with_long_words_with_cut_all.txt', ], ]; From 0fcd92471f6dc188ec0fa179b75954fa8d06cebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Wed, 13 Mar 2019 17:19:25 +0100 Subject: [PATCH 04/17] Code upgrade for PHP7.1 + Add some documentations --- .../Console/Helper/PrettyWordWrapper.php | 32 ++++++++++++++---- .../Tests/Helper/PrettyWordWrapperTest.php | 33 +++++++++---------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php index fbfacbd963a16..b76fef047b142 100644 --- a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php +++ b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php @@ -11,9 +11,27 @@ namespace Symfony\Component\Console\Helper; /** + * It helps you to wrap long text with pretty breaks and useful cuts. You can control the cuts with the control option: + * - CUT_DISABLE: Always break the text at word boundary. + * - CUT_LONG_WORDS: If the word is longer than one row it will be cut. + * - CUT_WORDS: Always break at set length, it will cut all words. It would be useful if you have little + * space. (Info: It "contains" the CUT_LONG_WORDS option) + * - CUT_URLS: Lots of terminal can recognize URL-s in text and make them clickable (if there isn't break + * inside the URL) The URLS can be long, default we keep it in one block even if it gets ugly + * response. You can switch this behavior off with this option. The result will be pretty, + * but the URL won't be clickable. + * + * + * $message = "This is a comment message with info ..."; + * // Default: + * $output->writeln(PrettyWordWrapper::wrap($message, 120); + * // Use custom settings: + * $output->writeln(PrettyWordWrapper::wrap($message, 20, PrettyWordWrapper::CUT_ALL, PHP_EOL); + * + * * @author Krisztián Ferenczi */ -class WordWrapper +class PrettyWordWrapper { // Defaults const DEFAULT_WIDTH = 120; @@ -64,27 +82,27 @@ protected static function getInstance() /** * @param string $string The text * @param int $width Character width of one line - * @param string $break The line breaking character(s) * @param int $cutOptions You can mix your needs with CUT_* constants + * @param string $break The line breaking character(s) * * @return string */ - public static function wrap(string $string, int $width = self::DEFAULT_WIDTH, string $break = self::DEFAULT_BREAK, int $cutOptions = self::DEFAULT_CUT): string + public static function wrap(string $string, int $width = self::DEFAULT_WIDTH, int $cutOptions = self::DEFAULT_CUT, string $break = self::DEFAULT_BREAK): string { $wrapper = self::getInstance(); - return $wrapper->wordwrap($string, $width, $break, $cutOptions); + return $wrapper->wordwrap($string, $width, $cutOptions, $break); } /** * @param string $string The text * @param int $width Character width of one line - * @param string $break The line breaking character(s) * @param int $cutOptions You can mix your needs with CUT_* constants + * @param string $break The line breaking character(s) * * @return string */ - public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, string $break = self::DEFAULT_BREAK, int $cutOptions = self::DEFAULT_CUT): string + public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, int $cutOptions = self::DEFAULT_CUT, string $break = self::DEFAULT_BREAK): string { if ($width <= 0) { throw new \InvalidArgumentException('You have to set more than 0 width!'); @@ -112,7 +130,7 @@ public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, strin } /** - * This function handles what what does + * This function handles what to happen at end of the line. * * @param string $token * @param int $virtualTokenLength diff --git a/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php b/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php index a5276b811800c..bd7545f7d150a 100644 --- a/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php @@ -8,20 +8,19 @@ /** * @author Krisztián Ferenczi */ -class WordWrapperTest extends TestCase +class PrettyWordWrapperTest extends TestCase { /** * @param int $width * @param string $break * * @dataProvider dpTestConstructorExceptions - * - * @expectedException \InvalidArgumentException */ public function testConstructorExceptions($width, $break) { $wordWrapper = new PrettyWordWrapper(); - $wordWrapper->wordwrap('test', $width, $break); + $this->expectException(\InvalidArgumentException::class); + $wordWrapper->wordwrap('test', $width, PrettyWordWrapper::DEFAULT_CUT, $break); } public function dpTestConstructorExceptions() @@ -43,10 +42,10 @@ public function dpTestConstructorExceptions() * * @dataProvider dpWordwrap */ - public function testWordwrap($input, $width, $break, $cutOptions, $output) + public function testWordwrap($input, $width, $cutOptions, $break, $output) { $wordWrapper = new PrettyWordWrapper(); - $response = $wordWrapper->wordwrap($this->getInputContents($input), $width, $break, $cutOptions); + $response = $wordWrapper->wordwrap($this->getInputContents($input), $width, $cutOptions, $break); $this->assertEquals($this->getOutputContents($output), $response); } @@ -62,9 +61,9 @@ public function testWordwrap($input, $width, $break, $cutOptions, $output) * * @dataProvider dpWordwrap */ - public function testStaticWrap($input, $width, $break, $cutOptions, $output) + public function testStaticWrap($input, $width, $cutOptions, $break, $output) { - $response = PrettyWordWrapper::wrap($this->getInputContents($input), $width, $break, $cutOptions); + $response = PrettyWordWrapper::wrap($this->getInputContents($input), $width, $cutOptions, $break); $this->assertEquals($this->getOutputContents($output), $response); } @@ -76,60 +75,60 @@ public function dpWordwrap() return [ // Check empty - ['', 120, $baseBreak, true, ''], - [$baseBreak, 120, $baseBreak, true, $baseBreak], + ['', 120, PrettyWordWrapper::DEFAULT_CUT, $baseBreak, ''], + [$baseBreak, 120, PrettyWordWrapper::DEFAULT_CUT, $baseBreak, $baseBreak], // Check limit and UTF-8 [ 'utf120.txt', 120, - $baseBreak, PrettyWordWrapper::DEFAULT_CUT, + $baseBreak, 'utf120.txt', ], // Check simple text [ 'lipsum.txt', 120, - $baseBreak, PrettyWordWrapper::DEFAULT_CUT, + $baseBreak, 'lipsum.txt', ], // Check colored text [ 'lipsum_with_tags.txt', 120, - $baseBreak, PrettyWordWrapper::DEFAULT_CUT, + $baseBreak, 'lipsum_with_tags.txt', ], // Check custom break [ 'lipsum_with_tags_and_custom_break.txt', 120, - $customBreak, PrettyWordWrapper::DEFAULT_CUT, + $customBreak, 'lipsum_with_tags_and_custom_break.txt', ], // Check long words [ 'with_long_words.txt', 30, - $baseBreak, PrettyWordWrapper::DEFAULT_CUT, + $baseBreak, 'with_long_words_with_default_cut.txt', ], [ 'with_long_words.txt', 30, - $baseBreak, PrettyWordWrapper::CUT_DISABLE, + $baseBreak, 'with_long_words_without_cut.txt', ], [ 'with_long_words.txt', 30, - $baseBreak, PrettyWordWrapper::CUT_ALL, + $baseBreak, 'with_long_words_with_cut_all.txt', ], ]; From f45ea2d7dd35d3215cd5deb324c519e128523a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Wed, 13 Mar 2019 17:22:31 +0100 Subject: [PATCH 05/17] Comment fix --- src/Symfony/Component/Console/Helper/PrettyWordWrapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php index b76fef047b142..f229acdeff54c 100644 --- a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php +++ b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php @@ -325,7 +325,7 @@ protected function hasCutOption(int $option, int $cutOptions): bool * * Eg: * $replacement = 'STARTTAG>\\0 Date: Wed, 13 Mar 2019 17:26:07 +0100 Subject: [PATCH 06/17] PrettyWordWrap: add complex format tag to the test --- .../Fixtures/Helper/WordWrapper/input/lipsum_with_tags.txt | 2 +- .../Fixtures/Helper/WordWrapper/output/lipsum_with_tags.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags.txt index 5aee3ac84129d..e3bf1f6d73880 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/input/lipsum_with_tags.txt @@ -2,4 +2,4 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis ex in dolor Aliquam a bibendum diam, nec semper ipsum. Donec magna felis, molestie in nulla ut, cursus luctus nisl. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla lobortis nulla mi. Fusce a libero nec lorem aliquet molestie. Praesent sem diam, ultricies et posuere eu, blandit at lacus. Proin eleifend nisi id neque porta tincidunt. Quisque tempus purus sit amet erat posuere hendrerit. Proin vitae nisi eros. In hac habitasse platea dictumst. Ut ut metus eu diam aliquam feugiat. Pellentesque leo urna, efficitur ac velit quis, tempor molestie odio. Cras vitae cursus leo. -Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie erat viverra ut. Vestibulum nisl ex, cursus quis magna id, pulvinar condimentum sem. Nunc ac orci volutpat turpis luctus tempor. Phasellus non ultrices est. Proin quis risus ut risus interdum pellentesque. Vestibulum lobortis, est in accumsan porttitor, nunc neque vulputate ipsum, vel varius metus orci condimentum magna. Duis vulputate leo et mi interdum sollicitudin. Suspendisse malesuada sagittis urna ac mattis. Cras vel nisi eu enim interdum maximus in mollis augue. In faucibus vestibulum lectus at pharetra. Maecenas maximus massa ac massa ornare, sit amet blandit lacus ultricies. Suspendisse tristique pellentesque velit, a finibus libero pellentesque vel. Quisque pellentesque ornare tincidunt. +Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie erat viverra ut. Vestibulum nisl ex, cursus quis magna id, pulvinar condimentum sem. Nunc ac orci volutpat turpis luctus tempor. Phasellus non ultrices est. Proin quis risus ut risus interdum pellentesque. Vestibulum lobortis, est in accumsan porttitor, nunc neque vulputate ipsum, vel varius metus orci condimentum magna. Duis vulputate leo et mi interdum sollicitudin. Suspendisse malesuada sagittis urna ac mattis. Cras vel nisi eu enim interdum maximus in mollis augue. In faucibus vestibulum lectus at pharetra. Maecenas maximus massa ac massa ornare, sit amet blandit lacus ultricies. Suspendisse tristique pellentesque velit, a finibus libero pellentesque vel. Quisque pellentesque ornare tincidunt. diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags.txt b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags.txt index bd9d865f1f0b0..441db530bd664 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/Helper/WordWrapper/output/lipsum_with_tags.txt @@ -14,7 +14,7 @@ lacus. Proin eleifend nisi id neque porta tincidunt. Quisque tempus purus sit am nisi eros. In hac habitasse platea dictumst. Ut ut metus eu diam aliquam feugiat. Pellentesque leo urna, efficitur ac velit quis, tempor molestie odio. Cras vitae cursus leo. -Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie +Duis in libero ut odio porta dignissim. In molestie diam at ante dictum ullamcorper. Ut auctor eros elit, nec molestie erat viverra ut. Vestibulum nisl ex, cursus quis magna id, pulvinar condimentum sem. Nunc ac orci volutpat turpis luctus tempor. Phasellus non ultrices est. Proin quis risus ut risus interdum pellentesque. Vestibulum lobortis, est in accumsan porttitor, nunc neque vulputate ipsum, vel varius metus orci condimentum magna. Duis vulputate leo et mi From 56013db4cfa482bd14b38bea3c71efbf027cb00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Wed, 13 Mar 2019 18:01:29 +0100 Subject: [PATCH 07/17] Console Table Helper: refactor with PrettyWordWrapper --- src/Symfony/Component/Console/Helper/Table.php | 10 ++++++++-- .../Component/Console/Tests/Helper/TableTest.php | 15 ++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 99aa83d4c8173..414c3614713bf 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -82,6 +82,7 @@ class Table */ private $columnWidths = []; private $columnMaxWidths = []; + private $columnWordWrapCutOptions = []; private static $styles; @@ -228,13 +229,14 @@ public function setColumnWidths(array $widths) * * @return $this */ - public function setColumnMaxWidth(int $columnIndex, int $width): self + public function setColumnMaxWidth(int $columnIndex, int $width, int $cutOptions = PrettyWordWrapper::CUT_LONG_WORDS): self { if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, \get_class($this->output->getFormatter()))); } $this->columnMaxWidths[$columnIndex] = $width; + $this->columnWordWrapCutOptions[$columnIndex] = $cutOptions; return $this; } @@ -523,7 +525,11 @@ private function buildTableRows($rows) // Remove any new line breaks and replace it with a new line foreach ($rows[$rowKey] as $column => $cell) { if (isset($this->columnMaxWidths[$column]) && Helper::strlenWithoutDecoration($formatter, $cell) > $this->columnMaxWidths[$column]) { - $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column]); + $cell = $formatter->format(PrettyWordWrapper::wrap( + $cell, + $this->columnMaxWidths[$column], + $this->columnWordWrapCutOptions[$column] + )); } if (!strstr($cell, "\n")) { continue; diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index 43b90fd073c91..019c64be75e17 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\PrettyWordWrapper; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Helper\TableSeparator; @@ -1057,7 +1058,7 @@ public function testColumnMaxWidths() ->setRows([ ['Divine Comedy', 'A Tale of Two Cities', 'The Lord of the Rings', 'And Then There Were None'], ]) - ->setColumnMaxWidth(1, 5) + ->setColumnMaxWidth(1, 5, PrettyWordWrapper::CUT_ALL) ->setColumnMaxWidth(2, 10) ->setColumnMaxWidth(3, 15); @@ -1065,12 +1066,12 @@ public function testColumnMaxWidths() $expected = << Date: Wed, 13 Mar 2019 18:30:09 +0100 Subject: [PATCH 08/17] Console Symfony Style: refactor with PrettyWordWrapper --- src/Symfony/Component/Console/Style/SymfonyStyle.php | 8 +++++++- .../Fixtures/Style/SymfonyStyle/output/output_13.txt | 9 ++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Console/Style/SymfonyStyle.php b/src/Symfony/Component/Console/Style/SymfonyStyle.php index b46162de683e8..8ea85d9f9a7ec 100644 --- a/src/Symfony/Component/Console/Style/SymfonyStyle.php +++ b/src/Symfony/Component/Console/Style/SymfonyStyle.php @@ -14,6 +14,7 @@ use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\PrettyWordWrapper; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Helper\Table; @@ -406,7 +407,12 @@ private function createBlock(iterable $messages, string $type = null, string $st $message = OutputFormatter::escape($message); } - $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true))); + $lines = array_merge($lines, explode(PHP_EOL, PrettyWordWrapper::wrap( + $message, + $this->lineLength - $prefixLength - $indentLength, + PrettyWordWrapper::CUT_LONG_WORDS, + PHP_EOL + ))); if (\count($messages) > 1 && $key < \count($messages) - 1) { $lines[] = ''; diff --git a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt index 0f3704b7482ea..4ecb6ae30e755 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt @@ -1,7 +1,6 @@ - // Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et  - // dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea  - // commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla  - // pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim - // id est laborum + // Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + // aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.  + // Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + // sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum From f4f914bf88ec0f644fb0974555db99a76e306dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Thu, 14 Mar 2019 10:28:50 +0100 Subject: [PATCH 09/17] Console Helper: add format tags regex helper method --- .../Component/Console/Helper/Helper.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Symfony/Component/Console/Helper/Helper.php b/src/Symfony/Component/Console/Helper/Helper.php index 0ddddf6bc5023..150b5c92e6a61 100644 --- a/src/Symfony/Component/Console/Helper/Helper.php +++ b/src/Symfony/Component/Console/Helper/Helper.php @@ -20,6 +20,8 @@ */ abstract class Helper implements HelperInterface { + const FORMAT_TAG_REGEX = '[a-z][a-z0-9,_=;-]*+'; + protected $helperSet = null; /** @@ -123,6 +125,25 @@ public static function strlenWithoutDecoration(OutputFormatterInterface $formatt return self::strlen(self::removeDecoration($formatter, $string)); } + /** + * Sometimes we need to find the format tags. This regex "placeholders": + * - \\0 --> full open or close tag + * - \\1 --> tag "inside" + * - \\2 --> only tag name + * + * | \\0 | \\1 | \\2 | + * | ---------- | -------- | ------- | + * | | comment | comment | + * | | /comment | comment | + * | | / | (empty) | + * + * @return string + */ + public static function getFormatTagRegexPattern(): string + { + return sprintf('{<((%1$s)|/(%1$s)?)>}ix', self::FORMAT_TAG_REGEX); + } + public static function removeDecoration(OutputFormatterInterface $formatter, $string) { $isDecorated = $formatter->isDecorated(); From 4f7847ad6bbf538947b1c5c5156aee9cb219ac71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Sun, 17 Mar 2019 17:20:48 +0100 Subject: [PATCH 10/17] Console: output formatter refactoring with PrettyWordWrapper --- src/Symfony/Component/Console/CHANGELOG.md | 8 +- .../Console/Formatter/OutputFormatter.php | 98 ++--- .../WrappableOutputFormatterInterface.php | 12 + .../Console/Helper/PrettyWordWrapper.php | 338 +++++++++++++----- .../Component/Console/Helper/Table.php | 2 +- .../Tests/Formatter/OutputFormatterTest.php | 38 +- .../Tests/Helper/PrettyWordWrapperTest.php | 87 ++++- 7 files changed, 418 insertions(+), 165 deletions(-) diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 399bbc2213368..c04853d5bdeb8 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -1,6 +1,8 @@ CHANGELOG ========= + * Refactor word wrapping with PrettyWordWrapping + 4.2.0 ----- @@ -24,7 +26,7 @@ CHANGELOG * `OutputFormatter` throws an exception when unknown options are used * removed `QuestionHelper::setInputStream()/getInputStream()` - * removed `Application::getTerminalWidth()/getTerminalHeight()` and + * removed `Application::getTerminalWidth()/getTerminalHeight()` and `Application::setTerminalDimensions()/getTerminalDimensions()` * removed `ConsoleExceptionEvent` * removed `ConsoleEvents::EXCEPTION` @@ -50,7 +52,7 @@ CHANGELOG with value optional explicitly passed empty * added console.error event to catch exceptions thrown by other listeners * deprecated console.exception event in favor of console.error -* added ability to handle `CommandNotFoundException` through the +* added ability to handle `CommandNotFoundException` through the `console.error` event * deprecated default validation in `SymfonyQuestionHelper::ask` @@ -66,7 +68,7 @@ CHANGELOG ----- * added truncate method to FormatterHelper - * added setColumnWidth(s) method to Table + * added setColumnWidth(s) method to Table 2.8.3 ----- diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index a333f45bd6205..888921ac5fe56 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -12,18 +12,22 @@ namespace Symfony\Component\Console\Formatter; use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\PrettyWordWrapper; /** * Formatter class for console output. * * @author Konstantin Kudryashov * @author Roland Franssen + * @author Krisztián Ferenczi */ class OutputFormatter implements WrappableOutputFormatterInterface { private $decorated; private $styles = []; private $styleStack; + private $wrapCutOptions = PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING; /** * Escapes "<" special char in given text. @@ -127,23 +131,36 @@ public function getStyle($name) } /** - * {@inheritdoc} + * @return int */ - public function format($message) + public function getWrapCutOptions(): int { - return $this->formatAndWrap((string) $message, 0); + return $this->wrapCutOptions; + } + + /** + * @param int $wrapCutOptions + * + * @return $this + * + * @see PrettyWordWrapper + */ + public function setWrapCutOptions(int $wrapCutOptions) + { + $this->wrapCutOptions = $wrapCutOptions; + + return $this; } /** * {@inheritdoc} */ - public function formatAndWrap(string $message, int $width) + public function format($message) { + $message = (string) $message; $offset = 0; $output = ''; - $tagRegex = '[a-z][a-z0-9,_=;-]*+'; - $currentLineLength = 0; - preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE); + preg_match_all(Helper::getFormatTagRegexPattern(), $message, $matches, PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; $text = $match[0]; @@ -153,7 +170,7 @@ public function formatAndWrap(string $message, int $width) } // add the text up to the next tag - $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); + $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset)); $offset = $pos + \strlen($text); // opening tag? @@ -166,8 +183,8 @@ public function formatAndWrap(string $message, int $width) if (!$open && !$tag) { // $this->styleStack->pop(); - } elseif (false === $style = $this->createStyleFromString($tag)) { - $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength); + } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) { + $output .= $this->applyCurrentStyle($text); } elseif ($open) { $this->styleStack->push($style); } else { @@ -175,7 +192,7 @@ public function formatAndWrap(string $message, int $width) } } - $output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength); + $output .= $this->applyCurrentStyle(substr($message, $offset)); if (false !== strpos($output, "\0")) { return strtr($output, ["\0" => '\\', '\\<' => '<']); @@ -184,6 +201,22 @@ public function formatAndWrap(string $message, int $width) return str_replace('\\<', '<', $output); } + /** + * {@inheritdoc} + */ + public function formatAndWrap(string $message, int $width) + { + return $this->format($this->wordwrap($message, $width)); + } + + /** + * {@inheritdoc} + */ + public function wordwrap(string $message, int $width, int $cutOptions = null): string + { + return PrettyWordWrapper::wrap($message, $width, null === $cutOptions ? $this->wrapCutOptions : $cutOptions); + } + /** * @return OutputFormatterStyleStack */ @@ -195,6 +228,8 @@ public function getStyleStack() /** * Tries to create new style instance from string. * + * @param string $string + * * @return OutputFormatterStyle|false False if string is not format string */ private function createStyleFromString(string $string) @@ -233,46 +268,17 @@ private function createStyleFromString(string $string) /** * Applies current style from stack to text, if must be applied. */ - private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength): string + private function applyCurrentStyle(string $text): string { - if ('' === $text) { - return ''; - } - - if (!$width) { - return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text; - } - - if (!$currentLineLength && '' !== $current) { - $text = ltrim($text); - } - - if ($currentLineLength) { - $prefix = substr($text, 0, $i = $width - $currentLineLength)."\n"; - $text = substr($text, $i); - } else { - $prefix = ''; - } - - preg_match('~(\\n)$~', $text, $matches); - $text = $prefix.preg_replace('~([^\\n]{'.$width.'})\\ *~', "\$1\n", $text); - $text = rtrim($text, "\n").($matches[1] ?? ''); - - if (!$currentLineLength && '' !== $current && "\n" !== substr($current, -1)) { - $text = "\n".$text; - } - - $lines = explode("\n", $text); - if ($width === $currentLineLength = \strlen(end($lines))) { - $currentLineLength = 0; - } - - if ($this->isDecorated()) { + if ($this->isDecorated() && \strlen($text) > 0) { + $lines = explode(PHP_EOL, $text); foreach ($lines as $i => $line) { $lines[$i] = $this->styleStack->getCurrent()->apply($line); } + + return implode(PHP_EOL, $lines); } - return implode("\n", $lines); + return $text; } } diff --git a/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php b/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php index 6694053f057ea..d73c273485f5f 100644 --- a/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php +++ b/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php @@ -15,6 +15,7 @@ * Formatter interface for console output that supports word wrapping. * * @author Roland Franssen + * @author Krisztián Ferenczi */ interface WrappableOutputFormatterInterface extends OutputFormatterInterface { @@ -22,4 +23,15 @@ interface WrappableOutputFormatterInterface extends OutputFormatterInterface * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping). */ public function formatAndWrap(string $message, int $width); + + /** + * Separate word wrapping method. + * + * @param string $message + * @param int $width + * @param int|null $cutOptions + * + * @return string + */ + public function wordwrap(string $message, int $width, int $cutOptions = null): string; } diff --git a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php index f229acdeff54c..039e5bfdba72c 100644 --- a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php +++ b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php @@ -12,30 +12,57 @@ /** * It helps you to wrap long text with pretty breaks and useful cuts. You can control the cuts with the control option: - * - CUT_DISABLE: Always break the text at word boundary. - * - CUT_LONG_WORDS: If the word is longer than one row it will be cut. - * - CUT_WORDS: Always break at set length, it will cut all words. It would be useful if you have little - * space. (Info: It "contains" the CUT_LONG_WORDS option) - * - CUT_URLS: Lots of terminal can recognize URL-s in text and make them clickable (if there isn't break - * inside the URL) The URLS can be long, default we keep it in one block even if it gets ugly - * response. You can switch this behavior off with this option. The result will be pretty, - * but the URL won't be clickable. + * - CUT_DISABLE: Always break the text at word boundary. + * - CUT_LONG_WORDS: If the word is longer than one row it will be cut. + * - CUT_WORDS: Always break at set length, it will cut all words. It would be useful if you have little + * space. (Info: It "contains" the CUT_LONG_WORDS option) + * - CUT_URLS: Lots of terminal can recognize URL-s in text and make them clickable (if there isn't break + * inside the URL) The URLS can be long, default we keep it in one block even if it gets ugly + * response. You can switch this behavior off with this option. The result will be pretty, + * but the URL won't be clickable. + * - CUT_FILL_UP_MISSING: The program will fill up the rows with spaces in order to every row will be same long. * * * $message = "This is a comment message with info ..."; * // Default: * $output->writeln(PrettyWordWrapper::wrap($message, 120); * // Use custom settings: - * $output->writeln(PrettyWordWrapper::wrap($message, 20, PrettyWordWrapper::CUT_ALL, PHP_EOL); + * $output->writeln(PrettyWordWrapper::wrap( + * $message, + * 20, + * PrettyWordWrapper::CUT_ALL | PrettyWordWrap::CUT_FILL_UP_MISSING, + * PHP_EOL + * ); * * + * Known problems, limitations: + * - You can't call PrettyWordWrapper::wrap() inside a "running wrap" because there are "cache" properties and + * it causes problems within a Singleton class. Solution: you can create a PrettyWordWrapper object, and + * use the $wrapper->wordwrap() non-static method. + * - If you use escaped tags AND (the line width is too short OR you use the CUT_WORDS option): `\Message\`, + * the wrapper could wrap inside the tag: + * + * \Me + * ssage\ + * + * In this case maybe the OutputFormatter won't remove the second `\` character, because the wrapper broke the + * tag also, so it will shown like this: + * + * Me + * ssage\ + * * @author Krisztián Ferenczi */ class PrettyWordWrapper { // Defaults + /** @var int */ const DEFAULT_WIDTH = 120; + /** @var string */ const DEFAULT_BREAK = PHP_EOL; + /** @var int */ const DEFAULT_CUT = self::CUT_LONG_WORDS; // Cut options @@ -44,33 +71,69 @@ class PrettyWordWrapper const CUT_WORDS = 3; // Cut long words too const CUT_URLS = 4; const CUT_ALL = 7; + const CUT_FILL_UP_MISSING = 8; - const TAG_REGEX = '[a-z][a-z0-9,_=;-]*+'; + /** + * This is a ZERO_WIDTH_SPACE UTF-8 character. It is used when we try to protect the escaped tags, eg: `\` + * + * @see https://en.wikipedia.org/wiki/Zero-width_space + * @see https://www.fileformat.info/info/unicode/char/200b/index.htm + */ + const ESCAPE_PROTECTION_CHAR = "\u{200B}"; + /** + * @var self + */ protected static $instance; /** - * We collect the new lines into this array. + * "Cache". + * + * @var int|null + */ + protected $width; + + /** + * "Cache". Here you can use the CUT_* constants. + * + * @var int|null + */ + protected $cutOptions; + + /** + * "Cache". + * + * @var string + */ + protected $break; + + /** + * "Cache". We collect the new lines into this array. * * @var array */ protected $newLines; /** - * The current line "words". + * "Cache". The current line "words". * * @var array */ protected $newLineTokens; /** - * The current line "real" length, without the formatter "tags" and the spaces! + * "Cache". The current line "real" length, without the formatter "tags" and the spaces! * * @var int */ protected $currentLength; - protected static function getInstance() + /** + * "Singleton.", but it isn't forbidden to create new objects, if you want. + * + * @return PrettyWordWrapper + */ + protected static function getInstance(): self { if (!self::$instance) { self::$instance = new self(); @@ -104,13 +167,22 @@ public static function wrap(string $string, int $width = self::DEFAULT_WIDTH, in */ public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, int $cutOptions = self::DEFAULT_CUT, string $break = self::DEFAULT_BREAK): string { + // If the "cache" properties are in use, the program throw an exception, because you mustn't wrap inside a wrap. + // If you need this, you can create a new wrapper object and you have to use this. + if (null !== $this->width) { + throw new \LogicException('You mustn\'t wrap inside a wrap!'); + } if ($width <= 0) { throw new \InvalidArgumentException('You have to set more than 0 width!'); } if (0 == mb_strlen($break)) { throw new \InvalidArgumentException('You have to use existing end of the line character or string!'); } - $this->reset(); + // Reset all cache properties. + $this->reset($width, $cutOptions, $break); + // Protect the escaped characters and tags. + $string = $this->escape($string); + // Slice string by break string $lines = explode($break, $string); foreach ($lines as $n => $line) { // Token can be a word @@ -126,7 +198,7 @@ public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, int $ $this->closeLine(); } - return $this->finish($break); + return $this->finish(); } /** @@ -137,28 +209,32 @@ public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, int $ * @param int $width * @param int $cutOptions */ - protected function handleLineEnding(string $token, int $virtualTokenLength, int $width, int $cutOptions) + protected function handleLineEnding(string $token, int $virtualTokenLength, int $width, int $cutOptions): void { switch (true) { // Token is an URL and we don't want to cut it - case $this->tokenIsAnUrl($token) && !$this->hasCutOption(self::CUT_URLS, $cutOptions): + case $this->tokenIsAnUrl($token) && !$this->hasCutOption(self::CUT_URLS): $this->closeLine(); $this->addTokenToLine($token, $virtualTokenLength); break; // We cut everything - case $this->hasCutOption(self::CUT_WORDS, $cutOptions): - $freeSpace = $width - $this->getCurrentLineLength() - 1; - $this->sliceToken($token, $freeSpace, $width); + case $this->hasCutOption(self::CUT_WORDS): + $this->sliceToken($token); break; // We want to cut the long words - case $virtualTokenLength > $width && $this->hasCutOption(self::CUT_LONG_WORDS, $cutOptions): - $freeSpace = $width - $this->getCurrentLineLength() - 1; - // A little prettifying - if ($freeSpace < 5 && $width > 10) { + case $virtualTokenLength > $width && $this->hasCutOption(self::CUT_LONG_WORDS): + // A little prettifying, avoid like this: + // Lorem ipsum ve + // rylongtext dol + // or sit amet + // With this: + // Lorem ipsum + // verylongtext + // dolor sit amet + if ($this->getFreeSpace() < 5 && $width > 10) { $this->closeLine(); - $freeSpace = $width; } - $this->sliceToken($token, $freeSpace, $width); + $this->sliceToken($token); break; // Other situation... default: @@ -171,46 +247,124 @@ protected function handleLineEnding(string $token, int $virtualTokenLength, int /** * Close a line. */ - protected function closeLine() + protected function closeLine(): void { if (\count($this->newLineTokens)) { - $this->newLines[] = implode(' ', $this->newLineTokens); + // If the last word is empty, and there are other words, we drop it. + if (\count($this->newLineTokens) > 1 && $this->newLineTokens[\count($this->newLineTokens) - 1] == '') { + array_pop($this->newLineTokens); + } + $line = $this->unescape(trim(implode(' ', $this->newLineTokens))); + // Fill up the ends if necessary + if ($this->hasCutOption(self::CUT_FILL_UP_MISSING)) { + $line .= str_repeat(' ', max($this->getFreeSpace(), 0)); + } + // Add current line and reset "line caches". + $this->newLines[] = $line; $this->newLineTokens = []; $this->currentLength = 0; } } /** - * Register a token with set length. + * Register a token with set length. We will implode them with ' ' - space -, that is why the $appendToLast could + * be important if we adding a part of longer word. + * + * $appendToLast = false + * Error --> Error + * + * $appendToLast = true + * Error --> Error * * @param string $token * @param int $virtualTokenLength + * @param bool $appendToLast We set it true if we slice a longer word with tags eg. */ - protected function addTokenToLine(string $token, int $virtualTokenLength) + protected function addTokenToLine(string $token, int $virtualTokenLength, bool $appendToLast = false): void { + if ($appendToLast) { + $last = \count($this->newLineTokens) > 0 + ? array_pop($this->newLineTokens) + : ''; + $token = $last . $token; + } $this->newLineTokens[] = $token; $this->currentLength += $virtualTokenLength; } /** - * Close everything and build the formatted text. + * We try to protect every escaped characters, especially the escaped formatting tags: * - * @param string $break + * \ --> [ZERO_WIDTH_SPACE]\<[ZERO_WIDTH_SPACE]error> + * + * In this form the tag regular expression won't find this as a tag. + * + * !!! PAY ATTANTION !!! Don't use the mb_* functions with preg_match() position answers. preg_match() gets "bytes", + * not characters! + * + * @param string $string * * @return string */ - protected function finish(string $break) + protected function escape(string $string): string + { + $output = ''; + $offset = 0; + // The OFFSET value will be in byte!!!! Don't use mb_* functions when you use these numbers! + preg_match_all('{\\\\<}u', $string, $matches, PREG_OFFSET_CAPTURE); + foreach ($matches[0] as $i => $match) { + $pos = $match[1]; + $protectedBlock = $match[0]; + // Don't use the mb_* function here!!! + $output .= substr($string, $offset, $pos - $offset) + . self::ESCAPE_PROTECTION_CHAR + . $protectedBlock + . self::ESCAPE_PROTECTION_CHAR; + // Don't use the mb_* function here!!! + $offset = $pos + strlen($protectedBlock); + } + // Don't use the mb_* function here!!! + $output .= substr($string, $offset); + + return $output; + } + + protected function unescape(string $string): string + { + return preg_replace('{' . self::ESCAPE_PROTECTION_CHAR . '(\\\\<)' . self::ESCAPE_PROTECTION_CHAR . '}u', '\\1', $string); + } + + /** + * Close everything and build the formatted text. + * + * @return string + */ + protected function finish(): string { $this->closeLine(); + $fullEscapedText = implode($this->break, $this->newLines); + $unescaped = $this->unescape($fullEscapedText); + + // reset "caches" + $this->width = null; + $this->cutOptions = null; + $this->break = null; - return implode($break, $this->newLines); + return $unescaped; } /** - * Reset the array containers. + * Reset and set properties. + * + * @param int $width + * @param int $cutOptions + * @param string $break */ - protected function reset() + protected function reset(int $width, int $cutOptions, string $break): void { + $this->width = $width; + $this->cutOptions = $cutOptions; + $this->break = $break; $this->newLineTokens = []; $this->newLines = []; } @@ -220,15 +374,21 @@ protected function reset() * * @return int */ - protected function getCurrentLineLength() + protected function getCurrentLineLength(): int { return $this->currentLength + \count($this->newLineTokens) - 1; } + protected function getFreeSpace(): int + { + return $this->width - $this->getCurrentLineLength(); + } + /** * Virtual token length = length without "formatter tags". Eg: * - lorem --> 5 - * - lorem --> 5. + * - lorem --> 5 + * - \lorem\ --> 24 // We removed the two \ escaping character! * * @param string $token * @@ -237,9 +397,11 @@ protected function getCurrentLineLength() protected function getVirtualTokenLength(string $token): int { $virtualTokenLength = mb_strlen($token); - if (false !== strpos($token, '<')) { + if (false !== strpos($token, '<') || false !== strpos($token, self::ESCAPE_PROTECTION_CHAR)) { $untaggedToken = $this->pregReplaceTags('', $token); - $virtualTokenLength = mb_strlen($untaggedToken); + $unescapedToken = $this->unescape($untaggedToken); + // Remove escaped tags + $virtualTokenLength = mb_strlen($unescapedToken) - substr_count($unescapedToken, '\\<'); } return $virtualTokenLength; @@ -255,56 +417,60 @@ protected function tokenIsAnUrl(string $token): bool return false !== mb_strpos($token, 'http://') || false !== mb_strpos($token, 'https://'); } - protected function sliceToken(string $token, int $freeChars, int $width) - { - // We try to finds "formatter tags": - // verylongwordwithtags --> verylongword withtags - $tokenBlocks = explode(' ', $this->pregReplaceTags(' \\0 ', $token)); - $slicedToken = ''; - $slicedTokenVirtualLength = 0; - foreach ($tokenBlocks as $block) { - while ($block) { - if ($freeChars <= 0) { - if ('' != $slicedToken) { - $this->addTokenToLine($slicedToken, $slicedTokenVirtualLength); - } - $this->closeLine(); - $slicedToken = ''; - $slicedTokenVirtualLength = 0; - $freeChars = $width; - } - list($partial, $block, $blockLength) = $this->sliceTokenBlock($block, $freeChars); - $freeChars -= $blockLength; - $slicedTokenVirtualLength += $blockLength; - $slicedToken .= $partial; - } - } - $this->addTokenToLine($slicedToken, $slicedTokenVirtualLength); - } - /** - * It handles the long word "blocks". + * Slice a long token. * - * @param string $tokenBlock - * @param int $freeChars + * !!! PAY ATTANTION !!! Don't use the mb_* functions with preg_match() position answers. preg_match() gets "bytes", + * not characters! * - * @return array [$token, $block, $blockLength] + * @param string $token */ - protected function sliceTokenBlock(string $tokenBlock, int $freeChars): array + protected function sliceToken(string $token): void { - if ('<' == $tokenBlock[0] && '>' == mb_substr($tokenBlock, -1)) { - return [$tokenBlock, '', 0]; + if ($this->getFreeSpace() <= 0) { + $this->closeLine(); + } + $offset = 0; + preg_match_all(Helper::getFormatTagRegexPattern(), $token, $matches, PREG_OFFSET_CAPTURE); + // Init: append to this... See addTokenToLine(), $appendToLast parameter + $this->addTokenToLine('', 0); + foreach ($matches[0] as $i => $match) { + $pos = $match[1]; + $tag = $match[0]; + + // Add the text up to the next tag. + // Don't replace it to mb_* function! + $block = \substr($token, $offset, $pos - $offset); + $offset = $pos + \strlen($tag); + + $this->breakLongToken($block); + if ($this->getFreeSpace() == 0 && $tag[1] != '/') { + $this->closeLine(); + } + $this->addTokenToLine($tag, 0, true); } - $blockLength = mb_strlen($tokenBlock); - if ($blockLength <= $freeChars) { - return [$tokenBlock, '', $blockLength]; + // Don't replace it to mb_* function! + $block = \substr($token, $offset); + if ($block) { + $this->breakLongToken($block); } + } - return [ - mb_substr($tokenBlock, 0, $freeChars), - mb_substr($tokenBlock, $freeChars), - $freeChars, - ]; + protected function breakLongToken(string $token): void + { + $freeChars = $this->getFreeSpace(); + $token = $this->unescape($token); + $prefix = \mb_substr($token, 0, $freeChars); + $this->addTokenToLine($prefix, \mb_strlen($prefix), true); + $tokenLength = \mb_strlen($token); + for ($offset = $freeChars;$offset<$tokenLength;$offset+=$this->width) { + $subLength = min($this->width, $tokenLength-$offset); + $subToken = \mb_substr($token, $offset, $subLength); + if ($subLength + $this->getCurrentLineLength() > $this->width) { + $this->closeLine(); + } + $this->addTokenToLine($subToken, \mb_strlen($subToken), true); + } } /** @@ -315,9 +481,9 @@ protected function sliceTokenBlock(string $tokenBlock, int $freeChars): array * * @return bool */ - protected function hasCutOption(int $option, int $cutOptions): bool + protected function hasCutOption(int $option): bool { - return ($cutOptions & $option) === $option; + return ($this->cutOptions & $option) === $option; } /** @@ -342,7 +508,7 @@ protected function hasCutOption(int $option, int $cutOptions): bool protected function pregReplaceTags(string $replacement, string $string): string { return preg_replace( - sprintf('{<((%1$s)|/(%1$s)?)>}', self::TAG_REGEX), + Helper::getFormatTagRegexPattern(), $replacement, $string ); diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 414c3614713bf..53a7f385c2d82 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -525,7 +525,7 @@ private function buildTableRows($rows) // Remove any new line breaks and replace it with a new line foreach ($rows[$rowKey] as $column => $cell) { if (isset($this->columnMaxWidths[$column]) && Helper::strlenWithoutDecoration($formatter, $cell) > $this->columnMaxWidths[$column]) { - $cell = $formatter->format(PrettyWordWrapper::wrap( + $cell = $formatter->format($formatter->wordwrap( $cell, $this->columnMaxWidths[$column], $this->columnWordWrapCutOptions[$column] diff --git a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php index 3a7906173862c..b651cd3bc74c4 100644 --- a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php +++ b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php @@ -277,8 +277,8 @@ public function testContentWithLineBreaks() $formatter = new OutputFormatter(true); $this->assertEquals(<<format(<<<'EOF' @@ -287,8 +287,8 @@ public function testContentWithLineBreaks() )); $this->assertEquals(<<format(<<<'EOF' some text @@ -297,9 +297,9 @@ public function testContentWithLineBreaks() )); $this->assertEquals(<<format(<<<'EOF' @@ -309,10 +309,10 @@ public function testContentWithLineBreaks() )); $this->assertEquals(<<format(<<<'EOF' @@ -327,19 +327,19 @@ public function testFormatAndWrap() { $formatter = new OutputFormatter(true); - $this->assertSame("fo\no\e[37;41mb\e[39;49m\n\e[37;41mar\e[39;49m\nba\nz", $formatter->formatAndWrap('foobar baz', 2)); - $this->assertSame("pr\ne \e[37;41m\e[39;49m\n\e[37;41mfo\e[39;49m\n\e[37;41mo \e[39;49m\n\e[37;41mba\e[39;49m\n\e[37;41mr \e[39;49m\n\e[37;41mba\e[39;49m\n\e[37;41mz\e[39;49m \npo\nst", $formatter->formatAndWrap('pre foo bar baz post', 2)); - $this->assertSame("pre\e[37;41m\e[39;49m\n\e[37;41mfoo\e[39;49m\n\e[37;41mbar\e[39;49m\n\e[37;41mbaz\e[39;49m\npos\nt", $formatter->formatAndWrap('pre foo bar baz post', 3)); - $this->assertSame("pre \e[37;41m\e[39;49m\n\e[37;41mfoo \e[39;49m\n\e[37;41mbar \e[39;49m\n\e[37;41mbaz\e[39;49m \npost", $formatter->formatAndWrap('pre foo bar baz post', 4)); - $this->assertSame("pre \e[37;41mf\e[39;49m\n\e[37;41moo ba\e[39;49m\n\e[37;41mr baz\e[39;49m\npost", $formatter->formatAndWrap('pre foo bar baz post', 5)); + $this->assertSame("fo\no\e[37;41mb\e[39;49m\n\e[37;41mar\e[39;49m\nba\nz ", $formatter->formatAndWrap('foobar baz', 2)); + $this->assertSame("pr\ne \n\e[37;41mfo\e[39;49m\n\e[37;41mo \e[39;49m\n\e[37;41mba\e[39;49m\n\e[37;41mr \e[39;49m\n\e[37;41mba\e[39;49m\n\e[37;41mz\e[39;49m \npo\nst", $formatter->formatAndWrap('pre foo bar baz post', 2)); + $this->assertSame("pre\n\e[37;41mfoo\e[39;49m\n\e[37;41mbar\e[39;49m\n\e[37;41mbaz\e[39;49m\npos\nt ", $formatter->formatAndWrap('pre foo bar baz post', 3)); + $this->assertSame("pre \n\e[37;41mfoo \e[39;49m\n\e[37;41mbar \e[39;49m\n\e[37;41mbaz\e[39;49m \npost", $formatter->formatAndWrap('pre foo bar baz post', 4)); + $this->assertSame("pre \n\e[37;41mfoo \e[39;49m\n\e[37;41mbar \e[39;49m\n\e[37;41mbaz\e[39;49m \npost ", $formatter->formatAndWrap('pre foo bar baz post', 5)); $formatter = new OutputFormatter(); - $this->assertSame("fo\nob\nar\nba\nz", $formatter->formatAndWrap('foobar baz', 2)); + $this->assertSame("fo\nob\nar\nba\nz ", $formatter->formatAndWrap('foobar baz', 2)); $this->assertSame("pr\ne \nfo\no \nba\nr \nba\nz \npo\nst", $formatter->formatAndWrap('pre foo bar baz post', 2)); - $this->assertSame("pre\nfoo\nbar\nbaz\npos\nt", $formatter->formatAndWrap('pre foo bar baz post', 3)); + $this->assertSame("pre\nfoo\nbar\nbaz\npos\nt ", $formatter->formatAndWrap('pre foo bar baz post', 3)); $this->assertSame("pre \nfoo \nbar \nbaz \npost", $formatter->formatAndWrap('pre foo bar baz post', 4)); - $this->assertSame("pre f\noo ba\nr baz\npost", $formatter->formatAndWrap('pre foo bar baz post', 5)); + $this->assertSame("pre \nfoo \nbar \nbaz \npost ", $formatter->formatAndWrap('pre foo bar baz post', 5)); } } diff --git a/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php b/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php index bd7545f7d150a..905f73b1a19da 100644 --- a/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php @@ -75,21 +75,88 @@ public function dpWordwrap() return [ // Check empty - ['', 120, PrettyWordWrapper::DEFAULT_CUT, $baseBreak, ''], - [$baseBreak, 120, PrettyWordWrapper::DEFAULT_CUT, $baseBreak, $baseBreak], + ['', 2, PrettyWordWrapper::CUT_ALL, $baseBreak, ''], + ['', 2, PrettyWordWrapper::CUT_ALL | PrettyWordWrapper::CUT_FILL_UP_MISSING, $baseBreak, ' '], + [$baseBreak, 2, PrettyWordWrapper::CUT_ALL, $baseBreak, $baseBreak], + [$baseBreak, 2, PrettyWordWrapper::CUT_ALL | PrettyWordWrapper::CUT_FILL_UP_MISSING, $baseBreak, ' ' . $baseBreak . ' '], // Check limit and UTF-8 [ - 'utf120.txt', - 120, - PrettyWordWrapper::DEFAULT_CUT, + 'öüóőúéáű', + 8, + PrettyWordWrapper::CUT_LONG_WORDS, + $baseBreak, + 'öüóőúéáű', + ], + [ + 'öüóőúéáű', + 4, + PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + $baseBreak, + 'öüóő' . $baseBreak . 'úéáű', + ], + [ + 'öüóőúéáű', + 6, + PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + $baseBreak, + 'öüóőúé' . $baseBreak . 'áű ', + ], + // UTF-8 + tags + [ + 'öüóőúéáű', + 8, + PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + $baseBreak, + 'öüóőúéáű', + ], + [ + 'öüóőúéáű', + 8, + PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + $baseBreak, + 'öüóőúéáű', + ], + [ + 'foo bar baz', + 3, + PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + $baseBreak, + implode($baseBreak, ['foo', 'bar', 'baz']), + ], + [ + 'foo bar baz', + 2, + PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + $baseBreak, + implode($baseBreak, ['fo', 'o ','ba', 'r ', 'ba', 'z ']), + ], + // Escaped tags + [ + 'foo \bar\ baz', + 3, + PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + $baseBreak, + implode($baseBreak, ['foo', '\b', 'ar\\', ' ', 'baz']), + ], + [ + 'foobarbaz foo', + 3, + PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + $baseBreak, + implode($baseBreak, ['foo', 'bar', 'baz', 'foo']), + ], + [ + 'foobarbaz foo', + 2, + PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, $baseBreak, - 'utf120.txt', + implode($baseBreak, ['fo', 'ob', 'ar', 'ba', 'z ', 'fo', 'o ']), ], // Check simple text [ 'lipsum.txt', 120, - PrettyWordWrapper::DEFAULT_CUT, + PrettyWordWrapper::CUT_LONG_WORDS, $baseBreak, 'lipsum.txt', ], @@ -97,7 +164,7 @@ public function dpWordwrap() [ 'lipsum_with_tags.txt', 120, - PrettyWordWrapper::DEFAULT_CUT, + PrettyWordWrapper::CUT_LONG_WORDS, $baseBreak, 'lipsum_with_tags.txt', ], @@ -105,7 +172,7 @@ public function dpWordwrap() [ 'lipsum_with_tags_and_custom_break.txt', 120, - PrettyWordWrapper::DEFAULT_CUT, + PrettyWordWrapper::CUT_LONG_WORDS, $customBreak, 'lipsum_with_tags_and_custom_break.txt', ], @@ -113,7 +180,7 @@ public function dpWordwrap() [ 'with_long_words.txt', 30, - PrettyWordWrapper::DEFAULT_CUT, + PrettyWordWrapper::CUT_LONG_WORDS, $baseBreak, 'with_long_words_with_default_cut.txt', ], From 5ca38fbffe1a27fe3623972610f4551dcbad6bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Sun, 17 Mar 2019 17:40:43 +0100 Subject: [PATCH 11/17] CS fix --- .../Component/Console/Helper/Helper.php | 2 +- .../Console/Helper/PrettyWordWrapper.php | 32 +++++++++---------- .../Tests/Helper/PrettyWordWrapperTest.php | 8 ++--- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/Helper.php b/src/Symfony/Component/Console/Helper/Helper.php index 150b5c92e6a61..68e3b9baa608c 100644 --- a/src/Symfony/Component/Console/Helper/Helper.php +++ b/src/Symfony/Component/Console/Helper/Helper.php @@ -129,7 +129,7 @@ public static function strlenWithoutDecoration(OutputFormatterInterface $formatt * Sometimes we need to find the format tags. This regex "placeholders": * - \\0 --> full open or close tag * - \\1 --> tag "inside" - * - \\2 --> only tag name + * - \\2 --> only tag name. * * | \\0 | \\1 | \\2 | * | ---------- | -------- | ------- | diff --git a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php index 039e5bfdba72c..f90ce4e1080c7 100644 --- a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php +++ b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php @@ -74,7 +74,7 @@ class PrettyWordWrapper const CUT_FILL_UP_MISSING = 8; /** - * This is a ZERO_WIDTH_SPACE UTF-8 character. It is used when we try to protect the escaped tags, eg: `\` + * This is a ZERO_WIDTH_SPACE UTF-8 character. It is used when we try to protect the escaped tags, eg: `\`. * * @see https://en.wikipedia.org/wiki/Zero-width_space * @see https://www.fileformat.info/info/unicode/char/200b/index.htm @@ -251,7 +251,7 @@ protected function closeLine(): void { if (\count($this->newLineTokens)) { // If the last word is empty, and there are other words, we drop it. - if (\count($this->newLineTokens) > 1 && $this->newLineTokens[\count($this->newLineTokens) - 1] == '') { + if (\count($this->newLineTokens) > 1 && '' == $this->newLineTokens[\count($this->newLineTokens) - 1]) { array_pop($this->newLineTokens); } $line = $this->unescape(trim(implode(' ', $this->newLineTokens))); @@ -278,7 +278,7 @@ protected function closeLine(): void * * @param string $token * @param int $virtualTokenLength - * @param bool $appendToLast We set it true if we slice a longer word with tags eg. + * @param bool $appendToLast we set it true if we slice a longer word with tags eg */ protected function addTokenToLine(string $token, int $virtualTokenLength, bool $appendToLast = false): void { @@ -286,14 +286,14 @@ protected function addTokenToLine(string $token, int $virtualTokenLength, bool $ $last = \count($this->newLineTokens) > 0 ? array_pop($this->newLineTokens) : ''; - $token = $last . $token; + $token = $last.$token; } $this->newLineTokens[] = $token; $this->currentLength += $virtualTokenLength; } /** - * We try to protect every escaped characters, especially the escaped formatting tags: + * We try to protect every escaped characters, especially the escaped formatting tags:. * * \ --> [ZERO_WIDTH_SPACE]\<[ZERO_WIDTH_SPACE]error> * @@ -317,11 +317,11 @@ protected function escape(string $string): string $protectedBlock = $match[0]; // Don't use the mb_* function here!!! $output .= substr($string, $offset, $pos - $offset) - . self::ESCAPE_PROTECTION_CHAR - . $protectedBlock - . self::ESCAPE_PROTECTION_CHAR; + .self::ESCAPE_PROTECTION_CHAR + .$protectedBlock + .self::ESCAPE_PROTECTION_CHAR; // Don't use the mb_* function here!!! - $offset = $pos + strlen($protectedBlock); + $offset = $pos + \strlen($protectedBlock); } // Don't use the mb_* function here!!! $output .= substr($string, $offset); @@ -331,7 +331,7 @@ protected function escape(string $string): string protected function unescape(string $string): string { - return preg_replace('{' . self::ESCAPE_PROTECTION_CHAR . '(\\\\<)' . self::ESCAPE_PROTECTION_CHAR . '}u', '\\1', $string); + return preg_replace('{'.self::ESCAPE_PROTECTION_CHAR.'(\\\\<)'.self::ESCAPE_PROTECTION_CHAR.'}u', '\\1', $string); } /** @@ -356,8 +356,8 @@ protected function finish(): string /** * Reset and set properties. * - * @param int $width - * @param int $cutOptions + * @param int $width + * @param int $cutOptions * @param string $break */ protected function reset(int $width, int $cutOptions, string $break): void @@ -444,7 +444,7 @@ protected function sliceToken(string $token): void $offset = $pos + \strlen($tag); $this->breakLongToken($block); - if ($this->getFreeSpace() == 0 && $tag[1] != '/') { + if (0 == $this->getFreeSpace() && '/' != $tag[1]) { $this->closeLine(); } $this->addTokenToLine($tag, 0, true); @@ -463,8 +463,8 @@ protected function breakLongToken(string $token): void $prefix = \mb_substr($token, 0, $freeChars); $this->addTokenToLine($prefix, \mb_strlen($prefix), true); $tokenLength = \mb_strlen($token); - for ($offset = $freeChars;$offset<$tokenLength;$offset+=$this->width) { - $subLength = min($this->width, $tokenLength-$offset); + for ($offset = $freeChars; $offset < $tokenLength; $offset += $this->width) { + $subLength = min($this->width, $tokenLength - $offset); $subToken = \mb_substr($token, $offset, $subLength); if ($subLength + $this->getCurrentLineLength() > $this->width) { $this->closeLine(); @@ -487,7 +487,7 @@ protected function hasCutOption(int $option): bool } /** - * It replaces all tags to something different. If you want to use original tags, use the `\\0` placeholder: + * It replaces all tags to something different. If you want to use original tags, use the `\\0` placeholder:. * * Eg: * $replacement = 'STARTTAG>\\0ba', 'r ', 'ba', 'z ']), + implode($baseBreak, ['fo', 'o ', 'ba', 'r ', 'ba', 'z ']), ], // Escaped tags [ From a4a64a481efc3ef23f094e9e2cc31a24d70f18a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Mon, 18 Mar 2019 10:37:41 +0100 Subject: [PATCH 12/17] Try to fix the Windows line endings error --- .../Component/Console/Formatter/OutputFormatter.php | 4 ++-- .../Component/Console/Helper/PrettyWordWrapper.php | 9 +++++++-- src/Symfony/Component/Console/Helper/Table.php | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index 888921ac5fe56..31bbc581cba6f 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -271,12 +271,12 @@ private function createStyleFromString(string $string) private function applyCurrentStyle(string $text): string { if ($this->isDecorated() && \strlen($text) > 0) { - $lines = explode(PHP_EOL, $text); + $lines = explode("\n", $text); foreach ($lines as $i => $line) { $lines[$i] = $this->styleStack->getCurrent()->apply($line); } - return implode(PHP_EOL, $lines); + return implode("\n", $lines); } return $text; diff --git a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php index f90ce4e1080c7..c649fdf3b3b3b 100644 --- a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php +++ b/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php @@ -21,6 +21,7 @@ * response. You can switch this behavior off with this option. The result will be pretty, * but the URL won't be clickable. * - CUT_FILL_UP_MISSING: The program will fill up the rows with spaces in order to every row will be same long. + * - CUT_REPLACE_PHP_EOL: The program will replace the PHP_EOL in the input string to $break. * * * $message = "This is a comment message with info ..."; @@ -61,9 +62,9 @@ class PrettyWordWrapper /** @var int */ const DEFAULT_WIDTH = 120; /** @var string */ - const DEFAULT_BREAK = PHP_EOL; + const DEFAULT_BREAK = "\n"; /** @var int */ - const DEFAULT_CUT = self::CUT_LONG_WORDS; + const DEFAULT_CUT = self::CUT_LONG_WORDS | self::CUT_REPLACE_PHP_EOL; // Cut options const CUT_DISABLE = 0; @@ -72,6 +73,7 @@ class PrettyWordWrapper const CUT_URLS = 4; const CUT_ALL = 7; const CUT_FILL_UP_MISSING = 8; + const CUT_REPLACE_PHP_EOL = 16; /** * This is a ZERO_WIDTH_SPACE UTF-8 character. It is used when we try to protect the escaped tags, eg: `\`. @@ -180,6 +182,9 @@ public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, int $ } // Reset all cache properties. $this->reset($width, $cutOptions, $break); + if ($this->hasCutOption(self::CUT_REPLACE_PHP_EOL)) { + $string = str_replace(PHP_EOL, $break, $string); + } // Protect the escaped characters and tags. $string = $this->escape($string); // Slice string by break string diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 53a7f385c2d82..536ee872e8c75 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -229,7 +229,7 @@ public function setColumnWidths(array $widths) * * @return $this */ - public function setColumnMaxWidth(int $columnIndex, int $width, int $cutOptions = PrettyWordWrapper::CUT_LONG_WORDS): self + public function setColumnMaxWidth(int $columnIndex, int $width, int $cutOptions = PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_REPLACE_PHP_EOL): self { if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, \get_class($this->output->getFormatter()))); From a818772c5cfcb6fb75ce544c2dde389f77a59cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Mon, 18 Mar 2019 12:40:01 +0100 Subject: [PATCH 13/17] Console: extends table with some wrapping setter/getter --- .../Component/Console/Helper/Table.php | 67 +++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 536ee872e8c75..50c124f059193 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -82,7 +82,8 @@ class Table */ private $columnWidths = []; private $columnMaxWidths = []; - private $columnWordWrapCutOptions = []; + private $columnWordWrapCutOption = []; + private $defaultColumnWordWrapCutOption = PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_REPLACE_PHP_EOL; private static $styles; @@ -229,14 +230,72 @@ public function setColumnWidths(array $widths) * * @return $this */ - public function setColumnMaxWidth(int $columnIndex, int $width, int $cutOptions = PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_REPLACE_PHP_EOL): self + public function setColumnMaxWidth(int $columnIndex, int $width, int $cutOption = null): self { if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, \get_class($this->output->getFormatter()))); } $this->columnMaxWidths[$columnIndex] = $width; - $this->columnWordWrapCutOptions[$columnIndex] = $cutOptions; + $this->columnWordWrapCutOption[$columnIndex] = $cutOption; + + return $this; + } + + /** + * Sets the cut options of a column. + * + * @param int $columnIndex + * @param int $cutOptions + * + * @return $this + */ + public function setColumnWordWrapCutOption(int $columnIndex, int $cutOptions): self + { + $this->columnWordWrapCutOption[$columnIndex] = $cutOptions; + + return $this; + } + + /** + * @param int $columnIndex + * + * @return int + */ + public function getColumnWordWrapCutOption(int $columnIndex): int + { + if (!array_key_exists($columnIndex, $this->columnWordWrapCutOption)) { + return $this->defaultColumnWordWrapCutOption; + } + + return $this->columnWordWrapCutOption[$columnIndex]; + } + + /** + * @param int $defaultColumnWordWrapCutOption + * + * @return $this + */ + public function setDefaultColumnWordWrapCutOption(int $defaultColumnWordWrapCutOption): self + { + $this->defaultColumnWordWrapCutOption = $defaultColumnWordWrapCutOption; + + return $this; + } + + /** + * + * + * @param array $columnWordWrapCutOptions + * + * @return $this + */ + public function setColumnsWordWrapCutOptions(array $columnWordWrapCutOptions): self + { + $this->columnWordWrapCutOption = []; + foreach ($columnWordWrapCutOptions as $columnIndex => $columnOption) { + $this->setColumnWordWrapCutOption($columnIndex, $columnOption); + } return $this; } @@ -528,7 +587,7 @@ private function buildTableRows($rows) $cell = $formatter->format($formatter->wordwrap( $cell, $this->columnMaxWidths[$column], - $this->columnWordWrapCutOptions[$column] + $this->getColumnWordWrapCutOption($column) )); } if (!strstr($cell, "\n")) { From 149778fac844c2899a26eed237640056c293a1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Tue, 19 Mar 2019 16:58:12 +0100 Subject: [PATCH 14/17] Console: Some fixes and changes because of documentation --- .../Console/Formatter/OutputFormatter.php | 20 +++--- .../WrappableOutputFormatterInterface.php | 4 +- ...rapper.php => PrettyWordWrapperHelper.php} | 61 +++++++++++-------- .../Component/Console/Helper/Table.php | 6 +- .../Component/Console/Style/SymfonyStyle.php | 6 +- .../Tests/Helper/PrettyWordWrapperTest.php | 50 +++++++-------- .../Console/Tests/Helper/TableTest.php | 4 +- 7 files changed, 82 insertions(+), 69 deletions(-) rename src/Symfony/Component/Console/Helper/{PrettyWordWrapper.php => PrettyWordWrapperHelper.php} (91%) diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index 31bbc581cba6f..af8d9eac878a3 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -13,7 +13,7 @@ use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\PrettyWordWrapper; +use Symfony\Component\Console\Helper\PrettyWordWrapperHelper; /** * Formatter class for console output. @@ -27,7 +27,7 @@ class OutputFormatter implements WrappableOutputFormatterInterface private $decorated; private $styles = []; private $styleStack; - private $wrapCutOptions = PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING; + private $defaultWrapCutOption = PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING; /** * Escapes "<" special char in given text. @@ -133,21 +133,21 @@ public function getStyle($name) /** * @return int */ - public function getWrapCutOptions(): int + public function getDefaultWrapCutOption(): int { - return $this->wrapCutOptions; + return $this->defaultWrapCutOption; } /** - * @param int $wrapCutOptions + * @param int $defaultWrapCutOption * * @return $this * - * @see PrettyWordWrapper + * @see PrettyWordWrapperHelper */ - public function setWrapCutOptions(int $wrapCutOptions) + public function setDefaultWrapCutOption(int $defaultWrapCutOption) { - $this->wrapCutOptions = $wrapCutOptions; + $this->defaultWrapCutOption = $defaultWrapCutOption; return $this; } @@ -212,9 +212,9 @@ public function formatAndWrap(string $message, int $width) /** * {@inheritdoc} */ - public function wordwrap(string $message, int $width, int $cutOptions = null): string + public function wordwrap(string $message, int $width, int $cutOption = null): string { - return PrettyWordWrapper::wrap($message, $width, null === $cutOptions ? $this->wrapCutOptions : $cutOptions); + return PrettyWordWrapperHelper::wrap($message, $width, null === $cutOption ? $this->defaultWrapCutOption : $cutOption); } /** diff --git a/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php b/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php index d73c273485f5f..818cf70e6c35b 100644 --- a/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php +++ b/src/Symfony/Component/Console/Formatter/WrappableOutputFormatterInterface.php @@ -29,9 +29,9 @@ public function formatAndWrap(string $message, int $width); * * @param string $message * @param int $width - * @param int|null $cutOptions + * @param int|null $cutOption * * @return string */ - public function wordwrap(string $message, int $width, int $cutOptions = null): string; + public function wordwrap(string $message, int $width, int $cutOption = null): string; } diff --git a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php b/src/Symfony/Component/Console/Helper/PrettyWordWrapperHelper.php similarity index 91% rename from src/Symfony/Component/Console/Helper/PrettyWordWrapper.php rename to src/Symfony/Component/Console/Helper/PrettyWordWrapperHelper.php index c649fdf3b3b3b..e9d773240d531 100644 --- a/src/Symfony/Component/Console/Helper/PrettyWordWrapper.php +++ b/src/Symfony/Component/Console/Helper/PrettyWordWrapperHelper.php @@ -21,7 +21,7 @@ * response. You can switch this behavior off with this option. The result will be pretty, * but the URL won't be clickable. * - CUT_FILL_UP_MISSING: The program will fill up the rows with spaces in order to every row will be same long. - * - CUT_REPLACE_PHP_EOL: The program will replace the PHP_EOL in the input string to $break. + * - CUT_NO_REPLACE_EOL: The program will replace the PHP_EOL in the input string to $break. * * * $message = "This is a comment message with info ..."; @@ -56,7 +56,7 @@ * * @author Krisztián Ferenczi */ -class PrettyWordWrapper +class PrettyWordWrapperHelper extends Helper { // Defaults /** @var int */ @@ -64,7 +64,7 @@ class PrettyWordWrapper /** @var string */ const DEFAULT_BREAK = "\n"; /** @var int */ - const DEFAULT_CUT = self::CUT_LONG_WORDS | self::CUT_REPLACE_PHP_EOL; + const DEFAULT_CUT = self::CUT_LONG_WORDS; // Cut options const CUT_DISABLE = 0; @@ -73,7 +73,7 @@ class PrettyWordWrapper const CUT_URLS = 4; const CUT_ALL = 7; const CUT_FILL_UP_MISSING = 8; - const CUT_REPLACE_PHP_EOL = 16; + const CUT_NO_REPLACE_EOL = 16; /** * This is a ZERO_WIDTH_SPACE UTF-8 character. It is used when we try to protect the escaped tags, eg: `\`. @@ -100,7 +100,7 @@ class PrettyWordWrapper * * @var int|null */ - protected $cutOptions; + protected $cutOption; /** * "Cache". @@ -133,7 +133,7 @@ class PrettyWordWrapper /** * "Singleton.", but it isn't forbidden to create new objects, if you want. * - * @return PrettyWordWrapper + * @return PrettyWordWrapperHelper */ protected static function getInstance(): self { @@ -145,18 +145,28 @@ protected static function getInstance(): self } /** - * @param string $string The text - * @param int $width Character width of one line - * @param int $cutOptions You can mix your needs with CUT_* constants - * @param string $break The line breaking character(s) + * Returns the canonical name of this helper. + * + * @return string The canonical name + */ + public function getName() + { + return 'prettywordwrapper'; + } + + /** + * @param string $string The text + * @param int $width Character width of one line + * @param int $cutOption You can mix your needs with CUT_* constants + * @param string $break The line breaking character(s) * * @return string */ - public static function wrap(string $string, int $width = self::DEFAULT_WIDTH, int $cutOptions = self::DEFAULT_CUT, string $break = self::DEFAULT_BREAK): string + public static function wrap(string $string, int $width = self::DEFAULT_WIDTH, int $cutOption = self::DEFAULT_CUT, string $break = self::DEFAULT_BREAK): string { $wrapper = self::getInstance(); - return $wrapper->wordwrap($string, $width, $cutOptions, $break); + return $wrapper->wordwrap($string, $width, $cutOption, $break); } /** @@ -182,8 +192,12 @@ public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, int $ } // Reset all cache properties. $this->reset($width, $cutOptions, $break); - if ($this->hasCutOption(self::CUT_REPLACE_PHP_EOL)) { - $string = str_replace(PHP_EOL, $break, $string); + // Unifies the line endings + if (!$this->hasCutOption(self::CUT_NO_REPLACE_EOL)) { + $string = str_replace(PHP_EOL, "\n", $string); + $string = str_replace("\r\n", "\n", $string); + $string = str_replace("\n\r", "\n", $string); + $string = str_replace("\r", "\n", $string); } // Protect the escaped characters and tags. $string = $this->escape($string); @@ -197,7 +211,7 @@ public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, int $ if ($lineLength + $virtualTokenLength < $width) { $this->addTokenToLine($token, $virtualTokenLength); } else { - $this->handleLineEnding($token, $virtualTokenLength, $width, $cutOptions); + $this->handleLineEnding($token, $virtualTokenLength); } } $this->closeLine(); @@ -211,10 +225,8 @@ public function wordwrap(string $string, int $width = self::DEFAULT_WIDTH, int $ * * @param string $token * @param int $virtualTokenLength - * @param int $width - * @param int $cutOptions */ - protected function handleLineEnding(string $token, int $virtualTokenLength, int $width, int $cutOptions): void + protected function handleLineEnding(string $token, int $virtualTokenLength): void { switch (true) { // Token is an URL and we don't want to cut it @@ -227,7 +239,7 @@ protected function handleLineEnding(string $token, int $virtualTokenLength, int $this->sliceToken($token); break; // We want to cut the long words - case $virtualTokenLength > $width && $this->hasCutOption(self::CUT_LONG_WORDS): + case $virtualTokenLength > $this->width && $this->hasCutOption(self::CUT_LONG_WORDS): // A little prettifying, avoid like this: // Lorem ipsum ve // rylongtext dol @@ -236,7 +248,7 @@ protected function handleLineEnding(string $token, int $virtualTokenLength, int // Lorem ipsum // verylongtext // dolor sit amet - if ($this->getFreeSpace() < 5 && $width > 10) { + if ($this->getFreeSpace() < 5 && $this->width > 10) { $this->closeLine(); } $this->sliceToken($token); @@ -352,7 +364,7 @@ protected function finish(): string // reset "caches" $this->width = null; - $this->cutOptions = null; + $this->cutOption = null; $this->break = null; return $unescaped; @@ -368,7 +380,7 @@ protected function finish(): string protected function reset(int $width, int $cutOptions, string $break): void { $this->width = $width; - $this->cutOptions = $cutOptions; + $this->cutOption = $cutOptions; $this->break = $break; $this->newLineTokens = []; $this->newLines = []; @@ -425,7 +437,7 @@ protected function tokenIsAnUrl(string $token): bool /** * Slice a long token. * - * !!! PAY ATTANTION !!! Don't use the mb_* functions with preg_match() position answers. preg_match() gets "bytes", + * !!! PAY ATTENTION !!! Don't use the mb_* functions with preg_match() position answers. preg_match() gets "bytes", * not characters! * * @param string $token @@ -482,13 +494,12 @@ protected function breakLongToken(string $token): void * It checks the cut option is set. See the CUT_* constants. * * @param int $option - * @param int $cutOptions * * @return bool */ protected function hasCutOption(int $option): bool { - return ($this->cutOptions & $option) === $option; + return ($this->cutOption & $option) === $option; } /** diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index 50c124f059193..dba0b86fb3f54 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -83,7 +83,7 @@ class Table private $columnWidths = []; private $columnMaxWidths = []; private $columnWordWrapCutOption = []; - private $defaultColumnWordWrapCutOption = PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_REPLACE_PHP_EOL; + private $defaultColumnWordWrapCutOption = PrettyWordWrapperHelper::CUT_LONG_WORDS; private static $styles; @@ -264,7 +264,9 @@ public function setColumnWordWrapCutOption(int $columnIndex, int $cutOptions): s */ public function getColumnWordWrapCutOption(int $columnIndex): int { - if (!array_key_exists($columnIndex, $this->columnWordWrapCutOption)) { + if (!array_key_exists($columnIndex, $this->columnWordWrapCutOption) + || null === $this->columnWordWrapCutOption[$columnIndex] + ) { return $this->defaultColumnWordWrapCutOption; } diff --git a/src/Symfony/Component/Console/Style/SymfonyStyle.php b/src/Symfony/Component/Console/Style/SymfonyStyle.php index 8ea85d9f9a7ec..3eb9f0d533c9f 100644 --- a/src/Symfony/Component/Console/Style/SymfonyStyle.php +++ b/src/Symfony/Component/Console/Style/SymfonyStyle.php @@ -14,7 +14,7 @@ use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\PrettyWordWrapper; +use Symfony\Component\Console\Helper\PrettyWordWrapperHelper; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Helper\Table; @@ -407,10 +407,10 @@ private function createBlock(iterable $messages, string $type = null, string $st $message = OutputFormatter::escape($message); } - $lines = array_merge($lines, explode(PHP_EOL, PrettyWordWrapper::wrap( + $lines = array_merge($lines, explode(PHP_EOL, PrettyWordWrapperHelper::wrap( $message, $this->lineLength - $prefixLength - $indentLength, - PrettyWordWrapper::CUT_LONG_WORDS, + PrettyWordWrapperHelper::CUT_LONG_WORDS, PHP_EOL ))); diff --git a/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php b/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php index 37f3591d810d5..325077cd6a7fb 100644 --- a/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php @@ -3,7 +3,7 @@ namespace Symfony\Component\Console\Tests\Helper; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\PrettyWordWrapper; +use Symfony\Component\Console\Helper\PrettyWordWrapperHelper; /** * @author Krisztián Ferenczi @@ -18,9 +18,9 @@ class PrettyWordWrapperTest extends TestCase */ public function testConstructorExceptions($width, $break) { - $wordWrapper = new PrettyWordWrapper(); + $wordWrapper = new PrettyWordWrapperHelper(); $this->expectException(\InvalidArgumentException::class); - $wordWrapper->wordwrap('test', $width, PrettyWordWrapper::DEFAULT_CUT, $break); + $wordWrapper->wordwrap('test', $width, PrettyWordWrapperHelper::DEFAULT_CUT, $break); } public function dpTestConstructorExceptions() @@ -44,7 +44,7 @@ public function dpTestConstructorExceptions() */ public function testWordwrap($input, $width, $cutOptions, $break, $output) { - $wordWrapper = new PrettyWordWrapper(); + $wordWrapper = new PrettyWordWrapperHelper(); $response = $wordWrapper->wordwrap($this->getInputContents($input), $width, $cutOptions, $break); $this->assertEquals($this->getOutputContents($output), $response); @@ -63,7 +63,7 @@ public function testWordwrap($input, $width, $cutOptions, $break, $output) */ public function testStaticWrap($input, $width, $cutOptions, $break, $output) { - $response = PrettyWordWrapper::wrap($this->getInputContents($input), $width, $cutOptions, $break); + $response = PrettyWordWrapperHelper::wrap($this->getInputContents($input), $width, $cutOptions, $break); $this->assertEquals($this->getOutputContents($output), $response); } @@ -75,29 +75,29 @@ public function dpWordwrap() return [ // Check empty - ['', 2, PrettyWordWrapper::CUT_ALL, $baseBreak, ''], - ['', 2, PrettyWordWrapper::CUT_ALL | PrettyWordWrapper::CUT_FILL_UP_MISSING, $baseBreak, ' '], - [$baseBreak, 2, PrettyWordWrapper::CUT_ALL, $baseBreak, $baseBreak], - [$baseBreak, 2, PrettyWordWrapper::CUT_ALL | PrettyWordWrapper::CUT_FILL_UP_MISSING, $baseBreak, ' '.$baseBreak.' '], + ['', 2, PrettyWordWrapperHelper::CUT_ALL, $baseBreak, ''], + ['', 2, PrettyWordWrapperHelper::CUT_ALL | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, ' '], + [$baseBreak, 2, PrettyWordWrapperHelper::CUT_ALL, $baseBreak, $baseBreak], + [$baseBreak, 2, PrettyWordWrapperHelper::CUT_ALL | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, ' '.$baseBreak.' '], // Check limit and UTF-8 [ 'öüóőúéáű', 8, - PrettyWordWrapper::CUT_LONG_WORDS, + PrettyWordWrapperHelper::CUT_LONG_WORDS, $baseBreak, 'öüóőúéáű', ], [ 'öüóőúéáű', 4, - PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, 'öüóő'.$baseBreak.'úéáű', ], [ 'öüóőúéáű', 6, - PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, 'öüóőúé'.$baseBreak.'áű ', ], @@ -105,28 +105,28 @@ public function dpWordwrap() [ 'öüóőúéáű', 8, - PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, 'öüóőúéáű', ], [ 'öüóőúéáű', 8, - PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, 'öüóőúéáű', ], [ 'foo bar baz', 3, - PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['foo', 'bar', 'baz']), ], [ 'foo bar baz', 2, - PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['fo', 'o ', 'ba', 'r ', 'ba', 'z ']), ], @@ -134,21 +134,21 @@ public function dpWordwrap() [ 'foo \bar\ baz', 3, - PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['foo', '\b', 'ar\\', ' ', 'baz']), ], [ 'foobarbaz foo', 3, - PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['foo', 'bar', 'baz', 'foo']), ], [ 'foobarbaz foo', 2, - PrettyWordWrapper::CUT_LONG_WORDS | PrettyWordWrapper::CUT_FILL_UP_MISSING, + PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['fo', 'ob', 'ar', 'ba', 'z ', 'fo', 'o ']), ], @@ -156,7 +156,7 @@ public function dpWordwrap() [ 'lipsum.txt', 120, - PrettyWordWrapper::CUT_LONG_WORDS, + PrettyWordWrapperHelper::CUT_LONG_WORDS, $baseBreak, 'lipsum.txt', ], @@ -164,7 +164,7 @@ public function dpWordwrap() [ 'lipsum_with_tags.txt', 120, - PrettyWordWrapper::CUT_LONG_WORDS, + PrettyWordWrapperHelper::CUT_LONG_WORDS, $baseBreak, 'lipsum_with_tags.txt', ], @@ -172,7 +172,7 @@ public function dpWordwrap() [ 'lipsum_with_tags_and_custom_break.txt', 120, - PrettyWordWrapper::CUT_LONG_WORDS, + PrettyWordWrapperHelper::CUT_LONG_WORDS, $customBreak, 'lipsum_with_tags_and_custom_break.txt', ], @@ -180,21 +180,21 @@ public function dpWordwrap() [ 'with_long_words.txt', 30, - PrettyWordWrapper::CUT_LONG_WORDS, + PrettyWordWrapperHelper::CUT_LONG_WORDS, $baseBreak, 'with_long_words_with_default_cut.txt', ], [ 'with_long_words.txt', 30, - PrettyWordWrapper::CUT_DISABLE, + PrettyWordWrapperHelper::CUT_DISABLE, $baseBreak, 'with_long_words_without_cut.txt', ], [ 'with_long_words.txt', 30, - PrettyWordWrapper::CUT_ALL, + PrettyWordWrapperHelper::CUT_ALL, $baseBreak, 'with_long_words_with_cut_all.txt', ], diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index 019c64be75e17..ef4d9919488ac 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -13,7 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Helper\PrettyWordWrapper; +use Symfony\Component\Console\Helper\PrettyWordWrapperHelper; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Helper\TableSeparator; @@ -1058,7 +1058,7 @@ public function testColumnMaxWidths() ->setRows([ ['Divine Comedy', 'A Tale of Two Cities', 'The Lord of the Rings', 'And Then There Were None'], ]) - ->setColumnMaxWidth(1, 5, PrettyWordWrapper::CUT_ALL) + ->setColumnMaxWidth(1, 5, PrettyWordWrapperHelper::CUT_ALL) ->setColumnMaxWidth(2, 10) ->setColumnMaxWidth(3, 15); From 90582f412a040eb0ed5fec4f9c95587068365992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Tue, 19 Mar 2019 16:59:05 +0100 Subject: [PATCH 15/17] Console: CS fix --- src/Symfony/Component/Console/Helper/Table.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index dba0b86fb3f54..acda228fe0def 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -264,7 +264,7 @@ public function setColumnWordWrapCutOption(int $columnIndex, int $cutOptions): s */ public function getColumnWordWrapCutOption(int $columnIndex): int { - if (!array_key_exists($columnIndex, $this->columnWordWrapCutOption) + if (!\array_key_exists($columnIndex, $this->columnWordWrapCutOption) || null === $this->columnWordWrapCutOption[$columnIndex] ) { return $this->defaultColumnWordWrapCutOption; @@ -286,8 +286,6 @@ public function setDefaultColumnWordWrapCutOption(int $defaultColumnWordWrapCutO } /** - * - * * @param array $columnWordWrapCutOptions * * @return $this From e669dd14cfea1c982a32f0bb3244eb9faff747c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Fri, 22 Mar 2019 12:33:22 +0100 Subject: [PATCH 16/17] Console: Rename WordWrapperHelper --- src/Symfony/Component/Console/CHANGELOG.md | 2 +- .../Console/Formatter/OutputFormatter.php | 8 +-- .../Component/Console/Helper/Table.php | 2 +- ...rapperHelper.php => WordWrapperHelper.php} | 16 +++--- .../Component/Console/Style/SymfonyStyle.php | 6 +-- .../Console/Tests/Helper/TableTest.php | 4 +- ...pperTest.php => WordWrapperHelperTest.php} | 52 +++++++++---------- 7 files changed, 45 insertions(+), 45 deletions(-) rename src/Symfony/Component/Console/Helper/{PrettyWordWrapperHelper.php => WordWrapperHelper.php} (97%) rename src/Symfony/Component/Console/Tests/Helper/{PrettyWordWrapperTest.php => WordWrapperHelperTest.php} (71%) diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index c04853d5bdeb8..89fb893ed7404 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -1,7 +1,7 @@ CHANGELOG ========= - * Refactor word wrapping with PrettyWordWrapping + * Refactor word wrapping with WordWrapperHelper 4.2.0 ----- diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index af8d9eac878a3..f6519a1fcf544 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -13,7 +13,7 @@ use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\PrettyWordWrapperHelper; +use Symfony\Component\Console\Helper\WordWrapperHelper; /** * Formatter class for console output. @@ -27,7 +27,7 @@ class OutputFormatter implements WrappableOutputFormatterInterface private $decorated; private $styles = []; private $styleStack; - private $defaultWrapCutOption = PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING; + private $defaultWrapCutOption = WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING; /** * Escapes "<" special char in given text. @@ -143,7 +143,7 @@ public function getDefaultWrapCutOption(): int * * @return $this * - * @see PrettyWordWrapperHelper + * @see WordWrapperHelper */ public function setDefaultWrapCutOption(int $defaultWrapCutOption) { @@ -214,7 +214,7 @@ public function formatAndWrap(string $message, int $width) */ public function wordwrap(string $message, int $width, int $cutOption = null): string { - return PrettyWordWrapperHelper::wrap($message, $width, null === $cutOption ? $this->defaultWrapCutOption : $cutOption); + return WordWrapperHelper::wrap($message, $width, null === $cutOption ? $this->defaultWrapCutOption : $cutOption); } /** diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index acda228fe0def..d22c5672871f6 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -83,7 +83,7 @@ class Table private $columnWidths = []; private $columnMaxWidths = []; private $columnWordWrapCutOption = []; - private $defaultColumnWordWrapCutOption = PrettyWordWrapperHelper::CUT_LONG_WORDS; + private $defaultColumnWordWrapCutOption = WordWrapperHelper::CUT_LONG_WORDS; private static $styles; diff --git a/src/Symfony/Component/Console/Helper/PrettyWordWrapperHelper.php b/src/Symfony/Component/Console/Helper/WordWrapperHelper.php similarity index 97% rename from src/Symfony/Component/Console/Helper/PrettyWordWrapperHelper.php rename to src/Symfony/Component/Console/Helper/WordWrapperHelper.php index e9d773240d531..f115e67685c52 100644 --- a/src/Symfony/Component/Console/Helper/PrettyWordWrapperHelper.php +++ b/src/Symfony/Component/Console/Helper/WordWrapperHelper.php @@ -26,19 +26,19 @@ * * $message = "This is a comment message with info ..."; * // Default: - * $output->writeln(PrettyWordWrapper::wrap($message, 120); + * $output->writeln(WordWrapperHelper::wrap($message, 120); * // Use custom settings: - * $output->writeln(PrettyWordWrapper::wrap( + * $output->writeln(WordWrapperHelper::wrap( * $message, * 20, - * PrettyWordWrapper::CUT_ALL | PrettyWordWrap::CUT_FILL_UP_MISSING, + * WordWrapperHelper::CUT_ALL | WordWrapperHelper::CUT_FILL_UP_MISSING, * PHP_EOL * ); * * * Known problems, limitations: - * - You can't call PrettyWordWrapper::wrap() inside a "running wrap" because there are "cache" properties and - * it causes problems within a Singleton class. Solution: you can create a PrettyWordWrapper object, and + * - You can't call WordWrapperHelper::wrap() inside a "running wrap" because there are "cache" properties and + * it causes problems within a Singleton class. Solution: you can create a WordWrapperHelper object, and * use the $wrapper->wordwrap() non-static method. * - If you use escaped tags AND (the line width is too short OR you use the CUT_WORDS option): `\Message\`, * the wrapper could wrap inside the tag: @@ -56,7 +56,7 @@ * * @author Krisztián Ferenczi */ -class PrettyWordWrapperHelper extends Helper +class WordWrapperHelper extends Helper { // Defaults /** @var int */ @@ -133,7 +133,7 @@ class PrettyWordWrapperHelper extends Helper /** * "Singleton.", but it isn't forbidden to create new objects, if you want. * - * @return PrettyWordWrapperHelper + * @return WordWrapperHelper */ protected static function getInstance(): self { @@ -151,7 +151,7 @@ protected static function getInstance(): self */ public function getName() { - return 'prettywordwrapper'; + return 'WordWrapperHelper'; } /** diff --git a/src/Symfony/Component/Console/Style/SymfonyStyle.php b/src/Symfony/Component/Console/Style/SymfonyStyle.php index 3eb9f0d533c9f..94d3b8e615d20 100644 --- a/src/Symfony/Component/Console/Style/SymfonyStyle.php +++ b/src/Symfony/Component/Console/Style/SymfonyStyle.php @@ -14,7 +14,7 @@ use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\PrettyWordWrapperHelper; +use Symfony\Component\Console\Helper\WordWrapperHelper; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Helper\Table; @@ -407,10 +407,10 @@ private function createBlock(iterable $messages, string $type = null, string $st $message = OutputFormatter::escape($message); } - $lines = array_merge($lines, explode(PHP_EOL, PrettyWordWrapperHelper::wrap( + $lines = array_merge($lines, explode(PHP_EOL, WordWrapperHelper::wrap( $message, $this->lineLength - $prefixLength - $indentLength, - PrettyWordWrapperHelper::CUT_LONG_WORDS, + WordWrapperHelper::CUT_LONG_WORDS, PHP_EOL ))); diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index ef4d9919488ac..9105243f5a7b4 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -13,7 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Helper\PrettyWordWrapperHelper; +use Symfony\Component\Console\Helper\WordWrapperHelper; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Helper\TableSeparator; @@ -1058,7 +1058,7 @@ public function testColumnMaxWidths() ->setRows([ ['Divine Comedy', 'A Tale of Two Cities', 'The Lord of the Rings', 'And Then There Were None'], ]) - ->setColumnMaxWidth(1, 5, PrettyWordWrapperHelper::CUT_ALL) + ->setColumnMaxWidth(1, 5, WordWrapperHelper::CUT_ALL) ->setColumnMaxWidth(2, 10) ->setColumnMaxWidth(3, 15); diff --git a/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php b/src/Symfony/Component/Console/Tests/Helper/WordWrapperHelperTest.php similarity index 71% rename from src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php rename to src/Symfony/Component/Console/Tests/Helper/WordWrapperHelperTest.php index 325077cd6a7fb..da24f6908e906 100644 --- a/src/Symfony/Component/Console/Tests/Helper/PrettyWordWrapperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/WordWrapperHelperTest.php @@ -3,12 +3,12 @@ namespace Symfony\Component\Console\Tests\Helper; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\PrettyWordWrapperHelper; +use Symfony\Component\Console\Helper\WordWrapperHelper; /** * @author Krisztián Ferenczi */ -class PrettyWordWrapperTest extends TestCase +class WordWrapperHelperTest extends TestCase { /** * @param int $width @@ -18,9 +18,9 @@ class PrettyWordWrapperTest extends TestCase */ public function testConstructorExceptions($width, $break) { - $wordWrapper = new PrettyWordWrapperHelper(); + $wordWrapper = new WordWrapperHelper(); $this->expectException(\InvalidArgumentException::class); - $wordWrapper->wordwrap('test', $width, PrettyWordWrapperHelper::DEFAULT_CUT, $break); + $wordWrapper->wordwrap('test', $width, WordWrapperHelper::DEFAULT_CUT, $break); } public function dpTestConstructorExceptions() @@ -44,7 +44,7 @@ public function dpTestConstructorExceptions() */ public function testWordwrap($input, $width, $cutOptions, $break, $output) { - $wordWrapper = new PrettyWordWrapperHelper(); + $wordWrapper = new WordWrapperHelper(); $response = $wordWrapper->wordwrap($this->getInputContents($input), $width, $cutOptions, $break); $this->assertEquals($this->getOutputContents($output), $response); @@ -63,7 +63,7 @@ public function testWordwrap($input, $width, $cutOptions, $break, $output) */ public function testStaticWrap($input, $width, $cutOptions, $break, $output) { - $response = PrettyWordWrapperHelper::wrap($this->getInputContents($input), $width, $cutOptions, $break); + $response = WordWrapperHelper::wrap($this->getInputContents($input), $width, $cutOptions, $break); $this->assertEquals($this->getOutputContents($output), $response); } @@ -75,29 +75,29 @@ public function dpWordwrap() return [ // Check empty - ['', 2, PrettyWordWrapperHelper::CUT_ALL, $baseBreak, ''], - ['', 2, PrettyWordWrapperHelper::CUT_ALL | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, ' '], - [$baseBreak, 2, PrettyWordWrapperHelper::CUT_ALL, $baseBreak, $baseBreak], - [$baseBreak, 2, PrettyWordWrapperHelper::CUT_ALL | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, ' '.$baseBreak.' '], + ['', 2, WordWrapperHelper::CUT_ALL, $baseBreak, ''], + ['', 2, WordWrapperHelper::CUT_ALL | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, ' '], + [$baseBreak, 2, WordWrapperHelper::CUT_ALL, $baseBreak, $baseBreak], + [$baseBreak, 2, WordWrapperHelper::CUT_ALL | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, ' '.$baseBreak.' '], // Check limit and UTF-8 [ 'öüóőúéáű', 8, - PrettyWordWrapperHelper::CUT_LONG_WORDS, + WordWrapperHelper::CUT_LONG_WORDS, $baseBreak, 'öüóőúéáű', ], [ 'öüóőúéáű', 4, - PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, + WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, 'öüóő'.$baseBreak.'úéáű', ], [ 'öüóőúéáű', 6, - PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, + WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, 'öüóőúé'.$baseBreak.'áű ', ], @@ -105,28 +105,28 @@ public function dpWordwrap() [ 'öüóőúéáű', 8, - PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, + WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, 'öüóőúéáű', ], [ 'öüóőúéáű', 8, - PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, + WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, 'öüóőúéáű', ], [ 'foo bar baz', 3, - PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, + WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['foo', 'bar', 'baz']), ], [ 'foo bar baz', 2, - PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, + WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['fo', 'o ', 'ba', 'r ', 'ba', 'z ']), ], @@ -134,21 +134,21 @@ public function dpWordwrap() [ 'foo \bar\ baz', 3, - PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, + WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['foo', '\b', 'ar\\', ' ', 'baz']), ], [ 'foobarbaz foo', 3, - PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, + WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['foo', 'bar', 'baz', 'foo']), ], [ 'foobarbaz foo', 2, - PrettyWordWrapperHelper::CUT_LONG_WORDS | PrettyWordWrapperHelper::CUT_FILL_UP_MISSING, + WordWrapperHelper::CUT_LONG_WORDS | WordWrapperHelper::CUT_FILL_UP_MISSING, $baseBreak, implode($baseBreak, ['fo', 'ob', 'ar', 'ba', 'z ', 'fo', 'o ']), ], @@ -156,7 +156,7 @@ public function dpWordwrap() [ 'lipsum.txt', 120, - PrettyWordWrapperHelper::CUT_LONG_WORDS, + WordWrapperHelper::CUT_LONG_WORDS, $baseBreak, 'lipsum.txt', ], @@ -164,7 +164,7 @@ public function dpWordwrap() [ 'lipsum_with_tags.txt', 120, - PrettyWordWrapperHelper::CUT_LONG_WORDS, + WordWrapperHelper::CUT_LONG_WORDS, $baseBreak, 'lipsum_with_tags.txt', ], @@ -172,7 +172,7 @@ public function dpWordwrap() [ 'lipsum_with_tags_and_custom_break.txt', 120, - PrettyWordWrapperHelper::CUT_LONG_WORDS, + WordWrapperHelper::CUT_LONG_WORDS, $customBreak, 'lipsum_with_tags_and_custom_break.txt', ], @@ -180,21 +180,21 @@ public function dpWordwrap() [ 'with_long_words.txt', 30, - PrettyWordWrapperHelper::CUT_LONG_WORDS, + WordWrapperHelper::CUT_LONG_WORDS, $baseBreak, 'with_long_words_with_default_cut.txt', ], [ 'with_long_words.txt', 30, - PrettyWordWrapperHelper::CUT_DISABLE, + WordWrapperHelper::CUT_DISABLE, $baseBreak, 'with_long_words_without_cut.txt', ], [ 'with_long_words.txt', 30, - PrettyWordWrapperHelper::CUT_ALL, + WordWrapperHelper::CUT_ALL, $baseBreak, 'with_long_words_with_cut_all.txt', ], From 260b1d38b1d4430715c96c38a428f23394f189bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Ferenczi?= Date: Fri, 22 Mar 2019 12:37:20 +0100 Subject: [PATCH 17/17] CS fix --- src/Symfony/Component/Console/Style/SymfonyStyle.php | 2 +- src/Symfony/Component/Console/Tests/Helper/TableTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Style/SymfonyStyle.php b/src/Symfony/Component/Console/Style/SymfonyStyle.php index 94d3b8e615d20..1452e9c4d3086 100644 --- a/src/Symfony/Component/Console/Style/SymfonyStyle.php +++ b/src/Symfony/Component/Console/Style/SymfonyStyle.php @@ -14,10 +14,10 @@ use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\WordWrapperHelper; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\WordWrapperHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index 9105243f5a7b4..7cdba4757b1a3 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -13,11 +13,11 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Helper\WordWrapperHelper; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Helper\TableStyle; +use Symfony\Component\Console\Helper\WordWrapperHelper; use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\StreamOutput;