update lock clucknut
All checks were successful
All checks were successful
This commit is contained in:
2
vendor/psy/psysh/src/Output/OutputPager.php
vendored
2
vendor/psy/psysh/src/Output/OutputPager.php
vendored
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
@@ -82,11 +82,11 @@ public function doWrite($message, $newline): void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if (isset($this->pipe)) {
|
||||
if (\is_resource($this->pipe)) {
|
||||
\fclose($this->pipe);
|
||||
}
|
||||
|
||||
if (isset($this->proc)) {
|
||||
if (\is_resource($this->proc)) {
|
||||
$exit = \proc_close($this->proc);
|
||||
if ($exit !== 0) {
|
||||
throw new \RuntimeException('Error closing output stream');
|
||||
|
||||
81
vendor/psy/psysh/src/Output/ShellOutput.php
vendored
81
vendor/psy/psysh/src/Output/ShellOutput.php
vendored
@@ -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.
|
||||
@@ -26,6 +26,8 @@ class ShellOutput extends ConsoleOutput
|
||||
private int $paging = 0;
|
||||
private OutputPager $pager;
|
||||
private Theme $theme;
|
||||
/** @var callable|null */
|
||||
private $writeListener = null;
|
||||
|
||||
/**
|
||||
* Construct a ShellOutput instance.
|
||||
@@ -42,15 +44,7 @@ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = nu
|
||||
$this->theme = $theme ?? new Theme('modern');
|
||||
$this->initFormatters();
|
||||
|
||||
if ($pager === null) {
|
||||
$this->pager = new PassthruPager($this);
|
||||
} elseif (\is_string($pager)) {
|
||||
$this->pager = new ProcOutputPager($this, $pager);
|
||||
} elseif ($pager instanceof OutputPager) {
|
||||
$this->pager = $pager;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Unexpected pager parameter: '.$pager);
|
||||
}
|
||||
$this->pager = $this->createPager($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,6 +83,14 @@ public function page($messages, int $type = 0)
|
||||
$this->stopPaging();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a listener invoked whenever visible output is written.
|
||||
*/
|
||||
public function setWriteListener(?callable $listener): void
|
||||
{
|
||||
$this->writeListener = $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start sending output to the output pager.
|
||||
*/
|
||||
@@ -128,14 +130,33 @@ public function write($messages, $newline = false, $type = 0): void
|
||||
|
||||
if ($type & self::NUMBER_LINES) {
|
||||
$pad = \strlen((string) \count($messages));
|
||||
$template = $this->isDecorated() ? "<aside>%{$pad}s</aside>: %s" : "%{$pad}s: %s";
|
||||
$template = $this->isDecorated() && $this->getFormatter()->hasStyle('whisper')
|
||||
? "<whisper>%{$pad}s:</whisper> %s"
|
||||
: "%{$pad}s: %s";
|
||||
|
||||
if ($type & self::OUTPUT_RAW) {
|
||||
$messages = \array_map([OutputFormatter::class, 'escape'], $messages);
|
||||
}
|
||||
|
||||
$indent = \str_repeat(' ', $pad + 2); // Indent continuation lines to align with text
|
||||
|
||||
foreach ($messages as $i => $line) {
|
||||
$messages[$i] = \sprintf($template, $i, $line);
|
||||
// Check if line contains newlines (multi-line entry)
|
||||
if (\strpos($line, "\n") !== false) {
|
||||
// Split into lines and indent continuation lines
|
||||
$lines = \explode("\n", $line);
|
||||
$firstLine = \array_shift($lines);
|
||||
$indentedLines = \array_map(function ($l) use ($indent) {
|
||||
return $indent.$l;
|
||||
}, $lines);
|
||||
|
||||
$messages[$i] = \sprintf($template, $i, $firstLine);
|
||||
if (!empty($indentedLines)) {
|
||||
$messages[$i] .= "\n".\implode("\n", $indentedLines);
|
||||
}
|
||||
} else {
|
||||
$messages[$i] = \sprintf($template, $i, $line);
|
||||
}
|
||||
}
|
||||
|
||||
// clean this up for super.
|
||||
@@ -155,6 +176,10 @@ public function write($messages, $newline = false, $type = 0): void
|
||||
*/
|
||||
public function doWrite($message, $newline): void
|
||||
{
|
||||
if ($this->writeListener) {
|
||||
($this->writeListener)();
|
||||
}
|
||||
|
||||
// @todo Update OutputPager interface to require doWrite
|
||||
if ($this->paging > 0 && ($this->pager instanceof ProcOutputPager || $this->pager instanceof PassthruPager)) {
|
||||
$this->pager->doWrite($message, $newline);
|
||||
@@ -172,6 +197,18 @@ public function setTheme(Theme $theme)
|
||||
$this->initFormatters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the output pager used for future paging operations.
|
||||
*
|
||||
* @param string|OutputPager|null $pager
|
||||
*/
|
||||
public function setPager($pager): void
|
||||
{
|
||||
$this->closePager();
|
||||
$this->paging = 0;
|
||||
$this->pager = $this->createPager($pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush and close the output pager.
|
||||
*/
|
||||
@@ -182,6 +219,26 @@ private function closePager()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|OutputPager|null $pager
|
||||
*/
|
||||
private function createPager($pager): OutputPager
|
||||
{
|
||||
if ($pager === null) {
|
||||
return new PassthruPager($this);
|
||||
}
|
||||
|
||||
if (\is_string($pager)) {
|
||||
return new ProcOutputPager($this, $pager);
|
||||
}
|
||||
|
||||
if ($pager instanceof OutputPager) {
|
||||
return $pager;
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Unexpected pager parameter: '.$pager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize output formatter styles.
|
||||
*/
|
||||
|
||||
249
vendor/psy/psysh/src/Output/ShellOutputAdapter.php
vendored
Normal file
249
vendor/psy/psysh/src/Output/ShellOutputAdapter.php
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2026 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\Output;
|
||||
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Adapter for output methods provided by ShellOutput but used by commands.
|
||||
*
|
||||
* This allows commands to use paging and line numbering with any
|
||||
* OutputInterface implementation.
|
||||
*
|
||||
* @todo On the next major release, consider removing ShellOutput and folding
|
||||
* its functionality entirely into this adapter.
|
||||
*/
|
||||
class ShellOutputAdapter implements OutputInterface
|
||||
{
|
||||
// @todo Remove ShellOutput::NUMBER_LINES alias on next major release.
|
||||
public const NUMBER_LINES = ShellOutput::NUMBER_LINES;
|
||||
|
||||
private OutputInterface $output;
|
||||
|
||||
/**
|
||||
* @param OutputInterface $output
|
||||
*/
|
||||
public function __construct(OutputInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page multiple lines of output.
|
||||
*
|
||||
* @param string|array|\Closure $messages
|
||||
*/
|
||||
public function page($messages, int $type = 0): void
|
||||
{
|
||||
if ($this->output instanceof ShellOutput) {
|
||||
$this->output->page($messages, $type);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (\is_string($messages)) {
|
||||
// Split on newlines to avoid O(n^2) performance in Symfony's OutputFormatter
|
||||
// when processing large strings with many style tags.
|
||||
$messages = \explode("\n", $messages);
|
||||
}
|
||||
|
||||
if (!\is_array($messages) && !\is_callable($messages)) {
|
||||
throw new \InvalidArgumentException('Paged output requires a string, array or callback');
|
||||
}
|
||||
|
||||
$this->startPaging();
|
||||
|
||||
if (\is_callable($messages)) {
|
||||
$messages($this);
|
||||
} else {
|
||||
$this->write($messages, true, $type);
|
||||
}
|
||||
|
||||
$this->stopPaging();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start sending output to the output pager.
|
||||
*/
|
||||
public function startPaging(): void
|
||||
{
|
||||
if ($this->output instanceof ShellOutput) {
|
||||
$this->output->startPaging();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop paging output and flush the output pager.
|
||||
*/
|
||||
public function stopPaging(): void
|
||||
{
|
||||
if ($this->output instanceof ShellOutput) {
|
||||
$this->output->stopPaging();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a message to the output.
|
||||
*
|
||||
* @param string|array $messages
|
||||
*/
|
||||
public function write($messages, $newline = false, $type = 0): void
|
||||
{
|
||||
if ($this->output instanceof ShellOutput) {
|
||||
$this->output->write($messages, $newline, $type);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$messages = (array) $messages;
|
||||
|
||||
if ($type & self::NUMBER_LINES) {
|
||||
$messages = $this->numberLines($messages, $type);
|
||||
|
||||
// clean this up for the wrapped output.
|
||||
$type = $type & ~self::NUMBER_LINES & ~OutputInterface::OUTPUT_RAW;
|
||||
}
|
||||
|
||||
$this->output->write($messages, $newline, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a message to the output and adds a newline at the end.
|
||||
*
|
||||
* @param string|array $messages
|
||||
*/
|
||||
public function writeln($messages, $type = 0): void
|
||||
{
|
||||
$this->write($messages, true, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setVerbosity($level): void
|
||||
{
|
||||
$this->output->setVerbosity($level);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVerbosity(): int
|
||||
{
|
||||
return $this->output->getVerbosity();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isQuiet(): bool
|
||||
{
|
||||
return $this->output->isQuiet();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVerbose(): bool
|
||||
{
|
||||
return $this->output->isVerbose();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVeryVerbose(): bool
|
||||
{
|
||||
return $this->output->isVeryVerbose();
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Remove method_exists guard when dropping support for Symfony < 7.2.
|
||||
*
|
||||
* @suppress PhanUndeclaredMethod
|
||||
*/
|
||||
public function isSilent(): bool
|
||||
{
|
||||
if (\method_exists($this->output, 'isSilent')) {
|
||||
return $this->output->isSilent();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDebug(): bool
|
||||
{
|
||||
return $this->output->isDebug();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDecorated($decorated): void
|
||||
{
|
||||
$this->output->setDecorated($decorated);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDecorated(): bool
|
||||
{
|
||||
return $this->output->isDecorated();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setFormatter(OutputFormatterInterface $formatter): void
|
||||
{
|
||||
$this->output->setFormatter($formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormatter(): OutputFormatterInterface
|
||||
{
|
||||
return $this->output->getFormatter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add line numbers to a message array.
|
||||
*
|
||||
* @param string[] $messages
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function numberLines(array $messages, int $type): array
|
||||
{
|
||||
$pad = \strlen((string) \count($messages));
|
||||
$template = $this->output->isDecorated() && $this->output->getFormatter()->hasStyle('whisper')
|
||||
? "<whisper>%{$pad}s:</whisper> %s"
|
||||
: "%{$pad}s: %s";
|
||||
|
||||
if ($type & OutputInterface::OUTPUT_RAW) {
|
||||
$messages = \array_map([OutputFormatter::class, 'escape'], $messages);
|
||||
}
|
||||
|
||||
foreach ($messages as $i => $line) {
|
||||
$messages[$i] = \sprintf($template, $i, $line);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
}
|
||||
102
vendor/psy/psysh/src/Output/Theme.php
vendored
102
vendor/psy/psysh/src/Output/Theme.php
vendored
@@ -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]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user