Skip to content

Commit f4f7184

Browse files
committed
[Console] Fix linewraps in OutputFormatter
1 parent b504a3d commit f4f7184

File tree

3 files changed

+57
-43
lines changed

3 files changed

+57
-43
lines changed

Diff for: Formatter/OutputFormatter.php

+10-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use Symfony\Component\Console\Exception\InvalidArgumentException;
1515

16+
use function Symfony\Component\String\b;
17+
1618
/**
1719
* Formatter class for console output.
1820
*
@@ -258,7 +260,7 @@ private function applyCurrentStyle(string $text, string $current, int $width, in
258260
}
259261

260262
preg_match('~(\\n)$~', $text, $matches);
261-
$text = $prefix.preg_replace('~([^\\n]{'.$width.'})\\ *~', "\$1\n", $text);
263+
$text = $prefix.$this->addLineBreaks($text, $width);
262264
$text = rtrim($text, "\n").($matches[1] ?? '');
263265

264266
if (!$currentLineLength && '' !== $current && "\n" !== substr($current, -1)) {
@@ -282,4 +284,11 @@ private function applyCurrentStyle(string $text, string $current, int $width, in
282284

283285
return implode("\n", $lines);
284286
}
287+
288+
private function addLineBreaks(string $text, int $width): string
289+
{
290+
$encoding = mb_detect_encoding($text, null, true) ?: 'UTF-8';
291+
292+
return b($text)->toCodePointString($encoding)->wordwrap($width, "\n", true)->toByteString($encoding);
293+
}
285294
}

Diff for: Tests/Formatter/OutputFormatterTest.php

+8-6
Original file line numberDiff line numberDiff line change
@@ -367,21 +367,23 @@ public function testFormatAndWrap()
367367
$formatter = new OutputFormatter(true);
368368

369369
$this->assertSame("fo\no\e[37;41mb\e[39;49m\n\e[37;41mar\e[39;49m\nba\nz", $formatter->formatAndWrap('foo<error>bar</error> baz', 2));
370-
$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 <error>foo bar baz</error> post', 2));
370+
$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 <error>foo bar baz</error> post', 2));
371371
$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 <error>foo bar baz</error> post', 3));
372-
$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 <error>foo bar baz</error> post', 4));
373-
$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 <error>foo bar baz</error> post', 5));
372+
$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 <error>foo bar baz</error> post', 4));
373+
$this->assertSame("pre \e[37;41mf\e[39;49m\n\e[37;41moo\e[39;49m\n\e[37;41mbar\e[39;49m\n\e[37;41mbaz\e[39;49m p\nost", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 5));
374374
$this->assertSame("Lore\nm \e[37;41mip\e[39;49m\n\e[37;41msum\e[39;49m \ndolo\nr \e[32msi\e[39m\n\e[32mt\e[39m am\net", $formatter->formatAndWrap('Lorem <error>ipsum</error> dolor <info>sit</info> amet', 4));
375375
$this->assertSame("Lorem \e[37;41mip\e[39;49m\n\e[37;41msum\e[39;49m dolo\nr \e[32msit\e[39m am\net", $formatter->formatAndWrap('Lorem <error>ipsum</error> dolor <info>sit</info> amet', 8));
376376
$this->assertSame("Lorem \e[37;41mipsum\e[39;49m dolor \e[32m\e[39m\n\e[32msit\e[39m, \e[37;41mamet\e[39;49m et \e[32mlauda\e[39m\n\e[32mntium\e[39m architecto", $formatter->formatAndWrap('Lorem <error>ipsum</error> dolor <info>sit</info>, <error>amet</error> et <info>laudantium</info> architecto', 18));
377377

378378
$formatter = new OutputFormatter();
379379

380380
$this->assertSame("fo\nob\nar\nba\nz", $formatter->formatAndWrap('foo<error>bar</error> baz', 2));
381-
$this->assertSame("pr\ne \nfo\no \nba\nr \nba\nz \npo\nst", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 2));
381+
$this->assertSame("pr\ne \nfo\no\nba\nr\nba\nz \npo\nst", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 2));
382382
$this->assertSame("pre\nfoo\nbar\nbaz\npos\nt", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 3));
383-
$this->assertSame("pre \nfoo \nbar \nbaz \npost", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 4));
384-
$this->assertSame("pre f\noo ba\nr baz\npost", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 5));
383+
$this->assertSame("pre \nfoo\nbar\nbaz \npost", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 4));
384+
$this->assertSame("pre f\noo\nbar\nbaz p\nost", $formatter->formatAndWrap('pre <error>foo bar baz</error> post', 5));
385+
$this->assertSame("Â rèälly\nlöng tîtlè\nthät cöüld\nnèêd\nmúltîplê\nlínès", $formatter->formatAndWrap('Â rèälly löng tîtlè thät cöüld nèêd múltîplê línès', 10));
386+
$this->assertSame("Â rèälly\nlöng tîtlè\nthät cöüld\nnèêd\nmúltîplê\n línès", $formatter->formatAndWrap("Â rèälly löng tîtlè thät cöüld nèêd múltîplê\n línès", 10));
385387
$this->assertSame('', $formatter->formatAndWrap(null, 5));
386388
}
387389
}

Diff for: Tests/Helper/TableTest.php

+39-36
Original file line numberDiff line numberDiff line change
@@ -118,30 +118,30 @@ public static function renderProvider()
118118
['ISBN', 'Title', 'Author'],
119119
$books,
120120
'compact',
121-
<<<'TABLE'
122-
ISBN Title Author
123-
99921-58-10-7 Divine Comedy Dante Alighieri
124-
9971-5-0210-0 A Tale of Two Cities Charles Dickens
125-
960-425-059-0 The Lord of the Rings J. R. R. Tolkien
126-
80-902734-1-6 And Then There Were None Agatha Christie
127-
128-
TABLE
121+
implode("\n", [
122+
'ISBN Title Author ',
123+
'99921-58-10-7 Divine Comedy Dante Alighieri ',
124+
'9971-5-0210-0 A Tale of Two Cities Charles Dickens ',
125+
'960-425-059-0 The Lord of the Rings J. R. R. Tolkien ',
126+
'80-902734-1-6 And Then There Were None Agatha Christie ',
127+
'',
128+
]),
129129
],
130130
[
131131
['ISBN', 'Title', 'Author'],
132132
$books,
133133
'borderless',
134-
<<<'TABLE'
135-
=============== ========================== ==================
136-
ISBN Title Author
137-
=============== ========================== ==================
138-
99921-58-10-7 Divine Comedy Dante Alighieri
139-
9971-5-0210-0 A Tale of Two Cities Charles Dickens
140-
960-425-059-0 The Lord of the Rings J. R. R. Tolkien
141-
80-902734-1-6 And Then There Were None Agatha Christie
142-
=============== ========================== ==================
143-
144-
TABLE
134+
implode("\n", [
135+
' =============== ========================== ================== ',
136+
' ISBN Title Author ',
137+
' =============== ========================== ================== ',
138+
' 99921-58-10-7 Divine Comedy Dante Alighieri ',
139+
' 9971-5-0210-0 A Tale of Two Cities Charles Dickens ',
140+
' 960-425-059-0 The Lord of the Rings J. R. R. Tolkien ',
141+
' 80-902734-1-6 And Then There Were None Agatha Christie ',
142+
' =============== ========================== ================== ',
143+
'',
144+
]),
145145
],
146146
[
147147
['ISBN', 'Title', 'Author'],
@@ -1378,12 +1378,14 @@ public function testColumnMaxWidths()
13781378

13791379
$expected =
13801380
<<<TABLE
1381-
+---------------+-------+------------+-----------------+
1382-
| Divine Comedy | A Tal | The Lord o | And Then There |
1383-
| | e of | f the Ring | Were None |
1384-
| | Two C | s | |
1385-
| | ities | | |
1386-
+---------------+-------+------------+-----------------+
1381+
+---------------+-------+----------+----------------+
1382+
| Divine Comedy | A | The Lord | And Then There |
1383+
| | Tale | of the | Were None |
1384+
| | of | Rings | |
1385+
| | Two | | |
1386+
| | Citie | | |
1387+
| | s | | |
1388+
+---------------+-------+----------+----------------+
13871389
13881390
TABLE;
13891391

@@ -1416,8 +1418,8 @@ public function testColumnMaxWidthsHeaders()
14161418
| Publication | Very long header with a lot of |
14171419
| | information |
14181420
+-------------+--------------------------------+
1419-
| 1954 | The Lord of the Rings, by J.R. |
1420-
| | R. Tolkien |
1421+
| 1954 | The Lord of the Rings, by |
1422+
| | J.R.R. Tolkien |
14211423
+-------------+--------------------------------+
14221424
14231425
TABLE;
@@ -1577,22 +1579,22 @@ public function testWithColspanAndMaxWith()
15771579
| Lorem ipsum dolor sit amet, consectetur adipi |
15781580
| scing elit, sed do eiusmod tempor |
15791581
+-----------------+-----------------+-----------------+
1580-
| Lorem ipsum dolor sit amet, consectetur adipi |
1581-
| scing elit, sed do eiusmod tempor |
1582+
| Lorem ipsum dolor sit amet, consectetur |
1583+
| adipiscing elit, sed do eiusmod tempor |
15821584
+-----------------+-----------------+-----------------+
15831585
| Lorem ipsum dolor sit amet, co | hello world |
15841586
| nsectetur | |
15851587
+-----------------+-----------------+-----------------+
15861588
| hello world | Lorem ipsum dolor sit amet, co |
15871589
| | nsectetur adipiscing elit |
15881590
+-----------------+-----------------+-----------------+
1589-
| hello | world | Lorem ipsum dol |
1590-
| | | or sit amet, co |
1591-
| | | nsectetur |
1591+
| hello | world | Lorem ipsum |
1592+
| | | dolor sit amet, |
1593+
| | | consectetur |
15921594
+-----------------+-----------------+-----------------+
15931595
| Symfony | Test | Lorem ipsum dol |
1594-
| | | or sit amet, co |
1595-
| | | nsectetur |
1596+
| | | or sit amet, |
1597+
| | | consectetur |
15961598
+-----------------+-----------------+-----------------+
15971599
15981600
TABLE;
@@ -1614,8 +1616,9 @@ public function testWithHyperlinkAndMaxWidth()
16141616
$expected =
16151617
<<<TABLE
16161618
+----------------------+
1617-
| \033]8;;Lorem\033\\Lorem ipsum dolor si\033]8;;\033\\ |
1618-
| \033]8;;Lorem\033\\t amet, consectetur \033]8;;\033\\ |
1619+
| \033]8;;Lorem\033\\Lorem ipsum dolor\033]8;;\033\\ |
1620+
| \033]8;;Lorem\033\\sit amet,\033]8;;\033\\ |
1621+
| \033]8;;Lorem\033\\consectetur\033]8;;\033\\ |
16191622
| \033]8;;Lorem\033\\adipiscing elit, sed\033]8;;\033\\ |
16201623
| \033]8;;Lorem\033\\do eiusmod tempor\033]8;;\033\\ |
16211624
+----------------------+

0 commit comments

Comments
 (0)