Improve number highlighting, finish step 156

This commit is contained in:
Timothy Warren 2019-10-24 16:22:52 -04:00
parent a59bcfb9d1
commit 88afc3909e
2 changed files with 71 additions and 6 deletions

View File

@ -135,12 +135,29 @@ class Row {
{
$this->hl = array_fill(0, $this->rsize, Highlight::NORMAL);
for ($i = 0; $i < $this->rsize; $i++)
$prevSep = TRUE;
$i = 0;
while ($i < $this->rsize)
{
if (is_digit($this->render[$i]))
$char = $this->render[$i];
$prevHl = ($i > 0) ? $this->hl[$i - 1] : Highlight::NORMAL;
// Numbers, including decimal points
if (
($char === '.' && $prevHl === Highlight::NUMBER) ||
(($prevSep || $prevHl === Highlight::NUMBER) && is_digit($char))
)
{
$this->hl[$i] = Highlight::NUMBER;
$i++;
$prevSep = FALSE;
continue;
}
$prevSep = is_separator($char);
$i++;
}
}
}
@ -497,6 +514,15 @@ class Editor {
static $lastMatch = -1;
static $direction = 1;
static $savedHlLine = 0;
static $savedHl = [];
if ( ! empty($savedHl))
{
$this->rows[$savedHlLine]->hl = $savedHl;
$savedHl = [];
}
if ($key === "\r" || $key === "\x1b")
{
$lastMatch = -1;
@ -536,16 +562,20 @@ class Editor {
$current = 0;
}
$match = strpos($this->rows[$current]->render, $query);
$row = $this->rows[$current];
$match = strpos($row->render, $query);
if ($match !== FALSE)
{
$lastMatch = $current;
$this->cursorY = $current;
$this->cursorX = $this->rowRxToCx($this->rows[$current], $match);
$this->cursorX = $this->rowRxToCx($row, $match);
$this->rowOffset = $this->numRows;
$savedHlLine = $current;
$savedHl = $row->hl;
// Update the highlight array of the relevant row with the 'MATCH' type
array_replace_range($this->rows[$current]->hl, $match, strlen($query), Highlight::MATCH);
array_replace_range($row->hl, $match, strlen($query), Highlight::MATCH);
break;
}
@ -662,7 +692,8 @@ class Editor {
{
if ($currentColor !== -1)
{
$this->ab .= "\x1b[39m";
$this->ab .= "\x1b[39m"; // Reset foreground color
$this->ab .= "\x1b[0m"; // Reset background color
$currentColor = -1;
}
$this->ab .= $c[$i];
@ -673,6 +704,7 @@ class Editor {
if ($color !== $currentColor)
{
$currentColor = $color;
$this->ab .= "\x1b[0m"; // Reset background color
$this->ab .= sprintf("\x1b[%dm", $color);
}
$this->ab .= $c[$i];
@ -680,6 +712,7 @@ class Editor {
}
$this->ab .= "\x1b[39m";
$this->ab .= "\x1b[0m";
}
$this->ab .= "\x1b[K"; // Clear the current line

View File

@ -161,6 +161,18 @@ function is_digit(string $char): bool
return is_ascii($char) && ( $c > 0x2f && $c < 0x3a );
}
/**
* Does the one-character string contain ascii whitespace?
*
* @param string $char
* @return bool
*/
function is_space(string $char): bool
{
$ws = [' ', "\t", "\n", "\r", "\xa", "\xb", "\xc"];
return is_ascii($char) && in_array($char, $ws, TRUE);
}
// ----------------------------------------------------------------------------
// ! Helper functions
// ----------------------------------------------------------------------------
@ -182,6 +194,26 @@ function get_ffi(): FFI
return $ffi;
}
/**
* Does the one-character string contain a character that separates tokens?
*
* @param string $char
* @return bool
*/
function is_separator(string $char): bool
{
if ( ! is_ascii($char))
{
return FALSE;
}
// `strpos` is used instead of `strchr`/`strstr` as we don't care about the actual match
// while `strchr` would match the C version, it also returns the match
$isSep = (strpos(',.()+-/*=~%<>[];', $char) !== FALSE);
return is_space($char) || $char === "\0" || $isSep;
}
/**
* Pull input from the stdin stream.
*