Skip to content

Commit dad9b25

Browse files
committed
feature #17761 [Console] Add non-auto column width functionality (akeeman)
This PR was squashed before being merged into the 3.1-dev branch (closes #17761). Discussion ---------- [Console] Add non-auto column width functionality | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | [#6296](symfony/symfony-docs#6296) Be able to fix a columns width in a console table (i.e. set a columns width beforehand). When a column's contents exceed the given column width, it will stretch. Very useful, for instance, when one wants to display multiple tables that are separated from each other, but still want to align their columns. Commits ------- 20c81b2 [Console] Add non-auto column width functionality
2 parents 200f109 + 2d1e5ce commit dad9b25

File tree

3 files changed

+114
-9
lines changed

3 files changed

+114
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
-----
66

77
* added truncate method to FormatterHelper
8+
* added setColumnWidth(s) method to Table
89

910
2.8.3
1011
-----

Helper/Table.php

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Table
4343
*
4444
* @var array
4545
*/
46-
private $columnWidths = array();
46+
private $effectiveColumnWidths = array();
4747

4848
/**
4949
* Number of columns cache.
@@ -67,6 +67,13 @@ class Table
6767
*/
6868
private $columnStyles = array();
6969

70+
/**
71+
* User set column widths.
72+
*
73+
* @var array
74+
*/
75+
private $columnWidths = array();
76+
7077
private static $styles;
7178

7279
public function __construct(OutputInterface $output)
@@ -186,6 +193,38 @@ public function getColumnStyle($columnIndex)
186193
return $this->getStyle();
187194
}
188195

196+
/**
197+
* Sets the minimum width of a column.
198+
*
199+
* @param int $columnIndex Column index
200+
* @param int $width Minimum column width in characters
201+
*
202+
* @return Table
203+
*/
204+
public function setColumnWidth($columnIndex, $width)
205+
{
206+
$this->columnWidths[intval($columnIndex)] = intval($width);
207+
208+
return $this;
209+
}
210+
211+
/**
212+
* Sets the minimum width of all columns.
213+
*
214+
* @param array $widths
215+
*
216+
* @return Table
217+
*/
218+
public function setColumnWidths(array $widths)
219+
{
220+
$this->columnWidths = array();
221+
foreach ($widths as $index => $width) {
222+
$this->setColumnWidth($index, $width);
223+
}
224+
225+
return $this;
226+
}
227+
189228
public function setHeaders(array $headers)
190229
{
191230
$headers = array_values($headers);
@@ -296,7 +335,7 @@ private function renderRowSeparator()
296335

297336
$markup = $this->style->getCrossingChar();
298337
for ($column = 0; $column < $count; ++$column) {
299-
$markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
338+
$markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->effectiveColumnWidths[$column]).$this->style->getCrossingChar();
300339
}
301340

302341
$this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
@@ -342,11 +381,11 @@ private function renderRow(array $row, $cellFormat)
342381
private function renderCell(array $row, $column, $cellFormat)
343382
{
344383
$cell = isset($row[$column]) ? $row[$column] : '';
345-
$width = $this->columnWidths[$column];
384+
$width = $this->effectiveColumnWidths[$column];
346385
if ($cell instanceof TableCell && $cell->getColspan() > 1) {
347386
// add the width of the following columns(numbers of colspan).
348387
foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
349-
$width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
388+
$width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn];
350389
}
351390
}
352391

@@ -572,7 +611,7 @@ private function calculateColumnsWidth($rows)
572611
$lengths[] = $this->getCellWidth($row, $column);
573612
}
574613

575-
$this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
614+
$this->effectiveColumnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
576615
}
577616
}
578617

@@ -596,26 +635,28 @@ private function getColumnSeparatorWidth()
596635
*/
597636
private function getCellWidth(array $row, $column)
598637
{
638+
$cellWidth = 0;
639+
599640
if (isset($row[$column])) {
600641
$cell = $row[$column];
601642
$cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
602643
if ($cell instanceof TableCell && $cell->getColspan() > 1) {
603644
// we assume that cell value will be across more than one column.
604645
$cellWidth = $cellWidth / $cell->getColspan();
605646
}
606-
607-
return $cellWidth;
608647
}
609648

610-
return 0;
649+
$columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0;
650+
651+
return max($cellWidth, $columnWidth);
611652
}
612653

613654
/**
614655
* Called after rendering to cleanup cache data.
615656
*/
616657
private function cleanup()
617658
{
618-
$this->columnWidths = array();
659+
$this->effectiveColumnWidths = array();
619660
$this->numberOfColumns = null;
620661
}
621662

Tests/Helper/TableTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,69 @@ public function testColumnStyle()
620620
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 |
621621
+---------------+----------------------+-----------------+--------+
622622
623+
TABLE;
624+
625+
$this->assertEquals($expected, $this->getOutputContent($output));
626+
}
627+
628+
public function testColumnWith()
629+
{
630+
$table = new Table($output = $this->getOutputStream());
631+
$table
632+
->setHeaders(array('ISBN', 'Title', 'Author', 'Price'))
633+
->setRows(array(
634+
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'),
635+
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'),
636+
))
637+
->setColumnWidth(0, 15)
638+
->setColumnWidth(3, 10);
639+
640+
$style = new TableStyle();
641+
$style->setPadType(STR_PAD_LEFT);
642+
$table->setColumnStyle(3, $style);
643+
644+
$table->render();
645+
646+
$expected =
647+
<<<TABLE
648+
+-----------------+----------------------+-----------------+------------+
649+
| ISBN | Title | Author | Price |
650+
+-----------------+----------------------+-----------------+------------+
651+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 |
652+
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 |
653+
+-----------------+----------------------+-----------------+------------+
654+
655+
TABLE;
656+
657+
$this->assertEquals($expected, $this->getOutputContent($output));
658+
}
659+
660+
public function testColumnWiths()
661+
{
662+
$table = new Table($output = $this->getOutputStream());
663+
$table
664+
->setHeaders(array('ISBN', 'Title', 'Author', 'Price'))
665+
->setRows(array(
666+
array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'),
667+
array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'),
668+
))
669+
->setColumnWidths(array(15, 0, -1, 10));
670+
671+
$style = new TableStyle();
672+
$style->setPadType(STR_PAD_LEFT);
673+
$table->setColumnStyle(3, $style);
674+
675+
$table->render();
676+
677+
$expected =
678+
<<<TABLE
679+
+-----------------+----------------------+-----------------+------------+
680+
| ISBN | Title | Author | Price |
681+
+-----------------+----------------------+-----------------+------------+
682+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 |
683+
| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 |
684+
+-----------------+----------------------+-----------------+------------+
685+
623686
TABLE;
624687

625688
$this->assertEquals($expected, $this->getOutputContent($output));

0 commit comments

Comments
 (0)