summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dged/buffer.c6
-rw-r--r--src/dged/lang.c116
-rw-r--r--src/dged/lang.h3
-rw-r--r--src/dged/settings.c40
-rw-r--r--src/dged/settings.h26
5 files changed, 129 insertions, 62 deletions
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(&regex, val, REG_EXTENDED) == 0 &&
regexec(&regex, 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(&regex);
free(settings);
- return lang_from_settings(lang_path);
+ return lang_from_settings(lang_id);
}
regfree(&regex);
}
@@ -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
@@ -77,17 +77,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 <category>.<sub-category>.<setting-name>.
- * @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.
*
* @param path The exact path of the setting on
@@ -119,6 +108,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 <category>.<sub-category>.<setting-name>.
+ * @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.
*
* @param setting Pointer to a setting to set.
@@ -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.
*