diff --git a/kilo b/kilo index cde26ce..dace6e4 100755 --- a/kilo +++ b/kilo @@ -9,11 +9,9 @@ require_once __DIR__ . '/src/Editor.php'; function main(int $argc, array $argv): int { - global $ffi; + enable_raw_mode(); - enableRawMode(); - - $editor = Editor::new($ffi); + $editor = Editor::new(); if ($argc >= 2) { diff --git a/src/Editor.php b/src/Editor.php index 5a63675..439aab1 100644 --- a/src/Editor.php +++ b/src/Editor.php @@ -2,7 +2,6 @@ namespace Kilo; -use FFI; use ReflectionClass; trait MagicProperties { @@ -45,15 +44,19 @@ class Key { class Highlight { public const NORMAL = 0; public const NUMBER = 1; + public const MATCH = 2; } -function syntaxToColor(int $hl): int +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 } @@ -134,7 +137,7 @@ class Row { for ($i = 0; $i < $this->rsize; $i++) { - if (isdigit($this->render[$i])) + if (is_digit($this->render[$i])) { $this->hl[$i] = Highlight::NUMBER; } @@ -148,7 +151,6 @@ class Row { class Editor { use MagicProperties; - private FFI $ffi; private string $ab = ''; protected int $cursorX = 0; @@ -169,20 +171,16 @@ class Editor { protected string $statusMsg = ''; protected int $statusMsgTime; - public static function new(FFI $ffi): Editor + public static function new(): Editor { - return new self($ffi); + return new self(); } - private function __construct($ffi) + private function __construct() { - $this->ffi = $ffi; $this->statusMsgTime = time(); - if ( ! $this->getWindowSize()) - { - die('Failed to get screen size'); - } + [$this->screenRows, $this->screenCols] = get_window_size(); $this->screenRows -= 2; @@ -242,48 +240,6 @@ class Editor { } } - /** - * @TODO fix - */ - private function getCursorPosition(): bool - { - write_stdout("\x1b[999C\x1b[999B"); - write_stdout("\x1b[6n"); - - $rows = 0; - $cols = 0; - - $buffer = read_stdout(); - - $res = sscanf($buffer, '\x1b[%d;%dR', $rows, $cols); - - if ($res === -1 || $buffer[0] !== '\x1b' || $buffer[1] !== '[') - { - die('Failed to get screen size'); - } - - $this->screenRows = $rows; - $this->screenCols = $cols; - - return TRUE; - } - - private function getWindowSize(): bool - { - $ws = $this->ffi->new('struct winsize'); - $res = $this->ffi->ioctl(STDOUT_FILENO, TIOCGWINSZ, FFI::addr($ws)); - - if ($res === -1 || $ws->ws_col === 0) - { - return $this->getCursorPosition(); - } - - $this->screenCols = $ws->ws_col; - $this->screenRows = $ws->ws_row; - - return true; - } - // ------------------------------------------------------------------------ // ! Row Operations // ------------------------------------------------------------------------ @@ -709,7 +665,7 @@ class Editor { } else { - $color = syntaxToColor($hl[$i]); + $color = syntax_to_color($hl[$i]); if ($color !== $currentColor) { $currentColor = $color; @@ -844,7 +800,7 @@ class Editor { { $buffer = substr($buffer, 0, -1); } - else if (isascii($c) && ( ! iscntrl($c)) && ! in_array($c, $modifiers, TRUE)) + else if (is_ascii($c) && ( ! is_cntrl($c)) && ! in_array($c, $modifiers, TRUE)) { $buffer .= $c; } diff --git a/src/functions.php b/src/functions.php index 11d1c3b..dcd9faa 100644 --- a/src/functions.php +++ b/src/functions.php @@ -7,12 +7,16 @@ use FFI; $ffi = FFI::load(__DIR__ . '/ffi.h'); $original_termios = $ffi->new('struct termios'); -function enableRawMode(): void +// ---------------------------------------------------------------------------- +// ! Raw mode / Terminal size +// ---------------------------------------------------------------------------- + +function enable_raw_mode(): void { global $ffi; global $original_termios; - register_shutdown_function('Kilo\\disableRawMode'); + register_shutdown_function('Kilo\disable_raw_mode'); // Populate the original terminal settings $res = $ffi->tcgetattr(STDIN_FILENO, FFI::addr($original_termios)); @@ -38,7 +42,7 @@ function enableRawMode(): void } } -function disableRawMode(): void +function disable_raw_mode(): void { global $ffi; global $original_termios; @@ -53,6 +57,95 @@ function disableRawMode(): void } } +/** + * @TODO fix + */ +function get_cursor_position() +{ + write_stdout("\x1b[999C\x1b[999B"); + write_stdout("\x1b[6n"); + + $rows = 0; + $cols = 0; + + $buffer = read_stdout(); + + $res = sscanf($buffer, '\x1b[%d;%dR', $rows, $cols); + + if ($res === -1 || $buffer[0] !== '\x1b' || $buffer[1] !== '[') + { + die('Failed to get screen size'); + } + + return [$rows, $cols]; +} + +function get_window_size() +{ + global $ffi; + + $ws = $ffi->new('struct winsize'); + $res = $ffi->ioctl(STDOUT_FILENO, TIOCGWINSZ, FFI::addr($ws)); + + if ($res === -1 || $ws->ws_col === 0) + { + return get_cursor_position(); + } + + return [$ws->ws_row, $ws->ws_col]; +} + + + +// ---------------------------------------------------------------------------- +// ! C function/macro equivalents +// ---------------------------------------------------------------------------- + +/** + * Do bit twiddling to convert a letter into + * its Ctrl-letter equivalent ordinal ascii value + * + * @param string $char + * @return int + */ +function ctrl_key(string $char): int +{ + if ( ! is_ascii($char)) + { + return -1; + } + + // b1,100,001 (a) & b0,011,111 = b0,000,001 + // b1,100,010 (b) & b0,011,111 = b0,000,010 + return ord($char) & 0x1f; +} + +function is_ascii(string $single_char): bool +{ + if (strlen($single_char) > 1) + { + return FALSE; + } + + return ord($single_char) < 0x80; +} + +function is_cntrl(string $char): bool +{ + $c = ord($char); + return is_ascii($char) && ( $c < 0x20 || $c === 0x7f ); +} + +function is_digit(string $char): bool +{ + $c = ord($char); + return is_ascii($char) && ( $c > 0x2f && $c < 0x3a ); +} + +// ---------------------------------------------------------------------------- +// ! Helper functions +// ---------------------------------------------------------------------------- + function read_stdin(int $len = 128): string { $handle = fopen('php://stdin', 'rb'); @@ -84,39 +177,3 @@ function read_stdout(int $len = 128): string return $input; } - -/** - * Do bit twiddling to convert a letter into - * its Ctrl-letter equivalent - * - * @param string $char - * @return int - */ -function ctrl_key(string $char): int -{ - // b1,100,001 (a) & b0,011,111 = b0,000,001 - // b1,100,010 (b) & b0,011,111 = b0,000,010 - return ord($char) & 0x1f; -} - -function isascii(string $single_char): bool -{ - if (strlen($single_char) > 1) - { - return FALSE; - } - - return ord($single_char) < 0x80; -} - -function iscntrl(string $char): bool -{ - $c = ord($char); - return isascii($char) && ( $c < 0x20 || $c === 0x7f ); -} - -function isdigit(string $char): bool -{ - $c = ord($char); - return isascii($char) && ( $c > 0x2f && $c < 0x3a ); -}