diff --git a/README.md b/README.md index 8f7735d..37e67cf 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ due to requiring the `FFI` extension. * The `editor` prefix has been removed from all the relevant functions, instead they are methods on the `Editor` class. * Enums are faked with class constants +* Basic PHP class auto-loading is used * Properties that must be manually updated in the C version (like counts/string length) are implemented with magic methods, so they are essentially calculated on read. * Generally, if a function exists in PHP, with the same name as the C function, the PHP version will be used. \ No newline at end of file diff --git a/kilo b/kilo index a2e0ad4..f058128 100755 --- a/kilo +++ b/kilo @@ -10,9 +10,16 @@ define('KILO_VERSION', '0.0.1'); define('KILO_TAB_STOP', 4); define('KILO_QUIT_TIMES', 3); -require_once __DIR__ . '/src/C.php'; +// Set up autoloading require_once __DIR__ . '/src/functions.php'; -require_once __DIR__ . '/src/Editor.php'; +spl_autoload_register(static function ($class) { + $parts = explode('\\', $class); + $file = __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . $parts[1] . '.php'; + if (file_exists($file)) + { + require_once $file; + } +}); function main(int $argc, array $argv): int { diff --git a/src/Editor.php b/src/Editor.php index 195de29..3e37508 100644 --- a/src/Editor.php +++ b/src/Editor.php @@ -2,165 +2,7 @@ namespace Kilo; -use ReflectionClass; -trait MagicProperties { - abstract public function __get(string $name); - - public function __set(string $name, $value) - { - if (property_exists($this, $name)) - { - $this->$name = $value; - } - } - - public function __isset(string $name): bool - { - return isset($this->$name); - } -} - -class Key { - public const ARROW_DOWN = 'ARROW_DOWN'; - public const ARROW_LEFT = 'ARROW_LEFT'; - public const ARROW_RIGHT = 'ARROW_RIGHT'; - public const ARROW_UP = 'ARROW_UP'; - public const BACKSPACE = 'BACKSPACE'; - public const DEL_KEY = 'DELETE'; - public const END_KEY = 'END'; - public const ENTER = 'ENTER'; - public const ESCAPE = 'ESCAPE'; - public const HOME_KEY = 'HOME'; - public const PAGE_DOWN = 'PAGE_DOWN'; - public const PAGE_UP = 'PAGE_UP'; - - public static function getConstList(): array - { - return (new ReflectionClass(static::class))->getConstants(); - } -} - -class Highlight { - public const NORMAL = 0; - public const NUMBER = 1; - public const MATCH = 2; -} - -function syntax_to_color(int $hl): int -{ - switch ($hl) - { - case Highlight::NUMBER: - return 31; // Foreground Red - - case Highlight::MATCH: - return 34; // Foreground Blue - - default: - return 37; // Foreground White - } -} - -/** - * @property-read int size - * @property-read int rsize - */ -class Row { - use MagicProperties; - - public string $chars = ''; - public string $render = ''; - - public array $hl = []; - - public static function new(string $chars): self - { - return new self($chars); - } - - private function __construct($chars) - { - $this->chars = $chars; - } - - public function __get(string $name) - { - switch ($name) - { - case 'size': - return strlen($this->chars); - - case 'rsize': - return strlen($this->render); - - default: - return NULL; - } - } - - public function __toString(): string - { - return $this->chars . "\n"; - } - - public function update(): void - { - $idx = 0; - - for ($i = 0; $i < $this->size; $i++) - { - if ($this->chars[$i] === "\t") - { - $this->render[$idx++] = ' '; - while ($idx % KILO_TAB_STOP !== 0) - { - $this->render[$idx++] = ' '; - } - } - else - { - $this->render[$idx++] = $this->chars[$i]; - } - } - - $this->updateSyntax(); - } - - // ------------------------------------------------------------------------ - // ! Syntax Highlighting - // ------------------------------------------------------------------------ - - protected function updateSyntax(): void - { - $this->hl = array_fill(0, $this->rsize, Highlight::NORMAL); - - $prevSep = TRUE; - - $i = 0; - - while ($i < $this->rsize) - { - $char = $this->render[$i]; - $prevHl = ($i > 0) ? $this->hl[$i - 1] : Highlight::NORMAL; - - // Numbers, including decimal points - if ( - ($char === '.' && $prevHl === Highlight::NUMBER) || - (($prevSep || $prevHl === Highlight::NUMBER) && is_digit($char)) - ) - { - $this->hl[$i] = Highlight::NUMBER; - $i++; - $prevSep = FALSE; - continue; - } - - $prevSep = is_separator($char); - $i++; - } - } -} /** * @property-read int numRows diff --git a/src/Highlight.php b/src/Highlight.php new file mode 100644 index 0000000..9c7832a --- /dev/null +++ b/src/Highlight.php @@ -0,0 +1,9 @@ +getConstants(); + } +} \ No newline at end of file diff --git a/src/MagicProperties.php b/src/MagicProperties.php new file mode 100644 index 0000000..29c7d80 --- /dev/null +++ b/src/MagicProperties.php @@ -0,0 +1,20 @@ +$name = $value; + } + } + + public function __isset(string $name): bool + { + return isset($this->$name); + } +} \ No newline at end of file diff --git a/src/Row.php b/src/Row.php new file mode 100644 index 0000000..307baf1 --- /dev/null +++ b/src/Row.php @@ -0,0 +1,103 @@ +chars = $chars; + } + + public function __get(string $name) + { + switch ($name) + { + case 'size': + return strlen($this->chars); + + case 'rsize': + return strlen($this->render); + + default: + return NULL; + } + } + + public function __toString(): string + { + return $this->chars . "\n"; + } + + public function update(): void + { + $idx = 0; + + for ($i = 0; $i < $this->size; $i++) + { + if ($this->chars[$i] === "\t") + { + $this->render[$idx++] = ' '; + while ($idx % KILO_TAB_STOP !== 0) + { + $this->render[$idx++] = ' '; + } + } + else + { + $this->render[$idx++] = $this->chars[$i]; + } + } + + $this->updateSyntax(); + } + + // ------------------------------------------------------------------------ + // ! Syntax Highlighting + // ------------------------------------------------------------------------ + + protected function updateSyntax(): void + { + $this->hl = array_fill(0, $this->rsize, Highlight::NORMAL); + + $prevSep = TRUE; + + $i = 0; + + while ($i < $this->rsize) + { + $char = $this->render[$i]; + $prevHl = ($i > 0) ? $this->hl[$i - 1] : Highlight::NORMAL; + + // Numbers, including decimal points + if ( + ($char === '.' && $prevHl === Highlight::NUMBER) || + (($prevSep || $prevHl === Highlight::NUMBER) && is_digit($char)) + ) + { + $this->hl[$i] = Highlight::NUMBER; + $i++; + $prevSep = FALSE; + continue; + } + + $prevSep = is_separator($char); + $i++; + } + } +} diff --git a/src/functions.php b/src/functions.php index 4cfd0a9..c5493d0 100644 --- a/src/functions.php +++ b/src/functions.php @@ -275,3 +275,18 @@ function array_replace_range(array &$array, int $offset, int $length, $value):vo $array[$i] = $value; } } + +function syntax_to_color(int $hl): int +{ + switch ($hl) + { + case Highlight::NUMBER: + return 31; // Foreground Red + + case Highlight::MATCH: + return 34; // Foreground Blue + + default: + return 37; // Foreground White + } +}