diff options
author | pommicket <pommicket@gmail.com> | 2023-03-02 09:53:11 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2023-03-02 09:53:11 -0500 |
commit | 595cc50b7985ec67c49c6e2ffc649cb04692a318 (patch) | |
tree | 970ab71aadabc9f0f0a7a1634512c31aedd23188 | |
parent | 6d9ebc8332b6cc54ada4bc17689e4de4040892c6 (diff) |
dynamic language registration working
-rw-r--r-- | buffer.c | 5 | ||||
-rw-r--r-- | command.c | 6 | ||||
-rw-r--r-- | config.c | 7 | ||||
-rw-r--r-- | lsp-write.c | 24 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | syntax.c | 70 | ||||
-rw-r--r-- | ted.h | 12 |
7 files changed, 66 insertions, 62 deletions
@@ -222,8 +222,9 @@ Language buffer_language(TextBuffer *buffer) { // @TODO(optimization): cache this? // (we're calling buffer_lsp on every edit and that calls this) - if (buffer->manual_language >= 1) - return (Language)(buffer->manual_language - 1); + + if (buffer->manual_language != LANG_NONE) + return (Language)buffer->manual_language; const Settings *settings = buffer->ted->default_settings; // important we don't use buffer_settings here since that would cause a loop! const char *filename = path_filename(buffer->path); size_t filename_len = strlen(filename); @@ -411,10 +411,10 @@ void command_execute(Ted *ted, Command c, i64 argument) { case CMD_SET_LANGUAGE: if (buffer && !buffer->is_line_buffer) { - if (argument < 0 || argument >= LANG_COUNT_MAX) - buffer->manual_language = -1; + if (argument <= 0 || argument > LANG_USER_MAX || !language_is_valid((Language)argument)) + buffer->manual_language = 0; else - buffer->manual_language = (i16)(argument + 1); + buffer->manual_language = argument; } break; case CMD_AUTOCOMPLETE: @@ -834,6 +834,10 @@ static void config_parse_line(ConfigReader *cfg, Settings **applicable_settings, char *p = exts; while (*p) { + while (*p == ',') + ++p; + if (*p == '\0') + break; size_t len = strcspn(p, ","); LanguageExtension *ext = arr_addp(settings->language_extensions); ext->language = lang; @@ -1029,7 +1033,8 @@ void config_parse(Ted *ted, ConfigPart **pparts) { arr_free(languages); arr_foreach_ptr(parts, ConfigPart, part) { - + cfg->filename = part->file; + cfg->line_number = part->line; arr_add(part->text, '\0'); // null termination char *line = part->text; while (*line) { diff --git a/lsp-write.c b/lsp-write.c index 2689869..830c0ab 100644 --- a/lsp-write.c +++ b/lsp-write.c @@ -8,27 +8,19 @@ typedef struct { u64 number; - char identifier[32]; + char *identifier; } LanguageId; -static LanguageId language_ids[512]; +static LanguageId *language_ids = NULL; // dynamic array void lsp_register_language(u64 id, const char *lsp_identifier) { - int i; - for (i = 0; *language_ids[i].identifier; ++i) { - if (language_ids[i].number == id) { - break; - } - } - if (i < (int)arr_count(language_ids) - 1) { - language_ids[i].number = id; - strbuf_cpy(language_ids[i].identifier, lsp_identifier); - } + LanguageId *lid = arr_addp(language_ids); + lid->number = id; + lid->identifier = str_dup(lsp_identifier); } static const char *lsp_language_id(u64 lang) { - int i; - for (i = 0; *language_ids[i].identifier; ++i) { - if (language_ids[i].number == lang) { - return language_ids[i].identifier; + arr_foreach_ptr(language_ids, LanguageId, lid) { + if (lid->number == lang) { + return lid->identifier; } } assert(0); @@ -1,6 +1,6 @@ /* @TODO: -- check bounds in CMD_SET_LANGUAGE +- check validity in CMD_SET_LANGUAGE - comment-start & comment-end settings FUTURE FEATURES: - manual.md @@ -318,7 +318,7 @@ int main(int argc, char **argv) { command_init(); color_init(); - + syntax_register_builtin_languages(); // read command-line arguments const char *starting_filename = NULL; @@ -67,28 +67,34 @@ enum { typedef struct { Language lang; - char name[32]; + char *name; } LanguageName; -static LanguageName language_names[LANG_COUNT_MAX]; +static LanguageName *language_names = NULL; // dynamic array -// returns the language this string is referring to, or LANG_NONE if it's invalid. Language language_from_str(const char *str) { - for (int i = 0; language_names[i].name[0]; ++i) { - if (strcmp_case_insensitive(language_names[i].name, str) == 0) - return language_names[i].lang; + arr_foreach_ptr(language_names, LanguageName, lname) { + if (strcmp_case_insensitive(lname->name, str) == 0) + return lname->lang; } return LANG_NONE; } +bool language_is_valid(Language language) { + arr_foreach_ptr(language_names, LanguageName, lname) { + if (lname->lang == language) + return true; + } + return false; +} + const char *language_to_str(Language language) { - for (int i = 0; language_names[i].name[0]; ++i) { - if (language_names[i].lang == language) - return language_names[i].name; + arr_foreach_ptr(language_names, LanguageName, lname) { + if (lname->lang == language) + return lname->name; } return "???"; - } // start of single line comment for language l -- used for comment/uncomment selection @@ -1719,12 +1725,12 @@ typedef struct { SyntaxHighlightFunction func; } SyntaxHighlighter; -static SyntaxHighlighter syntax_highlighters[LANG_COUNT_MAX]; +static SyntaxHighlighter *syntax_highlighters = NULL; // dynamic array void syntax_highlight(SyntaxState *state, Language lang, const char32_t *line, u32 line_len, SyntaxCharType *char_types) { - for (int i = 0; syntax_highlighters[i].func; ++i) { - if (syntax_highlighters[i].lang == lang) { - syntax_highlighters[i].func(state, line, line_len, char_types); + arr_foreach_ptr(syntax_highlighters, SyntaxHighlighter, highlighter) { + if (highlighter->lang == lang) { + highlighter->func(state, line, line_len, char_types); return; } } @@ -1883,30 +1889,28 @@ void syntax_register_language(const LanguageInfo *info) { return; } - int i; - for (i = 0; language_names[i].name[0]; i++) { - if (streq(language_names[i].name, info->name) || language_names[i].lang == info->id) { - // this language will be overridden i guess - break; + arr_foreach_ptr(language_names, LanguageName, lname) { + if (streq(lname->name, info->name)) { + debug_println("Language named %s registered twice.", info->name); + return; + } + if (lname->lang == info->id) { + debug_println("Language with ID %" PRIu32 " registered twice.", info->id); + return; } } - if (i < LANG_COUNT_MAX) { - language_names[i].lang = info->id; - strbuf_cpy(language_names[i].name, info->name); + { + LanguageName *lname = arr_addp(language_names); + lname->lang = info->id; + lname->name = str_dup(info->name); } + + if (info->highlighter) { - for (i = 0; syntax_highlighters[i].func; i++) { - if (syntax_highlighters[i].lang == info->id) { - // this language will be overridden i guess - break; - } - } - if (i < LANG_COUNT_MAX) { - syntax_highlighters[i].lang = info->id; - syntax_highlighters[i].func = info->highlighter; - } + SyntaxHighlighter *highlighter = arr_addp(syntax_highlighters); + highlighter->lang = info->id; + highlighter->func = info->highlighter; } lsp_register_language(info->id, info->lsp_identifier); - } @@ -94,10 +94,6 @@ enum { /// May be one of the `LANG_*` constants, or a dynamically registered language. typedef u32 Language; -/// Maximum number of languages available. -#define LANG_COUNT_MAX 511 - - /// Current state of syntax highlighting. typedef u32 SyntaxState; @@ -336,7 +332,7 @@ typedef struct { double scroll_x, scroll_y; /// last write time to `path` double last_write_time; - /// 1 + the language the buffer has been manually set to, or 0 if it hasn't been manually set to anything + /// the language the buffer has been manually set to, or `LANG_NONE` if it hasn't been set to anything i64 manual_language; /// position of cursor BufferPos cursor_pos; @@ -1492,7 +1488,13 @@ void session_read(Ted *ted); /// /// this should be done before loading configs so language-specific settings are recognized properly. void syntax_register_language(const LanguageInfo *info); +/// register ted's built-in languages. +void syntax_register_builtin_languages(void); +/// returns `true` if `language` is a valid language ID +bool language_is_valid(Language language); +/// read language name from `str`. returns `LANG_NONE` if `str` is invalid. Language language_from_str(const char *str); +/// convert language to string const char *language_to_str(Language language); /// string which should be put before comments in the given language const char *language_comment_start(Language l); |