From d0817b62c4038742a137cd57bf42ef05dc9e0b32 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Wed, 14 Apr 2021 16:38:41 -0400 Subject: [PATCH] Fix off-by-one highlighting error --- src/Editor.php | 13 ++---- src/Row.php | 45 ++++++++++--------- src/Tokens/PHP8.php | 1 - src/functions.php | 17 ++++++- tests/FunctionTest.php | 12 ++--- .../EditorTest__testOpen__1.json | 38 ++++++++-------- 6 files changed, 69 insertions(+), 57 deletions(-) diff --git a/src/Editor.php b/src/Editor.php index fe579a2..6689c1e 100644 --- a/src/Editor.php +++ b/src/Editor.php @@ -541,10 +541,7 @@ class Editor { { $this->scroll(); - $this->outputBuffer = ''; - - $this->outputBuffer .= ANSI::HIDE_CURSOR; - $this->outputBuffer .= ANSI::RESET_CURSOR; + $this->outputBuffer = ANSI::HIDE_CURSOR . ANSI::RESET_CURSOR; $this->drawRows(); $this->drawStatusBar(); @@ -719,15 +716,11 @@ class Editor { break; case KeyType::PAGE_UP: - $y = ($y > $this->terminalSize->rows) - ? $y - $this->terminalSize->rows - : 0; + $y = saturating_sub($y, $this->terminalSize->rows); break; case KeyType::PAGE_DOWN: - $y = ($y + $this->terminalSize->rows < $this->document->numRows) - ? $y + $this->terminalSize->rows - : $this->document->numRows; + $y = saturating_add($y, $this->terminalSize->rows, $this->document->numRows); break; case KeyType::HOME: diff --git a/src/Row.php b/src/Row.php index 88b8711..98219f9 100644 --- a/src/Row.php +++ b/src/Row.php @@ -202,6 +202,11 @@ class Row { return; } + if ($this->parent->fileType->name === 'No filetype') + { + return; + } + $syntax = $this->parent->fileType->syntax; $mcs = $syntax->multiLineCommentStart; @@ -245,17 +250,16 @@ class Row { } if ( - $this->highlightComment($i, $syntax) + $this->highlightCharacter($i, $syntax) + || $this->highlightComment($i, $syntax) || $this->highlightPrimaryKeywords($i, $syntax) || $this->highlightSecondaryKeywords($i, $syntax) - || $this->highlightCharacter($i, $syntax) || $this->highlightString($i, $syntax) - || $this->highlightNumber($i, $syntax) || $this->highlightOperators($i, $syntax) - || $this->highlightCommonOperators($i) || $this->highlightCommonDelimeters($i) + || $this->highlightCommonOperators($i) + || $this->highlightNumber($i, $syntax) ) { - $i++; continue; } @@ -266,7 +270,7 @@ class Row { $this->hlOpenComment = $inComment; if ($changed && $this->idx + 1 < $this->parent->numRows) { - $this->parent->rows[$this->idx + 1]->highlight(); + $this->parent->rows[$this->idx + 1]->update(); } } @@ -294,16 +298,14 @@ class Row { $nextChar = $this->render[$i]; if ($nextChar !== '.' && ! is_digit($nextChar)) { - break; + return true; } - } - else - { - break; - } - } - return true; + continue; + } + + break; + } } return false; @@ -330,7 +332,7 @@ class Row { if (substr($this->render, $i, $klen) === $k && is_separator($nextChar)) { array_replace_range($this->hl, $i, $klen, $syntaxType); - $i += $klen - 1; + $i += $klen; return true; } @@ -341,12 +343,17 @@ class Row { protected function highlightChar(int &$i, array $chars, int $syntaxType): bool { + if ($this->hl[$i] !== Highlight::NORMAL) + { + return false; + } + $char = $this->render[$i]; if (in_array($char, $chars, TRUE)) { $this->hl[$i] = $syntaxType; - $i += 1; + $i++; return true; } @@ -450,7 +457,7 @@ class Row { return false; } - if ($opts->strings() && $char === '"' || $char === '\'') + if ($opts->strings() && ($char === '"' || $char === '\'')) { $quote = $char; $this->hl[$i] = Highlight::STRING; @@ -470,13 +477,11 @@ class Row { } // End of the string! + $i++; if ($char === $quote) { - $i++; break; } - - $i++; } return true; diff --git a/src/Tokens/PHP8.php b/src/Tokens/PHP8.php index 45d14e9..782f0e3 100644 --- a/src/Tokens/PHP8.php +++ b/src/Tokens/PHP8.php @@ -4,7 +4,6 @@ namespace Aviat\Kilo\Tokens; use PhpToken; -use function Aviat\Kilo\str_contains; use function Aviat\Kilo\tabs_to_spaces; use const Aviat\Kilo\T_RAW; diff --git a/src/functions.php b/src/functions.php index bd1f0a5..bb7e437 100644 --- a/src/functions.php +++ b/src/functions.php @@ -138,7 +138,7 @@ function array_replace_range(array &$array, int $offset, int $length, mixed $val * @param int|null $offset * @return bool */ -function str_contains(string $haystack, string $str, ?int $offset = NULL): bool +function str_has(string $haystack, string $str, ?int $offset = NULL): bool { if (empty($str)) { @@ -208,4 +208,19 @@ function error_code_name(int $code): string E_USER_DEPRECATED => 'User Deprecated', default => 'Unknown', }; +} + +function saturating_add(int $a, int $b, int $max): int +{ + return ($a + $b > $max) ? $max : $a + $b; +} + +function saturating_sub(int $a, int $b): int +{ + if ($b > $a) + { + return 0; + } + + return $a - $b; } \ No newline at end of file diff --git a/tests/FunctionTest.php b/tests/FunctionTest.php index 3921475..9c55528 100644 --- a/tests/FunctionTest.php +++ b/tests/FunctionTest.php @@ -13,7 +13,7 @@ use function Aviat\Kilo\is_ctrl; use function Aviat\Kilo\is_digit; use function Aviat\Kilo\is_separator; use function Aviat\Kilo\is_space; -use function Aviat\Kilo\str_contains; +use function Aviat\Kilo\str_has; use function Aviat\Kilo\syntax_to_color; use function Aviat\Kilo\tabs_to_spaces; @@ -99,20 +99,20 @@ class FunctionTest extends TestCase { public function test_str_contains(): void { // Search from string offset - $this->assertTrue(str_contains(' vcd', 'vcd', 2)); + $this->assertTrue(str_has(' vcd', 'vcd', 2)); - $this->assertFalse(str_contains('', "\0")); + $this->assertFalse(str_has('', "\0")); // An empty search string returns false - $this->assertFalse(str_contains('', '')); + $this->assertFalse(str_has('', '')); - $this->assertTrue(str_contains('alphabet', 'phab')); + $this->assertTrue(str_has('alphabet', 'phab')); } public function test_tabs_to_spaces(): void { $original = "\t\t\t{"; - $this->assertFalse(str_contains(tabs_to_spaces($original), "\t")); + $this->assertFalse(str_has(tabs_to_spaces($original), "\t")); } public function test_array_replace_range_length_1(): void diff --git a/tests/__snapshots__/EditorTest__testOpen__1.json b/tests/__snapshots__/EditorTest__testOpen__1.json index a0a3b45..21fef52 100644 --- a/tests/__snapshots__/EditorTest__testOpen__1.json +++ b/tests/__snapshots__/EditorTest__testOpen__1.json @@ -654,7 +654,7 @@ 5, 5, 5, - 0 + 7 ], "idx": 16 }, @@ -678,7 +678,7 @@ 13, 13, 13, - 0 + 7 ], "idx": 17 }, @@ -1495,10 +1495,10 @@ 0, 0, 9, - 0, - 0, + 6, + 6, 9, - 0 + 7 ], "idx": 49 }, @@ -1589,7 +1589,7 @@ "render": "};", "hl": [ 9, - 0 + 7 ], "idx": 53 }, @@ -1616,9 +1616,9 @@ 0, 0, 9, - 0, - 0, - 0, + 4, + 4, + 4, 0, 0, 0, @@ -1650,7 +1650,7 @@ 0, 0, 9, - 0 + 7 ], "idx": 55 }, @@ -1672,9 +1672,9 @@ 0, 0, 9, - 0, - 0, - 0, + 4, + 4, + 4, 0, 0, 0, @@ -1734,7 +1734,7 @@ 0, 0, 9, - 0 + 7 ], "idx": 56 }, @@ -2098,7 +2098,7 @@ "render": "};", "hl": [ 9, - 0 + 7 ], "idx": 66 }, @@ -2116,9 +2116,9 @@ 0, 0, 9, - 0, - 0, - 0, + 4, + 4, + 4, 7, 0, 4, @@ -2130,7 +2130,7 @@ 0, 0, 9, - 0 + 7 ], "idx": 67 }