-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: Assign keyboard key to select() choices #144
Comments
Here's a quick and dirty class that extends <?php
declare(strict_types=1);
namespace App\Console;
use Illuminate\Support\Collection;
use InvalidArgumentException;
use Laravel\Prompts\Key;
use Laravel\Prompts\SelectPrompt;
use Laravel\Prompts\Themes\Default\SelectPromptRenderer;
class SelectQuickPrompt extends SelectPrompt
{
public function __construct(
public string $label,
array|Collection $options,
public int|string|null $default = null,
public int $scroll = 5,
public mixed $validate = null,
public string $hint = '',
public bool|string $required = true,
) {
if ($this->required === false) {
throw new InvalidArgumentException('Argument [required] must be true or a string.');
}
$this->options = $options instanceof Collection ? $options->all() : $options;
// This is new
$keys = [];
$i = 0;
foreach ($this->options as &$option) {
if(1===preg_match('`\[(\w)]`', $option, $matches)) {
$option = str_replace($matches[0], self::underline($matches[1]), $option);
if(array_key_exists(strtolower($matches[1]), $keys)) {
throw new InvalidArgumentException('Key '.strtolower($matches[1]).' is defined more than once');
}
$keys[strtolower($matches[1])] = $i;
}
$i++;
}
// End of new
if ($this->default) {
if (array_is_list($this->options)) {
$this->initializeScrolling(array_search($this->default, $this->options) ?: 0);
} else {
$this->initializeScrolling(array_search($this->default, array_keys($this->options)) ?: 0);
}
$this->scrollToHighlighted(count($this->options));
} else {
$this->initializeScrolling(0);
}
$this->on('key', fn ($key) => match ($key) {
Key::UP, Key::UP_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::SHIFT_TAB, Key::CTRL_P, Key::CTRL_B => $this->highlightPrevious(count($this->options)),
Key::DOWN, Key::DOWN_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::TAB, Key::CTRL_N, Key::CTRL_F => $this->highlightNext(count($this->options)),
Key::oneOf([Key::HOME, Key::CTRL_A], $key) => $this->highlight(0),
Key::oneOf([Key::END, Key::CTRL_E], $key) => $this->highlight(count($this->options) - 1),
// This is new
array_key_exists($key, $keys) ? $key : null => $this->highlight($keys[$key]),
// End of new
Key::ENTER => $this->submit(),
default => null,
});
}
protected function getRenderer(): callable
{
return new SelectPromptRenderer($this);
}
public static function select(): int|string
{
return (new self(...func_get_args()))->prompt();
}
} |
This is an interesting idea. I've often thought about adding a One of the biggest challenges is that we need to be able to use Symfony's console components as a fallback for Windows users without WSL and maintain any critical behaviour (e.g. disabled options should still be disabled in some way, which Symfony doesn't handle natively). In this case, the keyboard functionality wouldn't be possible with Symfony (as far as I'm aware), but it's not a critical behaviour, so we'd just need to transform the options before passing them to Symfony. An alternative would be to add this functionality automatically, i.e., automatically choose the first unique character in each option. (I'd imagine it would be case insensitive) We could potentially skip characters with existing behaviour like For consistency, the behaviour would need to at least work on I don't have the bandwidth to take this on right now, but I'm open to a PR. I'd personally lean towards the automatic version, which also has the benefit of not impacting the Symfony fallback, as the options array would remain unchanged. I don't think it's essential that the |
Hello,
To speed up using
select()
, I would like to see the possibility to assign some keyboard key to each choice.It could look something like one of these:
I think the last two ones are the ones that requires the least modification but may not be the most readable.
As for the implementation, I feel this is mostly updating this listener: https://github.com/laravel/prompts/blob/main/src/SelectPrompt.php#L51
On the display side, it would be nice if we could underline the assigned key.
The constructor should make sure that every key is unique.
The text was updated successfully, but these errors were encountered: