Skip to content

Commit

Permalink
Word wrap
Browse files Browse the repository at this point in the history
  • Loading branch information
inxilpro committed Apr 15, 2024
1 parent 21ee869 commit 53a242f
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 12 deletions.
3 changes: 2 additions & 1 deletion .idea/blade.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions src/AnsiChar.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

namespace Glhd\AnsiPants;

class AnsiChar
use Stringable;

class AnsiChar implements Stringable
{
public function __construct(
public string $value,
/** @var \Glhd\AnsiPants\Flag[] */
public array $flags,
public array $flags = [],
) {
}

Expand All @@ -20,4 +22,9 @@ public function hasFlag(Flag $flag): bool
{
return in_array($flag, $this->flags, true);
}

public function __toString(): string
{
return $this->value;
}
}
69 changes: 60 additions & 9 deletions src/AnsiString.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Glhd\AnsiPants;

use Generator;
use Glhd\AnsiPants\Support\Parsing\EscapeSequence;
use Glhd\AnsiPants\Support\Parsing\Text;
use Glhd\AnsiPants\Support\Parsing\Tokenizer;
Expand All @@ -18,8 +19,12 @@ public static function make(AnsiString|Collection|string $input): static
return new static($input);
}

public function __construct(AnsiString|Collection|string $input)
public function __construct(AnsiString|AnsiChar|Collection|string $input)
{
if ($input instanceof AnsiChar) {
$input = new Collection([$input]);
}

if ($input instanceof Collection) {
$input->ensure(AnsiChar::class);
$this->chars = clone $input;
Expand All @@ -35,18 +40,14 @@ public function withFlags(Flag ...$flags): static
return new static($this->chars->map(fn(AnsiChar $char) => $char->withFlags(...$flags)));
}

public function prepend(AnsiString|string $string): static
public function prepend(AnsiString|AnsiChar|string $string): static
{
$string = new AnsiString($string);

return new AnsiString($string->chars->merge($this->chars));
return new AnsiString(AnsiString::make($string)->chars->merge($this->chars));
}

public function append(AnsiString|string $string): static
public function append(AnsiString|AnsiChar|string $string): static
{
$string = new AnsiString($string);

return new AnsiString($this->chars->merge($string->chars));
return new AnsiString($this->chars->merge(AnsiString::make($string)->chars));
}

public function padLeft(int $length, AnsiString|string $pad = ' '): static
Expand Down Expand Up @@ -83,6 +84,34 @@ public function padBoth(int $length, AnsiString|string $pad = ' '): static
->append($right_padding);
}

public function wordwrap(int $width = 75, AnsiString|string $break = "\e[0m\n", bool $cut_long_words = false): static
{
$break = new AnsiString($break);
$buffer = new AnsiString('');
$wrapped = new AnsiString('');

foreach ($this->words() as $word) {
[$sep, $word] = $word;

if (($buffer->length() + $sep->length() + $word->length()) > $width) {
if ($wrapped->length()) {
$wrapped = $wrapped->append($break);
}

$wrapped = $wrapped->append($buffer);
$buffer = new AnsiString($word);
} else {
$buffer = $buffer->append($sep)->append($word);
}
}

if ($buffer->length() > 0) {
$wrapped = $wrapped->append($break)->append($buffer);
}

return $wrapped;
}

public function length(): int
{
return count($this->chars);
Expand Down Expand Up @@ -125,6 +154,28 @@ public function __toString(): string
return $result;
}

/** @return Generator<static[]> */
protected function words(): Generator
{
$sep = new static('');
$word = new static('');

foreach ($this->chars as $char) {
if ($word->length() > 0 && in_array($char->value, [' ', "\n"])) {
yield [$sep, $word];
$word = new static('');
$sep = new static($char);
continue;
}

$word->chars->push($char);
}

if ($word->length() > 0 || $sep->length() > 0) {
yield [$sep, $word];
}
}

/** @return \Glhd\AnsiPants\Flag[][] */
protected function diffFlags($a, $b): array
{
Expand Down
17 changes: 17 additions & 0 deletions tests/Unit/AnsiStringTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,21 @@ public function test_pad_both(): void

$this->assertEquals($expected, (string) $parsed->padBoth(15));
}

public function test_word_wrap(): void
{
$input = "The \e[1mquick\e[0m \e[33mbrown fox \e[3mjumps\e[0m over the lazy dog";

$expected = <<<EOF
The \e[1mquick\e[0m
\e[33mbrown fox\e[0m
\e[33m\e[3mjumps\e[0m over
the lazy
dog
EOF;

$parsed = new AnsiString($input);

$this->assertEquals($expected, (string) $parsed->wordwrap(10));
}
}

0 comments on commit 53a242f

Please sign in to comment.