update lock clucknut
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / build-and-push (push) Successful in 3m14s
Build, Push and Deploy / deploy-staging (push) Successful in 25s
Build, Push and Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-04-18 20:32:18 +07:00
parent 4554035227
commit dcaf267458
3359 changed files with 153185 additions and 205489 deletions

View File

@@ -3,7 +3,7 @@
/*
* This file is part of Psy Shell.
*
* (c) 2012-2025 Justin Hileman
* (c) 2012-2026 Justin Hileman
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -19,6 +19,8 @@
*/
class Theme
{
public const BUILTIN_THEMES = ['modern', 'compact', 'classic'];
const MODERN_THEME = []; // Defaults :)
const COMPACT_THEME = [
@@ -34,19 +36,29 @@ class Theme
'returnValue' => '=> ',
];
private const BUILTIN_THEME_CONFIGS = [
'modern' => self::MODERN_THEME,
'compact' => self::COMPACT_THEME,
'classic' => self::CLASSIC_THEME,
];
// Custom themes fall back to DEFAULT_STYLES for any undefined style.
const DEFAULT_STYLES = [
'info' => ['white', 'blue', ['bold']],
'info' => ['green', null, ['bold']],
'warning' => ['black', 'yellow'],
'error' => ['white', 'red', ['bold']],
'whisper' => ['gray'],
'aside' => ['blue'],
'strong' => [null, null, ['bold']],
'return' => ['cyan'],
'urgent' => ['red'],
'hidden' => ['black'],
'aside' => ['blue'],
'strong' => [null, null, ['bold']],
'return' => ['cyan'],
'urgent' => ['red'],
'hidden' => ['black'],
'command' => ['cyan', null, ['bold']],
'command_option' => ['yellow'],
'command_argument' => ['green'],
// Visibility
// Keywords
'public' => [null, null, ['bold']],
'protected' => ['yellow'],
'private' => ['red'],
@@ -54,13 +66,15 @@ class Theme
'const' => ['cyan'],
'class' => ['blue', null, ['underscore']],
'function' => [null],
'virtual' => ['magenta'],
'default' => [null],
// Types
'number' => ['magenta'],
'integer' => ['magenta'],
'float' => ['yellow'],
'float' => ['magenta'],
'string' => ['green'],
'array_key' => ['blue'],
'bool' => ['cyan'],
'keyword' => ['yellow'],
'comment' => ['blue'],
@@ -70,6 +84,11 @@ class Theme
// Code-specific formatting
'inline_html' => ['cyan'],
// Interactive readline
'input_frame' => ['bright-white', 'gray'],
'input_frame_error' => ['bright-white', 'red'],
'input_highlight' => [null, null, ['reverse']],
];
const ERROR_STYLES = ['info', 'warning', 'error', 'whisper', 'class'];
@@ -91,23 +110,11 @@ class Theme
public function __construct($config = 'modern')
{
if (\is_string($config)) {
switch ($config) {
case 'modern':
$config = static::MODERN_THEME;
break;
case 'compact':
$config = static::COMPACT_THEME;
break;
case 'classic':
$config = static::CLASSIC_THEME;
break;
default:
\trigger_error(\sprintf('Unknown theme: %s', $config), \E_USER_NOTICE);
$config = static::MODERN_THEME;
break;
if (isset(self::BUILTIN_THEME_CONFIGS[$config])) {
$config = self::BUILTIN_THEME_CONFIGS[$config];
} else {
\trigger_error(\sprintf('Unknown theme: %s', $config), \E_USER_NOTICE);
$config = static::MODERN_THEME;
}
}
@@ -253,6 +260,34 @@ public function setStyles(array $styles)
}
}
/**
* Get the built-in theme name, or null for custom themes.
*/
public function getName(): ?string
{
foreach (self::BUILTIN_THEMES as $name) {
if ($this->equals(new self($name))) {
return $name;
}
}
return null;
}
/**
* Compare two themes by effective config.
*/
public function equals(self $theme): bool
{
return $this->compact === $theme->compact
&& $this->prompt === $theme->prompt
&& $this->bufferPrompt === $theme->bufferPrompt
&& $this->replayPrompt === $theme->replayPrompt
&& $this->returnValue === $theme->returnValue
&& $this->grayFallback === $theme->grayFallback
&& $this->styles === $theme->styles;
}
/**
* Apply the current output formatter styles.
*/
@@ -280,9 +315,18 @@ public function applyErrorStyles(OutputFormatterInterface $errorFormatter, bool
*/
private function getStyle(string $name, bool $useGrayFallback): array
{
return \array_map(function ($style) use ($useGrayFallback) {
return ($useGrayFallback && $style === 'gray') ? $this->grayFallback : $style;
}, $this->styles[$name]);
if (!$useGrayFallback) {
return $this->styles[$name];
}
// The default input_frame styles use extended colors (bright-white,
// gray) unavailable on older Symfony Console. Drop them rather than
// falling back to unreadable backgrounds.
if (($name === 'input_frame' || $name === 'input_frame_error') && $this->styles[$name] === static::DEFAULT_STYLES[$name]) {
return [null, null];
}
return \array_map(fn ($style) => ($style === 'gray') ? $this->grayFallback : $style, $this->styles[$name]);
}
/**