2 namespace Consolidation\OutputFormatters\Transformations\Wrap;
4 use Symfony\Component\Console\Helper\TableStyle;
7 * Calculate column widths for table cells.
9 * Influenced by Drush and webmozart/console.
13 public function __construct()
18 * Given the total amount of available space, and the width of
19 * the columns to place, calculate the optimum column widths to use.
21 public function calculate($availableWidth, ColumnWidths $dataWidths, ColumnWidths $minimumWidths)
23 // First, check to see if all columns will fit at their full widths.
24 // If so, do no further calculations. (This may be redundant with
25 // the short column width calculation.)
26 if ($dataWidths->totalWidth() <= $availableWidth) {
27 return $dataWidths->enforceMinimums($minimumWidths);
30 // Get the short columns first. If there are none, then distribute all
31 // of the available width among the remaining columns.
32 $shortColWidths = $this->getShortColumns($availableWidth, $dataWidths, $minimumWidths);
33 if ($shortColWidths->isEmpty()) {
34 return $this->distributeLongColumns($availableWidth, $dataWidths, $minimumWidths);
37 // If some short columns were removed, then account for the length
38 // of the removed columns and make a recursive call (since the average
39 // width may be higher now, if the removed columns were shorter in
40 // length than the previous average).
41 $availableWidth -= $shortColWidths->totalWidth();
42 $remainingWidths = $dataWidths->removeColumns($shortColWidths->keys());
43 $remainingColWidths = $this->calculate($availableWidth, $remainingWidths, $minimumWidths);
45 return $shortColWidths->combine($remainingColWidths);
49 * Calculate the longest cell data from any row of each of the cells.
51 public function calculateLongestCell($rows)
53 return $this->calculateColumnWidths(
62 * Calculate the longest word and longest line in the provided data.
64 public function calculateLongestWord($rows)
66 return $this->calculateColumnWidths(
69 return static::longestWordLength($cell);
74 protected function calculateColumnWidths($rows, callable $fn)
78 // Examine each row and find the longest line length and longest
79 // word in each column.
80 foreach ($rows as $rowkey => $row) {
81 foreach ($row as $colkey => $cell) {
83 if ((!isset($widths[$colkey]) || ($widths[$colkey] < $value))) {
84 $widths[$colkey] = $value;
89 return new ColumnWidths($widths);
93 * Return all of the columns whose longest line length is less than or
94 * equal to the average width.
96 public function getShortColumns($availableWidth, ColumnWidths $dataWidths, ColumnWidths $minimumWidths)
98 $averageWidth = $dataWidths->averageWidth($availableWidth);
99 $shortColWidths = $dataWidths->findShortColumns($averageWidth);
100 return $shortColWidths->enforceMinimums($minimumWidths);
104 * Distribute the remainig space among the columns that were not
105 * included in the list of "short" columns.
107 public function distributeLongColumns($availableWidth, ColumnWidths $dataWidths, ColumnWidths $minimumWidths)
109 // First distribute the remainder without regard to the minimum widths.
110 $result = $dataWidths->distribute($availableWidth);
112 // Find columns that are shorter than their minimum width.
113 $undersized = $result->findUndersizedColumns($minimumWidths);
115 // Nothing too small? Great, we're done!
116 if ($undersized->isEmpty()) {
120 // Take out the columns that are too small and redistribute the rest.
121 $availableWidth -= $undersized->totalWidth();
122 $remaining = $dataWidths->removeColumns($undersized->keys());
123 $distributeRemaining = $this->distributeLongColumns($availableWidth, $remaining, $minimumWidths);
125 return $undersized->combine($distributeRemaining);
129 * Return the length of the longest word in the string.
133 protected static function longestWordLength($str)
135 $words = preg_split('#[ /-]#', $str);
136 $lengths = array_map(function ($s) {
139 return max($lengths);