Clean up key mapping with more constants
This commit is contained in:
parent
24baca3cb8
commit
54bc83e1f9
@ -103,6 +103,13 @@ class ANSI {
|
|||||||
return self::seq('%dT', $lines);
|
return self::seq('%dT', $lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simplify creating ansi escape codes
|
||||||
|
*
|
||||||
|
* @param string $pattern
|
||||||
|
* @param mixed ...$args
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
private static function seq(string $pattern, ...$args): string
|
private static function seq(string $pattern, ...$args): string
|
||||||
{
|
{
|
||||||
return sprintf("\e[{$pattern}", ...$args);
|
return sprintf("\e[{$pattern}", ...$args);
|
||||||
|
126
src/Editor.php
126
src/Editor.php
@ -2,11 +2,7 @@
|
|||||||
|
|
||||||
namespace Aviat\Kilo;
|
namespace Aviat\Kilo;
|
||||||
|
|
||||||
use Aviat\Kilo\Enum\{
|
use Aviat\Kilo\Enum\{Color, KeyCode, KeyType, Highlight};
|
||||||
Color,
|
|
||||||
Key,
|
|
||||||
Highlight,
|
|
||||||
};
|
|
||||||
use Aviat\Kilo\Tokens\PHP;
|
use Aviat\Kilo\Tokens\PHP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,40 +88,42 @@ class Editor {
|
|||||||
{
|
{
|
||||||
$c = read_stdin();
|
$c = read_stdin();
|
||||||
|
|
||||||
// @TODO Make this more DRY
|
$simpleMap = [
|
||||||
switch ($c)
|
KeyCode::ARROW_DOWN => KeyType::ARROW_DOWN,
|
||||||
|
KeyCode::ARROW_LEFT => KeyType::ARROW_LEFT,
|
||||||
|
KeyCode::ARROW_RIGHT => KeyType::ARROW_RIGHT,
|
||||||
|
KeyCode::ARROW_UP => KeyType::ARROW_UP,
|
||||||
|
KeyCode::BACKSPACE => KeyType::BACKSPACE,
|
||||||
|
KeyCode::DEL_KEY => KeyType::DEL_KEY,
|
||||||
|
KeyCode::ENTER => KeyType::ENTER,
|
||||||
|
KeyCode::ESCAPE => KeyType::ESCAPE,
|
||||||
|
KeyCode::PAGE_DOWN => KeyType::PAGE_DOWN,
|
||||||
|
KeyCode::PAGE_UP => KeyType::PAGE_UP,
|
||||||
|
];
|
||||||
|
|
||||||
|
$multiMap = [
|
||||||
|
"\eOH" => KeyType::HOME_KEY,
|
||||||
|
"\e[1~" => KeyType::HOME_KEY,
|
||||||
|
"\e[7~" => KeyType::HOME_KEY,
|
||||||
|
ANSI::RESET_CURSOR => KeyType::HOME_KEY,
|
||||||
|
|
||||||
|
"\eOF" => KeyType::END_KEY,
|
||||||
|
"\e[4~" => KeyType::END_KEY,
|
||||||
|
"\e[8~" => KeyType::END_KEY,
|
||||||
|
"\e[F" => KeyType::END_KEY,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (array_key_exists($c, $simpleMap))
|
||||||
{
|
{
|
||||||
case "\x7f": return Key::BACKSPACE;
|
return $simpleMap[$c];
|
||||||
|
|
||||||
case "\r": return Key::ENTER;
|
|
||||||
|
|
||||||
case "\e[A": return Key::ARROW_UP;
|
|
||||||
case "\e[B": return Key::ARROW_DOWN;
|
|
||||||
case "\e[C": return Key::ARROW_RIGHT;
|
|
||||||
case "\e[D": return Key::ARROW_LEFT;
|
|
||||||
|
|
||||||
case "\e[3~": return Key::DEL_KEY;
|
|
||||||
|
|
||||||
case "\e[5~": return Key::PAGE_UP;
|
|
||||||
case "\e[6~": return Key::PAGE_DOWN;
|
|
||||||
|
|
||||||
case "\eOH":
|
|
||||||
case "\e[1~":
|
|
||||||
case "\e[7~":
|
|
||||||
case ANSI::RESET_CURSOR:
|
|
||||||
return Key::HOME_KEY;
|
|
||||||
|
|
||||||
case "\eOF":
|
|
||||||
case "\e[4~":
|
|
||||||
case "\e[8~":
|
|
||||||
case "\e[F":
|
|
||||||
return Key::END_KEY;
|
|
||||||
|
|
||||||
case "\e":
|
|
||||||
return Key::ESCAPE;
|
|
||||||
|
|
||||||
default: return $c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (array_key_exists($c, $multiMap))
|
||||||
|
{
|
||||||
|
return $multiMap[$c];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function selectSyntaxHighlight(): void
|
protected function selectSyntaxHighlight(): void
|
||||||
@ -435,11 +433,11 @@ class Editor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($key === Key::ARROW_RIGHT || $key === Key::ARROW_DOWN)
|
if ($key === KeyType::ARROW_RIGHT || $key === KeyType::ARROW_DOWN)
|
||||||
{
|
{
|
||||||
$direction = 1;
|
$direction = 1;
|
||||||
}
|
}
|
||||||
else if ($key === Key::ARROW_LEFT || $key === Key::ARROW_UP)
|
else if ($key === KeyType::ARROW_LEFT || $key === KeyType::ARROW_UP)
|
||||||
{
|
{
|
||||||
$direction = -1;
|
$direction = -1;
|
||||||
}
|
}
|
||||||
@ -730,7 +728,7 @@ class Editor {
|
|||||||
protected function prompt(string $prompt, ?callable $callback = NULL): string
|
protected function prompt(string $prompt, ?callable $callback = NULL): string
|
||||||
{
|
{
|
||||||
$buffer = '';
|
$buffer = '';
|
||||||
$modifiers = Key::getConstList();
|
$modifiers = KeyType::getConstList();
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
$this->setStatusMessage($prompt, $buffer);
|
$this->setStatusMessage($prompt, $buffer);
|
||||||
@ -738,7 +736,7 @@ class Editor {
|
|||||||
|
|
||||||
$c = $this->readKey();
|
$c = $this->readKey();
|
||||||
|
|
||||||
if ($c === Key::ESCAPE)
|
if ($c === KeyType::ESCAPE)
|
||||||
{
|
{
|
||||||
$this->setStatusMessage('');
|
$this->setStatusMessage('');
|
||||||
if ($callback !== NULL)
|
if ($callback !== NULL)
|
||||||
@ -748,7 +746,7 @@ class Editor {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($c === Key::ENTER && $buffer !== '')
|
if ($c === KeyType::ENTER && $buffer !== '')
|
||||||
{
|
{
|
||||||
$this->setStatusMessage('');
|
$this->setStatusMessage('');
|
||||||
if ($callback !== NULL)
|
if ($callback !== NULL)
|
||||||
@ -758,7 +756,7 @@ class Editor {
|
|||||||
return $buffer;
|
return $buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($c === Key::DEL_KEY || $c === Key::BACKSPACE || $c === chr(ctrl_key('h')))
|
if ($c === KeyType::DEL_KEY || $c === KeyType::BACKSPACE || $c === chr(ctrl_key('h')))
|
||||||
{
|
{
|
||||||
$buffer = substr($buffer, 0, -1);
|
$buffer = substr($buffer, 0, -1);
|
||||||
}
|
}
|
||||||
@ -782,7 +780,7 @@ class Editor {
|
|||||||
|
|
||||||
switch ($key)
|
switch ($key)
|
||||||
{
|
{
|
||||||
case Key::ARROW_LEFT:
|
case KeyType::ARROW_LEFT:
|
||||||
if ($this->cursorX !== 0)
|
if ($this->cursorX !== 0)
|
||||||
{
|
{
|
||||||
$this->cursorX--;
|
$this->cursorX--;
|
||||||
@ -794,7 +792,7 @@ class Editor {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::ARROW_RIGHT:
|
case KeyType::ARROW_RIGHT:
|
||||||
if ($row && $this->cursorX < $row->size)
|
if ($row && $this->cursorX < $row->size)
|
||||||
{
|
{
|
||||||
$this->cursorX++;
|
$this->cursorX++;
|
||||||
@ -806,14 +804,14 @@ class Editor {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::ARROW_UP:
|
case KeyType::ARROW_UP:
|
||||||
if ($this->cursorY !== 0)
|
if ($this->cursorY !== 0)
|
||||||
{
|
{
|
||||||
$this->cursorY--;
|
$this->cursorY--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::ARROW_DOWN:
|
case KeyType::ARROW_DOWN:
|
||||||
if ($this->cursorY < $this->numRows)
|
if ($this->cursorY < $this->numRows)
|
||||||
{
|
{
|
||||||
$this->cursorY++;
|
$this->cursorY++;
|
||||||
@ -844,7 +842,7 @@ class Editor {
|
|||||||
|
|
||||||
switch ($c)
|
switch ($c)
|
||||||
{
|
{
|
||||||
case Key::ENTER:
|
case KeyType::ENTER:
|
||||||
$this->insertNewline();
|
$this->insertNewline();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -865,11 +863,11 @@ class Editor {
|
|||||||
$this->save();
|
$this->save();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::HOME_KEY:
|
case KeyType::HOME_KEY:
|
||||||
$this->cursorX = 0;
|
$this->cursorX = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::END_KEY:
|
case KeyType::END_KEY:
|
||||||
if ($this->cursorY < $this->numRows)
|
if ($this->cursorY < $this->numRows)
|
||||||
{
|
{
|
||||||
$this->cursorX = $this->rows[$this->cursorY]->size - 1;
|
$this->cursorX = $this->rows[$this->cursorY]->size - 1;
|
||||||
@ -880,30 +878,30 @@ class Editor {
|
|||||||
$this->find();
|
$this->find();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::BACKSPACE:
|
case KeyType::BACKSPACE:
|
||||||
case chr(ctrl_key('h')):
|
case chr(ctrl_key('h')):
|
||||||
case Key::DEL_KEY:
|
case KeyType::DEL_KEY:
|
||||||
if ($c === Key::DEL_KEY)
|
if ($c === KeyType::DEL_KEY)
|
||||||
{
|
{
|
||||||
$this->moveCursor(Key::ARROW_RIGHT);
|
$this->moveCursor(KeyType::ARROW_RIGHT);
|
||||||
}
|
}
|
||||||
$this->deleteChar();
|
$this->deleteChar();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::PAGE_UP:
|
case KeyType::PAGE_UP:
|
||||||
case Key::PAGE_DOWN:
|
case KeyType::PAGE_DOWN:
|
||||||
$this->pageUpOrDown($c);
|
$this->pageUpOrDown($c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::ARROW_UP:
|
case KeyType::ARROW_UP:
|
||||||
case Key::ARROW_DOWN:
|
case KeyType::ARROW_DOWN:
|
||||||
case Key::ARROW_LEFT:
|
case KeyType::ARROW_LEFT:
|
||||||
case Key::ARROW_RIGHT:
|
case KeyType::ARROW_RIGHT:
|
||||||
$this->moveCursor($c);
|
$this->moveCursor($c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case chr(ctrl_key('l')):
|
case chr(ctrl_key('l')):
|
||||||
case Key::ESCAPE:
|
case KeyType::ESCAPE:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -919,11 +917,11 @@ class Editor {
|
|||||||
|
|
||||||
private function pageUpOrDown(string $c): void
|
private function pageUpOrDown(string $c): void
|
||||||
{
|
{
|
||||||
if ($c === Key::PAGE_UP)
|
if ($c === KeyType::PAGE_UP)
|
||||||
{
|
{
|
||||||
$this->cursorY = $this->rowOffset;
|
$this->cursorY = $this->rowOffset;
|
||||||
}
|
}
|
||||||
else if ($c === Key::PAGE_DOWN)
|
else if ($c === KeyType::PAGE_DOWN)
|
||||||
{
|
{
|
||||||
$this->cursorY = $this->rowOffset + $this->screenRows - 1;
|
$this->cursorY = $this->rowOffset + $this->screenRows - 1;
|
||||||
if ($this->cursorY > $this->numRows)
|
if ($this->cursorY > $this->numRows)
|
||||||
@ -935,7 +933,7 @@ class Editor {
|
|||||||
$times = $this->screenRows;
|
$times = $this->screenRows;
|
||||||
for (; $times > 0; $times--)
|
for (; $times > 0; $times--)
|
||||||
{
|
{
|
||||||
$this->moveCursor($c === Key::PAGE_UP ? Key::ARROW_UP : Key::ARROW_DOWN);
|
$this->moveCursor($c === KeyType::PAGE_UP ? KeyType::ARROW_UP : KeyType::ARROW_DOWN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
src/Enum/Event.php
Normal file
12
src/Enum/Event.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Aviat\Kilo\Enum;
|
||||||
|
|
||||||
|
use Aviat\Kilo\Traits;
|
||||||
|
|
||||||
|
class Event {
|
||||||
|
use Traits\ConstList;
|
||||||
|
|
||||||
|
public const INPUT_KEY = 'INPUT_KEY';
|
||||||
|
public const QUIT_ATTEMPT = 'QUIT_ATTEMPT';
|
||||||
|
}
|
20
src/Enum/KeyCode.php
Normal file
20
src/Enum/KeyCode.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Aviat\Kilo\Enum;
|
||||||
|
|
||||||
|
use Aviat\Kilo\Traits;
|
||||||
|
|
||||||
|
class KeyCode {
|
||||||
|
use Traits\ConstList;
|
||||||
|
|
||||||
|
public const ARROW_DOWN = "\e[B";
|
||||||
|
public const ARROW_LEFT = "\e[D";
|
||||||
|
public const ARROW_RIGHT = "\e[C";
|
||||||
|
public const ARROW_UP = "\e[A";
|
||||||
|
public const BACKSPACE = "\x7f";
|
||||||
|
public const DEL_KEY = "\e[3~";
|
||||||
|
public const ENTER = "\r";
|
||||||
|
public const ESCAPE = "\e";
|
||||||
|
public const PAGE_DOWN = "\e[6~";
|
||||||
|
public const PAGE_UP = "\e[5~";
|
||||||
|
}
|
@ -4,7 +4,7 @@ namespace Aviat\Kilo\Enum;
|
|||||||
|
|
||||||
use Aviat\Kilo\Traits;
|
use Aviat\Kilo\Traits;
|
||||||
|
|
||||||
class Key {
|
class KeyType {
|
||||||
use Traits\ConstList;
|
use Traits\ConstList;
|
||||||
|
|
||||||
public const ARROW_DOWN = 'ARROW_DOWN';
|
public const ARROW_DOWN = 'ARROW_DOWN';
|
Loading…
Reference in New Issue
Block a user