Skip to content
Closed
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
2 changes: 2 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ parameters:
- tests
- workbench/app
- workbench/routes
stubFiles:
- stubs/ext-terminal.php
tmpDir: build/phpstan
50 changes: 43 additions & 7 deletions src/Prompt/Dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Chewie\Concerns\Loops;
use Chewie\Concerns\SetsUpAndResets;
use Illuminate\Support\Collection;
use Io\Terminal\Terminal as NativeTerminal;
use Laravel\Prompts\Prompt;
use Laravel\Prompts\Terminal;
use SoloTerm\Screen\Screen;
Expand Down Expand Up @@ -208,12 +209,45 @@ public function currentCommand(): Command
*/
public function getDimensions(): array
{
if (($dimensions = $this->nativeDimensions()) !== null) {
return $dimensions;
}

return [
$this->terminal()->cols(),
$this->terminal()->lines()
$this->terminal()->lines(),
];
}

/**
* @return array{0: int, 1: int}|null
*/
protected function nativeDimensions(): ?array
{
if (! $this->hasNativeTerminal()) {
return null;
}

$size = NativeTerminal::create()->getSize();

return $size === false
? null
: [$size->cols, $size->rows];
}

protected function hasNativeTerminal(): bool
{
if (! extension_loaded('terminal') || ! class_exists(NativeTerminal::class, false)) {
return false;
}

$version = phpversion('terminal');

return is_string($version)
&& version_compare($version, '1.0.0', '>=')
&& version_compare($version, '2.0.0', '<');
}

public function handleResize(): false
{
// Debounce rapid resize events (e.g., dragging window edge)
Expand All @@ -228,15 +262,17 @@ public function handleResize(): false
putenv('COLUMNS');
putenv('LINES');

$terminal = new Terminal;
$terminal->initDimensions();

// Put them back in, in case anyone else needs them.
putenv('COLUMNS=' . $terminal->cols());
putenv('LINES=' . $terminal->lines());
if ($this->nativeDimensions() === null) {
$terminal = new Terminal;
$terminal->initDimensions();
}

[$width, $height] = $this->getDimensions();

// Put them back in, in case anyone else needs them.
putenv("COLUMNS={$width}");
putenv("LINES={$height}");

if ($width !== $this->width || $height !== $this->height) {
$this->width = $width;
$this->height = $height;
Expand Down
17 changes: 17 additions & 0 deletions stubs/ext-terminal.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Io\Terminal;

final class TerminalSize
{
public readonly int $cols;

public readonly int $rows;
}

class Terminal
{
public static function create(): self {}

public function getSize(): TerminalSize|false {}
}
67 changes: 67 additions & 0 deletions tests/Unit/DashboardTerminalTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

/**
* @author Aaron Francis <aaron@tryhardstudios.com>
*
* @link https://aaronfrancis.com
* @link https://x.com/aarondfrancis
*/

namespace SoloTerm\Solo\Tests\Unit;

use PHPUnit\Framework\Attributes\Test;
use SoloTerm\Solo\Prompt\Dashboard;

class DashboardTerminalTest extends Base
{
#[Test]
public function it_prefers_native_terminal_dimensions_when_available(): void
{
$dashboard = new class extends Dashboard
{
public function __construct()
{
//
}

/**
* @return array{0: int, 1: int}|null
*/
protected function nativeDimensions(): ?array
{
return [132, 43];
}
};

$this->assertSame([132, 43], $dashboard->getDimensions());
}

#[Test]
public function resize_respects_a_get_dimensions_override(): void
{
$dashboard = new class extends Dashboard
{
public function __construct()
{
$this->width = 80;
$this->height = 24;
$this->commands = [];
}

public function getDimensions(): array
{
return [144, 48];
}

protected function nativeDimensions(): ?array
{
return [132, 43];
}
};

$dashboard->handleResize();

$this->assertSame(144, $dashboard->width);
$this->assertSame(48, $dashboard->height);
}
}