Fix more things that were broken
This commit is contained in:
parent
85e96264a8
commit
d7081d2b4e
7
kilo
7
kilo
@ -13,24 +13,25 @@ set_error_handler(static function (
|
|||||||
$errline
|
$errline
|
||||||
) {
|
) {
|
||||||
$msg = print_r([
|
$msg = print_r([
|
||||||
'code' => $errno,
|
'code' => error_code_name($errno),
|
||||||
'message' => $errstr,
|
'message' => $errstr,
|
||||||
'file' => $errfile,
|
'file' => $errfile,
|
||||||
'line' => $errline,
|
'line' => $errline,
|
||||||
], TRUE);
|
], TRUE);
|
||||||
file_put_contents('error.log', $msg, FILE_APPEND);
|
file_put_contents('kilo.log', $msg, FILE_APPEND);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, -1);
|
}, -1);
|
||||||
set_exception_handler(static function (mixed $e) {
|
set_exception_handler(static function (mixed $e) {
|
||||||
$msg = print_r([
|
$msg = print_r([
|
||||||
'code' => $e->getCode(),
|
'code' => $e->getCode(),
|
||||||
|
'codeName' => error_code_name($e->getCode()),
|
||||||
'message' => $e->getMessage(),
|
'message' => $e->getMessage(),
|
||||||
'file' => $e->getFile(),
|
'file' => $e->getFile(),
|
||||||
'line' => $e->getLine(),
|
'line' => $e->getLine(),
|
||||||
'trace' => $e->getTraceAsString(),
|
'trace' => $e->getTraceAsString(),
|
||||||
], TRUE);
|
], TRUE);
|
||||||
file_put_contents('exception.log', $msg, FILE_APPEND);
|
file_put_contents('kilo.log', $msg, FILE_APPEND);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ! Init with an IIFE
|
// ! Init with an IIFE
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Aviat\Kilo;
|
namespace Aviat\Kilo;
|
||||||
|
|
||||||
|
use Aviat\Kilo\Enum\KeyCode;
|
||||||
use Aviat\Kilo\Tokens\PHP8;
|
use Aviat\Kilo\Tokens\PHP8;
|
||||||
use Aviat\Kilo\Type\Point;
|
use Aviat\Kilo\Type\Point;
|
||||||
|
|
||||||
@ -39,13 +40,13 @@ class Document {
|
|||||||
return new self();
|
return new self();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function rowsToString(): string
|
public function row(int $index): ?Row
|
||||||
{
|
{
|
||||||
$lines = array_map(fn (Row $row) => (string)$row, $this->rows);
|
return (array_key_exists($index, $this->rows)) ? $this->rows[$index] : null;
|
||||||
|
|
||||||
return implode('', $lines);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// ! File I/O
|
// ! File I/O
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -97,11 +98,13 @@ class Document {
|
|||||||
|
|
||||||
$this->dirty = true;
|
$this->dirty = true;
|
||||||
|
|
||||||
if ($c === "\n")
|
if ($c === KeyCode::ENTER || $c === KeyCode::CARRIAGE_RETURN)
|
||||||
{
|
{
|
||||||
$this->insertNewline($at);
|
$this->insertNewline($at);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if ($at->y === $this->numRows)
|
|
||||||
|
if ($at->y === $this->numRows)
|
||||||
{
|
{
|
||||||
$this->insertRow($this->numRows, '');
|
$this->insertRow($this->numRows, '');
|
||||||
}
|
}
|
||||||
@ -226,7 +229,7 @@ class Document {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function selectSyntaxHighlight(): void
|
protected function selectSyntaxHighlight(): void
|
||||||
{
|
{
|
||||||
if (empty($this->filename))
|
if (empty($this->filename))
|
||||||
{
|
{
|
||||||
@ -241,6 +244,13 @@ class Document {
|
|||||||
$this->refreshSyntax();
|
$this->refreshSyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function rowsToString(): string
|
||||||
|
{
|
||||||
|
$lines = array_map(fn (Row $row) => (string)$row, $this->rows);
|
||||||
|
|
||||||
|
return implode('', $lines);
|
||||||
|
}
|
||||||
|
|
||||||
public function refreshSyntax(): void
|
public function refreshSyntax(): void
|
||||||
{
|
{
|
||||||
// Update the syntax highlighting for all the rows of the file
|
// Update the syntax highlighting for all the rows of the file
|
||||||
|
@ -97,6 +97,10 @@ class Editor {
|
|||||||
$this->document = $maybeDocument;
|
$this->document = $maybeDocument;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->document = Document::new();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __debugInfo(): array
|
public function __debugInfo(): array
|
||||||
@ -230,7 +234,13 @@ class Editor {
|
|||||||
|
|
||||||
if ( ! empty($savedHl))
|
if ( ! empty($savedHl))
|
||||||
{
|
{
|
||||||
$this->document->rows[$savedHlLine]->hl = $savedHl;
|
$row = $this->document->row($savedHlLine);
|
||||||
|
|
||||||
|
if ($row !== null)
|
||||||
|
{
|
||||||
|
$row->hl = $savedHl;
|
||||||
|
}
|
||||||
|
|
||||||
$savedHl = [];
|
$savedHl = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +291,11 @@ class Editor {
|
|||||||
$current = 0;
|
$current = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$row =& $this->document->rows[$current];
|
$row = $this->document->row($current);
|
||||||
|
if ($row === null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
$match = strpos($row->render, $query);
|
$match = strpos($row->render, $query);
|
||||||
if ($match !== FALSE)
|
if ($match !== FALSE)
|
||||||
@ -326,7 +340,13 @@ class Editor {
|
|||||||
$this->renderX = 0;
|
$this->renderX = 0;
|
||||||
if ($this->cursor->y < $this->document->numRows)
|
if ($this->cursor->y < $this->document->numRows)
|
||||||
{
|
{
|
||||||
$this->renderX = $this->rowCxToRx($this->document->rows[$this->cursor->y], $this->cursor->x);
|
$row = $this->document->row($this->cursor->y);
|
||||||
|
|
||||||
|
if ($row !== null)
|
||||||
|
{
|
||||||
|
$this->renderX = $this->rowCxToRx($row, $this->cursor->x);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertical Scrolling
|
// Vertical Scrolling
|
||||||
@ -368,7 +388,13 @@ class Editor {
|
|||||||
|
|
||||||
protected function drawRow(int $rowIdx): void
|
protected function drawRow(int $rowIdx): void
|
||||||
{
|
{
|
||||||
$len = $this->document->rows[$rowIdx]->rsize - $this->offset->x;
|
$row = $this->document->row($rowIdx);
|
||||||
|
if ($row === null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$len = $row->rsize - $this->offset->x;
|
||||||
if ($len < 0)
|
if ($len < 0)
|
||||||
{
|
{
|
||||||
$len = 0;
|
$len = 0;
|
||||||
@ -378,8 +404,8 @@ class Editor {
|
|||||||
$len = $this->terminalSize->cols;
|
$len = $this->terminalSize->cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
$chars = substr($this->document->rows[$rowIdx]->render, $this->offset->x, (int)$len);
|
$chars = substr($row->render, $this->offset->x, (int)$len);
|
||||||
$hl = array_slice($this->document->rows[$rowIdx]->hl, $this->offset->x, (int)$len);
|
$hl = array_slice($row->hl, $this->offset->x, (int)$len);
|
||||||
|
|
||||||
$currentColor = -1;
|
$currentColor = -1;
|
||||||
|
|
||||||
@ -464,7 +490,7 @@ class Editor {
|
|||||||
|
|
||||||
$statusFilename = $this->document->filename !== '' ? $this->document->filename : '[No Name]';
|
$statusFilename = $this->document->filename !== '' ? $this->document->filename : '[No Name]';
|
||||||
$syntaxType = $this->document->fileType->name;
|
$syntaxType = $this->document->fileType->name;
|
||||||
$isDirty = $this->document->dirty ? '(modified)' : '';
|
$isDirty = $this->document->isDirty() ? '(modified)' : '';
|
||||||
$status = sprintf('%.20s - %d lines %s', $statusFilename, $this->document->numRows, $isDirty);
|
$status = sprintf('%.20s - %d lines %s', $statusFilename, $this->document->numRows, $isDirty);
|
||||||
$rstatus = sprintf('%s | %d/%d', $syntaxType, $this->cursor->y + 1, $this->document->numRows);
|
$rstatus = sprintf('%s | %d/%d', $syntaxType, $this->cursor->y + 1, $this->document->numRows);
|
||||||
$len = strlen($status);
|
$len = strlen($status);
|
||||||
@ -492,12 +518,14 @@ class Editor {
|
|||||||
protected function drawMessageBar(): void
|
protected function drawMessageBar(): void
|
||||||
{
|
{
|
||||||
$this->outputBuffer .= ANSI::CLEAR_LINE;
|
$this->outputBuffer .= ANSI::CLEAR_LINE;
|
||||||
$len = strlen($this->statusMessage->text);
|
$len = $this->statusMessage->len;
|
||||||
if ($len > $this->terminalSize->cols)
|
if ($len > $this->terminalSize->cols)
|
||||||
{
|
{
|
||||||
$len = $this->terminalSize->cols;
|
$len = $this->terminalSize->cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there is a message, and it's been less than 5 seconds since
|
||||||
|
// last screen update, show the message
|
||||||
if ($len > 0 && (time() - $this->statusMessage->time) < 5)
|
if ($len > 0 && (time() - $this->statusMessage->time) < 5)
|
||||||
{
|
{
|
||||||
$this->outputBuffer .= substr($this->statusMessage->text, 0, $len);
|
$this->outputBuffer .= substr($this->statusMessage->text, 0, $len);
|
||||||
@ -530,7 +558,11 @@ class Editor {
|
|||||||
|
|
||||||
public function setStatusMessage(string $fmt, mixed ...$args): void
|
public function setStatusMessage(string $fmt, mixed ...$args): void
|
||||||
{
|
{
|
||||||
$this->statusMessage = StatusMessage::from($fmt, ...$args);
|
$text = func_num_args() > 1
|
||||||
|
? sprintf($fmt, ...$args)
|
||||||
|
: $fmt;
|
||||||
|
|
||||||
|
$this->statusMessage = StatusMessage::from($text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -546,17 +578,17 @@ class Editor {
|
|||||||
$this->setStatusMessage($prompt, $buffer);
|
$this->setStatusMessage($prompt, $buffer);
|
||||||
$this->refreshScreen();
|
$this->refreshScreen();
|
||||||
|
|
||||||
$c = $this->readKey();
|
$c = Terminal::readKey();
|
||||||
$isModifier = in_array($c, $modifiers, TRUE);
|
$isModifier = in_array($c, $modifiers, TRUE);
|
||||||
|
|
||||||
if ($c === KeyType::ESCAPE || ($c === KeyType::ENTER && $buffer !== ''))
|
if ($c === KeyType::ESCAPE || ($c === KeyCode::ENTER && $buffer !== ''))
|
||||||
{
|
{
|
||||||
$this->setStatusMessage('');
|
$this->setStatusMessage('');
|
||||||
if ($callback !== NULL)
|
if ($callback !== NULL)
|
||||||
{
|
{
|
||||||
$callback($buffer, $c);
|
$callback($buffer, $c);
|
||||||
}
|
}
|
||||||
return ($c === KeyType::ENTER) ? $buffer : '';
|
return ($c === KeyCode::ENTER) ? $buffer : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($c === KeyType::DEL_KEY || $c === KeyType::BACKSPACE)
|
if ($c === KeyType::DEL_KEY || $c === KeyType::BACKSPACE)
|
||||||
@ -579,7 +611,11 @@ class Editor {
|
|||||||
{
|
{
|
||||||
$x = $this->cursor->x;
|
$x = $this->cursor->x;
|
||||||
$y = $this->cursor->y;
|
$y = $this->cursor->y;
|
||||||
$row = $this->document->rows[$y];
|
$row = $this->document->row($y);
|
||||||
|
if ($row === NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch ($key)
|
switch ($key)
|
||||||
{
|
{
|
||||||
@ -592,16 +628,16 @@ class Editor {
|
|||||||
{
|
{
|
||||||
// Beginning of a line, go to end of previous line
|
// Beginning of a line, go to end of previous line
|
||||||
$y--;
|
$y--;
|
||||||
$x = $this->document->rows[$y]->size - 1;
|
$x = $row->size - 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyType::ARROW_RIGHT:
|
case KeyType::ARROW_RIGHT:
|
||||||
if ($row && $x < $row->size)
|
if ($x < $row->size)
|
||||||
{
|
{
|
||||||
$x++;
|
$x++;
|
||||||
}
|
}
|
||||||
else if ($row && $x === $row->size)
|
else if ($x === $row->size)
|
||||||
{
|
{
|
||||||
$y++;
|
$y++;
|
||||||
$x = 0;
|
$x = 0;
|
||||||
@ -641,7 +677,7 @@ class Editor {
|
|||||||
case KeyType::END_KEY:
|
case KeyType::END_KEY:
|
||||||
if ($y < $this->document->numRows)
|
if ($y < $this->document->numRows)
|
||||||
{
|
{
|
||||||
$x = $this->document->rows[$y]->size;
|
$x = $row->size;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -651,16 +687,18 @@ class Editor {
|
|||||||
|
|
||||||
// Snap cursor to the end of a row when moving
|
// Snap cursor to the end of a row when moving
|
||||||
// from a longer row to a shorter one
|
// from a longer row to a shorter one
|
||||||
$row = $this->document->rows[$y];
|
$row = $this->document->row($y);
|
||||||
$rowLen = ($row !== NULL) ? $row->size : 0;
|
if ($row !== null)
|
||||||
if ($x > $rowLen)
|
|
||||||
{
|
{
|
||||||
$x = $rowLen;
|
if ($x > $row->size)
|
||||||
|
{
|
||||||
|
$x = $row->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->cursor->x = $x;
|
$this->cursor->x = $x;
|
||||||
$this->cursor->y = $y;
|
$this->cursor->y = $y;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function processKeypress(): void
|
protected function processKeypress(): void
|
||||||
{
|
{
|
||||||
@ -713,6 +751,10 @@ class Editor {
|
|||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case KeyType::ENTER:
|
||||||
|
$this->insertChar("\n");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->insertChar($c);
|
$this->insertChar($c);
|
||||||
break;
|
break;
|
||||||
@ -728,7 +770,7 @@ class Editor {
|
|||||||
|
|
||||||
protected function quitAttempt(): void
|
protected function quitAttempt(): void
|
||||||
{
|
{
|
||||||
if ($this->document->dirty && $this->quitTimes > 0)
|
if ($this->document->isDirty() && $this->quitTimes > 0)
|
||||||
{
|
{
|
||||||
$this->setStatusMessage(
|
$this->setStatusMessage(
|
||||||
'WARNING!!! File has unsaved changes. Press Ctrl-Q %d more times to quit.',
|
'WARNING!!! File has unsaved changes. Press Ctrl-Q %d more times to quit.',
|
||||||
|
@ -17,6 +17,7 @@ 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 BELL = "\a";
|
||||||
public const CARRIAGE_RETURN = "\r";
|
public const CARRIAGE_RETURN = "\r";
|
||||||
public const DEL_KEY = "\e[3~";
|
public const DEL_KEY = "\e[3~";
|
||||||
public const EMPTY = '';
|
public const EMPTY = '';
|
||||||
|
@ -11,15 +11,16 @@ use Aviat\Kilo\Traits;
|
|||||||
class KeyType {
|
class KeyType {
|
||||||
use Traits\ConstList;
|
use Traits\ConstList;
|
||||||
|
|
||||||
public const ARROW_DOWN = 'ARROW_DOWN';
|
public const ARROW_DOWN = 'KEY_ARROW_DOWN';
|
||||||
public const ARROW_LEFT = 'ARROW_LEFT';
|
public const ARROW_LEFT = 'KEY_ARROW_LEFT';
|
||||||
public const ARROW_RIGHT = 'ARROW_RIGHT';
|
public const ARROW_RIGHT = 'KEY_ARROW_RIGHT';
|
||||||
public const ARROW_UP = 'ARROW_UP';
|
public const ARROW_UP = 'KEY_ARROW_UP';
|
||||||
public const BACKSPACE = 'BACKSPACE';
|
public const BACKSPACE = 'KEY_BACKSPACE';
|
||||||
public const DEL_KEY = 'DELETE';
|
public const DEL_KEY = 'KEY_DELETE';
|
||||||
public const END_KEY = 'END';
|
public const END_KEY = 'KEY_END';
|
||||||
public const ESCAPE = 'ESCAPE';
|
public const ENTER = 'KEY_ENTER';
|
||||||
public const HOME_KEY = 'HOME';
|
public const ESCAPE = 'KEY_ESCAPE';
|
||||||
public const PAGE_DOWN = 'PAGE_DOWN';
|
public const HOME_KEY = 'KEY_HOME';
|
||||||
public const PAGE_UP = 'PAGE_UP';
|
public const PAGE_DOWN = 'KEY_PAGE_DOWN';
|
||||||
|
public const PAGE_UP = 'KEY_PAGE_UP';
|
||||||
}
|
}
|
@ -13,15 +13,14 @@ class FileType {
|
|||||||
|
|
||||||
private static function getSyntaxFromFilename(string $filename): Syntax
|
private static function getSyntaxFromFilename(string $filename): Syntax
|
||||||
{
|
{
|
||||||
$ext = (string)strstr(basename($filename), '.');
|
$ext = strstr(basename($filename), '.');
|
||||||
|
$ext = ($ext !== FALSE) ? $ext : '';
|
||||||
return match ($ext) {
|
return match ($ext) {
|
||||||
'.php', 'kilo' => Syntax::new(
|
'.php', 'kilo' => Syntax::new(
|
||||||
'PHP',
|
'PHP',
|
||||||
['.php', 'kilo'],
|
|
||||||
),
|
),
|
||||||
'.c', '.h', '.cpp', '.cxx', '.cc', '.hpp' => Syntax::new(
|
'.c', '.h', '.cpp', '.cxx', '.cc', '.hpp' => Syntax::new(
|
||||||
'C',
|
'C',
|
||||||
['.c', '.h', '.cpp'],
|
|
||||||
[
|
[
|
||||||
'continue', 'typedef', 'switch', 'return', 'static', 'while', 'break', 'struct',
|
'continue', 'typedef', 'switch', 'return', 'static', 'while', 'break', 'struct',
|
||||||
'union', 'class', 'else', 'enum', 'for', 'case', 'if',
|
'union', 'class', 'else', 'enum', 'for', 'case', 'if',
|
||||||
@ -33,12 +32,10 @@ class FileType {
|
|||||||
),
|
),
|
||||||
'.css', '.less', '.sass', '.scss' => Syntax::new(
|
'.css', '.less', '.sass', '.scss' => Syntax::new(
|
||||||
'CSS',
|
'CSS',
|
||||||
['.css', '.less', '.sass', 'scss'],
|
|
||||||
slcs: '',
|
slcs: '',
|
||||||
),
|
),
|
||||||
'.js', '.jsx', '.ts', '.tsx', '.jsm', '.mjs', '.es' => Syntax::new(
|
'.js', '.jsx', '.ts', '.tsx', '.jsm', '.mjs', '.es' => Syntax::new(
|
||||||
'JavaScript',
|
'JavaScript',
|
||||||
['.js', '.jsx', '.ts', '.tsx', '.jsm', '.mjs', '.es'],
|
|
||||||
[
|
[
|
||||||
'instanceof', 'continue', 'debugger', 'function', 'default', 'extends',
|
'instanceof', 'continue', 'debugger', 'function', 'default', 'extends',
|
||||||
'finally', 'delete', 'export', 'import', 'return', 'switch', 'typeof',
|
'finally', 'delete', 'export', 'import', 'return', 'switch', 'typeof',
|
||||||
@ -52,7 +49,6 @@ class FileType {
|
|||||||
),
|
),
|
||||||
'.rs' => Syntax::new(
|
'.rs' => Syntax::new(
|
||||||
'Rust',
|
'Rust',
|
||||||
['.rs'],
|
|
||||||
[
|
[
|
||||||
'continue', 'return', 'static', 'struct', 'unsafe', 'break', 'const', 'crate',
|
'continue', 'return', 'static', 'struct', 'unsafe', 'break', 'const', 'crate',
|
||||||
'extern', 'match', 'super', 'trait', 'where', 'else', 'enum', 'false', 'impl',
|
'extern', 'match', 'super', 'trait', 'where', 'else', 'enum', 'false', 'impl',
|
||||||
|
@ -11,7 +11,6 @@ class Syntax {
|
|||||||
|
|
||||||
public static function new(
|
public static function new(
|
||||||
string $name,
|
string $name,
|
||||||
array $extList = [],
|
|
||||||
array $keywords1 = [],
|
array $keywords1 = [],
|
||||||
array $keywords2 = [],
|
array $keywords2 = [],
|
||||||
string $slcs = '//',
|
string $slcs = '//',
|
||||||
@ -20,7 +19,7 @@ class Syntax {
|
|||||||
int $flags = self::HIGHLIGHT_NUMBERS | self::HIGHLIGHT_STRINGS,
|
int $flags = self::HIGHLIGHT_NUMBERS | self::HIGHLIGHT_STRINGS,
|
||||||
): self
|
): self
|
||||||
{
|
{
|
||||||
return new self($name, $extList, $keywords1, $keywords2, $slcs, $mcs, $mce, $flags);
|
return new self($name, $keywords1, $keywords2, $slcs, $mcs, $mce, $flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function default(): self
|
public static function default(): self
|
||||||
@ -31,8 +30,6 @@ class Syntax {
|
|||||||
private function __construct(
|
private function __construct(
|
||||||
/** The name of the programming language */
|
/** The name of the programming language */
|
||||||
public string $filetype,
|
public string $filetype,
|
||||||
/** Relevant file extensions for the specified language */
|
|
||||||
public array $filematch,
|
|
||||||
/** Primary set of language keywords */
|
/** Primary set of language keywords */
|
||||||
public array $keywords1,
|
public array $keywords1,
|
||||||
/** Secondary set of language keywords */
|
/** Secondary set of language keywords */
|
||||||
|
@ -95,6 +95,7 @@ class Terminal {
|
|||||||
KeyCode::ARROW_RIGHT => KeyType::ARROW_RIGHT,
|
KeyCode::ARROW_RIGHT => KeyType::ARROW_RIGHT,
|
||||||
KeyCode::ARROW_UP => KeyType::ARROW_UP,
|
KeyCode::ARROW_UP => KeyType::ARROW_UP,
|
||||||
KeyCode::DEL_KEY => KeyType::DEL_KEY,
|
KeyCode::DEL_KEY => KeyType::DEL_KEY,
|
||||||
|
KeyCode::ENTER => KeyType::ENTER,
|
||||||
KeyCode::PAGE_DOWN => KeyType::PAGE_DOWN,
|
KeyCode::PAGE_DOWN => KeyType::PAGE_DOWN,
|
||||||
KeyCode::PAGE_UP => KeyType::PAGE_UP,
|
KeyCode::PAGE_UP => KeyType::PAGE_UP,
|
||||||
|
|
||||||
|
@ -5,11 +5,12 @@ namespace Aviat\Kilo\Type;
|
|||||||
class StatusMessage {
|
class StatusMessage {
|
||||||
private function __construct(
|
private function __construct(
|
||||||
public string $text,
|
public string $text,
|
||||||
|
public int $len,
|
||||||
public int $time,
|
public int $time,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public static function from(string $text, mixed ...$args): self
|
public static function from(string $text): self
|
||||||
{
|
{
|
||||||
return new self(sprintf($text, ...$args), time());
|
return new self($text, strlen($text), time());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -187,3 +187,24 @@ function tabs_to_spaces(string $str, int $number = KILO_TAB_STOP): string
|
|||||||
{
|
{
|
||||||
return str_replace(KeyCode::TAB, str_repeat(KeyCode::SPACE, $number), $str);
|
return str_replace(KeyCode::TAB, str_repeat(KeyCode::SPACE, $number), $str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function error_code_name(int $code): string
|
||||||
|
{
|
||||||
|
return match ($code) {
|
||||||
|
E_ERROR => 'Error',
|
||||||
|
E_WARNING => 'Warning',
|
||||||
|
E_PARSE => 'Parse Error',
|
||||||
|
E_NOTICE => 'Notice',
|
||||||
|
E_CORE_ERROR => 'Core Error',
|
||||||
|
E_CORE_WARNING => 'Core Warning',
|
||||||
|
E_COMPILE_ERROR => 'Compile Error',
|
||||||
|
E_COMPILE_WARNING => 'Compile Warning',
|
||||||
|
E_USER_ERROR => 'User Error',
|
||||||
|
E_USER_WARNING => 'User Warning',
|
||||||
|
E_USER_NOTICE => 'User Notice',
|
||||||
|
E_RECOVERABLE_ERROR => 'Recoverable Error',
|
||||||
|
E_DEPRECATED => 'Deprecated',
|
||||||
|
E_USER_DEPRECATED => 'User Deprecated',
|
||||||
|
default => 'Unknown',
|
||||||
|
};
|
||||||
|
}
|
@ -29,14 +29,6 @@ class MockEditor extends Editor {
|
|||||||
class EditorTest extends TestCase {
|
class EditorTest extends TestCase {
|
||||||
use MatchesSnapshots;
|
use MatchesSnapshots;
|
||||||
|
|
||||||
public function testSanity(): void
|
|
||||||
{
|
|
||||||
$editor = MockEditor::mock();
|
|
||||||
|
|
||||||
$this->assertEquals(0, $editor->numRows);
|
|
||||||
$this->assertNull($editor->syntax);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test__debugInfo(): void
|
public function test__debugInfo(): void
|
||||||
{
|
{
|
||||||
$editor = MockEditor::mock();
|
$editor = MockEditor::mock();
|
||||||
|
@ -8,7 +8,6 @@ use PHPUnit\Framework\TestCase;
|
|||||||
|
|
||||||
use function Aviat\Kilo\array_replace_range;
|
use function Aviat\Kilo\array_replace_range;
|
||||||
use function Aviat\Kilo\ctrl_key;
|
use function Aviat\Kilo\ctrl_key;
|
||||||
use function Aviat\Kilo\get_file_syntax_map;
|
|
||||||
use function Aviat\Kilo\is_ascii;
|
use function Aviat\Kilo\is_ascii;
|
||||||
use function Aviat\Kilo\is_ctrl;
|
use function Aviat\Kilo\is_ctrl;
|
||||||
use function Aviat\Kilo\is_digit;
|
use function Aviat\Kilo\is_digit;
|
||||||
@ -97,11 +96,6 @@ class FunctionTest extends TestCase {
|
|||||||
$this->assertNotEquals(syntax_to_color(Highlight::OPERATOR), Color::FG_WHITE);
|
$this->assertNotEquals(syntax_to_color(Highlight::OPERATOR), Color::FG_WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_get_file_syntax_map(): void
|
|
||||||
{
|
|
||||||
$this->assertNotEmpty(get_file_syntax_map());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_str_contains(): void
|
public function test_str_contains(): void
|
||||||
{
|
{
|
||||||
// Search from string offset
|
// Search from string offset
|
||||||
|
@ -2,19 +2,22 @@
|
|||||||
|
|
||||||
namespace Aviat\Kilo\Tests\Traits;
|
namespace Aviat\Kilo\Tests\Traits;
|
||||||
|
|
||||||
use Aviat\Kilo\{Editor, Row};
|
use Aviat\Kilo\
|
||||||
|
{
|
||||||
|
Document,
|
||||||
|
Row};
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class RowTest extends TestCase {
|
class RowTest extends TestCase {
|
||||||
protected Editor $editor;
|
protected Document $document;
|
||||||
protected Row $row;
|
protected Row $row;
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->editor = Editor::new();
|
$this->document = Document::new();
|
||||||
$this->row = Row::new($this->editor, '', 0);
|
$this->row = Row::new($this->document, '', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSanity(): void
|
public function testSanity(): void
|
||||||
@ -53,42 +56,42 @@ class RowTest extends TestCase {
|
|||||||
$this->assertEquals($expected, $actual);
|
$this->assertEquals($expected, $actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testInsertChar(): void
|
public function testInsert(): void
|
||||||
{
|
{
|
||||||
$this->row->chars = 'abde';
|
$this->row->chars = 'abde';
|
||||||
$this->row->insertChar(2, 'c');
|
$this->row->insert(2, 'c');
|
||||||
|
|
||||||
$this->assertEquals('abcde', $this->row->chars);
|
$this->assertEquals('abcde', $this->row->chars);
|
||||||
$this->assertEquals('abcde', $this->row->render);
|
$this->assertEquals('abcde', $this->row->render);
|
||||||
$this->assertEquals(true, $this->editor->dirty);
|
$this->assertEquals(true, $this->document->dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testInsertCharBadOffset(): void
|
public function testInsertBadOffset(): void
|
||||||
{
|
{
|
||||||
$this->row->chars = 'ab';
|
$this->row->chars = 'ab';
|
||||||
$this->row->insertChar(5, 'c');
|
$this->row->insert(5, 'c');
|
||||||
|
|
||||||
$this->assertEquals('abc', $this->row->chars);
|
$this->assertEquals('abc', $this->row->chars);
|
||||||
$this->assertEquals('abc', $this->row->render);
|
$this->assertEquals('abc', $this->row->render);
|
||||||
$this->assertEquals(true, $this->editor->dirty);
|
$this->assertEquals(true, $this->document->dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDeleteChar(): void
|
public function testDelete(): void
|
||||||
{
|
{
|
||||||
$this->row->chars = 'abcdef';
|
$this->row->chars = 'abcdef';
|
||||||
$this->row->deleteChar(5);
|
$this->row->delete(5);
|
||||||
|
|
||||||
$this->assertEquals('abcde', $this->row->chars);
|
$this->assertEquals('abcde', $this->row->chars);
|
||||||
$this->assertEquals('abcde', $this->row->render);
|
$this->assertEquals('abcde', $this->row->render);
|
||||||
$this->assertEquals(true, $this->editor->dirty);
|
$this->assertEquals(true, $this->document->dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDeleteCharBadOffset(): void
|
public function testDeleteBadOffset(): void
|
||||||
{
|
{
|
||||||
$this->row->chars = 'ab';
|
$this->row->chars = 'ab';
|
||||||
$this->row->deleteChar(5);
|
$this->row->delete(5);
|
||||||
|
|
||||||
$this->assertEquals('ab', $this->row->chars);
|
$this->assertEquals('ab', $this->row->chars);
|
||||||
$this->assertEquals(false, $this->editor->dirty);
|
$this->assertEquals(false, $this->document->dirty);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user