Cut down on number of keycode escapes with constants
All checks were successful
timw4mail/php-kilo/master This commit looks good

This commit is contained in:
Timothy Warren 2020-01-29 16:13:05 -05:00
parent a47b527a28
commit 60b1cca695
8 changed files with 52 additions and 46 deletions

View File

@ -177,7 +177,7 @@ class Editor {
$rx = 0; $rx = 0;
for ($i = 0; $i < $cx; $i++) for ($i = 0; $i < $cx; $i++)
{ {
if ($row->chars[$i] === "\t") if ($row->chars[$i] === KeyCode::TAB)
{ {
$rx += (KILO_TAB_STOP - 1) - ($rx % KILO_TAB_STOP); $rx += (KILO_TAB_STOP - 1) - ($rx % KILO_TAB_STOP);
} }
@ -192,7 +192,7 @@ class Editor {
$cur_rx = 0; $cur_rx = 0;
for ($cx = 0; $cx < $row->size; $cx++) for ($cx = 0; $cx < $row->size; $cx++)
{ {
if ($row->chars[$cx] === "\t") if ($row->chars[$cx] === KeyCode::TAB)
{ {
$cur_rx += (KILO_TAB_STOP - 1) - ($cur_rx % KILO_TAB_STOP); $cur_rx += (KILO_TAB_STOP - 1) - ($cur_rx % KILO_TAB_STOP);
} }
@ -426,7 +426,7 @@ class Editor {
$savedHl = []; $savedHl = [];
} }
if ($key === "\r" || $key === "\e") if ($key === KeyCode::ENTER || $key === KeyCode::ESCAPE)
{ {
$lastMatch = -1; $lastMatch = -1;
$direction = 1; $direction = 1;
@ -598,7 +598,7 @@ class Editor {
for ($i = 0; $i < $len; $i++) for ($i = 0; $i < $len; $i++)
{ {
// Handle 'non-printable' characters // Handle 'non-printable' characters
if (is_cntrl($c[$i])) if (is_ctrl($c[$i]))
{ {
$sym = (ord($c[$i]) <= 26) $sym = (ord($c[$i]) <= 26)
? chr(ord('@') + ord($c[$i])) ? chr(ord('@') + ord($c[$i]))
@ -760,7 +760,7 @@ class Editor {
{ {
$buffer = substr($buffer, 0, -1); $buffer = substr($buffer, 0, -1);
} }
else if (is_ascii($c) && ( ! is_cntrl($c)) && ! in_array($c, $modifiers, TRUE)) else if (is_ascii($c) && ( ! is_ctrl($c)) && ! in_array($c, $modifiers, TRUE))
{ {
$buffer .= $c; $buffer .= $c;
} }
@ -835,7 +835,7 @@ class Editor {
$c = $this->readKey(); $c = $this->readKey();
if ($c === "\0" || $c === '') if ($c === KeyCode::NULL || $c === KeyCode::EMPTY)
{ {
return ''; return '';
} }

View File

@ -1,12 +0,0 @@
<?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';
}

View File

@ -12,9 +12,17 @@ class KeyCode {
public const ARROW_RIGHT = "\e[C"; public const ARROW_RIGHT = "\e[C";
public const ARROW_UP = "\e[A"; public const ARROW_UP = "\e[A";
public const BACKSPACE = "\x7f"; public const BACKSPACE = "\x7f";
public const CARRIAGE_RETURN = "\r";
public const DEL_KEY = "\e[3~"; public const DEL_KEY = "\e[3~";
public const EMPTY = '';
public const ENTER = "\r"; public const ENTER = "\r";
public const ESCAPE = "\e"; public const ESCAPE = "\e";
public const FORM_FEED = "\f";
public const NEWLINE = "\n";
public const NULL = "\0";
public const PAGE_DOWN = "\e[6~"; public const PAGE_DOWN = "\e[6~";
public const PAGE_UP = "\e[5~"; public const PAGE_UP = "\e[5~";
public const SPACE = ' ';
public const TAB = "\t";
public const VERTICAL_TAB = "\v";
} }

View File

@ -2,9 +2,18 @@
namespace Aviat\Kilo; namespace Aviat\Kilo;
use Aviat\Kilo\Enum\Event as EventEnum;
class Event { class Event {
use Traits\ConstList;
// ------------------------------------------------------------------------
// Valid Events
// ------------------------------------------------------------------------
public const INPUT_KEY = 'INPUT_KEY';
public const PAGE_CHANGE = 'PAGE_CHANGE';
public const MOVE_CURSOR = 'MOVE_CURSOR';
public const QUIT_ATTEMPT = 'QUIT_ATTEMPT';
// Mapping of events to handlers
private static $subscribeMap = []; private static $subscribeMap = [];
public static function fire(string $eventName, $value): void public static function fire(string $eventName, $value): void
@ -20,7 +29,7 @@ class Event {
} }
} }
public static function bind(string $eventName, callable $fn): void public static function on(string $eventName, callable $fn): void
{ {
static::validateEvent($eventName); static::validateEvent($eventName);
@ -37,11 +46,11 @@ class Event {
private static function validateEvent(string $eventName): void private static function validateEvent(string $eventName): void
{ {
$validEvents = EventEnum::getConstList(); $validEvents = self::getConstList();
if ( ! array_key_exists($eventName, $validEvents)) if ( ! array_key_exists($eventName, $validEvents))
{ {
throw new \InvalidArgumentException("Invalid event '{$eventName}'. Event const must exist in Aviat\\Kilo\\Enum\\Event."); throw new \InvalidArgumentException("Invalid event '{$eventName}'. Event const must exist in Aviat\\Kilo\\Event.");
} }
} }
} }

View File

@ -3,6 +3,7 @@
namespace Aviat\Kilo; namespace Aviat\Kilo;
use Aviat\Kilo\Enum\Highlight; use Aviat\Kilo\Enum\Highlight;
use Aviat\Kilo\Enum\KeyCode;
/** /**
* @property-read int size * @property-read int size
@ -413,7 +414,7 @@ class Row {
$klen = strlen($k); $klen = strlen($k);
$nextCharOffset = $i + $klen; $nextCharOffset = $i + $klen;
$isEndOfLine = $nextCharOffset >= $this->rsize; $isEndOfLine = $nextCharOffset >= $this->rsize;
$nextChar = ($isEndOfLine) ? "\0" : $this->render[$nextCharOffset]; $nextChar = ($isEndOfLine) ? KeyCode::NULL : $this->render[$nextCharOffset];
if (substr($this->render, $i, $klen) === $k && is_separator($nextChar)) if (substr($this->render, $i, $klen) === $k && is_separator($nextChar))
{ {

View File

@ -4,11 +4,7 @@ namespace Aviat\Kilo;
use FFI; use FFI;
use Aviat\Kilo\Enum\{ use Aviat\Kilo\Enum\{C, Color, Highlight, KeyCode};
C,
Color,
Highlight,
};
/** /**
* See if tput exists for fallback terminal size detection * See if tput exists for fallback terminal size detection
@ -18,7 +14,7 @@ use Aviat\Kilo\Enum\{
*/ */
function has_tput(): bool function has_tput(): bool
{ {
return strpos(shell_exec('type tput'), ' is ') !== FALSE; return str_contains(shell_exec('type tput'), ' is ');
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -104,7 +100,7 @@ function is_ascii(string $single_char): bool
* @param string $char * @param string $char
* @return bool * @return bool
*/ */
function is_cntrl(string $char): bool function is_ctrl(string $char): bool
{ {
$c = ord($char); $c = ord($char);
return is_ascii($char) && ( $c === 0x7f || $c < 0x20 ); return is_ascii($char) && ( $c === 0x7f || $c < 0x20 );
@ -130,7 +126,14 @@ function is_digit(string $char): bool
*/ */
function is_space(string $char): bool function is_space(string $char): bool
{ {
$ws = [' ', "\t", "\n", "\r", "\v", "\f"]; $ws = [
KeyCode::CARRIAGE_RETURN,
KeyCode::FORM_FEED,
KeyCode::NEWLINE,
KeyCode::SPACE,
KeyCode::TAB,
KeyCode::VERTICAL_TAB,
];
return is_ascii($char) && in_array($char, $ws, TRUE); return is_ascii($char) && in_array($char, $ws, TRUE);
} }
@ -168,11 +171,9 @@ function is_separator(string $char): bool
return FALSE; return FALSE;
} }
// `strpos` is used instead of `strchr`/`strstr` as we don't care about the actual match $isSep = str_contains(',.()+-/*=~%<>[];', $char);
// while `strchr` would match the C version, it also returns the match
$isSep = (strpos(',.()+-/*=~%<>[];', $char) !== FALSE);
return is_space($char) || $char === "\0" || $isSep; return is_space($char) || $char === KeyCode::NULL || $isSep;
} }
/** /**
@ -287,7 +288,7 @@ function syntax_to_color(int $hl): int
*/ */
function tabs_to_spaces(string $str, ?int $number = KILO_TAB_STOP): string function tabs_to_spaces(string $str, ?int $number = KILO_TAB_STOP): string
{ {
return str_replace("\t", str_repeat(' ', $number), $str); return str_replace(KeyCode::TAB, str_repeat(KeyCode::SPACE, $number), $str);
} }
/** /**

View File

@ -3,7 +3,6 @@
namespace Aviat\Kilo\Tests; namespace Aviat\Kilo\Tests;
use Aviat\Kilo\Event; use Aviat\Kilo\Event;
use Aviat\Kilo\Enum\Event as EventType;
use InvalidArgumentException; use InvalidArgumentException;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -11,7 +10,7 @@ class EventTest extends TestCase {
public function testRequiresValidEvent(): void public function testRequiresValidEvent(): void
{ {
$this->expectException(InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
Event::bind('badEventName', fn () => null); Event::on('badEventName', fn () => null);
$this->expectException(InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
Event::fire('badEventName', []); Event::fire('badEventName', []);
@ -22,7 +21,7 @@ class EventTest extends TestCase {
$fn = static function($value = false) { $fn = static function($value = false) {
static::assertTrue($value); static::assertTrue($value);
}; };
Event::bind(EventType::INPUT_KEY, $fn); Event::on(Event::INPUT_KEY, $fn);
Event::fire(EventType::INPUT_KEY, TRUE); Event::fire(Event::INPUT_KEY, TRUE);
} }
} }

View File

@ -11,7 +11,7 @@ use function Aviat\Kilo\ctrl_key;
use function Aviat\Kilo\get_file_syntax_map; use function Aviat\Kilo\get_file_syntax_map;
use function Aviat\Kilo\get_window_size; use function Aviat\Kilo\get_window_size;
use function Aviat\Kilo\is_ascii; use function Aviat\Kilo\is_ascii;
use function Aviat\Kilo\is_cntrl; use function Aviat\Kilo\is_ctrl;
use function Aviat\Kilo\is_digit; use function Aviat\Kilo\is_digit;
use function Aviat\Kilo\is_separator; use function Aviat\Kilo\is_separator;
use function Aviat\Kilo\is_space; use function Aviat\Kilo\is_space;
@ -42,22 +42,22 @@ class FunctionTest extends TestCase {
$this->assertEquals(0x01, ctrl_key('a')); $this->assertEquals(0x01, ctrl_key('a'));
} }
public function test_is_cntrl(): void public function test_is_ctrl(): void
{ {
for ($i = 0x0; $i < 0x20; $i++) for ($i = 0x0; $i < 0x20; $i++)
{ {
$char = chr($i); $char = chr($i);
$this->assertTrue(is_cntrl($char), 'Should be a control character'); $this->assertTrue(is_ctrl($char), 'Should be a control character');
} }
for ($n = 0x20; $n < 0x7f; $n++) for ($n = 0x20; $n < 0x7f; $n++)
{ {
$char = chr($n); $char = chr($n);
$this->assertFalse(is_cntrl($char), 'Should not be a control character'); $this->assertFalse(is_ctrl($char), 'Should not be a control character');
} }
// Escape, code 7f, is an outlier // Escape, code 7f, is an outlier
$this->assertTrue(is_cntrl(chr(0x7f))); $this->assertTrue(is_ctrl(chr(0x7f)));
} }
public function test_is_space(): void public function test_is_space(): void