Skip to content

Commit

Permalink
Merge pull request #117 from dimtrovich/table-with-unicode-character
Browse files Browse the repository at this point in the history
Table with unicode character
  • Loading branch information
adhocore authored Nov 29, 2024
2 parents 2ca5a50 + fe273ac commit f96cc05
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 10 deletions.
28 changes: 28 additions & 0 deletions src/Helper/InflectsString.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
namespace Ahc\Cli\Helper;

use function lcfirst;
use function mb_strwidth;
use function mb_substr;
use function str_replace;
use function strlen;
use function substr;
use function trim;
use function ucwords;

Expand Down Expand Up @@ -47,4 +51,28 @@ public function toWords(string $string): string

return ucwords($words);
}

/**
* Return width of string
*/
public function strwidth(string $string): int
{
if (function_exists('mb_strwidth')) {
return mb_strwidth($string);
}

return strlen($string);
}

/**
* Get part of string
*/
public function substr(string $string, int $start, ?int $length = null): string
{
if (function_exists('mb_substr')) {
return mb_substr($string, $start, $length);
}

return substr($string, $start, $length);
}
}
25 changes: 17 additions & 8 deletions src/Output/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@
use function max;
use function reset;
use function sprintf;
use function str_pad;
use function str_repeat;
use function strlen;
use function trim;

use const PHP_EOL;
Expand All @@ -51,7 +49,7 @@ public function render(array $rows, array $styles = []): string
$pos = 0;
foreach ($head as $col => $size) {
$dash[] = str_repeat('-', $size + 2);
$title[] = str_pad($this->toWords($col), $size, ' ');
$title[] = $this->strPad($this->toWords($col), $size, ' ');
$positions[$col] = ++$pos;
}

Expand All @@ -62,7 +60,6 @@ public function render(array $rows, array $styles = []): string
$parts = [];
$line++;

[$start, $end] = $styles[['even', 'odd'][(int) $odd]];
foreach ($head as $col => $size) {
$colNumber = $positions[$col];

Expand All @@ -85,10 +82,10 @@ public function render(array $rows, array $styles = []): string
$word = str_replace($matches[1], '', $text);
$word = preg_replace('/\\x1b\[0m/', '', $word);

$size += strlen($text) - strlen($word);
$size += $this->strwidth($text) - $this->strwidth($word);
}

$parts[] = "$start " . str_pad($text, $size, ' ') . " $end";
$parts[] = "$start " . $this->strPad($text, $size, ' ') . " $end";
}

$odd = !$odd;
Expand Down Expand Up @@ -132,8 +129,8 @@ protected function normalize(array $rows): array
return $col;
}, $cols);

$span = array_map('strlen', $cols);
$span[] = strlen($col);
$span = array_map([$this, 'strwidth'], $cols);
$span[] = $this->strwidth($col);
$value = max($span);
}

Expand Down Expand Up @@ -177,4 +174,16 @@ protected function parseStyle(array|callable $style, $val, array $row, array $ta

return ['', ''];
}

/**
* Pad a multibyte string to a certain length with another multibyte string
*/
protected function strPad(string $string, int $length, string $pad_string = ' '): string
{
if (1 > $paddingRequired = $length - $this->strwidth($string)) {
return $string;
}

return $string . $this->substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired);
}
}
6 changes: 4 additions & 2 deletions src/Output/Writer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Ahc\Cli\Output;

use Ahc\Cli\Helper\InflectsString;
use Ahc\Cli\Helper\Terminal;

use function fopen;
Expand All @@ -19,7 +20,6 @@
use function method_exists;
use function str_repeat;
use function stripos;
use function strlen;
use function strpos;
use function ucfirst;

Expand Down Expand Up @@ -190,6 +190,8 @@
*/
class Writer
{
use InflectsString;

/** @var resource Output file handle */
protected $stream;

Expand Down Expand Up @@ -339,7 +341,7 @@ public function justify(string $first, ?string $second = null, array $options =

$second = (string) $second;
$terminalWidth = $this->terminal->width() ?? 80;
$dashWidth = $terminalWidth - (strlen($first) + strlen($second));
$dashWidth = $terminalWidth - ($this->strwidth($first) + $this->strwidth($second));
// remove left and right margins because we're going to add 1 space on each side (after/before the text).
// if we don't have a second element, we just remove the left margin
$dashWidth -= $second === '' ? 1 : 2;
Expand Down
26 changes: 26 additions & 0 deletions tests/Output/TableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -639,4 +639,30 @@ public function test_render_with_html_like_tags_in_cell_content(): void

$this->assertSame($expectedOutput, trim($result));
}

public function test_render_with_unicode_characters_in_cell_content(): void
{
if (! extension_loaded('mbstring')) {
$this->markTestSkipped('The mbstring extension is not installed. This test will faill without it');
}

$rows = [
['name' => 'François', 'greeting' => 'Bonjour'],
['name' => 'Jürgen', 'greeting' => 'Guten Tag'],
['name' => '北京', 'greeting' => '你好']
];

$expectedOutput =
"+----------+-----------+" . PHP_EOL .
"| Name | Greeting |" . PHP_EOL .
"+----------+-----------+" . PHP_EOL .
"| François | Bonjour |" . PHP_EOL .
"| Jürgen | Guten Tag |" . PHP_EOL .
"| 北京 | 你好 |" . PHP_EOL .
"+----------+-----------+";

$result = $this->table->render($rows);

$this->assertSame($expectedOutput, trim($result));
}
}

0 comments on commit f96cc05

Please sign in to comment.