Skip to content

Commit 21452dd

Browse files
committed
[FIX] TUI.
1 parent db04de9 commit 21452dd

2 files changed

Lines changed: 70 additions & 42 deletions

File tree

bin/evo

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -120,22 +120,22 @@ final class EvoBootstrapper
120120
$memoryLimit = ini_get('memory_limit') ?: 'Unknown';
121121

122122
$items = [
123-
['key' => 'os', 'label' => $os, 'level' => 'ok'],
124-
['key' => 'php', 'label' => "PHP - {$phpVersion}", 'level' => $phpOk ? 'ok' : 'error'],
125-
['key' => 'composer', 'label' => "Composer" . ($composerVersion ? " - {$composerVersion}" : ''), 'level' => $composerOk ? 'ok' : 'warn'],
126-
['key' => 'pdo', 'label' => 'PDO extension', 'level' => $pdoOk ? 'ok' : 'error'],
123+
['key' => 'os', 'label' => $os, 'level' => 'ok'],
124+
['key' => 'php', 'label' => "PHP - {$phpVersion}", 'level' => $phpOk ? 'ok' : 'error'],
125+
['key' => 'composer', 'label' => "Composer" . ($composerVersion ? " - {$composerVersion}" : ''), 'level' => $composerOk ? 'ok' : 'warn'],
126+
['key' => 'pdo', 'label' => 'PDO extension', 'level' => $pdoOk ? 'ok' : 'error'],
127127
// DB drivers: if unavailable, mark as warning (optional until user chooses a DB).
128-
['key' => 'pdo_mysql', 'label' => 'PDO MySQL driver', 'level' => $pdoMysqlOk ? 'ok' : 'warn'],
129-
['key' => 'pdo_pgsql', 'label' => 'PDO PostgreSQL driver', 'level' => $pdoPgsqlOk ? 'ok' : 'warn'],
130-
['key' => 'pdo_sqlite', 'label' => 'PDO SQLite driver', 'level' => $pdoSqliteOk ? 'ok' : 'warn'],
131-
['key' => 'pdo_sqlsrv', 'label' => 'PDO SQL Server driver', 'level' => $pdoSqlsrvOk ? 'ok' : 'warn'],
132-
['key' => 'json', 'label' => 'JSON extension', 'level' => $jsonOk ? 'ok' : 'error'],
133-
['key' => 'mysqli', 'label' => 'MySQLi extension', 'level' => $mysqliOk ? 'ok' : 'error'],
134-
['key' => 'mbstring', 'label' => 'MBString extension', 'level' => $mbstringOk ? 'ok' : 'error'],
135-
['key' => 'curl', 'label' => 'cURL extension', 'level' => $curlOk ? 'ok' : 'warn'],
136-
['key' => 'image', 'label' => $imageLabel, 'level' => $imageOk ? 'ok' : 'warn'],
137-
['key' => 'disk_free', 'label' => 'Disk free - ' . ($diskFree ?: 'Unknown'), 'level' => $diskFree !== null ? 'ok' : 'warn'],
138-
['key' => 'memory_limit', 'label' => 'Memory limit - ' . $memoryLimit, 'level' => 'ok'],
128+
['key' => 'pdo_mysql', 'label' => 'PDO MySQL driver', 'level' => $pdoMysqlOk ? 'ok' : 'warn'],
129+
['key' => 'pdo_pgsql', 'label' => 'PDO PostgreSQL driver', 'level' => $pdoPgsqlOk ? 'ok' : 'warn'],
130+
['key' => 'pdo_sqlite', 'label' => 'PDO SQLite driver', 'level' => $pdoSqliteOk ? 'ok' : 'warn'],
131+
['key' => 'pdo_sqlsrv', 'label' => 'PDO SQL Server driver', 'level' => $pdoSqlsrvOk ? 'ok' : 'warn'],
132+
['key' => 'json', 'label' => 'JSON extension', 'level' => $jsonOk ? 'ok' : 'error'],
133+
['key' => 'mysqli', 'label' => 'MySQLi extension', 'level' => $mysqliOk ? 'ok' : 'error'],
134+
['key' => 'mbstring', 'label' => 'MBString extension', 'level' => $mbstringOk ? 'ok' : 'error'],
135+
['key' => 'curl', 'label' => 'cURL extension', 'level' => $curlOk ? 'ok' : 'warn'],
136+
['key' => 'image', 'label' => $imageLabel, 'level' => $imageOk ? 'ok' : 'warn'],
137+
['key' => 'disk_free', 'label' => 'Disk free - ' . ($diskFree ?: 'Unknown'), 'level' => $diskFree !== null ? 'ok' : 'warn'],
138+
['key' => 'memory_limit', 'label' => 'Memory limit - ' . $memoryLimit, 'level' => 'ok'],
139139
];
140140

141141
$overall = 'ok';
@@ -150,9 +150,9 @@ final class EvoBootstrapper
150150
}
151151

152152
return [
153-
'status' => $overall,
154-
'overall' => $overall,
155-
'items' => $items,
153+
'status' => $overall,
154+
'overall' => $overall,
155+
'items' => $items,
156156
];
157157
}
158158

@@ -303,6 +303,32 @@ final class EvoBootstrapper
303303
*/
304304
private function execBinary(array $args): int
305305
{
306+
// Use proc_open with inherited stdio to preserve the TTY. Running via
307+
// passthru/exec typically pipes stdout/stderr which breaks Bubble Tea's
308+
// terminal size detection and full-screen rendering.
309+
if (function_exists('proc_open')) {
310+
$disabled = (string)ini_get('disable_functions');
311+
if ($disabled === '' || stripos($disabled, 'proc_open') === false) {
312+
$cmd = [$this->binaryPath, ...$args];
313+
$descriptors = [
314+
0 => STDIN,
315+
1 => STDOUT,
316+
2 => STDERR,
317+
];
318+
$options = [];
319+
if (PHP_OS_FAMILY === 'Windows') {
320+
$options['bypass_shell'] = true;
321+
}
322+
323+
$proc = @proc_open($cmd, $descriptors, $pipes, null, null, $options);
324+
if (is_resource($proc)) {
325+
$code = proc_close($proc);
326+
return (int)$code;
327+
}
328+
}
329+
}
330+
331+
// Fallback: execute via shell.
306332
$cmdParts = [escapeshellarg($this->binaryPath)];
307333
foreach ($args as $arg) {
308334
$cmdParts[] = escapeshellarg($arg);
@@ -601,7 +627,7 @@ final class EvoBootstrapper
601627
private function createHttpHeaders(bool $isApi): array
602628
{
603629
$headers = [
604-
'User-Agent: evo-bootstrapper',
630+
'User-Agent: evo-bootstrapper',
605631
];
606632
if ($isApi) {
607633
$headers[] = 'Accept: application/vnd.github+json';
@@ -617,17 +643,17 @@ final class EvoBootstrapper
617643
private function createHttpContext(bool $isApi): mixed
618644
{
619645
return stream_context_create([
620-
'http' => [
621-
'method' => 'GET',
622-
'header' => implode("\r\n", $this->createHttpHeaders($isApi)),
623-
'timeout' => 60,
624-
'follow_location' => 1,
625-
'max_redirects' => 5,
626-
],
627-
'ssl' => [
628-
'verify_peer' => true,
629-
'verify_peer_name' => true,
630-
],
646+
'http' => [
647+
'method' => 'GET',
648+
'header' => implode("\r\n", $this->createHttpHeaders($isApi)),
649+
'timeout' => 60,
650+
'follow_location' => 1,
651+
'max_redirects' => 5,
652+
],
653+
'ssl' => [
654+
'verify_peer' => true,
655+
'verify_peer_name' => true,
656+
],
631657
]);
632658
}
633659

internal/ui/layout.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ type layoutState struct {
1212
width int
1313
height int
1414

15-
gap int
15+
gap int
1616

1717
leftW int
1818
rightW int
1919

20-
headerH int
21-
questH int
22-
logH int
20+
headerH int
21+
questH int
22+
logH int
2323
logQuestionH int
2424

2525
topAreaH int
@@ -72,14 +72,16 @@ func computeLayout(width int, height int, stepsCount int) layoutState {
7272

7373
func computeLayoutWithHeader(width int, height int, stepsCount int, showLogo bool) layoutState {
7474
const (
75-
gap = 1
75+
gap = 1
7676

77-
minColW = 40
77+
// Allow the common 80-column terminal: two columns + 1 gap => 79 available,
78+
// split as 39/40, which is still usable with truncation.
79+
minColW = 39
7880

7981
minQuestH = 4 // border + title + 1 line
8082
minLogH = 5
8183

82-
sepLines = 1 // JoinVertical between top/log
84+
sepLines = 1 // JoinVertical between top/log
8385
)
8486

8587
headerH := compactHeaderHeight
@@ -88,11 +90,11 @@ func computeLayoutWithHeader(width int, height int, stepsCount int, showLogo boo
8890
}
8991

9092
l := layoutState{
91-
width: width,
92-
height: height,
93-
gap: gap,
94-
headerH: headerH,
95-
showLogo: showLogo,
93+
width: width,
94+
height: height,
95+
gap: gap,
96+
headerH: headerH,
97+
showLogo: showLogo,
9698
}
9799

98100
if width <= 0 || height <= 0 {

0 commit comments

Comments
 (0)