commit fb4217ce51a604a0d05a852d9c5bd804cc359bf0
parent ee4547f1f7c069b9aebf6899e50025a3f31f9cb3
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Sun, 9 Apr 2023 17:37:59 +0200
Extend syntax highlighting
* Add two more Keyword tags
* Add Operator tag
* Add Angle brackets tag
* Add support for individual character highlighting
* Extend C syntax highlighting
* Improve number literal detection
Diffstat:
M | kilo.c | | | 149 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
1 file changed, 125 insertions(+), 24 deletions(-)
diff --git a/kilo.c b/kilo.c
@@ -57,13 +57,29 @@ enum editorHighlight {
HL_MLCOMMENT,
HL_KEYWORD1,
HL_KEYWORD2,
- HL_STRING,
+ HL_KEYWORD3,
+ HL_KEYWORD4,
+ HL_MATCH,
HL_NUMBER,
- HL_MATCH
+ HL_OPERATORS,
+ HL_STRING,
+ HL_ABRAKETS,
+
+ HL_BRACKETS,
+ HL_SBRACKETS,
+ HL_CBRACKETS,
+ HL_SEMICOLON,
+ HL_COMMA,
};
-#define HL_HIGHLIGHT_NUMBERS (1 << 0)
-#define HL_HIGHLIGHT_STRINGS (1 << 1)
+#define HL_HIGHLIGHT_NUMBERS (1 << 0)
+#define HL_HIGHLIGHT_STRINGS (1 << 1)
+#define HL_HIGHLIGHT_ABRACKETS (1 << 2)
+#define HL_HIGHLIGHT_BRACKETS (1 << 3)
+#define HL_HIGHLIGHT_CBRACKETS (1 << 4)
+#define HL_HIGHLIGHT_SBRACKETS (1 << 5)
+#define HL_HIGHLIGHT_SEMICOLON (1 << 6)
+#define HL_HIGHLIGHT_COMMA (1 << 7)
/*** data ***/
@@ -71,6 +87,7 @@ struct editorSyntax {
char *filetype;
char **filematch;
char **keywords;
+ char **operators;
char *singleline_comment_start;
char *multiline_comment_start;
char *multiline_comment_end;
@@ -109,15 +126,35 @@ struct editorConfig E;
/*** filetypes ***/
char *C_HL_extensions[] = {".c", ".h", ".cpp", NULL};
-char *C_HL_keywords[] = {"switch", "if", "while", "for", "break",
- "continue", "return", "else", "struct", "union",
- "typedef", "static", "enum", "class", "case",
- "int|", "long|", "double|", "float|", "char|",
- "unsigned|", "signed|", "void|", NULL};
+
+/* clang-format off */
+char *C_HL_keywords[] = {
+ "auto", "break", "case", "const", "continue", "default",
+ "do", "else", "enum", "extern", "for", "goto",
+ "if", "register", "return", "sizeof", "static", "struct",
+ "switch", "typedef", "union", "volatile", "while",
+
+ "int|", "long|", "double|", "float|",
+ "char|", "unsigned|", "signed|", "void|",
+
+ "#include#", "#error#", "#define#", "#undef#",
+ "#ifdef#", "#ifndef#", "#endif#",
+
+ "__FILE__*", "__LINE__*", "__DATE__*", "__TIME__*",
+ "__STDC__*", "__STDC_VERSION__*", "__STDC_HOSTED__*", "NULL*", NULL};
+/* clang-format on */
+
+char *C_HL_operators[] = {
+ "...", "<=>", "<<=", ">>=", "++", "--", "==", "!=", ">=", "<=", "&&",
+ "||", "<<", ">>", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=",
+ "->", "::", "**", "-", "*", "/", "%", ">", "<", "!", "~",
+ "&", "|", "^", "=", ".", "+", "?", ":", NULL};
struct editorSyntax HLDB[] = {
- {"c", C_HL_extensions, C_HL_keywords, "//", "/*", "*/",
- HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS},
+ {"c", C_HL_extensions, C_HL_keywords, C_HL_operators, "//", "/*", "*/",
+ HL_HIGHLIGHT_NUMBERS | HL_HIGHLIGHT_STRINGS | HL_HIGHLIGHT_ABRACKETS |
+ HL_HIGHLIGHT_BRACKETS | HL_HIGHLIGHT_CBRACKETS |
+ HL_HIGHLIGHT_SBRACKETS | HL_HIGHLIGHT_COMMA | HL_HIGHLIGHT_SEMICOLON},
};
#define HLDB_ENTRIES (sizeof(HLDB) / sizeof(HLDB[0]))
@@ -243,7 +280,7 @@ int getWindowSize(int *rows, int *cols) {
/*** syntax highlighting ***/
int is_separator(int c) {
- return isspace(c) || c == '\0' || strchr(",.()+-/*=~%<>[];", c) != NULL;
+ return isspace(c) || c == '\0' || strchr(",.()+-/*=~%<>[]{};", c) != NULL;
}
void editorUpdateSyntax(erow *row) {
@@ -253,6 +290,7 @@ void editorUpdateSyntax(erow *row) {
if (E.syntax == NULL) return;
char **keywords = E.syntax->keywords;
+ char **operators = E.syntax->operators;
char *scs = E.syntax->singleline_comment_start;
char *mcs = E.syntax->multiline_comment_start;
@@ -262,7 +300,7 @@ void editorUpdateSyntax(erow *row) {
int mcs_len = mcs ? strlen(mcs) : 0;
int mce_len = mce ? strlen(mce) : 0;
- int prev_sep = 1, in_string = 0;
+ int prev_sep = 1, in_string = 0, in_abrackets = 0;
int in_comment = (row->idx > 0 && E.row[row->idx - 1].hl_open_comment);
int i = 0;
while (i < row->rsize) {
@@ -319,9 +357,25 @@ void editorUpdateSyntax(erow *row) {
}
}
+ if (E.syntax->flags & HL_HIGHLIGHT_ABRACKETS) {
+ if (in_abrackets) {
+ row->hl[i++] = HL_ABRAKETS;
+ if (c == '>') in_abrackets = 0;
+ prev_sep = 1;
+ continue;
+ } else {
+ if (c == '<' && strrchr(row->chars, '>')) {
+ in_abrackets = 1;
+ row->hl[i++] = HL_ABRAKETS;
+ continue;
+ }
+ }
+ }
+
if (E.syntax->flags & HL_HIGHLIGHT_NUMBERS) {
if ((isdigit(c) && (prev_sep || prev_hl == HL_NUMBER)) ||
- (c == '.' && prev_hl == HL_NUMBER)) {
+ ((c == '.' || c == 'x' || c == 'l' || c == 'u' || c == 'f') &&
+ prev_hl == HL_NUMBER)) {
row->hl[i] = HL_NUMBER;
i++;
prev_sep = 0;
@@ -331,28 +385,65 @@ void editorUpdateSyntax(erow *row) {
if (prev_sep) {
int j;
-
for (j = 0; keywords[j]; j++) {
int klen = strlen(keywords[j]);
- int kw2 = keywords[j][klen - 1] == '|';
- if (kw2) klen--;
+
+ enum editorHighlight hl = HL_KEYWORD1;
+ switch (keywords[j][--klen]) {
+ case '|': hl = HL_KEYWORD2; break;
+ case '#': hl = HL_KEYWORD3; break;
+ case '*': hl = HL_KEYWORD4; break;
+ default: klen++;
+ }
if (!strncmp(&row->render[i], keywords[j], klen) &&
is_separator(row->render[i + klen])) {
- memset(&row->hl[i], kw2 ? HL_KEYWORD2 : HL_KEYWORD1, klen);
+ memset(&row->hl[i], hl, klen);
i += klen;
- break;
+ prev_sep = 0;
+ goto next_iteration;
}
}
+ }
- if (keywords[j] != NULL) {
- prev_sep = 0;
- continue;
+ {
+ int j;
+ for (j = 0; operators[j]; j++) {
+ int olen = strlen(operators[j]);
+ if (!strncmp(&row->render[i], operators[j], olen)) {
+ memset(&row->hl[i], HL_OPERATORS, olen);
+ i += olen;
+ prev_sep = 1;
+ goto next_iteration;
+ }
}
}
+ switch (c) {
+ case '(':
+ case ')':
+ if (E.syntax->flags & HL_HIGHLIGHT_BRACKETS) row->hl[i] = HL_BRACKETS;
+ break;
+ case '[':
+ case ']':
+ if (E.syntax->flags & HL_HIGHLIGHT_SBRACKETS) row->hl[i] = HL_SBRACKETS;
+ break;
+ case '{':
+ case '}':
+ if (E.syntax->flags & HL_HIGHLIGHT_CBRACKETS) row->hl[i] = HL_CBRACKETS;
+ break;
+ case ';':
+ if (E.syntax->flags & HL_HIGHLIGHT_SEMICOLON) row->hl[i] = HL_SEMICOLON;
+ break;
+ case ',':
+ if (E.syntax->flags & HL_HIGHLIGHT_COMMA) row->hl[i] = HL_COMMA;
+ break;
+ }
+
+ // if ((prev_sep = is_separator(c))) row->hl[i] = HL_KEYWORD4;
prev_sep = is_separator(c);
i++;
+ next_iteration:;
}
int changed = (row->hl_open_comment != in_comment);
@@ -367,9 +458,19 @@ int editorSyntaxToColor(int hl) {
case HL_MLCOMMENT: return 36;
case HL_STRING: return 35;
case HL_KEYWORD1: return 33;
- case HL_KEYWORD2: return 32;
- case HL_NUMBER: return 31;
+ case HL_KEYWORD2: return 31;
+ case HL_KEYWORD3: return 91;
+ case HL_KEYWORD4: return 96;
+ case HL_OPERATORS: return 94;
+ case HL_NUMBER: return 32;
case HL_MATCH: return 34;
+ case HL_ABRAKETS: return 93;
+
+ case HL_BRACKETS: return 91;
+ case HL_SBRACKETS: return 37;
+ case HL_CBRACKETS: return 93;
+ case HL_SEMICOLON: return 93;
+ case HL_COMMA: return 91;
default: return 37;
}
}