diff --git a/src/FileType.php b/src/FileType.php index d30ac72..0d6cf50 100644 --- a/src/FileType.php +++ b/src/FileType.php @@ -3,7 +3,12 @@ namespace Aviat\Kilo; class FileType { - + /** + * Create the FileType object from the filename + * + * @param string|null $filename + * @return self + */ public static function from(?string $filename): self { $syntax = self::getSyntaxFromFilename((string)$filename); @@ -11,6 +16,12 @@ class FileType { return new self($syntax->filetype, $syntax); } + /** + * Create the Syntax object from the filename + * + * @param string $filename + * @return Syntax + */ private static function getSyntaxFromFilename(string $filename): Syntax { $ext = strstr(basename($filename), '.'); @@ -18,9 +29,16 @@ class FileType { return match ($ext) { '.sh', '.bash' => Syntax::new( 'Shell', + [ + 'case', 'do', 'done', 'elif', 'else', 'esac', 'fi', 'for', 'function', 'if', 'in', + 'select', 'then', 'time', 'until', 'while', 'declare', + ], + ['set'], + operators: ['[[', ']]'], slcs: '#', mcs: '', mce: '', + highlightNumbers: false, ), '.php', 'kilo' => Syntax::new( 'PHP', @@ -49,6 +67,7 @@ class FileType { '.css', '.less', '.sass', '.scss' => Syntax::new( 'CSS', slcs: '', + hasCommonOperators: false, ), '.go' => Syntax::new( 'Go', @@ -96,6 +115,12 @@ class FileType { 'usize', '&str', 'Copy', 'Drop', 'From', 'Into', 'None', 'Self', 'Send', 'Some', 'Sync', 'bool', 'char', 'i128', 'u128', 'Box', 'Err', 'Ord', 'Vec', 'dyn', 'f32', 'f64', 'i16', 'i32', 'i64', 'str', 'u16', 'u32', 'u64', 'Eq', 'Fn', 'Ok', 'i8', 'u8', + '&mut self', '&mut', '&self', 'self', + ], + [ + '...', '=>', '..', '>>=', '<<=', '--', '%=', '>>', ':=', '++', '/=', '<<', '>=', + '<-', '^=', '*=', '<=', '||', '|=', '-=', '!=', '==', '&&', '&=', '+=', '..=', + '.', ], hasCharType: true, highlightCharacters: true, diff --git a/src/Row.php b/src/Row.php index 91fe8ba..096e1b9 100644 --- a/src/Row.php +++ b/src/Row.php @@ -11,8 +11,6 @@ use Aviat\Kilo\Enum\RawKeyCode; * @property-read string $chars */ class Row { - // use Traits\MagicProperties; - /** * The version of the row to be displayed (where tabs are converted to display spaces) */ @@ -170,6 +168,11 @@ class Row { $this->update(); } + /** + * Set the contents of the Row + * + * @param string $chars + */ public function setChars(string $chars): void { $this->chars = $chars; @@ -257,7 +260,7 @@ class Row { || $this->highlightString($i, $syntax) || $this->highlightOperators($i, $syntax) || $this->highlightCommonDelimeters($i) - || $this->highlightCommonOperators($i) + || $this->highlightCommonOperators($i, $syntax) || $this->highlightNumber($i, $syntax) ) { continue; @@ -274,10 +277,17 @@ class Row { } } + /** + * Highlight number literals + * + * @param int $i + * @param Syntax $opts + * @return bool + */ protected function highlightNumber(int &$i, Syntax $opts): bool { $char = $this->render[$i]; - if ($opts->numbers() && is_digit($char)) + if ($opts->numbers() && is_digit($char) && $this->hl[$i] === Highlight::NORMAL) { if ($i > 0) { @@ -311,9 +321,18 @@ class Row { return false; } - protected function highlightWord(int &$i, array $keywords, int $syntaxType): bool + /** + * Highlight keywords and/or operators + * + * @param int $i + * @param array $keywords + * @param int $syntaxType + * @param bool $requireSeparator + * @return bool + */ + protected function highlightWord(int &$i, array $keywords, int $syntaxType, bool $requireSeparator = true): bool { - if ($i > 0) + if ($i > 0 && $requireSeparator) { $prevChar = $this->render[$i - 1]; if ( ! is_separator($prevChar)) @@ -341,6 +360,14 @@ class Row { return false; } + /** + * Highlight a single-char character from a list of provided keywords + * + * @param int $i + * @param array $chars + * @param int $syntaxType + * @return bool + */ protected function highlightChar(int &$i, array $chars, int $syntaxType): bool { if ($this->hl[$i] !== Highlight::NORMAL) @@ -361,23 +388,56 @@ class Row { return false; } + /** + * Highlight primary keywords + * + * @param int $i + * @param Syntax $opts + * @return bool + */ protected function highlightPrimaryKeywords(int &$i, Syntax $opts): bool { return $this->highlightWord($i, $opts->keywords1, Highlight::KEYWORD1); } + /** + * Highlight secondary keywords + * + * @param int $i + * @param Syntax $opts + * @return bool + */ protected function highlightSecondaryKeywords(int &$i, Syntax $opts): bool { return $this->highlightWord($i, $opts->keywords2, Highlight::KEYWORD2); } + /** + * Highlight language-specific operators + * + * @param int $i + * @param Syntax $opts + * @return bool + */ protected function highlightOperators(int &$i, Syntax $opts): bool { - return $this->highlightWord($i, $opts->operators, Highlight::OPERATOR); + return $this->highlightWord($i, $opts->operators, Highlight::OPERATOR, false); } - protected function highlightCommonOperators(int &$i): bool + /** + * Highlight common single-character operators + * + * @param int $i + * @param Syntax $opts + * @return bool + */ + protected function highlightCommonOperators(int &$i, Syntax $opts): bool { + if ( ! $opts->commonOperators()) + { + return false; + } + return $this->highlightChar( $i, ['+', '-', '*', '/', '<', '^', '>', '%', '=', ':', ',', ';', '&', '~', '!', '|', '.'], @@ -385,6 +445,12 @@ class Row { ); } + /** + * Highlight brackets and braces + * + * @param int $i + * @return bool + */ protected function highlightCommonDelimeters(int &$i): bool { return $this->highlightChar( @@ -394,6 +460,13 @@ class Row { ); } + /** + * Highlight character literals + * + * @param int $i + * @param Syntax $opts + * @return bool + */ protected function highlightCharacter(int &$i, Syntax $opts): bool { if (($i + 1) >= $this->rsize) @@ -426,6 +499,13 @@ class Row { return false; } + /** + * Highlight single-line comments + * + * @param int $i + * @param Syntax $opts + * @return bool + */ protected function highlightComment(int &$i, Syntax $opts): bool { if ( ! $opts->comments()) @@ -447,6 +527,13 @@ class Row { return false; } + /** + * Highlight quote-delimited string literals + * + * @param int $i + * @param Syntax $opts + * @return bool + */ protected function highlightString(int &$i, Syntax $opts): bool { $char = $this->render[$i]; @@ -490,6 +577,9 @@ class Row { return false; } + /** + * Highlight PHP code based on pre-parsed tokens + */ protected function highlightPHP(): void { $rowNum = $this->idx + 1; diff --git a/src/Syntax.php b/src/Syntax.php index 3d6cb0d..06ac164 100644 --- a/src/Syntax.php +++ b/src/Syntax.php @@ -19,6 +19,7 @@ class Syntax { bool $highlightComments = true, bool $hasCharType = false, bool $highlightCharacters = false, + bool $hasCommonOperators = true, ): self { return new self( @@ -34,12 +35,21 @@ class Syntax { $highlightCharacters, $highlightStrings, $highlightComments, + $hasCommonOperators, ); } public static function default(): self { - return self::new('No filetype', slcs: '', mcs: '', mce: '', highlightNumbers: false, highlightStrings: false); + return self::new( + 'No filetype', slcs: + '', mcs: + '', mce: + '', + highlightNumbers: false, + highlightStrings: false, + hasCommonOperators: false, + ); } private function __construct( @@ -55,7 +65,7 @@ class Syntax { public string $singleLineCommentStart, /** Syntax to start a multi-line comment */ public string $multiLineCommentStart, - /** Syntax to end a multi-line commment */ + /** Syntax to end a multi-line comment */ public string $multiLineCommentEnd, /** Should we highlight numbers? */ private bool $highlightNumbers, @@ -67,6 +77,8 @@ class Syntax { private bool $highlightStrings, /** should we highlight comments? */ private bool $highlightComments, + /** should we highlight common operators? */ + private bool $hasCommonOperators, ) {} public function numbers(): bool @@ -100,4 +112,9 @@ class Syntax { { return $this->highlightComments && strlen($this->singleLineCommentStart) !== 0; } + + public function commonOperators(): bool + { + return $this->hasCommonOperators; + } } \ No newline at end of file diff --git a/tests/Type/PointTest.php b/tests/Type/PointTest.php new file mode 100644 index 0000000..5b4c4e2 --- /dev/null +++ b/tests/Type/PointTest.php @@ -0,0 +1,24 @@ +assertEquals(1, $p->x); + $this->assertEquals(2, $p->y); + } + + public function testPointFrom(): void + { + $p = Point::new(3, 7); + $p2 = Point::from($p); + + $this->assertEquals($p->x, $p2->x); + $this->assertEquals($p->y, $p2->y); + } +}