Skip to content

Commit

Permalink
Added table formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardoboss committed Apr 12, 2022
1 parent 93a1c9e commit 2e1d372
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 1 deletion.
Binary file modified screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
105 changes: 105 additions & 0 deletions src/Console.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,111 @@ public static function emergency(string $message, ...$args): void
self::writeln("[EGY] " . vsprintf($message, $args), null, 'red', ['bold', 'underscore'], true);
}

/**
* @param iterable<int, array<string, scalar>> $data
* @return iterable<int, string>
*/
public static function table(iterable $data, bool $ascii = false, bool $compact = false, string $borderColor = 'gray'): iterable
{
if (!is_array($data)) {
$rows = [];
foreach ($data as $row) {
$rows[] = $row;
}
} else {
$rows = $data;
}

$columns = array_reduce($rows, static function (array $carry, array $row): array {
foreach ($row as $key => $value) {
if (!isset($carry[$key])) {
$carry[$key] = [];
}

$carry[$key][] = $value;
}

return $carry;
}, []);

$columnWidths = array_map(static function (array $column): int {
return max(array_map('strlen', $column));
}, $columns);

$hsep = $ascii ? '-' : '';
$vsep = Console::$borderColor($ascii ? '|' : '');
$cross = $ascii ? '+' : '';

$headerHsep = $ascii ? '=' : '';
$headerCrossStart = $ascii ? '+' : '';
$headerCrossMid = $ascii ? '+' : '';
$headerCrossEnd = $ascii ? '+' : '';

$crossStart = $ascii ? '+' : '';
$crossEnd = $ascii ? '+' : '';
$crossStartTop = $ascii ? '+' : '';
$crossMidTop = $ascii ? '+' : '';
$crossEndTop = $ascii ? '+' : '';
$crossStartBottom = $ascii ? '+' : '';
$crossMidBottom = $ascii ? '+' : '';
$crossEndBottom = $ascii ? '+' : '';

$printSeparator = static function (bool $top = false, bool $bottom = false, bool $header = false) use (
$columnWidths, $borderColor,
$hsep, $cross,
$headerHsep, $headerCrossStart, $headerCrossMid, $headerCrossEnd,
$crossStart, $crossEnd, $crossStartTop, $crossMidTop, $crossEndTop, $crossStartBottom, $crossMidBottom, $crossEndBottom,
): string {
$crossStart = $top ? $crossStartTop : ($header ? $headerCrossStart : ($bottom ? $crossStartBottom : $crossStart));
$crossMid = $top ? $crossMidTop : ($header ? $headerCrossMid : ($bottom ? $crossMidBottom : $cross));
$crossEnd = $top ? $crossEndTop : ($header ? $headerCrossEnd : ($bottom ? $crossEndBottom : $crossEnd));

$line = $header ? $headerHsep : $hsep;

if (empty($columnWidths)) {
return $crossStart . $line . $crossEnd;
}

$first = true;

$output = '';
foreach ($columnWidths as $width) {
if ($first) {
$output .= $crossStart . str_repeat($line, $width + 2);
$first = false;
} else {
$output .= $crossMid . str_repeat($line, $width + 2);
}
}
return Console::$borderColor($output . $crossEnd);
};

$header = array_shift($rows);
yield $printSeparator(top: true);
$output = '';
foreach ($header as $key => $value) {
$output .= $vsep . ' ' . str_pad($value, $columnWidths[$key], ' ', STR_PAD_RIGHT) . ' ';
}
yield $output . $vsep;
yield $printSeparator(header: true);

$rowCount = count($rows);
foreach ($rows as $i => $row) {
$output = "";
foreach ($row as $key => $value) {
$output .= $vsep . ' ' . str_pad($value, $columnWidths[$key], ' ', STR_PAD_RIGHT) . ' ';
}
$output .= $vsep;

yield $output;
$lastLine = $i === $rowCount - 1;

if ($lastLine || !$compact) {
yield $printSeparator(bottom: $lastLine);
}
}
}

public static function writeln(
string $message,
?string $foreground = null,
Expand Down
9 changes: 8 additions & 1 deletion test.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,11 @@
Console::timestamps();
Console::notice("Call the methods with no format to restore the defaults.");

Console::warn("The streams get closed automatically when the runtime shuts down.");
Console::info("This is a table:");
foreach (Console::table([
['name', 'age', 'email'],
['John', '25', '[email protected]'],
['Jane', '24', '[email protected]'],
], compact: true, borderColor: 'yellow') as $line) {
Console::info($line);
}

0 comments on commit 2e1d372

Please sign in to comment.