Fix off-by-one highlighting error
All checks were successful
timw4mail/php-kilo/pipeline/head This commit looks good
All checks were successful
timw4mail/php-kilo/pipeline/head This commit looks good
This commit is contained in:
parent
a50c22c0e0
commit
d0817b62c4
@ -541,10 +541,7 @@ class Editor {
|
|||||||
{
|
{
|
||||||
$this->scroll();
|
$this->scroll();
|
||||||
|
|
||||||
$this->outputBuffer = '';
|
$this->outputBuffer = ANSI::HIDE_CURSOR . ANSI::RESET_CURSOR;
|
||||||
|
|
||||||
$this->outputBuffer .= ANSI::HIDE_CURSOR;
|
|
||||||
$this->outputBuffer .= ANSI::RESET_CURSOR;
|
|
||||||
|
|
||||||
$this->drawRows();
|
$this->drawRows();
|
||||||
$this->drawStatusBar();
|
$this->drawStatusBar();
|
||||||
@ -719,15 +716,11 @@ class Editor {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyType::PAGE_UP:
|
case KeyType::PAGE_UP:
|
||||||
$y = ($y > $this->terminalSize->rows)
|
$y = saturating_sub($y, $this->terminalSize->rows);
|
||||||
? $y - $this->terminalSize->rows
|
|
||||||
: 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyType::PAGE_DOWN:
|
case KeyType::PAGE_DOWN:
|
||||||
$y = ($y + $this->terminalSize->rows < $this->document->numRows)
|
$y = saturating_add($y, $this->terminalSize->rows, $this->document->numRows);
|
||||||
? $y + $this->terminalSize->rows
|
|
||||||
: $this->document->numRows;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyType::HOME:
|
case KeyType::HOME:
|
||||||
|
45
src/Row.php
45
src/Row.php
@ -202,6 +202,11 @@ class Row {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->parent->fileType->name === 'No filetype')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$syntax = $this->parent->fileType->syntax;
|
$syntax = $this->parent->fileType->syntax;
|
||||||
|
|
||||||
$mcs = $syntax->multiLineCommentStart;
|
$mcs = $syntax->multiLineCommentStart;
|
||||||
@ -245,17 +250,16 @@ class Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
$this->highlightComment($i, $syntax)
|
$this->highlightCharacter($i, $syntax)
|
||||||
|
|| $this->highlightComment($i, $syntax)
|
||||||
|| $this->highlightPrimaryKeywords($i, $syntax)
|
|| $this->highlightPrimaryKeywords($i, $syntax)
|
||||||
|| $this->highlightSecondaryKeywords($i, $syntax)
|
|| $this->highlightSecondaryKeywords($i, $syntax)
|
||||||
|| $this->highlightCharacter($i, $syntax)
|
|
||||||
|| $this->highlightString($i, $syntax)
|
|| $this->highlightString($i, $syntax)
|
||||||
|| $this->highlightNumber($i, $syntax)
|
|
||||||
|| $this->highlightOperators($i, $syntax)
|
|| $this->highlightOperators($i, $syntax)
|
||||||
|| $this->highlightCommonOperators($i)
|
|
||||||
|| $this->highlightCommonDelimeters($i)
|
|| $this->highlightCommonDelimeters($i)
|
||||||
|
|| $this->highlightCommonOperators($i)
|
||||||
|
|| $this->highlightNumber($i, $syntax)
|
||||||
) {
|
) {
|
||||||
$i++;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +270,7 @@ class Row {
|
|||||||
$this->hlOpenComment = $inComment;
|
$this->hlOpenComment = $inComment;
|
||||||
if ($changed && $this->idx + 1 < $this->parent->numRows)
|
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];
|
$nextChar = $this->render[$i];
|
||||||
if ($nextChar !== '.' && ! is_digit($nextChar))
|
if ($nextChar !== '.' && ! is_digit($nextChar))
|
||||||
{
|
{
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -330,7 +332,7 @@ class Row {
|
|||||||
if (substr($this->render, $i, $klen) === $k && is_separator($nextChar))
|
if (substr($this->render, $i, $klen) === $k && is_separator($nextChar))
|
||||||
{
|
{
|
||||||
array_replace_range($this->hl, $i, $klen, $syntaxType);
|
array_replace_range($this->hl, $i, $klen, $syntaxType);
|
||||||
$i += $klen - 1;
|
$i += $klen;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -341,12 +343,17 @@ class Row {
|
|||||||
|
|
||||||
protected function highlightChar(int &$i, array $chars, int $syntaxType): bool
|
protected function highlightChar(int &$i, array $chars, int $syntaxType): bool
|
||||||
{
|
{
|
||||||
|
if ($this->hl[$i] !== Highlight::NORMAL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$char = $this->render[$i];
|
$char = $this->render[$i];
|
||||||
|
|
||||||
if (in_array($char, $chars, TRUE))
|
if (in_array($char, $chars, TRUE))
|
||||||
{
|
{
|
||||||
$this->hl[$i] = $syntaxType;
|
$this->hl[$i] = $syntaxType;
|
||||||
$i += 1;
|
$i++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -450,7 +457,7 @@ class Row {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($opts->strings() && $char === '"' || $char === '\'')
|
if ($opts->strings() && ($char === '"' || $char === '\''))
|
||||||
{
|
{
|
||||||
$quote = $char;
|
$quote = $char;
|
||||||
$this->hl[$i] = Highlight::STRING;
|
$this->hl[$i] = Highlight::STRING;
|
||||||
@ -470,13 +477,11 @@ class Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// End of the string!
|
// End of the string!
|
||||||
|
$i++;
|
||||||
if ($char === $quote)
|
if ($char === $quote)
|
||||||
{
|
{
|
||||||
$i++;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -4,7 +4,6 @@ namespace Aviat\Kilo\Tokens;
|
|||||||
|
|
||||||
use PhpToken;
|
use PhpToken;
|
||||||
|
|
||||||
use function Aviat\Kilo\str_contains;
|
|
||||||
use function Aviat\Kilo\tabs_to_spaces;
|
use function Aviat\Kilo\tabs_to_spaces;
|
||||||
use const Aviat\Kilo\T_RAW;
|
use const Aviat\Kilo\T_RAW;
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ function array_replace_range(array &$array, int $offset, int $length, mixed $val
|
|||||||
* @param int|null $offset
|
* @param int|null $offset
|
||||||
* @return bool
|
* @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))
|
if (empty($str))
|
||||||
{
|
{
|
||||||
@ -209,3 +209,18 @@ function error_code_name(int $code): string
|
|||||||
default => 'Unknown',
|
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;
|
||||||
|
}
|
@ -13,7 +13,7 @@ use function Aviat\Kilo\is_ctrl;
|
|||||||
use function Aviat\Kilo\is_digit;
|
use function Aviat\Kilo\is_digit;
|
||||||
use function Aviat\Kilo\is_separator;
|
use function Aviat\Kilo\is_separator;
|
||||||
use function Aviat\Kilo\is_space;
|
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\syntax_to_color;
|
||||||
use function Aviat\Kilo\tabs_to_spaces;
|
use function Aviat\Kilo\tabs_to_spaces;
|
||||||
|
|
||||||
@ -99,20 +99,20 @@ class FunctionTest extends TestCase {
|
|||||||
public function test_str_contains(): void
|
public function test_str_contains(): void
|
||||||
{
|
{
|
||||||
// Search from string offset
|
// 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
|
// 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
|
public function test_tabs_to_spaces(): void
|
||||||
{
|
{
|
||||||
$original = "\t\t\t{";
|
$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
|
public function test_array_replace_range_length_1(): void
|
||||||
|
@ -654,7 +654,7 @@
|
|||||||
5,
|
5,
|
||||||
5,
|
5,
|
||||||
5,
|
5,
|
||||||
0
|
7
|
||||||
],
|
],
|
||||||
"idx": 16
|
"idx": 16
|
||||||
},
|
},
|
||||||
@ -678,7 +678,7 @@
|
|||||||
13,
|
13,
|
||||||
13,
|
13,
|
||||||
13,
|
13,
|
||||||
0
|
7
|
||||||
],
|
],
|
||||||
"idx": 17
|
"idx": 17
|
||||||
},
|
},
|
||||||
@ -1495,10 +1495,10 @@
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
9,
|
9,
|
||||||
0,
|
6,
|
||||||
0,
|
6,
|
||||||
9,
|
9,
|
||||||
0
|
7
|
||||||
],
|
],
|
||||||
"idx": 49
|
"idx": 49
|
||||||
},
|
},
|
||||||
@ -1589,7 +1589,7 @@
|
|||||||
"render": "};",
|
"render": "};",
|
||||||
"hl": [
|
"hl": [
|
||||||
9,
|
9,
|
||||||
0
|
7
|
||||||
],
|
],
|
||||||
"idx": 53
|
"idx": 53
|
||||||
},
|
},
|
||||||
@ -1616,9 +1616,9 @@
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
9,
|
9,
|
||||||
0,
|
4,
|
||||||
0,
|
4,
|
||||||
0,
|
4,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -1650,7 +1650,7 @@
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
9,
|
9,
|
||||||
0
|
7
|
||||||
],
|
],
|
||||||
"idx": 55
|
"idx": 55
|
||||||
},
|
},
|
||||||
@ -1672,9 +1672,9 @@
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
9,
|
9,
|
||||||
0,
|
4,
|
||||||
0,
|
4,
|
||||||
0,
|
4,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -1734,7 +1734,7 @@
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
9,
|
9,
|
||||||
0
|
7
|
||||||
],
|
],
|
||||||
"idx": 56
|
"idx": 56
|
||||||
},
|
},
|
||||||
@ -2098,7 +2098,7 @@
|
|||||||
"render": "};",
|
"render": "};",
|
||||||
"hl": [
|
"hl": [
|
||||||
9,
|
9,
|
||||||
0
|
7
|
||||||
],
|
],
|
||||||
"idx": 66
|
"idx": 66
|
||||||
},
|
},
|
||||||
@ -2116,9 +2116,9 @@
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
9,
|
9,
|
||||||
0,
|
4,
|
||||||
0,
|
4,
|
||||||
0,
|
4,
|
||||||
7,
|
7,
|
||||||
0,
|
0,
|
||||||
4,
|
4,
|
||||||
@ -2130,7 +2130,7 @@
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
9,
|
9,
|
||||||
0
|
7
|
||||||
],
|
],
|
||||||
"idx": 67
|
"idx": 67
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user