Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/php.xml

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

20 changes: 20 additions & 0 deletions demo/null.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

use RobertWesner\AWDY\AWDY;
use RobertWesner\AWDY\Template\Templates\NullTemplate;

require __DIR__ . '/../vendor/autoload.php';

const LIMIT = 1337;
const PROGRESS_AFTER = 10;

AWDY::setUp(new NullTemplate());
AWDY::progress(0);
AWDY::echo('Scream into the void!', PHP_EOL);
AWDY::progress(0.5);
AWDY::echo('Pure silence.', PHP_EOL);
AWDY::progress(1);

echo 'Nothing ever happens around here.', PHP_EOL;
37 changes: 37 additions & 0 deletions demo/stderr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

use RobertWesner\AWDY\AWDY;
use RobertWesner\AWDY\Template\Templates\SimpleTemplate;

require __DIR__ . '/../vendor/autoload.php';

const LIMIT = 13370;
const PROGRESS_AFTER = 100;

AWDY::setUp(new SimpleTemplate(), output: STDERR);

// none of this should show up in stdout
$i = 0;
while (true) {
if ($i >= LIMIT) {
break;
}

usleep(rand(100, 500));

if (($i % 777) === 0) {
AWDY::printf('%d is your lucky number!' . PHP_EOL, $i);
}

$i++;

if ($i >= LIMIT || ($i % PROGRESS_AFTER) === 0) {
AWDY::progress($i / LIMIT, $i, LIMIT);
}
}

AWDY::clear();

echo "This should be greppable!";
6 changes: 5 additions & 1 deletion phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
<arg name="colors" />
<arg name="extensions" value="php"/>

<rule ref="PSR12" />
<rule ref="PSR12">
<exclude name="PSR2.Classes.ClassDeclaration.OpenBraceNewLine" />
<exclude name="Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine" />
<exclude name="Squiz.WhiteSpace.ScopeClosingBrace" />
</rule>
<rule ref="Generic.PHP.RequireStrictTypes"/>

<file>src/</file>
Expand Down
98 changes: 61 additions & 37 deletions src/AWDY.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,27 @@

final class AWDY
{
private static mixed $outputHandle;
private static ?int $fixedWidth = null;
private static ?int $fixedHeight = null;
private static int $previousWidth = 0;
private static int $previousHeight = 0;

private static TemplateInterface $template;

private static function getWidth(): int
{
return self::$fixedWidth ?? (int)exec('tput cols');
}

private static function getHeight(): int
{
return self::$fixedHeight ?? (int)exec('tput lines');
}

private static function render(): void
{
$width = self::getWidth();
$height = self::getHeight();

if ($width !== self::$previousWidth || $height !== self::$previousHeight) {
echo self::$template->getBorder()->getBuffer(self::getWidth(), self::getHeight());
echo AnsiEscape::moveToBeginning();

self::$previousWidth = $width;
self::$previousHeight = $height;

// mark all as dirty on resize so everything will be properly rendered again
array_map(fn (Area $area) => $area->dirty(), self::$template->getAreas());
}

foreach (self::$template->getAreas() as $area) {
$area->render($width, $height);
echo AnsiEscape::resetColor();
echo AnsiEscape::moveToBeginning();
}
}

public static function setUp(TemplateInterface $template, ?int $width = null, ?int $height = null): void
{
public static function setUp(
TemplateInterface $template,
?int $width = null,
?int $height = null,
mixed $output = null
): void {
self::$template = $template;
self::$fixedWidth = $width;
self::$fixedHeight = $height;
self::$outputHandle = $output;

echo AnsiEscape::clear();
echo AnsiEscape::moveToBeginning();
self::__out(AnsiEscape::clear());
self::__out(AnsiEscape::moveToBeginning());

self::render();
}
Expand All @@ -83,4 +56,55 @@ public static function progress(float $progress, int $current = 0, int $total =
self::$template->handleProgress($progress, $current, $total);
self::render();
}

public static function __out(string $text): void
{
if (self::$outputHandle === null) {
// deliberately not using STDOUT as default, since it does not work with ob_*()
echo $text;
} else {
fwrite(self::$outputHandle, $text);
}
}

/**
* If you so wish as to clear the screen after being done.
*/
public static function clear(): void
{
self::__out(AnsiEscape::clear());
}

private static function getWidth(): int
{
return self::$fixedWidth ?? (int)exec('tput cols');
}

private static function getHeight(): int
{
return self::$fixedHeight ?? (int)exec('tput lines');
}

private static function render(): void
{
$width = self::getWidth();
$height = self::getHeight();

if ($width !== self::$previousWidth || $height !== self::$previousHeight) {
self::__out((string)self::$template->getBorder()->getBuffer(self::getWidth(), self::getHeight()));
self::__out(AnsiEscape::moveToBeginning());

self::$previousWidth = $width;
self::$previousHeight = $height;

// mark all as dirty on resize so everything will be properly rendered again
array_map(fn (Area $area) => $area->dirty(), self::$template->getAreas());
}

foreach (self::$template->getAreas() as $area) {
$area->render($width, $height);
self::__out(AnsiEscape::resetColor());
self::__out(AnsiEscape::moveToBeginning());
}
}
}
3 changes: 2 additions & 1 deletion src/Template/Area.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace RobertWesner\AWDY\Template;

use RobertWesner\AWDY\AnsiEscape;
use RobertWesner\AWDY\AWDY;

class Area
{
Expand Down Expand Up @@ -56,7 +57,7 @@ public function render(int $screenWidth, int $screenHeight): void
}

foreach (explode(PHP_EOL, (string)$buffer) as $line) {
echo AnsiEscape::moveTo($x, $y), $line;
AWDY::__out(AnsiEscape::moveTo($x, $y) . $line);

$y++;
}
Expand Down
29 changes: 29 additions & 0 deletions src/Template/Templates/NullTemplate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace RobertWesner\AWDY\Template\Templates;

use RobertWesner\AWDY\Template\Border;
use RobertWesner\AWDY\Template\TemplateInterface;

/**
* Throws all logs into the void, never to be seen again.
*/
class NullTemplate implements TemplateInterface
{

public function getBorder(): Border
{
return Border::create();
}

public function getAreas(): array
{
return [];
}

public function handleEcho(string $echo): void {}

public function handleProgress(float $progress, int $current = 0, int $total = 0): void {}
}
2 changes: 2 additions & 0 deletions tests/Template/AreaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
use RobertWesner\AWDY\AnsiEscape;
use RobertWesner\AWDY\AWDY;
use RobertWesner\AWDY\Template\Area;
use RobertWesner\AWDY\Template\Buffer;
use RobertWesner\AWDY\Tests\BaseTestCase;

#[CoversClass(Area::class)]
#[UsesClass(Buffer::class)]
#[UsesClass(AWDY::class)]
final class AreaTest extends BaseTestCase
{
private string $changingValue = 'Hello';
Expand Down