Skip to content

Commit

Permalink
support more readline key shortcut
Browse files Browse the repository at this point in the history
(CTRL_A, CTRL_E, CTRL_U, CTRL_W)
  • Loading branch information
storyn26383 committed Sep 14, 2023
1 parent a4b5675 commit 6cc71dd
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
26 changes: 25 additions & 1 deletion src/Concerns/TypedValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ protected function trackTypedValue(string $default = '', bool $submit = true): v
}

$this->on('key', function ($key) use ($submit) {
if ($key[0] === "\e" || in_array($key, [Key::CTRL_B, Key::CTRL_F])) {
if ($key[0] === "\e" || in_array($key, [Key::CTRL_B, Key::CTRL_F, Key::CTRL_A, Key::CTRL_E])) {
match ($key) {
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::HOME, Key::CTRL_A => $this->cursorPosition = 0,
Key::END, Key::CTRL_E => $this->cursorPosition = mb_strlen($this->typedValue),
Key::DELETE => $this->typedValue = mb_substr($this->typedValue, 0, $this->cursorPosition).mb_substr($this->typedValue, $this->cursorPosition + 1),
default => null,
};
Expand All @@ -52,6 +54,28 @@ protected function trackTypedValue(string $default = '', bool $submit = true): v

$this->typedValue = mb_substr($this->typedValue, 0, $this->cursorPosition - 1).mb_substr($this->typedValue, $this->cursorPosition);
$this->cursorPosition--;
} elseif ($key === Key::CTRL_U) {
if ($this->cursorPosition === 0) {
return;
}

$this->typedValue = mb_substr($this->typedValue, $this->cursorPosition);
$this->cursorPosition = 0;
} elseif ($key === Key::CTRL_W) {
if ($this->cursorPosition === 0) {
return;
}

$symbols = '[!@#%^&*()-=[\]{};:\'",.<>?\/\s]';
$regex = "/{$symbols}(?!{$symbols})/";
$left = mb_substr($this->typedValue, 0, $this->cursorPosition);
$words = preg_split($regex, $left, -1, PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_NO_EMPTY);
$lastWordPosition = end($words)[1];
$left = mb_substr($left, 0, $lastWordPosition);
$right = mb_substr($this->typedValue, $this->cursorPosition);

$this->typedValue = $left.$right;
$this->cursorPosition = mb_strlen($left);
} elseif (ord($key) >= 32) {
$this->typedValue = mb_substr($this->typedValue, 0, $this->cursorPosition).$key.mb_substr($this->typedValue, $this->cursorPosition);
$this->cursorPosition++;
Expand Down
12 changes: 12 additions & 0 deletions src/Key.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class Key

const SHIFT_TAB = "\e[Z";

const HOME = "\e[1~";

const END = "\e[4~";

const CTRL_C = "\x03";

const CTRL_P = "\x10";
Expand All @@ -43,4 +47,12 @@ class Key
const CTRL_B = "\x02";

const CTRL_H = "\x08";

const CTRL_A = "\x01";

const CTRL_E = "\x05";

const CTRL_U = "\x15";

const CTRL_W = "\x17";
}
24 changes: 24 additions & 0 deletions tests/Feature/TextPromptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,27 @@

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

test('move to the beginning and end of line', function () {
Prompt::fake(['e', 's', Key::HOME, 'J', KEY::END, 's', Key::ENTER]);

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

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

test('cut text to the beginning of line', function () {
Prompt::fake(['z', 'z', 'J', Key::LEFT, Key::CTRL_U, Key::RIGHT, 'e', 's', 's', Key::ENTER]);

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

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

test('cut previous word', function () {
Prompt::fake(['z', ' ', 'z', 'z', 'J', Key::LEFT, Key::CTRL_W, Key::CTRL_W, Key::RIGHT, 'e', 's', 's', Key::ENTER]);

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

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

0 comments on commit 6cc71dd

Please sign in to comment.