summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-03-02 09:53:11 -0500
committerpommicket <pommicket@gmail.com>2023-03-02 09:53:11 -0500
commit595cc50b7985ec67c49c6e2ffc649cb04692a318 (patch)
tree970ab71aadabc9f0f0a7a1634512c31aedd23188
parent6d9ebc8332b6cc54ada4bc17689e4de4040892c6 (diff)
dynamic language registration working
-rw-r--r--buffer.c5
-rw-r--r--command.c6
-rw-r--r--config.c7
-rw-r--r--lsp-write.c24
-rw-r--r--main.c4
-rw-r--r--syntax.c70
-rw-r--r--ted.h12
7 files changed, 66 insertions, 62 deletions
diff --git a/buffer.c b/buffer.c
index 95cd3a3..5852c68 100644
--- a/buffer.c
+++ b/buffer.c
@@ -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);
diff --git a/command.c b/command.c
index 775d6bc..e9af9c3 100644
--- a/command.c
+++ b/command.c
@@ -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:
diff --git a/config.c b/config.c
index f19603a..c5f6c31 100644
--- a/config.c
+++ b/config.c
@@ -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);
diff --git a/main.c b/main.c
index 6050771..5031f93 100644
--- a/main.c
+++ b/main.c
@@ -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;
diff --git a/syntax.c b/syntax.c
index 936f925..e1ced05 100644
--- a/syntax.c
+++ b/syntax.c
@@ -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);
-
}
diff --git a/ted.h b/ted.h
index 9dbbbc2..35c35b0 100644
--- a/ted.h
+++ b/ted.h
@@ -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);