summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-04-20 14:18:56 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2021-04-20 14:18:56 -0400
commitf90d98c3c451aa5be2979ff05863b5aa8bee9336 (patch)
treef565281789262225d28dc177ce97640b19dce646
parentf5bb2118eadc20402e69d575c9be8a02cf673caa (diff)
cfg syntax highlighting
-rw-r--r--README.md2
-rw-r--r--keywords.h9
-rwxr-xr-xkeywords.py4
-rw-r--r--main.c2
-rw-r--r--syntax.c85
-rw-r--r--ted.cfg1
-rw-r--r--ted.h2
7 files changed, 96 insertions, 9 deletions
diff --git a/README.md b/README.md
index 054ce0e..9450b98 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ in other editors.
- Multiple tabs, each with a different file
- Split screen (default: Ctrl+\\, Ctrl+Shift+\\)
- Auto-indent
-- Syntax highlighting for C, C++, Rust, Python, LaTeX, and Markdown.
+- Syntax highlighting for C, C++, HTML, LaTeX, Markdown, Python, and Rust.
- Find and replace (with regular expressions!)
- Run build command (F4), go to errors
- Run any shell command (Ctrl+!)
diff --git a/keywords.h b/keywords.h
index 5fdb0e5..c880b77 100644
--- a/keywords.h
+++ b/keywords.h
@@ -203,3 +203,12 @@ static Keyword const *const syntax_all_keywords_html[] = {
['a'] = syntax_keywords_html_a, ['b'] = syntax_keywords_html_b, ['c'] = syntax_keywords_html_c, ['d'] = syntax_keywords_html_d, ['e'] = syntax_keywords_html_e, ['f'] = syntax_keywords_html_f, ['h'] = syntax_keywords_html_h, ['i'] = syntax_keywords_html_i, ['k'] = syntax_keywords_html_k, ['l'] = syntax_keywords_html_l, ['m'] = syntax_keywords_html_m, ['n'] = syntax_keywords_html_n, ['o'] = syntax_keywords_html_o, ['p'] = syntax_keywords_html_p, ['r'] = syntax_keywords_html_r, ['s'] = syntax_keywords_html_s, ['t'] = syntax_keywords_html_t, ['u'] = syntax_keywords_html_u, ['v'] = syntax_keywords_html_v, ['w'] = syntax_keywords_html_w
};
+static Keyword const syntax_keywords_config_f[2] = {{"false", SYNTAX_CONSTANT}};
+static Keyword const syntax_keywords_config_n[2] = {{"no", SYNTAX_CONSTANT}};
+static Keyword const syntax_keywords_config_o[3] = {{"off", SYNTAX_CONSTANT},{"on", SYNTAX_CONSTANT}};
+static Keyword const syntax_keywords_config_t[2] = {{"true", SYNTAX_CONSTANT}};
+static Keyword const syntax_keywords_config_y[2] = {{"yes", SYNTAX_CONSTANT}};
+static Keyword const *const syntax_all_keywords_config[] = {
+ ['f'] = syntax_keywords_config_f, ['n'] = syntax_keywords_config_n, ['o'] = syntax_keywords_config_o, ['t'] = syntax_keywords_config_t, ['y'] = syntax_keywords_config_y
+};
+
diff --git a/keywords.py b/keywords.py
index c8f7e9c..2413dd9 100755
--- a/keywords.py
+++ b/keywords.py
@@ -243,6 +243,9 @@ attributes_html = [
'srclang','srcset','start','step','style','tabindex','target',
'title','translate','type','usemap','value','width','wrap'
]
+constants_config = [
+ 'on', 'off', 'yes', 'no', 'true', 'false'
+]
assert len(attributes_html) == len(set(attributes_html))
@@ -274,4 +277,5 @@ output_keywords(file, cpp_things, 'cpp')
output_keywords(file, label(keywords_rust, SYNTAX_KEYWORD) + label(builtins_rust, SYNTAX_BUILTIN) + label(constants_rust, SYNTAX_CONSTANT), 'rust')
output_keywords(file, label(keywords_python, SYNTAX_KEYWORD) + label(builtins_python, SYNTAX_BUILTIN), 'python')
output_keywords(file, label(builtins_html, SYNTAX_BUILTIN), 'html')
+output_keywords(file, label(constants_config, SYNTAX_CONSTANT), 'config')
file.close()
diff --git a/main.c b/main.c
index 044a11b..d140f29 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,3 @@
-// Highlighting for:
-// - Config (cfg)
// :set-language command; -1 = default language for this extension
#include "base.h"
diff --git a/syntax.c b/syntax.c
index 2e361cf..bc8803c 100644
--- a/syntax.c
+++ b/syntax.c
@@ -16,12 +16,18 @@ Language language_from_str(char const *str) {
// start of single line comment for language l -- used for comment/uncomment selection
char const *language_comment_start(Language l) {
switch (l) {
- case LANG_C: return "/* ";
+ case LANG_C:
+ return "/* ";
case LANG_RUST:
- case LANG_CPP: return "// ";
- case LANG_PYTHON: return "# ";
- case LANG_TEX: return "% ";
- case LANG_HTML: return "<!-- ";
+ case LANG_CPP:
+ return "// ";
+ case LANG_CONFIG:
+ case LANG_PYTHON:
+ return "# ";
+ case LANG_TEX:
+ return "% ";
+ case LANG_HTML:
+ return "<!-- ";
case LANG_NONE:
case LANG_MARKDOWN:
case LANG_COUNT:
@@ -697,7 +703,7 @@ static void syntax_highlight_markdown(SyntaxState *state, char32_t const *line,
}
if (multiline_code) {
- static_assert_if_possible(sizeof *char_types == 1)
+ static_assert_if_possible(sizeof *char_types == 1) // NOTE: memset is used extensively in this file this way
memset(char_types, SYNTAX_CODE, line_len);
return;
}
@@ -947,6 +953,10 @@ static void syntax_highlight_html(SyntaxState *state, char32_t const *line, u32
break;
default:
if (char_types) {
+
+ if ((i && is32_ident(line[i - 1])) || !is32_ident(line[i]))
+ break; // can't be a keyword on its own.
+
u32 keyword_len = syntax_keyword_len(LANG_HTML, line, i, line_len);
Keyword const *keyword = syntax_keyword_lookup(syntax_all_keywords_html, arr_count(syntax_all_keywords_html),
&line[i], keyword_len);
@@ -973,6 +983,66 @@ static void syntax_highlight_html(SyntaxState *state, char32_t const *line, u32
*state = (comment * SYNTAX_STATE_HTML_COMMENT);
}
+static void syntax_highlight_config(SyntaxState *state, char32_t const *line, u32 line_len, SyntaxCharType *char_types) {
+ (void)state;
+ if (line_len == 0) return;
+ if (!char_types) return; // there's no state for config files.
+
+ if (line[0] == '#') {
+ memset(char_types, SYNTAX_COMMENT, line_len);
+ return;
+ }
+ if (line[0] == '[' && line[line_len - 1] == ']') {
+ memset(char_types, SYNTAX_BUILTIN, line_len);
+ return;
+ }
+ bool string = false;
+ for (u32 i = 0; i < line_len; ++i) {
+ char_types[i] = string ? SYNTAX_STRING : SYNTAX_NORMAL;
+ switch (line[i]) {
+ case '"':
+ string = !string;
+ if (string)
+ char_types[i] = SYNTAX_STRING;
+ break;
+ case '#':
+ // don't try highlighting the rest of the line.
+ // for ted.cfg, this could be a color, but for other cfg files,
+ // it might be a comment
+ memset(&char_types[i], 0, line_len - i);
+ i = line_len;
+ break;
+ case ANY_DIGIT:
+ if (i > 0 && !string) {
+ if (is32_ident(line[i-1]) // something like e5
+ || line[i-1] == '+') // key combinations, e.g. Alt+0
+ break;
+ while (i < line_len && syntax_number_continues(line, line_len, i))
+ char_types[i++] = SYNTAX_CONSTANT;
+ }
+ break;
+ default: {
+ if (i == 0) // none of the keywords in syntax_all_keywords_config should appear at the start of the line
+ break;
+ if (is32_ident(line[i - 1]) || !is32_ident(line[i]))
+ break; // can't be a keyword on its own.
+
+ u32 keyword_len = syntax_keyword_len(LANG_CONFIG, line, i, line_len);
+ Keyword const *keyword = syntax_keyword_lookup(syntax_all_keywords_config, arr_count(syntax_all_keywords_config),
+ &line[i], keyword_len);
+ if (keyword) {
+ SyntaxCharType type = keyword->type;
+ for (size_t j = 0; j < keyword_len; ++j) {
+ char_types[i++] = type;
+ }
+ --i; // we'll increment i from the for loop
+ break;
+ }
+ } break;
+ }
+ }
+}
+
// This is the main syntax highlighting function. It will determine which colors to use for each character.
// Rather than returning colors, it returns a character type (e.g. comment) which can be converted to a color.
// To highlight multiple lines, start out with a zeroed SyntaxState, and pass a pointer to it each time.
@@ -1004,6 +1074,9 @@ void syntax_highlight(SyntaxState *state, Language lang, char32_t const *line, u
case LANG_HTML:
syntax_highlight_html(state, line, line_len, char_types);
break;
+ case LANG_CONFIG:
+ syntax_highlight_config(state, line, line_len, char_types);
+ break;
case LANG_COUNT: assert(0); break;
}
}
diff --git a/ted.cfg b/ted.cfg
index aa15520..bad356e 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -210,3 +210,4 @@ Python = .py
Tex = .tex
Markdown = .md
HTML = .html, .php
+Config = .cfg
diff --git a/ted.h b/ted.h
index 6e61ea9..e08f222 100644
--- a/ted.h
+++ b/ted.h
@@ -52,6 +52,7 @@ ENUM_U16 {
LANG_TEX,
LANG_MARKDOWN,
LANG_HTML,
+ LANG_CONFIG, // .cfg files, e.g. ted.cfg
LANG_COUNT
} ENUM_U16_END(Language);
@@ -69,6 +70,7 @@ static LanguageName const language_names[] = {
{LANG_TEX, "Tex"},
{LANG_MARKDOWN, "Markdown"},
{LANG_HTML, "HTML"},
+ {LANG_CONFIG, "Config"},
};
static_assert_if_possible(arr_count(language_names) == LANG_COUNT)