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.
@@ -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.
*/