8000 Add title table · symfony/symfony@706bab2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 706bab2

Browse files
committed
Add title table
1 parent 782ffe2 commit 706bab2

File tree

4 files changed

+121
-2
lines changed

4 files changed

+121
-2
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,18 @@ public static function substr($string, $from, $length = null)
7272
return mb_substr($string, $from, $length, $encoding);
7373
}
7474

75+
/**
76+
* Returns the text within a portion of a string, using mb_substr if it is available.
77+
*/
78+
public static function substr_replace(string $string, string $replacement, int $start, int $length = null): string
79+
{
80+
if (false === mb_detect_encoding($string, null, true)) {
81+
return substr_replace($string, $replacement, $start, $length);
82+
}
83+
84+
return mb_substr($string, 0, $start).$replacement.mb_substr($string, $start + $length);
85+
}
86+
7587
public static function formatTime($secs)
7688
{
7789
static $timeFormats = array(

src/Symfony/Component/Console/Helper/Table.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class Table
3434
private const BORDER_OUTSIDE = 0;
3535
private const BORDER_INSIDE = 1;
3636

37+
private $title;
38+
3739
/**
3840
* Table headers.
3941
*/
@@ -290,6 +292,13 @@ public function setRow($column, array $row)
290292
return $this;
291293
}
292294

295+
public function setTitle(?string $title): self
296+
{
297+
$this->title = $title;
298+
299+
return $this;
300+
}
301+
293302
/**
294303
* Renders table to output.
295304
*
@@ -331,9 +340,11 @@ public function render()
331340
}
332341

333342
if ($isHeader || $isFirstRow) {
334-
$this->renderRowSeparator($isFirstRow ? self::SEPARATOR_TOP_BOTTOM : self::SEPARATOR_TOP);
335343
if ($isFirstRow) {
344+
$this->renderRowSeparator(self::SEPARATOR_TOP_BOTTOM);
336345
$isFirstRow = false;
346+
} else {
347+
$this->renderRowSeparator(self::SEPARATOR_TOP, $this->title);
337348
}
338349
}
339350

@@ -350,7 +361,7 @@ public function render()
350361
*
351362
* Example: <code>+-----+-----------+-------+</code>
352363
*/
353-
private function renderRowSeparator(int $type = self::SEPARATOR_MID)
364+
private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null)
354365
{
355366
if (0 === $count = $this->numberOfColumns) {
356367
return;
@@ -378,6 +389,17 @@ private function renderRowSeparator(int $type = self::SEPARATOR_MID)
378389
$markup .= $column === $count - 1 ? $rightChar : $midChar 6D47 ;
379390
}
380391

392+
if (null !== $title) {
393+
$lenT = Helper::strlenWithoutDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($format = $this->style->getTitleFormat(), $title));
394+
$lenM = Helper::strlen($markup);
395+
if ($lenT > $limit = $lenM - 2) {
396+
$lenT = $limit;
397+
$lenF = Helper::strlenWithoutDecoration($formatter, sprintf($format, ''));
398+
$formattedTitle = sprintf($format, Helper::substr($title, 0, $lenM - $lenF - 5).'...');
399+
}
400+
$markup = Helper::substr_replace($markup, $formattedTitle, ($lenM - $lenT) / 2, $lenT);
401+
}
402+
381403
$this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
382404
}
383405

src/Symfony/Component/Console/Helper/TableStyle.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class TableStyle
4040
private $crossingTopLeftBottomChar = '+';
4141
private $crossingTopMidBottomChar = '+';
4242
private $crossingTopRightBottomChar = '+';
43+
private $titleFormat = '<fg=black;bg=white;options=bold> %s </>';
4344
private $cellHeaderFormat = '<info>%s</info>';
4445
private $cellRowFormat = '%s';
4546
private $cellRowContentFormat = ' %s ';
@@ -429,4 +430,16 @@ public function getPadType()
429430
{
430431
return $this->padType;
431432
}
433+
434+
public function getTitleFormat(): string
435+
{
436+
return $this->titleFormat;
437+
}
438+
439+
public function setTitleFormat(string $titleFormat): self
440+
{
441+
$this->titleFormat = $titleFormat;
442+
443+
return $this;
444+
}
432445
}

src/Symfony/Component/Console/Tests/Helper/TableTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,78 @@ public function testGetStyleDefinition()
974974
Table::getStyleDefinition('absent');
975975
}
976976

977+
/**
978+
* @dataProvider renderSetTitle
979+
*/
980+
public function testSetTitle($title, $style, $expected)
981+
{
982+
(new Table($output = $this->getOutputStream()))
983+
->setTitle($title)
984+
->setHeaders(array('ISBN', 'Title', 'Author'))
985+
->setRows(array(
986+
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
987+
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
988+
array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
989+
array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
990+
))
991+
->setStyle($style)
992+
->render()
993+
;
994+
995+
$this->assertEquals($expected, $this->getOutputContent($output));
996+
}
997+
998+
public function renderSetTitle()
999+
{
1000+
return array(
1001+
array(
1002+
'Books',
1003+
'default',
1004+
<<<'TABLE'
1005+
+---------------+----------- Books --------+------------------+
1006+
| ISBN | Title | Author |
1007+
+---------------+--------------------------+------------------+
1008+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
1009+
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
1010+
| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
1011+
| 80-902734-1-6 | And Then There Were None | Agatha Christie |
1012+
+---------------+--------------------------+------------------+
1013+
1014+
TABLE
1015+
),
1016+
array(
1017+
'Books',
1018+
'box',
1019+
<<<'TABLE'
1020+
┌───────────────┬─────────── Books ────────┬──────────────────┐
1021+
│ ISBN │ Title │ Author │
1022+
├───────────────┼──────────────────────────┼──────────────────┤
1023+
│ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri │
1024+
│ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens │
1025+
│ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien │
1026+
│ 80-902734-1-6 │ And Then There Were None │ Agatha Christie │
1027+
└───────────────┴──────────────────────────┴──────────────────┘
1028+
1029+
TABLE
1030+
),
1031+
array(
1032+
'Boooooooooooooooooooooooooooooooooooooooooooooooooooooooooks',
1033+
'default',
1034+
<<<'TABLE'
1035+
+ Booooooooooooooooooooooooooooooooooooooooooooooooooooooo... +
1036+
| ISBN | Title | Author |
1037+
+---------------+--------------------------+------------------+
1038+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
1039+
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
1040+
| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
1041+
| 80-902734-1-6 | And Then There Were None | Agatha Christie |
1042+
+---------------+--------------------------+------------------+
1043+
1044+
TABLE
1045+
),
1046+
);
1047+
}
1048+
9771049
protected function getOutputStream($decorated = false)
9781050
{
9791051
return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, $decorated);

0 commit comments

Comments
 (0)
0