Move some logic to Document class
This commit is contained in:
parent
633094ea9f
commit
7d381d10e9
130
src/Document.php
130
src/Document.php
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Aviat\Kilo;
|
||||
|
||||
use Aviat\Kilo\Tokens\PHP8;
|
||||
use Aviat\Kilo\Type\Point;
|
||||
|
||||
/**
|
||||
@ -10,16 +11,18 @@ use Aviat\Kilo\Type\Point;
|
||||
* @property-read int $numRows
|
||||
*/
|
||||
class Document {
|
||||
public ?Syntax $syntax = NULL;
|
||||
public FileType $fileType;
|
||||
|
||||
// Tokens for highlighting PHP
|
||||
public array $tokens = [];
|
||||
|
||||
private function __construct(
|
||||
public array $rows = [],
|
||||
public ?string $filename = NULL,
|
||||
private bool $dirty = FALSE,
|
||||
) {}
|
||||
public string $filename = '',
|
||||
public bool $dirty = FALSE,
|
||||
) {
|
||||
$this->fileType = FileType::from($this->filename);
|
||||
}
|
||||
|
||||
public function __get(string $name): ?int
|
||||
{
|
||||
@ -31,21 +34,53 @@ class Document {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public static function new(): self
|
||||
public static function default(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
public static function open(?string $filename = NULL): self
|
||||
protected function rowsToString(): string
|
||||
{
|
||||
// @TODO move logic from Editor
|
||||
return new self(filename: $filename);
|
||||
$lines = array_map(fn (Row $row) => (string)$row, $this->rows);
|
||||
|
||||
return implode('', $lines);
|
||||
}
|
||||
|
||||
public function save(): bool
|
||||
public static function open(string $filename): ?self
|
||||
{
|
||||
// @TODO move logic
|
||||
return false;
|
||||
$handle = fopen($filename, 'rb');
|
||||
if ($handle === FALSE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$self = new self(filename: $filename);
|
||||
|
||||
while (($line = fgets($handle)) !== FALSE)
|
||||
{
|
||||
// Remove line endings when reading the file
|
||||
$self->insertRow($self->numRows, rtrim($line), FALSE);
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
|
||||
$self->selectSyntaxHighlight();
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
public function save(): int|false
|
||||
{
|
||||
$contents = $this->rowsToString();
|
||||
|
||||
$res = file_put_contents($this->filename, $contents);
|
||||
|
||||
if ($res === strlen($contents))
|
||||
{
|
||||
$this->dirty = FALSE;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function insertChar(Point $at, string $c): void
|
||||
@ -53,6 +88,47 @@ class Document {
|
||||
|
||||
}
|
||||
|
||||
public function insertRow(int $at, string $s, bool $updateSyntax = TRUE): void
|
||||
{
|
||||
if ($at > $this->numRows)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$row = Row::new($this, $s, $at);
|
||||
|
||||
if ($at === $this->numRows)
|
||||
{
|
||||
$this->rows[] = $row;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->rows = [
|
||||
...array_slice($this->rows, 0, $at),
|
||||
$row,
|
||||
...array_slice($this->rows, $at),
|
||||
];
|
||||
|
||||
// Update indexes of each row so that correct highlighting is done
|
||||
for ($idx = $at; $idx < $this->numRows; $idx++)
|
||||
{
|
||||
$this->rows[$idx]->idx = $idx;
|
||||
}
|
||||
}
|
||||
|
||||
ksort($this->rows);
|
||||
|
||||
$this->rows[$at]->update();
|
||||
|
||||
$this->dirty = true;
|
||||
|
||||
// Re-tokenize the file
|
||||
if ($updateSyntax)
|
||||
{
|
||||
$this->refreshPHPSyntax();
|
||||
}
|
||||
}
|
||||
|
||||
public function isDirty(): bool
|
||||
{
|
||||
return $this->dirty;
|
||||
@ -67,4 +143,36 @@ class Document {
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function selectSyntaxHighlight(): void
|
||||
{
|
||||
if (empty($this->filename))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->fileType->name === 'PHP')
|
||||
{
|
||||
$this->tokens = PHP8::getFileTokens($this->filename);
|
||||
}
|
||||
|
||||
$this->refreshSyntax();
|
||||
}
|
||||
|
||||
public function refreshSyntax(): void
|
||||
{
|
||||
// Update the syntax highlighting for all the rows of the file
|
||||
array_walk($this->rows, static fn (Row $row) => $row->update());
|
||||
}
|
||||
|
||||
private function refreshPHPSyntax(): void
|
||||
{
|
||||
if ($this->fileType->name !== 'PHP')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->tokens = PHP8::getTokens($this->rowsToString());
|
||||
$this->refreshSyntax();
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ use Aviat\Kilo\Type\{Point, StatusMessage};
|
||||
|
||||
/**
|
||||
* // Don't highlight this!
|
||||
* @property-read int $numRows
|
||||
*/
|
||||
class Editor {
|
||||
use Traits\MagicProperties;
|
||||
|
76
src/FileType.php
Normal file
76
src/FileType.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Aviat\Kilo;
|
||||
|
||||
class FileType {
|
||||
|
||||
public static function from(?string $filename): self
|
||||
{
|
||||
$syntax = self::getSyntaxFromFilename((string)$filename);
|
||||
|
||||
return new self($syntax->filetype, $syntax);
|
||||
}
|
||||
|
||||
private static function getSyntaxFromFilename(string $filename): Syntax
|
||||
{
|
||||
$ext = (string)strstr(basename($filename), '.');
|
||||
return match ($ext) {
|
||||
'.php', 'kilo' => Syntax::new(
|
||||
'PHP',
|
||||
['.php', 'kilo'],
|
||||
),
|
||||
'.c', '.h', '.cpp', '.cxx', '.cc', '.hpp' => Syntax::new(
|
||||
'C',
|
||||
['.c', '.h', '.cpp'],
|
||||
[
|
||||
'continue', 'typedef', 'switch', 'return', 'static', 'while', 'break', 'struct',
|
||||
'union', 'class', 'else', 'enum', 'for', 'case', 'if',
|
||||
],
|
||||
[
|
||||
'#include', 'unsigned', '#define', '#ifndef', 'double', 'signed', '#endif',
|
||||
'#ifdef', 'float', '#error', '#undef', 'long', 'char', 'int', 'void', '#if',
|
||||
],
|
||||
),
|
||||
'.css', '.less', '.sass', '.scss' => Syntax::new(
|
||||
'CSS',
|
||||
['.css', '.less', '.sass', 'scss'],
|
||||
slcs: '',
|
||||
),
|
||||
'.js', '.jsx', '.ts', '.tsx', '.jsm', '.mjs', '.es' => Syntax::new(
|
||||
'JavaScript',
|
||||
['.js', '.jsx', '.ts', '.tsx', '.jsm', '.mjs', '.es'],
|
||||
[
|
||||
'instanceof', 'continue', 'debugger', 'function', 'default', 'extends',
|
||||
'finally', 'delete', 'export', 'import', 'return', 'switch', 'typeof',
|
||||
'break', 'catch', 'class', 'const', 'super', 'throw', 'while', 'yield',
|
||||
'case', 'else', 'this', 'void', 'with', 'from', 'for', 'new', 'try',
|
||||
'var', 'do', 'if', 'in', 'as',
|
||||
],
|
||||
[
|
||||
'=>', 'Number', 'String', 'Object', 'Math', 'JSON', 'Boolean',
|
||||
],
|
||||
),
|
||||
'.rs' => Syntax::new(
|
||||
'Rust',
|
||||
['.rs'],
|
||||
[
|
||||
'continue', 'return', 'static', 'struct', 'unsafe', 'break', 'const', 'crate',
|
||||
'extern', 'match', 'super', 'trait', 'where', 'else', 'enum', 'false', 'impl',
|
||||
'loop', 'move', 'self', 'type', 'while', 'for', 'let', 'mod', 'pub', 'ref', 'true',
|
||||
'use', 'mut', 'as', 'fn', 'if', 'in',
|
||||
],
|
||||
[
|
||||
'DoubleEndedIterator', 'ExactSizeIterator', 'IntoIterator', 'PartialOrd', 'PartialEq',
|
||||
'Iterator', 'ToString', 'Default', 'ToOwned', 'Extend', 'FnOnce', 'Option', 'String',
|
||||
'AsMut', 'AsRef', 'Clone', 'Debug', 'FnMut', 'Sized', 'Unpin', 'array', 'isize',
|
||||
'usize', '&str', 'Copy', 'Drop', 'From', 'Into', 'None', 'Self', 'Send', 'Some',
|
||||
'Sync', 'bool', 'char', 'i128', 'u128', 'Box', 'Err', 'Ord', 'Vec', 'dyn', 'f32',
|
||||
'f64', 'i16', 'i32', 'i64', 'str', 'u16', 'u32', 'u64', 'Eq', 'Fn', 'Ok', 'i8', 'u8',
|
||||
],
|
||||
),
|
||||
default => Syntax::default(),
|
||||
};
|
||||
}
|
||||
|
||||
private function __construct(public string $name, public Syntax $syntax) {}
|
||||
}
|
@ -17,12 +17,17 @@ class Syntax {
|
||||
string $slcs = '//',
|
||||
string $mcs = '/*',
|
||||
string $mce = '*/',
|
||||
int $flags = 0,
|
||||
int $flags = self::HIGHLIGHT_NUMBERS | self::HIGHLIGHT_STRINGS,
|
||||
): self
|
||||
{
|
||||
return new self($name, $extList, $keywords1, $keywords2, $slcs, $mcs, $mce, $flags);
|
||||
}
|
||||
|
||||
public static function default(): self
|
||||
{
|
||||
return self::new('No filetype', slcs: '', mcs: '', mce: '', flags: 0);
|
||||
}
|
||||
|
||||
private function __construct(
|
||||
/** The name of the programming language */
|
||||
public string $filetype,
|
||||
|
Loading…
Reference in New Issue
Block a user