diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | keywords.h | 9 | ||||
-rwxr-xr-x | keywords.py | 4 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | syntax.c | 85 | ||||
-rw-r--r-- | ted.cfg | 1 | ||||
-rw-r--r-- | ted.h | 2 |
7 files changed, 96 insertions, 9 deletions
@@ -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+!) @@ -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() @@ -1,5 +1,3 @@ -// Highlighting for: -// - Config (cfg) // :set-language command; -1 = default language for this extension #include "base.h" @@ -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; } } @@ -210,3 +210,4 @@ Python = .py Tex = .tex Markdown = .md HTML = .html, .php +Config = .cfg @@ -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) |