diff --git a/kilo b/kilo index e271952..93239c3 100755 --- a/kilo +++ b/kilo @@ -26,14 +26,7 @@ function main(int $argc, array $argv): int while (true) { $editor->refreshScreen(); - - // Spin while waiting for a keypress $char = $editor->processKeypress(); - while ($char === '') - { - $char = $editor->processKeypress(); - } - if ($char === NULL) { break; diff --git a/src/Editor.php b/src/Editor.php index 9bb66ee..e3849d7 100644 --- a/src/Editor.php +++ b/src/Editor.php @@ -22,10 +22,10 @@ trait MagicProperties { } class Key { - public const ARROW_LEFT = 'a';//'ARROW_LEFT'; - public const ARROW_RIGHT = 'd';//ARROW_RIGHT'; - public const ARROW_UP = 'w';//'ARROW_UP'; - public const ARROW_DOWN = 's';//'ARROW_DOWN'; + public const ARROW_LEFT = 'ARROW_LEFT'; + public const ARROW_RIGHT = 'ARROW_RIGHT'; + public const ARROW_UP = 'ARROW_UP'; + public const ARROW_DOWN = 'ARROW_DOWN'; public const DEL_KEY = 'DEL'; public const HOME_KEY = 'HOME'; public const END_KEY = 'END'; @@ -130,67 +130,35 @@ class Editor { // ------------------------------------------------------------------------ protected function readKey(): string { - $c = read_stdin(1); + $c = read_stdin(); - if ($c === '\x1b') + // @TODO Make this more DRY + switch ($c) { - $seq = read_stdin(); + case "\x1b[A": return Key::ARROW_UP; + case "\x1b[B": return Key::ARROW_DOWN; + case "\x1b[C": return Key::ARROW_RIGHT; + case "\x1b[D": return Key::ARROW_LEFT; - if (strlen($seq) < 3) - { - return '\x1b'; - } + case "\x1b[3~": return Key::DEL_KEY; - if (strpos($seq, '[') === 0) - { - $seq1 = (int)$seq[1]; + case "\x1b[5~": return Key::PAGE_UP; + case "\x1b[6~": return Key::PAGE_DOWN; - if ($seq1 >= 0 && $seq1 <= 9) - { - if (strpos($seq, '~') === 2) - { - switch ($seq[1]) - { - case '1': - case '7': - return Key::HOME_KEY; + case "\x1bOH": + case "\x1b[1~": + case "\x1b[7~": + case "\x1b[H": + return Key::HOME_KEY; - case '4': - case '8': - return Key::END_KEY; + case "\x1bOF": + case "\x1b[4~": + case "\x1b[8~": + case "\x1b[F": + return Key::END_KEY; - case '3': return Key::DEL_KEY; - case '5': return Key::PAGE_UP; - case '6': return Key::PAGE_DOWN; - } - } - } - else - { - switch ($seq[1]) - { - case 'A': return Key::ARROW_UP; - case 'B': return Key::ARROW_DOWN; - case 'C': return Key::ARROW_RIGHT; - case 'D': return Key::ARROW_LEFT; - case 'H': return Key::HOME_KEY; - case 'F': return Key::END_KEY; - } - } - } - else if (strpos($seq, 'O') === 0) - { - switch ($seq[1]) - { - case 'H': return Key::HOME_KEY; - case 'F': return Key::END_KEY; - } - } - - return '\x1b'; + default: return $c; } - - return $c; } /** @@ -304,7 +272,8 @@ class Editor { while (($line = fgets($handle)) !== FALSE) { - $this->appendRow($line); + // Remove line endings when reading the file + $this->appendRow(rtrim($line)); } fclose($handle); @@ -552,7 +521,7 @@ class Editor { case Key::END_KEY: if ($this->cursorY < $this->numRows) { - $this->cursorX = $this->rows[$this->cursorY]->size; + $this->cursorX = $this->rows[$this->cursorY]->size - 1; } break; @@ -593,7 +562,6 @@ class Editor { if ($this->cursorY > $this->numRows) { $this->cursorY = $this->numRows; - } } diff --git a/src/functions.php b/src/functions.php index 25b25d0..62aa542 100644 --- a/src/functions.php +++ b/src/functions.php @@ -21,11 +21,12 @@ function enableRawMode(): void die('tcgetattr'); } - $termios = $ffi->new('struct termios'); - $termios->c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - $termios->c_oflag &= ~(OPOST); + // So, the only thing that seems to really matter here is that c_oflag is 0... + $termios = clone $original_termios; + $termios->c_iflag = $termios->c_iflag & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + $termios->c_oflag = 0; // $termios->c_oflag && ~(OPOST); $termios->c_cflag |= (CS8); - $termios->c_lflag &= ~(_ECHO | ICANON | IEXTEN | ISIG); + $termios->c_lflag = $termios->c_lflag & ~(_ECHO | ICANON | IEXTEN | ISIG); $termios->c_cc[VMIN] = 0; $termios->c_cc[VTIME] = 1;