diff --git a/README.md b/README.md index 878efd2..af004df 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PHP Kilo -[![Build Status](https://jenkins.timshomepage.net/buildStatus/icon?job=Gitea+-+Tutorials%2Fphp-kilo%2Fmaster)](https://jenkins.timshomepage.net/job/Gitea%20-%20Tutorials/job/php-kilo/job/master/) +[![Build Status](https://jenkins.timshomepage.net/buildStatus/icon?job=timw4mail%2Fphp-kilo%2Fmaster)](https://jenkins.timshomepage.net/job/timw4mail/job/php-kilo/job/master/) A reimplementation of the [Kilo](https://viewsourcecode.org/snaptoken/kilo/index.html) tutorial in PHP. Requires PHP 7.4, due to requiring the `FFI` extension. diff --git a/composer.lock b/composer.lock index 19f077e..1e23b8b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f11505a6676b236651e7784cfcd62ec8", + "content-hash": "6fa43d16a15a27c27d5070fe477fd13f", "packages": [], "packages-dev": [ { @@ -65,16 +65,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.9.3", + "version": "1.9.5", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef", + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef", "shasum": "" }, "require": { @@ -109,7 +109,7 @@ "object", "object graph" ], - "time": "2019-08-09T12:45:53+00:00" + "time": "2020-01-17T21:11:47+00:00" }, { "name": "phar-io/manifest", @@ -267,16 +267,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.2", + "version": "4.3.4", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", - "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", "shasum": "" }, "require": { @@ -288,6 +288,7 @@ "require-dev": { "doctrine/instantiator": "^1.0.5", "mockery/mockery": "^1.0", + "phpdocumentor/type-resolver": "0.4.*", "phpunit/phpunit": "^6.4" }, "type": "library", @@ -314,7 +315,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-09-12T14:27:41+00:00" + "time": "2019-12-28T18:55:12+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -365,33 +366,33 @@ }, { "name": "phpspec/prophecy", - "version": "1.9.0", + "version": "v1.10.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203" + "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203", - "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b4400efc9d206e83138e2bb97ed7f5b14b831cd9", + "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", + "phpspec/phpspec": "^2.5 || ^3.2", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { @@ -424,7 +425,7 @@ "spy", "stub" ], - "time": "2019-10-03T11:07:50+00:00" + "time": "2020-01-20T15:57:02+00:00" }, { "name": "phpunit/php-code-coverage", @@ -680,16 +681,16 @@ }, { "name": "phpunit/phpunit", - "version": "8.4.3", + "version": "8.5.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "67f9e35bffc0dd52d55d565ddbe4230454fd6a4e" + "reference": "018b6ac3c8ab20916db85fa91bf6465acb64d1e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/67f9e35bffc0dd52d55d565ddbe4230454fd6a4e", - "reference": "67f9e35bffc0dd52d55d565ddbe4230454fd6a4e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/018b6ac3c8ab20916db85fa91bf6465acb64d1e0", + "reference": "018b6ac3c8ab20916db85fa91bf6465acb64d1e0", "shasum": "" }, "require": { @@ -733,7 +734,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "8.4-dev" + "dev-master": "8.5-dev" } }, "autoload": { @@ -759,7 +760,7 @@ "testing", "xunit" ], - "time": "2019-11-06T09:42:23+00:00" + "time": "2020-01-08T08:49:49+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1378,23 +1379,23 @@ }, { "name": "spatie/phpunit-snapshot-assertions", - "version": "2.2.0", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/spatie/phpunit-snapshot-assertions.git", - "reference": "7da647e383d5ba960b384a45e8bd59c4211b366d" + "reference": "cc6769ab92a41d1d58d72f228e15d82d180f0b44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/phpunit-snapshot-assertions/zipball/7da647e383d5ba960b384a45e8bd59c4211b366d", - "reference": "7da647e383d5ba960b384a45e8bd59c4211b366d", + "url": "https://api.github.com/repos/spatie/phpunit-snapshot-assertions/zipball/cc6769ab92a41d1d58d72f228e15d82d180f0b44", + "reference": "cc6769ab92a41d1d58d72f228e15d82d180f0b44", "shasum": "" }, "require": { "ext-dom": "*", "php": "^7.2", "phpunit/phpunit": "^8.0", - "symfony/yaml": "^4.0" + "symfony/yaml": "^4.0|^5.0" }, "type": "library", "autoload": { @@ -1424,20 +1425,20 @@ "spatie", "testing" ], - "time": "2019-10-23T15:00:34+00:00" + "time": "2019-11-21T23:15:29+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.12.0", + "version": "v1.13.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "550ebaac289296ce228a706d0867afc34687e3f4" + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", - "reference": "550ebaac289296ce228a706d0867afc34687e3f4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", "shasum": "" }, "require": { @@ -1449,7 +1450,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.12-dev" + "dev-master": "1.13-dev" } }, "autoload": { @@ -1482,31 +1483,31 @@ "polyfill", "portable" ], - "time": "2019-08-06T08:03:45+00:00" + "time": "2019-11-27T13:56:44+00:00" }, { "name": "symfony/yaml", - "version": "v4.3.8", + "version": "v5.0.4", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "324cf4b19c345465fad14f3602050519e09e361d" + "reference": "69b44e3b8f90949aee2eb3aa9b86ceeb01cbf62a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/324cf4b19c345465fad14f3602050519e09e361d", - "reference": "324cf4b19c345465fad14f3602050519e09e361d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/69b44e3b8f90949aee2eb3aa9b86ceeb01cbf62a", + "reference": "69b44e3b8f90949aee2eb3aa9b86ceeb01cbf62a", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": "^7.2.5", "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/console": "<3.4" + "symfony/console": "<4.4" }, "require-dev": { - "symfony/console": "~3.4|~4.0" + "symfony/console": "^4.4|^5.0" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" @@ -1514,7 +1515,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.3-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -1541,7 +1542,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2019-10-30T12:58:49+00:00" + "time": "2020-01-21T11:12:28+00:00" }, { "name": "theseer/tokenizer", @@ -1585,31 +1586,29 @@ }, { "name": "webmozart/assert", - "version": "1.5.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", - "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", + "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925", + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925", "shasum": "" }, "require": { "php": "^5.3.3 || ^7.0", "symfony/polyfill-ctype": "^1.8" }, + "conflict": { + "vimeo/psalm": "<3.6.0" + }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -1631,7 +1630,7 @@ "check", "validate" ], - "time": "2019-08-24T08:43:50+00:00" + "time": "2019-11-24T13:36:37+00:00" } ], "aliases": [], @@ -1642,5 +1641,7 @@ "platform": { "ext-ffi": "*" }, - "platform-dev": [] + "platform-dev": { + "ext-json": "*" + } } diff --git a/src/Editor.php b/src/Editor.php index 61d67b3..1d9d607 100644 --- a/src/Editor.php +++ b/src/Editor.php @@ -135,35 +135,25 @@ class Editor { } // In PHP, `strchr` and `strstr` are the same function - $ext = (string)strstr($this->filename, '.'); + $ext = (string)strstr(basename($this->filename), '.'); foreach (get_file_syntax_map() as $syntax) { - foreach ($syntax->filematch as $searchExt) - { - $is_ext = (strpos($searchExt, '.') === 0); - if ( - ($is_ext && ( ! strcmp($ext, $searchExt))) || - (( ! $is_ext) && strpos($this->filename, $searchExt) !== FALSE) - ) { - $this->syntax = $syntax; + if ( + in_array($ext, $syntax->filematch, TRUE) || + in_array(basename($this->filename), $syntax->filematch, TRUE) + ) { + $this->syntax = $syntax; - // Pre-tokenize the file - if ($this->syntax->filetype === 'PHP') - { - $this->tokens = PHP::getFileTokens($this->filename); - } - - // Update the syntax highlighting for all the rows of the file - for ($i = 0; $i < $this->numRows; $i++) - { - // @codeCoverageIgnoreStart - $this->rows[$i]->updateSyntax(); - // @codeCoverageIgnoreEnd - } - - return; + // Pre-tokenize the file + if ($this->syntax->filetype === 'PHP') + { + $this->tokens = PHP::getFileTokens($this->filename); } + + $this->refreshSyntax(); + + return; } } } @@ -177,7 +167,7 @@ class Editor { $rx = 0; 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); } @@ -192,7 +182,7 @@ class Editor { $cur_rx = 0; 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); } @@ -231,12 +221,6 @@ class Editor { ksort($this->rows); - // Update row indexes - for ($i = 0; $i < $this->numRows; $i++) - { - $this->rows[$i]->idx = $i; - } - $this->rows[$at]->update(); $this->dirty++; @@ -358,15 +342,11 @@ class Editor { $this->selectSyntaxHighlight(); - // #TODO gracefully handle issues with loading a file $handle = fopen($filename, 'rb'); if ($handle === FALSE) { - write_stdout(ANSI::CLEAR_SCREEN); - write_stdout(ANSI::RESET_CURSOR); // Reposition cursor to top-left - Termios::disableRawMode(); - print_r(error_get_last()); - die(); + $this->setStatusMessage('Failed to open file: %s', $filename); + return; } while (($line = fgets($handle)) !== FALSE) @@ -426,25 +406,27 @@ class Editor { $savedHl = []; } - if ($key === "\r" || $key === "\e") + switch ($key) { - $lastMatch = -1; - $direction = 1; - return; - } + case KeyCode::ENTER: + case KeyCode::ESCAPE: + $lastMatch = -1; + $direction = 1; + return; - if ($key === KeyType::ARROW_RIGHT || $key === KeyType::ARROW_DOWN) - { - $direction = 1; - } - else if ($key === KeyType::ARROW_LEFT || $key === KeyType::ARROW_UP) - { - $direction = -1; - } - else - { - $lastMatch = -1; - $direction = 1; + case KeyType::ARROW_DOWN: + case KeyType::ARROW_RIGHT: + $direction = 1; + break; + + case KeyType::ARROW_UP: + case KeyType::ARROW_LEFT: + $direction = -1; + break; + + default: + $lastMatch = -1; + $direction = 1; } if ($lastMatch === -1) @@ -452,11 +434,6 @@ class Editor { $direction = 1; } - if (empty($query)) - { - return; - } - $current = $lastMatch; for ($i = 0; $i < $this->numRows; $i++) @@ -598,7 +575,7 @@ class Editor { for ($i = 0; $i < $len; $i++) { // Handle 'non-printable' characters - if (is_cntrl($c[$i])) + if (is_ctrl($c[$i])) { $sym = (ord($c[$i]) <= 26) ? chr(ord('@') + ord($c[$i])) @@ -736,7 +713,7 @@ class Editor { $c = $this->readKey(); - if ($c === KeyType::ESCAPE) + if ($c === KeyType::ESCAPE || ($c === KeyType::ENTER && $buffer !== '')) { $this->setStatusMessage(''); if ($callback !== NULL) @@ -746,21 +723,11 @@ class Editor { return ''; } - if ($c === KeyType::ENTER && $buffer !== '') - { - $this->setStatusMessage(''); - if ($callback !== NULL) - { - $callback($buffer, $c); - } - return $buffer; - } - - if ($c === KeyType::DEL_KEY || $c === KeyType::BACKSPACE || $c === chr(ctrl_key('h'))) + if ($c === KeyType::DEL_KEY || $c === KeyType::BACKSPACE || KeyType::CTRL('h')) { $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; } @@ -835,7 +802,7 @@ class Editor { $c = $this->readKey(); - if ($c === "\0" || $c === '') + if ($c === KeyCode::NULL || $c === KeyCode::EMPTY) { return ''; } @@ -846,7 +813,7 @@ class Editor { $this->insertNewline(); break; - case chr(ctrl_key('q')): + case KeyType::CTRL('q'): if ($this->dirty > 0 && $quit_times > 0) { $this->setStatusMessage('WARNING!!! File has unsaved changes.' . @@ -859,7 +826,7 @@ class Editor { return NULL; break; - case chr(ctrl_key('s')): + case KeyType::CTRL('s'): $this->save(); break; @@ -874,12 +841,12 @@ class Editor { } break; - case chr(ctrl_key('f')): + case KeyType::CTRL('f'): $this->find(); break; case KeyType::BACKSPACE: - case chr(ctrl_key('h')): + case KeyType::CTRL('h'): case KeyType::DEL_KEY: if ($c === KeyType::DEL_KEY) { @@ -900,7 +867,7 @@ class Editor { $this->moveCursor($c); break; - case chr(ctrl_key('l')): + case KeyType::CTRL('l'): case KeyType::ESCAPE: // Do nothing break; @@ -915,7 +882,7 @@ class Editor { return $c; } - private function pageUpOrDown(string $c): void + public function pageUpOrDown(string $c): void { if ($c === KeyType::PAGE_UP) { @@ -937,6 +904,12 @@ class Editor { } } + protected function refreshSyntax(): void + { + // Update the syntax highlighting for all the rows of the file + array_walk($this->rows, fn (Row $row) => $row->updateSyntax()); + } + private function refreshPHPSyntax(): void { if ($this->syntax->filetype !== 'PHP') @@ -945,9 +918,6 @@ class Editor { } $this->tokens = PHP::getTokens($this->rowsToString()); - for ($i = 0; $i < $this->numRows; $i++) - { - $this->rows[$i]->update(); - } + $this->refreshSyntax(); } } diff --git a/src/Enum/Event.php b/src/Enum/Event.php deleted file mode 100644 index e297d51..0000000 --- a/src/Enum/Event.php +++ /dev/null @@ -1,12 +0,0 @@ -= 0x61 && $ord <= 0x7a) + { + return chr(ctrl_key($char)); + } + + // Invalid input, not an ascii letter + return NULL; + } } \ No newline at end of file diff --git a/src/Event.php b/src/Event.php index 32bdc69..55d5fce 100644 --- a/src/Event.php +++ b/src/Event.php @@ -2,9 +2,18 @@ namespace Aviat\Kilo; -use Aviat\Kilo\Enum\Event as EventEnum; - 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 = []; 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); @@ -37,11 +46,11 @@ class Event { private static function validateEvent(string $eventName): void { - $validEvents = EventEnum::getConstList(); + $validEvents = self::getConstList(); 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."); } } } \ No newline at end of file diff --git a/src/Row.php b/src/Row.php index 229c269..7ecb7a2 100644 --- a/src/Row.php +++ b/src/Row.php @@ -3,6 +3,7 @@ namespace Aviat\Kilo; use Aviat\Kilo\Enum\Highlight; +use Aviat\Kilo\Enum\KeyCode; /** * @property-read int size @@ -413,7 +414,7 @@ class Row { $klen = strlen($k); $nextCharOffset = $i + $klen; $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)) { @@ -559,14 +560,12 @@ class Row { } // Types/identifiers/keywords that don't have their own token - if ($token['type'] === T_STRING) + if ($token['type'] === T_STRING && + in_array($token['char'], $this->parent->syntax->keywords2, TRUE)) { - if (in_array($token['char'], $this->parent->syntax->keywords2, TRUE)) - { - array_replace_range($this->hl, $charStart, $charLen, Highlight::KEYWORD2); - $offset = $charEnd; - continue; - } + array_replace_range($this->hl, $charStart, $charLen, Highlight::KEYWORD2); + $offset = $charEnd; + continue; } } diff --git a/src/functions.php b/src/functions.php index 794094e..7f40e4f 100644 --- a/src/functions.php +++ b/src/functions.php @@ -4,11 +4,7 @@ namespace Aviat\Kilo; use FFI; -use Aviat\Kilo\Enum\{ - C, - Color, - Highlight, -}; +use Aviat\Kilo\Enum\{C, Color, Highlight, KeyCode}; /** * See if tput exists for fallback terminal size detection @@ -18,7 +14,7 @@ use Aviat\Kilo\Enum\{ */ function has_tput(): bool { - return (int)shell_exec('type tput') === 0; + return str_contains(shell_exec('type tput'), ' is '); } // ---------------------------------------------------------------------------- @@ -104,7 +100,7 @@ function is_ascii(string $single_char): bool * @param string $char * @return bool */ -function is_cntrl(string $char): bool +function is_ctrl(string $char): bool { $c = ord($char); return is_ascii($char) && ( $c === 0x7f || $c < 0x20 ); @@ -130,7 +126,14 @@ function is_digit(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); } @@ -168,11 +171,9 @@ function is_separator(string $char): bool return FALSE; } - // `strpos` is used instead of `strchr`/`strstr` as we don't care about the actual match - // while `strchr` would match the C version, it also returns the match - $isSep = (strpos(',.()+-/*=~%<>[];', $char) !== FALSE); + $isSep = str_contains(',.()+-/*=~%<>[];', $char); - 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 { - return str_replace("\t", str_repeat(' ', $number), $str); + return str_replace(KeyCode::TAB, str_repeat(KeyCode::SPACE, $number), $str); } /** diff --git a/tests/EventTest.php b/tests/EventTest.php index 41e419e..09df342 100644 --- a/tests/EventTest.php +++ b/tests/EventTest.php @@ -3,7 +3,6 @@ namespace Aviat\Kilo\Tests; use Aviat\Kilo\Event; -use Aviat\Kilo\Enum\Event as EventType; use InvalidArgumentException; use PHPUnit\Framework\TestCase; @@ -11,7 +10,7 @@ class EventTest extends TestCase { public function testRequiresValidEvent(): void { $this->expectException(InvalidArgumentException::class); - Event::bind('badEventName', fn () => null); + Event::on('badEventName', fn () => null); $this->expectException(InvalidArgumentException::class); Event::fire('badEventName', []); @@ -22,7 +21,7 @@ class EventTest extends TestCase { $fn = static function($value = false) { static::assertTrue($value); }; - Event::bind(EventType::INPUT_KEY, $fn); - Event::fire(EventType::INPUT_KEY, TRUE); + Event::on(Event::INPUT_KEY, $fn); + Event::fire(Event::INPUT_KEY, TRUE); } } diff --git a/tests/FunctionTest.php b/tests/FunctionTest.php index 1945d6a..f7afa26 100644 --- a/tests/FunctionTest.php +++ b/tests/FunctionTest.php @@ -11,7 +11,7 @@ use function Aviat\Kilo\ctrl_key; use function Aviat\Kilo\get_file_syntax_map; use function Aviat\Kilo\get_window_size; 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_separator; use function Aviat\Kilo\is_space; @@ -42,22 +42,22 @@ class FunctionTest extends TestCase { $this->assertEquals(0x01, ctrl_key('a')); } - public function test_is_cntrl(): void + public function test_is_ctrl(): void { for ($i = 0x0; $i < 0x20; $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++) { $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 - $this->assertTrue(is_cntrl(chr(0x7f))); + $this->assertTrue(is_ctrl(chr(0x7f))); } public function test_is_space(): void