Up to step 71 in tutorial

This commit is contained in:
Timothy Warren 2019-10-15 13:23:25 -04:00
parent 5e6e6e7c7d
commit 9184a9b90f
2 changed files with 129 additions and 30 deletions

12
kilo
View File

@ -7,14 +7,20 @@ require_once __DIR__ . '/src/constants.php';
require_once __DIR__ . '/src/functions.php';
require_once __DIR__ . '/src/Editor.php';
function main(): int
function main(int $argc, array $argv): int
{
global $ffi;
enableRawMode();
// ob_start();
$editor = new Editor($ffi);
$editor = Editor::new($ffi);
if ($argc >= 2)
{
$editor->open($argv[1]);
}
// Input Loop
while (true)
@ -28,4 +34,4 @@ function main(): int
}
//! Init
main();
main($argc, $argv);

View File

@ -16,16 +16,42 @@ class Key {
public const PAGE_DOWN = 'PAGE_DOWN';
}
class Row {
public string $chars;
public static function new(string $chars): self
{
return new self($chars);
}
private function __construct($chars)
{
$this->chars = $chars;
}
}
class Editor {
private FFI $ffi;
protected int $cursorx = 0;
protected int $cursory = 0;
protected int $rowoff = 0;
protected int $coloff = 0;
protected int $screenRows = 0;
protected int $screenCols = 0;
protected string $ab = '';
public function __construct($ffi)
/**
* Array of Row objects
*/
protected array $rows = [];
public static function new(FFI $ffi): Editor
{
return new self($ffi);
}
private function __construct($ffi)
{
$this->ffi = $ffi;
@ -135,40 +161,102 @@ class Editor {
return true;
}
// ------------------------------------------------------------------------
// ! Row Operations
// ------------------------------------------------------------------------
protected function appendRow(string $s): void
{
$this->rows[] = Row::new($s);
}
// ------------------------------------------------------------------------
// ! File I/O
// ------------------------------------------------------------------------
public function open(string $filename): void
{
$baseFile = basename($filename);
$basePath = str_replace($baseFile, '', $filename);
$path = (is_dir($basePath)) ? $basePath : getcwd();
$fullname = $path . '/' . $baseFile;
$handle = fopen($fullname, 'rb');
while (($line = fgets($handle)) !== FALSE)
{
$this->appendRow($line);
}
fclose($handle);
}
// ------------------------------------------------------------------------
// ! Output
// ------------------------------------------------------------------------
protected function scroll(): void
{
if ($this->cursory < $this->rowoff)
{
$this->rowoff = $this->cursory;
}
if ($this->cursory >= $this->rowoff + $this->screenRows)
{
$this->rowoff = $this->cursory - $this->screenRows + 1;
}
}
protected function drawRows(): void
{
for ($y = 0; $y < $this->screenRows; $y++)
{
if ($y === ($this->screenRows / 3))
$filerow = $y + $this->rowoff;
if ($filerow >= count($this->rows))
{
$welcome = sprintf('PHP Kilo editor -- version %s', KILO_VERSION);
$welcomelen = strlen($welcome);
if ($welcomelen > $this->screenCols)
if (count($this->rows) === 0 && $y === $this->screenRows / 3)
{
$welcomelen = $this->screenCols;
}
$welcome = sprintf('PHP Kilo editor -- version %s', KILO_VERSION);
$welcomelen = strlen($welcome);
if ($welcomelen > $this->screenCols)
{
$welcomelen = $this->screenCols;
}
$padding = ($this->screenCols - $welcomelen) / 2;
if ($padding)
$padding = ($this->screenCols - $welcomelen) / 2;
if ($padding)
{
$this->ab .= '~';
$padding--;
}
while ($padding--)
{
$this->ab .= ' ';
}
$this->ab .= substr($welcome, 0, $welcomelen);
}
else
{
$this->ab .= '~';
$padding--;
}
while ($padding--)
{
$this->ab .= ' ';
}
$this->ab .= substr($welcome, 0, $welcomelen);
}
else
{
$this->ab .= '~';
$len = strlen($this->rows[$filerow]->chars) - $this->coloff;
if ($len < 0)
{
$len = 0;
}
if ($len > $this->screenCols)
{
$len = $this->screenCols;
}
$this->ab .= substr($this->rows[$filerow]->chars, $this->coloff, $len);
}
$this->ab .= "\x1b[K"; // Clear the current line
@ -181,6 +269,8 @@ class Editor {
public function refreshScreen(): void
{
$this->scroll();
$this->ab = '';
$this->ab .= "\x1b[?25l"; // Hide the cursor
@ -189,7 +279,7 @@ class Editor {
$this->drawRows();
// Specify the current cursor position
$this->ab .= sprintf("\x1b[%d;%dH", $this->cursory + 1, $this->cursorx + 1);
$this->ab .= sprintf("\x1b[%d;%dH", ($this->cursory - $this->rowoff) + 1, $this->cursorx + 1);
$this->ab .= "\x1b[?25h"; // Show the cursor
@ -226,7 +316,7 @@ class Editor {
break;
case Key::ARROW_DOWN:
if ($this->cursory !== $this->screenRows - 1)
if ($this->cursory < count($this->rows))
{
$this->cursory++;
}
@ -255,13 +345,7 @@ class Editor {
case Key::PAGE_UP:
case Key::PAGE_DOWN:
{
$times = $this->screenRows;
while ($times--)
{
$this->moveCursor($c === Key::PAGE_UP ? Key::ARROW_UP : Key::ARROW_DOWN);
}
}
$this->pageUpOrDown($c);
break;
case Key::ARROW_UP:
@ -274,4 +358,13 @@ class Editor {
return $c;
}
private function pageUpOrDown(string $c):void
{
$times = $this->screenRows;
while ($times--)
{
$this->moveCursor($c === Key::PAGE_UP ? Key::ARROW_UP : Key::ARROW_DOWN);
}
}
}