One Hat Cyber Team
Your IP:
216.73.216.176
Server IP:
198.54.114.155
Server:
Linux server71.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software:
LiteSpeed
PHP Version:
5.6.40
Create File
|
Create Folder
Execute
Dir :
~
/
proc
/
self
/
cwd
/
View File Name :
Themes.tar
Contracts/Scrolling.php 0000644 00000000314 15111316732 0011147 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Contracts; interface Scrolling { /** * The number of lines to reserve outside of the scrollable area. */ public function reservedLines(): int; } Default/PasswordPromptRenderer.php 0000644 00000003275 15111316732 0013343 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\PasswordPrompt; class PasswordPromptRenderer extends Renderer { use Concerns\DrawsBoxes; /** * Render the password prompt. */ public function __invoke(PasswordPrompt $prompt): string { $maxWidth = $prompt->terminal()->cols() - 6; return match ($prompt->state) { 'submit' => $this ->box( $this->dim($prompt->label), $this->truncate($prompt->masked(), $maxWidth), ), 'cancel' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $this->strikethrough($this->dim($this->truncate($prompt->masked() ?: $prompt->placeholder, $maxWidth))), color: 'red', ) ->error('Cancelled.'), 'error' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $prompt->maskedWithCursor($maxWidth), color: 'yellow', ) ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), default => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $prompt->maskedWithCursor($maxWidth), ) ->when( $prompt->hint, fn () => $this->hint($prompt->hint), fn () => $this->newLine() // Space for errors ), }; } } Default/MultiSearchPromptRenderer.php 0000644 00000013670 15111316732 0013761 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\MultiSearchPrompt; use Laravel\Prompts\Themes\Contracts\Scrolling; class MultiSearchPromptRenderer extends Renderer implements Scrolling { use Concerns\DrawsBoxes; use Concerns\DrawsScrollbars; /** * Render the suggest prompt. */ public function __invoke(MultiSearchPrompt $prompt): string { $maxWidth = $prompt->terminal()->cols() - 6; return match ($prompt->state) { 'submit' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->renderSelectedOptions($prompt), ), 'cancel' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))), color: 'red', ) ->error('Cancelled'), 'error' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $prompt->valueWithCursor($maxWidth), $this->renderOptions($prompt), color: 'yellow', info: $this->getInfoText($prompt), ) ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), 'searching' => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->valueWithCursorAndSearchIcon($prompt, $maxWidth), $this->renderOptions($prompt), info: $this->getInfoText($prompt), ) ->hint($prompt->hint), default => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $prompt->valueWithCursor($maxWidth), $this->renderOptions($prompt), info: $this->getInfoText($prompt), ) ->when( $prompt->hint, fn () => $this->hint($prompt->hint), fn () => $this->newLine() // Space for errors ) ->spaceForDropdown($prompt) }; } /** * Render the value with the cursor and a search icon. */ protected function valueWithCursorAndSearchIcon(MultiSearchPrompt $prompt, int $maxWidth): string { return preg_replace( '/\s$/', $this->cyan('…'), $this->pad($prompt->valueWithCursor($maxWidth - 1).' ', min($this->longest($prompt->matches(), padding: 2), $maxWidth)) ); } /** * Render a spacer to prevent jumping when the suggestions are displayed. */ protected function spaceForDropdown(MultiSearchPrompt $prompt): self { if ($prompt->searchValue() !== '') { return $this; } $this->newLine(max( 0, min($prompt->scroll, $prompt->terminal()->lines() - 7) - count($prompt->matches()), )); if ($prompt->matches() === []) { $this->newLine(); } return $this; } /** * Render the options. */ protected function renderOptions(MultiSearchPrompt $prompt): string { if ($prompt->searchValue() !== '' && empty($prompt->matches())) { return $this->gray(' '.($prompt->state === 'searching' ? 'Searching...' : 'No results.')); } return $this->scrollbar( collect($prompt->visible()) ->map(fn ($label) => $this->truncate($label, $prompt->terminal()->cols() - 10)) ->map(function ($label, $key) use ($prompt) { $index = array_search($key, array_keys($prompt->matches())); $active = $index === $prompt->highlighted; $selected = array_is_list($prompt->visible()) ? in_array($label, $prompt->value()) : in_array($key, $prompt->value()); return match (true) { $active && $selected => "{$this->cyan('› ◼')} {$label} ", $active => "{$this->cyan('›')} ◻ {$label} ", $selected => " {$this->cyan('◼')} {$this->dim($label)} ", default => " {$this->dim('◻')} {$this->dim($label)} ", }; }), $prompt->firstVisible, $prompt->scroll, count($prompt->matches()), min($this->longest($prompt->matches(), padding: 4), $prompt->terminal()->cols() - 6) )->implode(PHP_EOL); } /** * Render the selected options. */ protected function renderSelectedOptions(MultiSearchPrompt $prompt): string { if (count($prompt->labels()) === 0) { return $this->gray('None'); } return implode("\n", array_map( fn ($label) => $this->truncate($label, $prompt->terminal()->cols() - 6), $prompt->labels() )); } /** * Render the info text. */ protected function getInfoText(MultiSearchPrompt $prompt): string { $info = count($prompt->value()).' selected'; $hiddenCount = count($prompt->value()) - collect($prompt->matches()) ->filter(fn ($label, $key) => in_array(array_is_list($prompt->matches()) ? $label : $key, $prompt->value())) ->count(); if ($hiddenCount > 0) { $info .= " ($hiddenCount hidden)"; } return $info; } /** * The number of lines to reserve outside of the scrollable area. */ public function reservedLines(): int { return 7; } } Default/SearchPromptRenderer.php 0000644 00000010642 15111316732 0012742 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\SearchPrompt; use Laravel\Prompts\Themes\Contracts\Scrolling; class SearchPromptRenderer extends Renderer implements Scrolling { use Concerns\DrawsBoxes; use Concerns\DrawsScrollbars; /** * Render the suggest prompt. */ public function __invoke(SearchPrompt $prompt): string { $maxWidth = $prompt->terminal()->cols() - 6; return match ($prompt->state) { 'submit' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->truncate($prompt->label(), $maxWidth), ), 'cancel' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))), color: 'red', ) ->error('Cancelled'), 'error' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $prompt->valueWithCursor($maxWidth), $this->renderOptions($prompt), color: 'yellow', ) ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), 'searching' => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->valueWithCursorAndSearchIcon($prompt, $maxWidth), $this->renderOptions($prompt), ) ->hint($prompt->hint), default => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $prompt->valueWithCursor($maxWidth), $this->renderOptions($prompt), ) ->when( $prompt->hint, fn () => $this->hint($prompt->hint), fn () => $this->newLine() // Space for errors ) ->spaceForDropdown($prompt) }; } /** * Render the value with the cursor and a search icon. */ protected function valueWithCursorAndSearchIcon(SearchPrompt $prompt, int $maxWidth): string { return preg_replace( '/\s$/', $this->cyan('…'), $this->pad($prompt->valueWithCursor($maxWidth - 1).' ', min($this->longest($prompt->matches(), padding: 2), $maxWidth)) ); } /** * Render a spacer to prevent jumping when the suggestions are displayed. */ protected function spaceForDropdown(SearchPrompt $prompt): self { if ($prompt->searchValue() !== '') { return $this; } $this->newLine(max( 0, min($prompt->scroll, $prompt->terminal()->lines() - 7) - count($prompt->matches()), )); if ($prompt->matches() === []) { $this->newLine(); } return $this; } /** * Render the options. */ protected function renderOptions(SearchPrompt $prompt): string { if ($prompt->searchValue() !== '' && empty($prompt->matches())) { return $this->gray(' '.($prompt->state === 'searching' ? 'Searching...' : 'No results.')); } return $this->scrollbar( collect($prompt->visible()) ->map(fn ($label) => $this->truncate($label, $prompt->terminal()->cols() - 10)) ->map(function ($label, $key) use ($prompt) { $index = array_search($key, array_keys($prompt->matches())); return $prompt->highlighted === $index ? "{$this->cyan('›')} {$label} " : " {$this->dim($label)} "; }) ->values(), $prompt->firstVisible, $prompt->scroll, count($prompt->matches()), min($this->longest($prompt->matches(), padding: 4), $prompt->terminal()->cols() - 6) )->implode(PHP_EOL); } /** * The number of lines to reserve outside of the scrollable area. */ public function reservedLines(): int { return 7; } } Default/SpinnerRenderer.php 0000644 00000001646 15111316732 0011755 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\Spinner; class SpinnerRenderer extends Renderer { /** * The frames of the spinner. * * @var array<string> */ protected array $frames = ['⠂', '⠒', '⠐', '⠰', '⠠', '⠤', '⠄', '⠆']; /** * The frame to render when the spinner is static. */ protected string $staticFrame = '⠶'; /** * The interval between frames. */ protected int $interval = 75; /** * Render the spinner. */ public function __invoke(Spinner $spinner): string { if ($spinner->static) { return $this->line(" {$this->cyan($this->staticFrame)} {$spinner->message}"); } $spinner->interval = $this->interval; $frame = $this->frames[$spinner->count % count($this->frames)]; return $this->line(" {$this->cyan($frame)} {$spinner->message}"); } } Default/NoteRenderer.php 0000644 00000002734 15111316732 0011243 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\Note; class NoteRenderer extends Renderer { /** * Render the note. */ public function __invoke(Note $note): string { $lines = collect(explode(PHP_EOL, $note->message)); switch ($note->type) { case 'intro': case 'outro': $lines = $lines->map(fn ($line) => " {$line} "); $longest = $lines->map(fn ($line) => strlen($line))->max(); $lines ->each(function ($line) use ($longest) { $line = str_pad($line, $longest, ' '); $this->line(" {$this->bgCyan($this->black($line))}"); }); return $this; case 'warning': $lines->each(fn ($line) => $this->line($this->yellow(" {$line}"))); return $this; case 'error': $lines->each(fn ($line) => $this->line($this->red(" {$line}"))); return $this; case 'alert': $lines->each(fn ($line) => $this->line(" {$this->bgRed($this->white(" {$line} "))}")); return $this; case 'info': $lines->each(fn ($line) => $this->line($this->green(" {$line}"))); return $this; default: $lines->each(fn ($line) => $this->line(" {$line}")); return $this; } } } Default/Concerns/DrawsBoxes.php 0000644 00000005372 15111316732 0012503 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default\Concerns; use Laravel\Prompts\Prompt; trait DrawsBoxes { protected int $minWidth = 60; /** * Draw a box. * * @return $this */ protected function box( string $title, string $body, string $footer = '', string $color = 'gray', string $info = '', ): self { $this->minWidth = min($this->minWidth, Prompt::terminal()->cols() - 6); $bodyLines = collect(explode(PHP_EOL, $body)); $footerLines = collect(explode(PHP_EOL, $footer))->filter(); $width = $this->longest( $bodyLines ->merge($footerLines) ->push($title) ->toArray() ); $titleLength = mb_strwidth($this->stripEscapeSequences($title)); $titleLabel = $titleLength > 0 ? " {$title} " : ''; $topBorder = str_repeat('─', $width - $titleLength + ($titleLength > 0 ? 0 : 2)); $this->line("{$this->{$color}(' ┌')}{$titleLabel}{$this->{$color}($topBorder.'┐')}"); $bodyLines->each(function ($line) use ($width, $color) { $this->line("{$this->{$color}(' │')} {$this->pad($line, $width)} {$this->{$color}('│')}"); }); if ($footerLines->isNotEmpty()) { $this->line($this->{$color}(' ├'.str_repeat('─', $width + 2).'┤')); $footerLines->each(function ($line) use ($width, $color) { $this->line("{$this->{$color}(' │')} {$this->pad($line, $width)} {$this->{$color}('│')}"); }); } $this->line($this->{$color}(' └'.str_repeat( '─', $info ? ($width - mb_strwidth($this->stripEscapeSequences($info))) : ($width + 2) ).($info ? " {$info} " : '').'┘')); return $this; } /** * Get the length of the longest line. * * @param array<string> $lines */ protected function longest(array $lines, int $padding = 0): int { return max( $this->minWidth, collect($lines) ->map(fn ($line) => mb_strwidth($this->stripEscapeSequences($line)) + $padding) ->max() ); } /** * Pad text ignoring ANSI escape sequences. */ protected function pad(string $text, int $length): string { $rightPadding = str_repeat(' ', max(0, $length - mb_strwidth($this->stripEscapeSequences($text)))); return "{$text}{$rightPadding}"; } /** * Strip ANSI escape sequences from the given text. */ protected function stripEscapeSequences(string $text): string { $text = preg_replace("/\e[^m]*m/", '', $text); return preg_replace("/<(?:(?:[fb]g|options)=[a-z,;]+)+>(.*?)<\/>/i", '$1', $text); } } Default/Concerns/DrawsScrollbars.php 0000644 00000003005 15111316732 0013520 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default\Concerns; use Illuminate\Support\Collection; trait DrawsScrollbars { /** * Render a scrollbar beside the visible items. * * @param \Illuminate\Support\Collection<int, string> $visible * @return \Illuminate\Support\Collection<int, string> */ protected function scrollbar(Collection $visible, int $firstVisible, int $height, int $total, int $width, string $color = 'cyan'): Collection { if ($height >= $total) { return $visible; } $scrollPosition = $this->scrollPosition($firstVisible, $height, $total); return $visible ->values() ->map(fn ($line) => $this->pad($line, $width)) ->map(fn ($line, $index) => match ($index) { $scrollPosition => preg_replace('/.$/', $this->{$color}('┃'), $line), default => preg_replace('/.$/', $this->gray('│'), $line), }); } /** * Return the position where the scrollbar "handle" should be rendered. */ protected function scrollPosition(int $firstVisible, int $height, int $total): int { if ($firstVisible === 0) { return 0; } $maxPosition = $total - $height; if ($firstVisible === $maxPosition) { return $height - 1; } if ($height <= 2) { return -1; } $percent = $firstVisible / $maxPosition; return (int) round($percent * ($height - 3)) + 1; } } Default/TableRenderer.php 0000644 00000002466 15111316732 0011367 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\Output\BufferedConsoleOutput; use Laravel\Prompts\Table; use Symfony\Component\Console\Helper\Table as SymfonyTable; use Symfony\Component\Console\Helper\TableStyle; class TableRenderer extends Renderer { /** * Render the table. */ public function __invoke(Table $table): string { $tableStyle = (new TableStyle()) ->setHorizontalBorderChars('─') ->setVerticalBorderChars('│', '│') ->setCellHeaderFormat($this->dim('<fg=default>%s</>')) ->setCellRowFormat('<fg=default>%s</>'); if (empty($table->headers)) { $tableStyle->setCrossingChars('┼', '', '', '', '┤', '┘</>', '┴', '└', '├', '<fg=gray>┌', '┬', '┐'); } else { $tableStyle->setCrossingChars('┼', '<fg=gray>┌', '┬', '┐', '┤', '┘</>', '┴', '└', '├'); } $buffered = new BufferedConsoleOutput(); (new SymfonyTable($buffered)) ->setHeaders($table->headers) ->setRows($table->rows) ->setStyle($tableStyle) ->render(); collect(explode(PHP_EOL, trim($buffered->content(), PHP_EOL))) ->each(fn ($line) => $this->line(' '.$line)); return $this; } } Default/MultiSelectPromptRenderer.php 0000644 00000010723 15111316732 0013767 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\MultiSelectPrompt; use Laravel\Prompts\Themes\Contracts\Scrolling; class MultiSelectPromptRenderer extends Renderer implements Scrolling { use Concerns\DrawsBoxes; use Concerns\DrawsScrollbars; /** * Render the multiselect prompt. */ public function __invoke(MultiSelectPrompt $prompt): string { return match ($prompt->state) { 'submit' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->renderSelectedOptions($prompt) ), 'cancel' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $this->renderOptions($prompt), color: 'red', ) ->error('Cancelled.'), 'error' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $this->renderOptions($prompt), color: 'yellow', info: count($prompt->options) > $prompt->scroll ? (count($prompt->value()).' selected') : '', ) ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), default => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->renderOptions($prompt), info: count($prompt->options) > $prompt->scroll ? (count($prompt->value()).' selected') : '', ) ->when( $prompt->hint, fn () => $this->hint($prompt->hint), fn () => $this->newLine() // Space for errors ), }; } /** * Render the options. */ protected function renderOptions(MultiSelectPrompt $prompt): string { return $this->scrollbar( collect($prompt->visible()) ->map(fn ($label) => $this->truncate($label, $prompt->terminal()->cols() - 12)) ->map(function ($label, $key) use ($prompt) { $index = array_search($key, array_keys($prompt->options)); $active = $index === $prompt->highlighted; if (array_is_list($prompt->options)) { $value = $prompt->options[$index]; } else { $value = array_keys($prompt->options)[$index]; } $selected = in_array($value, $prompt->value()); if ($prompt->state === 'cancel') { return $this->dim(match (true) { $active && $selected => "› ◼ {$this->strikethrough($label)} ", $active => "› ◻ {$this->strikethrough($label)} ", $selected => " ◼ {$this->strikethrough($label)} ", default => " ◻ {$this->strikethrough($label)} ", }); } return match (true) { $active && $selected => "{$this->cyan('› ◼')} {$label} ", $active => "{$this->cyan('›')} ◻ {$label} ", $selected => " {$this->cyan('◼')} {$this->dim($label)} ", default => " {$this->dim('◻')} {$this->dim($label)} ", }; }) ->values(), $prompt->firstVisible, $prompt->scroll, count($prompt->options), min($this->longest($prompt->options, padding: 6), $prompt->terminal()->cols() - 6), $prompt->state === 'cancel' ? 'dim' : 'cyan' )->implode(PHP_EOL); } /** * Render the selected options. */ protected function renderSelectedOptions(MultiSelectPrompt $prompt): string { if (count($prompt->labels()) === 0) { return $this->gray('None'); } return implode("\n", array_map( fn ($label) => $this->truncate($label, $prompt->terminal()->cols() - 6), $prompt->labels() )); } /** * The number of lines to reserve outside of the scrollable area. */ public function reservedLines(): int { return 5; } } Default/ConfirmPromptRenderer.php 0000644 00000004560 15111316732 0013134 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\ConfirmPrompt; class ConfirmPromptRenderer extends Renderer { use Concerns\DrawsBoxes; /** * Render the confirm prompt. */ public function __invoke(ConfirmPrompt $prompt): string { return match ($prompt->state) { 'submit' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->truncate($prompt->label(), $prompt->terminal()->cols() - 6) ), 'cancel' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $this->renderOptions($prompt), color: 'red' ) ->error('Cancelled.'), 'error' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $this->renderOptions($prompt), color: 'yellow', ) ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), default => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->renderOptions($prompt), ) ->when( $prompt->hint, fn () => $this->hint($prompt->hint), fn () => $this->newLine() // Space for errors ), }; } /** * Render the confirm prompt options. */ protected function renderOptions(ConfirmPrompt $prompt): string { $length = (int) floor(($prompt->terminal()->cols() - 14) / 2); $yes = $this->truncate($prompt->yes, $length); $no = $this->truncate($prompt->no, $length); if ($prompt->state === 'cancel') { return $this->dim($prompt->confirmed ? "● {$this->strikethrough($yes)} / ○ {$this->strikethrough($no)}" : "○ {$this->strikethrough($yes)} / ● {$this->strikethrough($no)}"); } return $prompt->confirmed ? "{$this->green('●')} {$yes} {$this->dim('/ ○ '.$no)}" : "{$this->dim('○ '.$yes.' /')} {$this->green('●')} {$no}"; } } Default/SelectPromptRenderer.php 0000644 00000006234 15111316732 0012756 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\SelectPrompt; use Laravel\Prompts\Themes\Contracts\Scrolling; class SelectPromptRenderer extends Renderer implements Scrolling { use Concerns\DrawsBoxes; use Concerns\DrawsScrollbars; /** * Render the select prompt. */ public function __invoke(SelectPrompt $prompt): string { $maxWidth = $prompt->terminal()->cols() - 6; return match ($prompt->state) { 'submit' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->truncate($prompt->label(), $maxWidth), ), 'cancel' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $this->renderOptions($prompt), color: 'red', ) ->error('Cancelled.'), 'error' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $this->renderOptions($prompt), color: 'yellow', ) ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), default => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->renderOptions($prompt), ) ->when( $prompt->hint, fn () => $this->hint($prompt->hint), fn () => $this->newLine() // Space for errors ), }; } /** * Render the options. */ protected function renderOptions(SelectPrompt $prompt): string { return $this->scrollbar( collect($prompt->visible()) ->map(fn ($label) => $this->truncate($label, $prompt->terminal()->cols() - 12)) ->map(function ($label, $key) use ($prompt) { $index = array_search($key, array_keys($prompt->options)); if ($prompt->state === 'cancel') { return $this->dim($prompt->highlighted === $index ? "› ● {$this->strikethrough($label)} " : " ○ {$this->strikethrough($label)} " ); } return $prompt->highlighted === $index ? "{$this->cyan('›')} {$this->cyan('●')} {$label} " : " {$this->dim('○')} {$this->dim($label)} "; }) ->values(), $prompt->firstVisible, $prompt->scroll, count($prompt->options), min($this->longest($prompt->options, padding: 6), $prompt->terminal()->cols() - 6), $prompt->state === 'cancel' ? 'dim' : 'cyan' )->implode(PHP_EOL); } /** * The number of lines to reserve outside of the scrollable area. */ public function reservedLines(): int { return 5; } } Default/Renderer.php 0000644 00000005176 15111316732 0010420 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\Concerns\Colors; use Laravel\Prompts\Concerns\Truncation; use Laravel\Prompts\Prompt; use RuntimeException; abstract class Renderer { use Colors; use Truncation; /** * The output to be rendered. */ protected string $output = ''; /** * Create a new renderer instance. */ public function __construct(protected Prompt $prompt) { $this->checkTerminalSize($prompt); } /** * Render a line of output. */ protected function line(string $message): self { $this->output .= $message.PHP_EOL; return $this; } /** * Render a new line. */ protected function newLine(int $count = 1): self { $this->output .= str_repeat(PHP_EOL, $count); return $this; } /** * Render a warning message. */ protected function warning(string $message): self { return $this->line($this->yellow(" ⚠ {$message}")); } /** * Render an error message. */ protected function error(string $message): self { return $this->line($this->red(" ⚠ {$message}")); } /** * Render an hint message. */ protected function hint(string $message): self { if ($message === '') { return $this; } $message = $this->truncate($message, $this->prompt->terminal()->cols() - 6); return $this->line($this->gray(" {$message}")); } /** * Apply the callback if the given "value" is truthy. * * @return $this */ protected function when(mixed $value, callable $callback, callable $default = null): self { if ($value) { $callback($this); } elseif ($default) { $default($this); } return $this; } /** * Render the output with a blank line above and below. */ public function __toString() { return str_repeat(PHP_EOL, max(2 - $this->prompt->newLinesWritten(), 0)) .$this->output .(in_array($this->prompt->state, ['submit', 'cancel']) ? PHP_EOL : ''); } /** * Check that the terminal is large enough to render the prompt. */ private function checkTerminalSize(Prompt $prompt): void { $required = 8; $actual = $prompt->terminal()->lines(); if ($actual < $required) { throw new RuntimeException( "The terminal height must be at least [$required] lines but is currently [$actual]. Please increase the height or reduce the font size." ); } } } Default/ProgressRenderer.php 0000644 00000004021 15111316732 0012131 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\Progress; class ProgressRenderer extends Renderer { use Concerns\DrawsBoxes; /** * The character to use for the progress bar. */ protected string $barCharacter = '█'; /** * Render the progress bar. * * @param Progress<int|iterable<mixed>> $progress */ public function __invoke(Progress $progress): string { $filled = str_repeat($this->barCharacter, (int) ceil($progress->percentage() * min($this->minWidth, $progress->terminal()->cols() - 6))); return match ($progress->state) { 'submit' => $this ->box( $this->dim($this->truncate($progress->label, $progress->terminal()->cols() - 6)), $this->dim($filled), info: $progress->progress.'/'.$progress->total, ), 'error' => $this ->box( $this->truncate($progress->label, $progress->terminal()->cols() - 6), $this->dim($filled), color: 'red', info: $progress->progress.'/'.$progress->total, ), 'cancel' => $this ->box( $this->truncate($progress->label, $progress->terminal()->cols() - 6), $this->dim($filled), color: 'red', info: $progress->progress.'/'.$progress->total, ) ->error('Cancelled.'), default => $this ->box( $this->cyan($this->truncate($progress->label, $progress->terminal()->cols() - 6)), $this->dim($filled), info: $progress->progress.'/'.$progress->total, ) ->when( $progress->hint, fn () => $this->hint($progress->hint), fn () => $this->newLine() // Space for errors ) }; } } Default/SuggestPromptRenderer.php 0000644 00000010067 15111316732 0013157 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\SuggestPrompt; use Laravel\Prompts\Themes\Contracts\Scrolling; class SuggestPromptRenderer extends Renderer implements Scrolling { use Concerns\DrawsBoxes; use Concerns\DrawsScrollbars; /** * Render the suggest prompt. */ public function __invoke(SuggestPrompt $prompt): string { $maxWidth = $prompt->terminal()->cols() - 6; return match ($prompt->state) { 'submit' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->truncate($prompt->value(), $maxWidth), ), 'cancel' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))), color: 'red', ) ->error('Cancelled'), 'error' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $this->valueWithCursorAndArrow($prompt, $maxWidth), $this->renderOptions($prompt), color: 'yellow', ) ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), default => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->valueWithCursorAndArrow($prompt, $maxWidth), $this->renderOptions($prompt), ) ->when( $prompt->hint, fn () => $this->hint($prompt->hint), fn () => $this->newLine() // Space for errors ) ->spaceForDropdown($prompt), }; } /** * Render the value with the cursor and an arrow. */ protected function valueWithCursorAndArrow(SuggestPrompt $prompt, int $maxWidth): string { if ($prompt->highlighted !== null || $prompt->value() !== '' || count($prompt->matches()) === 0) { return $prompt->valueWithCursor($maxWidth); } return preg_replace( '/\s$/', $this->cyan('⌄'), $this->pad($prompt->valueWithCursor($maxWidth - 1).' ', min($this->longest($prompt->matches(), padding: 2), $maxWidth)) ); } /** * Render a spacer to prevent jumping when the suggestions are displayed. */ protected function spaceForDropdown(SuggestPrompt $prompt): self { if ($prompt->value() === '' && $prompt->highlighted === null) { $this->newLine(min( count($prompt->matches()), $prompt->scroll, $prompt->terminal()->lines() - 7 ) + 1); } return $this; } /** * Render the options. */ protected function renderOptions(SuggestPrompt $prompt): string { if (empty($prompt->matches()) || ($prompt->value() === '' && $prompt->highlighted === null)) { return ''; } return $this->scrollbar( collect($prompt->visible()) ->map(fn ($label) => $this->truncate($label, $prompt->terminal()->cols() - 10)) ->map(fn ($label, $key) => $prompt->highlighted === $key ? "{$this->cyan('›')} {$label} " : " {$this->dim($label)} " ), $prompt->firstVisible, $prompt->scroll, count($prompt->matches()), min($this->longest($prompt->matches(), padding: 4), $prompt->terminal()->cols() - 6), $prompt->state === 'cancel' ? 'dim' : 'cyan' )->implode(PHP_EOL); } /** * The number of lines to reserve outside of the scrollable area. */ public function reservedLines(): int { return 7; } } Default/TextPromptRenderer.php 0000644 00000003316 15111316732 0012461 0 ustar 00 <?php namespace Laravel\Prompts\Themes\Default; use Laravel\Prompts\TextPrompt; class TextPromptRenderer extends Renderer { use Concerns\DrawsBoxes; /** * Render the text prompt. */ public function __invoke(TextPrompt $prompt): string { $maxWidth = $prompt->terminal()->cols() - 6; return match ($prompt->state) { 'submit' => $this ->box( $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $this->truncate($prompt->value(), $maxWidth), ), 'cancel' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))), color: 'red', ) ->error('Cancelled.'), 'error' => $this ->box( $this->truncate($prompt->label, $prompt->terminal()->cols() - 6), $prompt->valueWithCursor($maxWidth), color: 'yellow', ) ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)), default => $this ->box( $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)), $prompt->valueWithCursor($maxWidth), ) ->when( $prompt->hint, fn () => $this->hint($prompt->hint), fn () => $this->newLine() // Space for errors ) }; } }