Skip to content

Commit

Permalink
Support emacs style key binding (#67)
Browse files Browse the repository at this point in the history
* support emacs style key binding
(CTRL_P, CTRL_F, CTRL_N, CTRL_B, CTRL_H)

* add missing key bindings
  • Loading branch information
storyn26383 authored Sep 14, 2023
1 parent 85f0a1e commit 532dd02
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 15 deletions.
8 changes: 4 additions & 4 deletions src/Concerns/TypedValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ protected function trackTypedValue(string $default = '', bool $submit = true): v
}

$this->on('key', function ($key) use ($submit) {
if ($key[0] === "\e") {
if ($key[0] === "\e" || in_array($key, [Key::CTRL_B, Key::CTRL_F])) {
match ($key) {
Key::LEFT, Key::LEFT_ARROW => $this->cursorPosition = max(0, $this->cursorPosition - 1),
Key::RIGHT, Key::RIGHT_ARROW => $this->cursorPosition = min(mb_strlen($this->typedValue), $this->cursorPosition + 1),
Key::LEFT, Key::LEFT_ARROW , Key::CTRL_B => $this->cursorPosition = max(0, $this->cursorPosition - 1),
Key::RIGHT, Key::RIGHT_ARROW, Key::CTRL_F => $this->cursorPosition = min(mb_strlen($this->typedValue), $this->cursorPosition + 1),
Key::DELETE => $this->typedValue = mb_substr($this->typedValue, 0, $this->cursorPosition).mb_substr($this->typedValue, $this->cursorPosition + 1),
default => null,
};
Expand All @@ -45,7 +45,7 @@ protected function trackTypedValue(string $default = '', bool $submit = true): v
$this->submit();

return;
} elseif ($key === Key::BACKSPACE) {
} elseif ($key === Key::BACKSPACE || $key === Key::CTRL_H) {
if ($this->cursorPosition === 0) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ConfirmPrompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function __construct(
$this->on('key', fn ($key) => match ($key) {
'y' => $this->confirmed = true,
'n' => $this->confirmed = false,
Key::TAB, Key::UP, Key::UP_ARROW, Key::DOWN, Key::DOWN_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW, 'h', 'j', 'k', 'l' => $this->confirmed = ! $this->confirmed,
Key::TAB, Key::UP, Key::UP_ARROW, Key::DOWN, Key::DOWN_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::CTRL_P, Key::CTRL_F, Key::CTRL_N, Key::CTRL_B, 'h', 'j', 'k', 'l' => $this->confirmed = ! $this->confirmed,
Key::ENTER => $this->submit(),
default => null,
});
Expand Down
10 changes: 10 additions & 0 deletions src/Key.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,14 @@ class Key
const SHIFT_TAB = "\e[Z";

const CTRL_C = "\x03";

const CTRL_P = "\x10";

const CTRL_N = "\x0E";

const CTRL_F = "\x06";

const CTRL_B = "\x02";

const CTRL_H = "\x08";
}
4 changes: 2 additions & 2 deletions src/MultiSelectPrompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ public function __construct(
$this->reduceScrollingToFitTerminal();

$this->on('key', fn ($key) => match ($key) {
Key::UP, Key::UP_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::SHIFT_TAB, 'k', 'h' => $this->highlightPrevious(),
Key::DOWN, Key::DOWN_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::TAB, 'j', 'l' => $this->highlightNext(),
Key::UP, Key::UP_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::SHIFT_TAB, Key::CTRL_P, Key::CTRL_B, 'k', 'h' => $this->highlightPrevious(),
Key::DOWN, Key::DOWN_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::TAB, Key::CTRL_N, Key::CTRL_F, 'j', 'l' => $this->highlightNext(),
Key::SPACE => $this->toggleHighlighted(),
Key::ENTER => $this->submit(),
default => null,
Expand Down
6 changes: 3 additions & 3 deletions src/SearchPrompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ public function __construct(
$this->reduceScrollingToFitTerminal();

$this->on('key', fn ($key) => match ($key) {
Key::UP, Key::UP_ARROW, Key::SHIFT_TAB => $this->highlightPrevious(),
Key::DOWN, Key::DOWN_ARROW, Key::TAB => $this->highlightNext(),
Key::UP, Key::UP_ARROW, Key::SHIFT_TAB, Key::CTRL_P => $this->highlightPrevious(),
Key::DOWN, Key::DOWN_ARROW, Key::TAB, Key::CTRL_N => $this->highlightNext(),
Key::ENTER => $this->highlighted !== null ? $this->submit() : $this->search(),
Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW => $this->highlighted = null,
Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::CTRL_B, Key::CTRL_F => $this->highlighted = null,
default => $this->search(),
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/SelectPrompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ public function __construct(
}

$this->on('key', fn ($key) => match ($key) {
Key::UP, Key::UP_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::SHIFT_TAB, 'k', 'h' => $this->highlightPrevious(),
Key::DOWN, Key::DOWN_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::TAB, 'j', 'l' => $this->highlightNext(),
Key::UP, Key::UP_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::SHIFT_TAB, Key::CTRL_P, Key::CTRL_B, 'k', 'h' => $this->highlightPrevious(),
Key::DOWN, Key::DOWN_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::TAB, Key::CTRL_N, Key::CTRL_F, 'j', 'l' => $this->highlightNext(),
Key::ENTER => $this->submit(),
default => null,
});
Expand Down
6 changes: 3 additions & 3 deletions src/SuggestPrompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ public function __construct(
$this->reduceScrollingToFitTerminal();

$this->on('key', fn ($key) => match ($key) {
Key::UP, Key::UP_ARROW, Key::SHIFT_TAB => $this->highlightPrevious(),
Key::DOWN, Key::DOWN_ARROW, Key::TAB => $this->highlightNext(),
Key::UP, Key::UP_ARROW, Key::SHIFT_TAB, Key::CTRL_P => $this->highlightPrevious(),
Key::DOWN, Key::DOWN_ARROW, Key::TAB, Key::CTRL_N => $this->highlightNext(),
Key::ENTER => $this->selectHighlighted(),
Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW => $this->highlighted = null,
Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::CTRL_B, Key::CTRL_F => $this->highlighted = null,
default => (function () {
$this->highlighted = null;
$this->matches = null;
Expand Down
8 changes: 8 additions & 0 deletions tests/Feature/ConfirmPromptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,11 @@

expect($result)->toBeTrue();
});

test('support emacs style key binding', function () {
Prompt::fake([Key::CTRL_N, Key::ENTER]);

$result = confirm(label: 'Are you sure?');

expect($result)->toBeFalse();
});
15 changes: 15 additions & 0 deletions tests/Feature/MultiselectPromptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,18 @@

expect($result)->toBe(['Blue']);
});

it('support emacs style key binding', function () {
Prompt::fake([Key::CTRL_N, Key::SPACE, Key::CTRL_N, Key::SPACE, Key::ENTER]);

$result = multiselect(
label: 'What are your favorite colors?',
options: [
'red' => 'Red',
'green' => 'Green',
'blue' => 'Blue',
]
);

expect($result)->toBe(['green', 'blue']);
});
18 changes: 18 additions & 0 deletions tests/Feature/SearchPromptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,21 @@

expect($result)->toBe('result');
});

it('support emacs style key binding', function () {
Prompt::fake(['u', 'e', Key::CTRL_N, Key::ENTER]);

$result = search(
label: 'What is your favorite color?',
options: fn (string $value) => array_filter(
[
'red' => 'Red',
'green' => 'Green',
'blue' => 'Blue',
],
fn ($option) => str_contains(strtolower($option), strtolower($value)),
),
);

expect($result)->toBe('blue');
});
15 changes: 15 additions & 0 deletions tests/Feature/SelectPromptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,18 @@
],
],
]);

it('support emacs style key binding', function () {
Prompt::fake([Key::CTRL_N, Key::CTRL_P, Key::CTRL_N, Key::ENTER]);

$result = select(
label: 'What is your favorite color?',
options: [
'Red',
'Green',
'Blue',
]
);

expect($result)->toBe('Green');
});
13 changes: 13 additions & 0 deletions tests/Feature/SuggestPromptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,16 @@

expect($result)->toBe('result');
});

it('support emacs style key binding', function () {
Prompt::fake(['b', Key::CTRL_N, Key::CTRL_N, Key::CTRL_N, Key::CTRL_P, Key::ENTER]);

$result = suggest('What is your favorite color?', [
'Red',
'Blue',
'Black',
'Blurple',
]);

expect($result)->toBe('Black');
});
8 changes: 8 additions & 0 deletions tests/Feature/TextPromptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,11 @@

expect($result)->toBe('result');
});

test('support emacs style key binding', function () {
Prompt::fake(['J', 'z', 'e', Key::CTRL_B, Key::CTRL_H, key::CTRL_F, 's', 's', Key::ENTER]);

$result = text(label: 'What is your name?');

expect($result)->toBe('Jess');
});

0 comments on commit 532dd02

Please sign in to comment.