From 9382250e21488feec982ff7dfffb5df05b39a290 Mon Sep 17 00:00:00 2001 From: Albert Cervin Date: Wed, 31 Jan 2024 14:32:10 +0100 Subject: Change how language and settings work No need to register settings anymore and languages can better handle arbitrary settings now. --- src/dged/buffer.c | 6 +-- src/dged/lang.c | 116 ++++++++++++++++++++++++++++++++++++---------------- src/dged/lang.h | 3 ++ src/dged/settings.c | 40 ++++++++++++------ src/dged/settings.h | 26 +++++++----- 5 files changed, 129 insertions(+), 62 deletions(-) (limited to 'src/dged') diff --git a/src/dged/buffer.c b/src/dged/buffer.c index e114bef..9867835 100644 --- a/src/dged/buffer.c +++ b/src/dged/buffer.c @@ -130,11 +130,11 @@ uint32_t buffer_add_destroy_hook(struct buffer *buffer, void buffer_static_init() { VEC_INIT(&g_create_hooks, 8); - settings_register_setting( + settings_set_default( "editor.tab-width", (struct setting_value){.type = Setting_Number, .number_value = 4}); - settings_register_setting( + settings_set_default( "editor.show-whitespace", (struct setting_value){.type = Setting_Bool, .bool_value = true}); } @@ -270,7 +270,7 @@ static void write_line(struct text_chunk *chunk, void *userdata) { static bool is_word_break(uint8_t c) { return c == ' ' || c == '.' || c == '(' || c == ')' || c == '[' || c == ']' || - c == '{' || c == '}'; + c == '{' || c == '}' || c == ';'; } static bool is_word_char(uint8_t c) { return !is_word_break(c); } diff --git a/src/dged/lang.c b/src/dged/lang.c index fb740e8..7c7e478 100644 --- a/src/dged/lang.c +++ b/src/dged/lang.c @@ -11,34 +11,40 @@ void define_lang(const char *name, const char *id, const char *pattern, uint32_t tab_width, const char *lang_srv) { char namebuf[128] = {0}; - size_t offs = snprintf(namebuf, 128, "languages.%s.", id); + const char *key = setting_join_key("languages", id); - char *b = namebuf + offs; - snprintf(b, 128 - offs, "%s", "pattern"); - settings_register_setting( - namebuf, (struct setting_value){.type = Setting_String, - .string_value = (char *)pattern}); + const char *pat_key = setting_join_key(key, "pattern"); + settings_set_default(pat_key, + (struct setting_value){.type = Setting_String, + .string_value = (char *)pattern}); + free((void *)pat_key); - snprintf(b, 128 - offs, "%s", "tab-width"); - settings_register_setting(namebuf, - (struct setting_value){.type = Setting_Number, - .number_value = tab_width}); + const char *tabw_key = setting_join_key(key, "tab-width"); + settings_set_default(tabw_key, + (struct setting_value){.type = Setting_Number, + .number_value = tab_width}); + free((void *)tabw_key); + // TODO: move lang server if (lang_srv != NULL) { - snprintf(b, 128 - offs, "%s", "lang-srv"); - settings_register_setting( - namebuf, (struct setting_value){.type = Setting_String, - .string_value = (char *)lang_srv}); + const char *langsrv_key = setting_join_key(key, "lang-srv"); + settings_set_default( + langsrv_key, (struct setting_value){.type = Setting_String, + .string_value = (char *)lang_srv}); + free((void *)langsrv_key); } - snprintf(b, 128 - offs, "%s", "name"); - settings_register_setting( - namebuf, (struct setting_value){.type = Setting_String, - .string_value = (char *)name}); + const char *name_key = setting_join_key(key, "name"); + settings_set_default(name_key, + (struct setting_value){.type = Setting_String, + .string_value = (char *)name}); + free((void *)name_key); + free((void *)key); } static struct language g_fundamental = { .name = "Fundamental", + .id = "fnd", .tab_width = 4, .lang_srv = NULL, }; @@ -54,19 +60,22 @@ void languages_init(bool register_default) { } } -struct language lang_from_settings(const char *lang_path) { - char setting_name_buf[128] = {0}; - size_t offs = snprintf(setting_name_buf, 128, "%s.", lang_path); - char *b = setting_name_buf + offs; - +struct language lang_from_settings(const char *id) { struct language l; + l.id = strdup(id); + + const char *key = setting_join_key("languages", id); - snprintf(b, 128 - offs, "%s", "name"); - struct setting *name = settings_get(setting_name_buf); + // name + const char *name_key = setting_join_key(key, "name"); + struct setting *name = settings_get(name_key); + free((void *)name_key); l.name = name != NULL ? name->value.string_value : "Unknown"; - snprintf(b, 128 - offs, "%s", "tab-width"); - struct setting *tab_width = settings_get(setting_name_buf); + // tab width + const char *tabw_key = setting_join_key(key, "tab-width"); + struct setting *tab_width = settings_get(tabw_key); + free((void *)tabw_key); // fall back to global value if (tab_width == NULL) { @@ -74,10 +83,13 @@ struct language lang_from_settings(const char *lang_path) { } l.tab_width = tab_width != NULL ? tab_width->value.number_value : 4; - snprintf(b, 128 - offs, "%s", "lang-srv"); - struct setting *lang_srv = settings_get(setting_name_buf); + // language server, TODO: move + const char *langsrv_key = setting_join_key(key, "lang-srv"); + struct setting *lang_srv = settings_get(langsrv_key); + free((void *)langsrv_key); l.lang_srv = lang_srv != NULL ? lang_srv->value.string_value : NULL; + free((void *)key); return l; } @@ -96,6 +108,36 @@ void next_ext(const char *curr, const char **nxt, const char **end) { } } +void lang_settings(struct language *lang, struct setting **settings[], + uint32_t *nsettings) { + const char *key = setting_join_key("languages", lang->id); + settings_get_prefix(key, settings, nsettings); + free((void *)key); +} + +struct setting *lang_setting(struct language *lang, const char *key) { + const char *langkey = setting_join_key("languages", lang->id); + const char *setting_key = setting_join_key(langkey, key); + + struct setting *res = settings_get(setting_key); + + free((void *)setting_key); + free((void *)langkey); + + return res; +} + +void lang_setting_set(struct language *lang, const char *key, + struct setting_value value) { + const char *langkey = setting_join_key("languages", lang->id); + const char *setting_key = setting_join_key(langkey, key); + + settings_set(setting_key, value); + + free((void *)setting_key); + free((void *)langkey); +} + struct language lang_from_filename(const char *filename) { if (strlen(filename) == 0) { @@ -117,12 +159,15 @@ struct language lang_from_filename(const char *filename) { if (regcomp(®ex, val, REG_EXTENDED) == 0 && regexec(®ex, filename, 0, NULL, 0) == 0) { - char lang_path[128] = {0}; - strncpy(lang_path, setting->path, setting_name - setting->path); + // len of "languages." + size_t id_len = setting_name - (setting->path + 10); + char lang_id[128] = {0}; + memcpy(lang_id, setting->path + 10, id_len); + lang_id[id_len] = '\0'; regfree(®ex); free(settings); - return lang_from_settings(lang_path); + return lang_from_settings(lang_id); } regfree(®ex); } @@ -140,18 +185,17 @@ struct language lang_from_id(const char *id) { return g_fundamental; } - char lang_path[128] = {0}; - snprintf(lang_path, 128, "languages.%s", id); - // check that it exists struct setting **settings = NULL; uint32_t nsettings = 0; + const char *lang_path = setting_join_key("languages", id); settings_get_prefix(lang_path, &settings, &nsettings); + free((void *)lang_path); free(settings); if (nsettings > 0) { - return lang_from_settings(lang_path); + return lang_from_settings(id); } else { minibuffer_echo_timeout(4, "failed to find language \"%s\"", id); return lang_from_settings("languages.fnd"); diff --git a/src/dged/lang.h b/src/dged/lang.h index 5aff52c..51d9ac3 100644 --- a/src/dged/lang.h +++ b/src/dged/lang.h @@ -8,6 +8,9 @@ * Settings for a programming language. */ struct language { + /** Language id */ + const char *id; + /** Descriptive name of the programming language */ const char *name; diff --git a/src/dged/settings.c b/src/dged/settings.c index 7b5e4dc..df3af1c 100644 --- a/src/dged/settings.c +++ b/src/dged/settings.c @@ -40,8 +40,8 @@ void setting_set_value(struct setting *setting, struct setting_value val) { } } -void settings_register_setting(const char *path, - struct setting_value default_value) { +static void settings_register_setting(const char *path, + struct setting_value default_value) { HASHMAP_APPEND(&g_settings.settings, struct setting_entry, path, struct setting_entry * s); @@ -81,14 +81,14 @@ void settings_set(const char *path, struct setting_value value) { struct setting *setting = settings_get(path); if (setting != NULL) { setting_set_value(setting, value); + } else { + settings_register_setting(path, value); } } -static void settings_upsert(const char *path, struct setting_value value) { +void settings_set_default(const char *path, struct setting_value value) { struct setting *setting = settings_get(path); - if (setting != NULL) { - setting_set_value(setting, value); - } else { + if (setting == NULL) { settings_register_setting(path, value); } } @@ -156,21 +156,21 @@ static int32_t parse_toml(struct parser *state, char **errmsgs[]) { case Token_IntValue: i = *((int64_t *)t.data); - settings_upsert(curkey, (struct setting_value){.type = Setting_Number, - .number_value = i}); + settings_set(curkey, (struct setting_value){.type = Setting_Number, + .number_value = i}); break; case Token_BoolValue: b = *((bool *)t.data); - settings_upsert(curkey, (struct setting_value){.type = Setting_Bool, - .bool_value = b}); + settings_set(curkey, (struct setting_value){.type = Setting_Bool, + .bool_value = b}); break; case Token_StringValue: v = calloc(t.len + 1, 1); strncpy(v, (char *)t.data, t.len); - settings_upsert(curkey, (struct setting_value){.type = Setting_String, - .string_value = v}); + settings_set(curkey, (struct setting_value){.type = Setting_String, + .string_value = v}); free(v); break; @@ -295,3 +295,19 @@ int32_t settings_from_file(const char *path, char **errmsgs[]) { parser_destroy(&parser); return ret; } + +const char *setting_join_key(const char *initial, const char *setting) { + size_t l1 = strlen(initial); + size_t l2 = strlen(setting); + char *combined = (char *)malloc(sizeof(char) * (l1 + l2 + 2)); + + uint32_t idx = 0; + memcpy(&combined[idx], initial, l1); + idx += l1; + combined[idx++] = '.'; + memcpy(&combined[idx], setting, l2); + idx += l2; + combined[idx++] = '\0'; + + return combined; +} diff --git a/src/dged/settings.h b/src/dged/settings.h index 637844b..6e94d64 100644 --- a/src/dged/settings.h +++ b/src/dged/settings.h @@ -76,17 +76,6 @@ void settings_init(uint32_t initial_capacity); */ void settings_destroy(); -/** - * Register a new setting. - * - * @param path The path of the new setting on - * the form ... - * @param default_value The default value for the setting. - * All settings are required to declare a default value. - */ -void settings_register_setting(const char *path, - struct setting_value default_value); - /** * Retrieve a single setting by path. * @@ -118,6 +107,19 @@ void settings_get_prefix(const char *prefix, struct setting **settings_out[], */ void settings_set(const char *path, struct setting_value value); +/** + * Set the default value for a setting. + * + * This works the same as @ref settings_set but + * will not overwrite the value if the setting already has one. + * + * @param path The exact path of the setting on + * the form ... + * @param value The new value of the setting. The type has to match the declared + * type for the setting. If not, the new value is ignored. + */ +void settings_set_default(const char *path, struct setting_value value); + /** * Set a value for a setting. * @@ -136,6 +138,8 @@ void setting_set_value(struct setting *setting, struct setting_value val); */ void setting_to_string(struct setting *setting, char *buf, size_t n); +const char *setting_join_key(const char *initial, const char *setting); + /** * Parse settings from a string in TOML format. * -- cgit v1.2.3