php-kilo/src/Document.php

179 lines
3.0 KiB
PHP
Raw Normal View History

2021-03-10 16:24:02 -05:00
<?php declare(strict_types=1);
namespace Aviat\Kilo;
2021-03-16 18:37:53 -04:00
use Aviat\Kilo\Tokens\PHP8;
2021-03-11 17:11:00 -05:00
use Aviat\Kilo\Type\Point;
/**
* The representation of the current document being edited
*
* @property-read int $numRows
*/
2021-03-10 16:24:02 -05:00
class Document {
2021-03-16 18:37:53 -04:00
public FileType $fileType;
2021-03-11 17:11:00 -05:00
// Tokens for highlighting PHP
public array $tokens = [];
2021-03-10 16:24:02 -05:00
private function __construct(
public array $rows = [],
2021-03-16 18:37:53 -04:00
public string $filename = '',
public bool $dirty = FALSE,
) {
$this->fileType = FileType::from($this->filename);
}
2021-03-10 16:24:02 -05:00
public function __get(string $name): ?int
{
if ($name === 'numRows')
{
return count($this->rows);
}
return NULL;
}
2021-03-16 18:37:53 -04:00
public static function default(): self
{
return new self();
}
2021-03-16 18:37:53 -04:00
protected function rowsToString(): string
2021-03-10 16:24:02 -05:00
{
2021-03-16 18:37:53 -04:00
$lines = array_map(fn (Row $row) => (string)$row, $this->rows);
return implode('', $lines);
2021-03-10 16:24:02 -05:00
}
2021-03-16 18:37:53 -04:00
public static function open(string $filename): ?self
{
2021-03-16 18:37:53 -04:00
$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
{
}
2021-03-16 18:37:53 -04:00
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;
}
public function deleteChar(Point $at): void
{
}
private function insertNewline(Point $at): void
{
}
2021-03-16 18:37:53 -04:00
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();
}
}