Skip to content

Commit

Permalink
fix: support ansi chars
Browse files Browse the repository at this point in the history
  • Loading branch information
theus77 committed Sep 29, 2023
1 parent 741b73f commit b84ed9b
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 2 deletions.
65 changes: 64 additions & 1 deletion EMS/core-bundle/src/Command/JobOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,71 @@ public function doWrite(string $message, bool $newline): void
{
$job = $this->jobRepository->findById($this->jobId);
$job->setStatus($message);
$job->setOutput($job->getOutput().$this->getFormatter()->format($message).($newline ? PHP_EOL : ''));
$job->setOutput(self::concatenateAnsiString($job->getOutput() ?? '', $this->getFormatter()->format($message)).($newline ? PHP_EOL : ''));

Check failure on line 31 in EMS/core-bundle/src/Command/JobOutput.php

View workflow job for this annotation

GitHub Actions / PHPStan

Parameter #2 $right of static method EMS\CoreBundle\Command\JobOutput::concatenateAnsiString() expects string, string|null given.

$this->jobRepository->save($job);
}

public static function concatenateAnsiString(string $left, string $right): string
{
$pos = \strrpos($left, "\n");
if (false === $pos) {
$content = '';
$lastLine = $left;
} else {
$content = \substr($left, 0, $pos + 1);
$lastLine = \substr($left, $pos + 1);
}
$lines = \explode("\n", $right);
$first = true;
foreach ($lines as $line) {
if ($first) {
$first = false;
} else {
$content .= "\n";
}
$content .= self::concatenateAnsiLines($lastLine, $line);
}

return $content.$lastLine;
}

private static function concatenateAnsiLines(string &$lastLine, string $newLine): string
{
$newLine = preg_replace("/.\x08/", '', $newLine);
\preg_match_all("/\e\[(?P<backspace>[0-9]+)D/", $newLine, $matches, PREG_OFFSET_CAPTURE);

Check failure on line 63 in EMS/core-bundle/src/Command/JobOutput.php

View workflow job for this annotation

GitHub Actions / PHPStan

Parameter #2 $subject of function preg_match_all expects string, string|null given.
if (!empty($matches['backspace'])) {
$line = '';
$cursor = 0;
foreach ($matches['backspace'] as $backspace) {
$count = (int) $backspace[0];
$line .= \substr($newLine, $cursor, $backspace[1] - 2);

Check failure on line 69 in EMS/core-bundle/src/Command/JobOutput.php

View workflow job for this annotation

GitHub Actions / PHPStan

Parameter #1 $string of function substr expects string, string|null given.
$line = \substr($line, 0, strlen($line) - $count);
$cursor = $backspace[1] + strlen($backspace[0]) + 1;
}
$newLine = $line . \substr($newLine, $cursor);

Check failure on line 73 in EMS/core-bundle/src/Command/JobOutput.php

View workflow job for this annotation

GitHub Actions / PHPStan

Parameter #1 $string of function substr expects string, string|null given.
}

\preg_match_all("/\e\[(?P<column>[0-9]+)G/", $newLine, $matches, PREG_OFFSET_CAPTURE);

Check failure on line 76 in EMS/core-bundle/src/Command/JobOutput.php

View workflow job for this annotation

GitHub Actions / PHPStan

Parameter #2 $subject of function preg_match_all expects string, string|null given.
$cursor = 0;
foreach ($matches['column'] as $column) {
$lastLine .= substr($newLine, $cursor, $column[1] - 2);

Check failure on line 79 in EMS/core-bundle/src/Command/JobOutput.php

View workflow job for this annotation

GitHub Actions / PHPStan

Parameter #1 $string of function substr expects string, string|null given.
$position = (int) $column[0];
if ($position > \strlen($lastLine)) {
$lastLine = \str_pad($lastLine, $position - 1, ' ', STR_PAD_RIGHT);
} else {
$lastLine = \substr($lastLine, $cursor, $position - 1 );
}
$endOfLine = \substr($newLine, $column[1] + \strlen($column[0]) + 1);

Check failure on line 86 in EMS/core-bundle/src/Command/JobOutput.php

View workflow job for this annotation

GitHub Actions / PHPStan

Parameter #1 $string of function substr expects string, string|null given.
$cursor = $column[1] - 1;
}
if (!empty($matches['column'])) {
$newLine = $endOfLine;
}

$output = $lastLine;
$lastLine = $newLine;

return $output;
}
}
2 changes: 1 addition & 1 deletion EMS/core-bundle/src/Service/JobService.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public function start(Job $job): JobOutput
$this->repository->save($job);

$output = new JobOutput($this->repository, $job->getId());
$output->setDecorated(false);
$output->setDecorated(true);
$output->writeln('Job ready to be launch');

return $output;
Expand Down
39 changes: 39 additions & 0 deletions EMS/core-bundle/tests/Unit/Core/Command/JobOutputTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace EMS\CoreBundle\Tests\Unit\Core\Command;

use EMS\CoreBundle\Command\JobOutput;
use PHPUnit\Framework\TestCase;

class JobOutputTest extends TestCase
{
public function testSimpleConcatenation(): void
{
self::assertEquals("foobar", JobOutput::concatenateAnsiString('foo','bar'));
self::assertEquals("foo\nbar", JobOutput::concatenateAnsiString("foo\n",'bar'));
self::assertEquals("foo\n", JobOutput::concatenateAnsiString("foo\nbar","\e[1G"));
self::assertEquals("foo\n", JobOutput::concatenateAnsiString("foo\nbar","Toto\e[1G"));
self::assertEquals("foo\nb", JobOutput::concatenateAnsiString("foo\nbar","\e[2G"));
self::assertEquals("foo\nbar ", JobOutput::concatenateAnsiString("foo\nbar","\e[10G"));
self::assertEquals("foo\nYes", JobOutput::concatenateAnsiString("foo\nbar","Toto\e[1GNo\e[1GYes"));
self::assertEquals("couille", JobOutput::concatenateAnsiString("","coq\x08uille"));
self::assertEquals("couille", JobOutput::concatenateAnsiString("","coq\033[1Duille"));
self::assertEquals("cuille", JobOutput::concatenateAnsiString("","coq\033[2Duille"));
}

public function testProgressBar(): void
{
$output = '';
$rewind = "\e[1G";
$output = JobOutput::concatenateAnsiString($output,'[>-----------------]');
self::assertEquals('[>-----------------]', $output);
$output = JobOutput::concatenateAnsiString($output, $rewind);
$output = JobOutput::concatenateAnsiString($output,'[=>----------------]');
self::assertEquals('[=>----------------]', $output);
$output = JobOutput::concatenateAnsiString($output, $rewind);
$output = JobOutput::concatenateAnsiString($output,'[==>---------------]');
self::assertEquals('[==>---------------]', $output);
}
}

0 comments on commit b84ed9b

Please sign in to comment.