diff --git a/src/Concerns/TypedValue.php b/src/Concerns/TypedValue.php index f8951862..56d356ad 100644 --- a/src/Concerns/TypedValue.php +++ b/src/Concerns/TypedValue.php @@ -88,7 +88,7 @@ public function value(): string /** * Add a virtual cursor to the value and truncate if necessary. */ - protected function addCursor(string $value, int $cursorPosition, int $maxWidth): string + protected function addCursor(string $value, int $cursorPosition, ?int $maxWidth = null): string { $before = mb_substr($value, 0, $cursorPosition); $current = mb_substr($value, $cursorPosition, 1); @@ -96,12 +96,12 @@ protected function addCursor(string $value, int $cursorPosition, int $maxWidth): $cursor = mb_strlen($current) && $current !== PHP_EOL ? $current : ' '; - $spaceBefore = $maxWidth < 0 ? mb_strwidth($before) : $maxWidth - mb_strwidth($cursor) - (mb_strwidth($after) > 0 ? 1 : 0); + $spaceBefore = $maxWidth < 0 || $maxWidth === null ? mb_strwidth($before) : $maxWidth - mb_strwidth($cursor) - (mb_strwidth($after) > 0 ? 1 : 0); [$truncatedBefore, $wasTruncatedBefore] = mb_strwidth($before) > $spaceBefore ? [$this->trimWidthBackwards($before, 0, $spaceBefore - 1), true] : [$before, false]; - $spaceAfter = $maxWidth < 0 ? mb_strwidth($after) : $maxWidth - ($wasTruncatedBefore ? 1 : 0) - mb_strwidth($truncatedBefore) - mb_strwidth($cursor); + $spaceAfter = $maxWidth < 0 || $maxWidth === null ? mb_strwidth($after) : $maxWidth - ($wasTruncatedBefore ? 1 : 0) - mb_strwidth($truncatedBefore) - mb_strwidth($cursor); [$truncatedAfter, $wasTruncatedAfter] = mb_strwidth($after) > $spaceAfter ? [mb_strimwidth($after, 0, $spaceAfter - 1), true] : [$after, false]; diff --git a/src/TextareaPrompt.php b/src/TextareaPrompt.php index 203317b4..19a94e6b 100644 --- a/src/TextareaPrompt.php +++ b/src/TextareaPrompt.php @@ -58,17 +58,23 @@ public function __construct( } /** - * The currently visible lines. - * - * @return array + * Get the formatted value with a virtual cursor. */ - public function visible(): array + public function valueWithCursor(): string { - $this->adjustVisibleWindow(); + if ($this->value() === '') { + return $this->wrappedPlaceholderWithCursor(); + } - $withCursor = $this->valueWithCursor(); + return $this->addCursor($this->wrappedValue(), $this->cursorPosition + $this->cursorOffset(), -1); + } - return array_slice(explode(PHP_EOL, $withCursor), $this->firstVisible, $this->scroll, preserve_keys: true); + /** + * The word-wrapped version of the typed value. + */ + public function wrappedValue(): string + { + return $this->mbWordwrap($this->value(), $this->width, PHP_EOL, true); } /** @@ -78,9 +84,21 @@ public function visible(): array */ public function lines(): array { - $value = $this->mbWordwrap($this->value(), $this->width, PHP_EOL, true); + return explode(PHP_EOL, $this->wrappedValue()); + } + + /** + * The currently visible lines. + * + * @return array + */ + public function visible(): array + { + $this->adjustVisibleWindow(); - return explode(PHP_EOL, $value); + $withCursor = $this->valueWithCursor(); + + return array_slice(explode(PHP_EOL, $withCursor), $this->firstVisible, $this->scroll, preserve_keys: true); } /** @@ -193,20 +211,6 @@ protected function currentLineIndex(): int }) ?: 0; } - /** - * Get the formatted value with a virtual cursor. - */ - public function valueWithCursor(): string - { - $value = implode(PHP_EOL, $this->lines()); - - if ($this->value() === '') { - return $this->dim($this->addCursor($this->placeholder, 0, PHP_INT_MAX)); - } - - return $this->addCursor($value, $this->cursorPosition + $this->cursorOffset(), -1); - } - /** * Calculate the cursor offset considering wrapped words. */ @@ -224,4 +228,18 @@ protected function cursorOffset(): int return $cursorOffset; } + + /** + * A wrapped version of the placeholder with the virtual cursor. + */ + protected function wrappedPlaceholderWithCursor(): string + { + return implode(PHP_EOL, array_map( + $this->dim(...), + explode(PHP_EOL, $this->addCursor( + $this->mbWordwrap($this->placeholder, $this->width, PHP_EOL, true), + cursorPosition: 0, + )) + )); + } }