Split classes and setup autoloading
This commit is contained in:
parent
88afc3909e
commit
cb8eb05249
@ -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.
|
* 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
|
* 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,
|
* 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.
|
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.
|
* Generally, if a function exists in PHP, with the same name as the C function, the PHP version will be used.
|
11
kilo
11
kilo
@ -10,9 +10,16 @@ define('KILO_VERSION', '0.0.1');
|
|||||||
define('KILO_TAB_STOP', 4);
|
define('KILO_TAB_STOP', 4);
|
||||||
define('KILO_QUIT_TIMES', 3);
|
define('KILO_QUIT_TIMES', 3);
|
||||||
|
|
||||||
require_once __DIR__ . '/src/C.php';
|
// Set up autoloading
|
||||||
require_once __DIR__ . '/src/functions.php';
|
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
|
function main(int $argc, array $argv): int
|
||||||
{
|
{
|
||||||
|
158
src/Editor.php
158
src/Editor.php
@ -2,165 +2,7 @@
|
|||||||
|
|
||||||
namespace Kilo;
|
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
|
* @property-read int numRows
|
||||||
|
9
src/Highlight.php
Normal file
9
src/Highlight.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kilo;
|
||||||
|
|
||||||
|
class Highlight {
|
||||||
|
public const NORMAL = 0;
|
||||||
|
public const NUMBER = 1;
|
||||||
|
public const MATCH = 2;
|
||||||
|
}
|
25
src/Key.php
Normal file
25
src/Key.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kilo;
|
||||||
|
|
||||||
|
use ReflectionClass;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
20
src/MagicProperties.php
Normal file
20
src/MagicProperties.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kilo;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
103
src/Row.php
Normal file
103
src/Row.php
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kilo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -275,3 +275,18 @@ function array_replace_range(array &$array, int $offset, int $length, $value):vo
|
|||||||
$array[$i] = $value;
|
$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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user