From b070e5ce01c829bd101b1e0eda49f1e25d9d125c Mon Sep 17 00:00:00 2001 From: pommicket Date: Wed, 2 Nov 2022 13:29:09 -0400 Subject: new settings system bugfixes, use ted_active_settings more --- buffer.c | 16 ++++++++-------- build.c | 2 +- command.c | 2 +- config.c | 47 +++++++++++++++++++++++++++++++++++------------ find.c | 4 ++-- main.c | 10 +++------- menu.c | 8 ++++---- session.c | 4 ++-- tags.c | 4 ++-- ted.c | 7 ++++--- ted.cfg | 1 - ted.h | 3 ++- ui.c | 32 ++++++++++++++++---------------- 13 files changed, 80 insertions(+), 60 deletions(-) diff --git a/buffer.c b/buffer.c index a91257e..d7e3062 100644 --- a/buffer.c +++ b/buffer.c @@ -247,7 +247,7 @@ static inline Font *buffer_font(TextBuffer *buffer) { Language buffer_language(TextBuffer *buffer) { if (buffer->manual_language >= 1 && buffer->manual_language <= LANG_COUNT) return (Language)(buffer->manual_language - 1); - Settings const *settings = buffer->ted->settings; + Settings const *settings = buffer->ted->default_settings; // important we don't use buffer_settings here since that would cause a loop! char const *filename = buffer->filename; if (!filename) return LANG_NONE; @@ -272,17 +272,17 @@ Language buffer_language(TextBuffer *buffer) { return LANG_NONE; } -// score is higher if buffer more closely matches context. -static long buffer_context_score(TextBuffer *buffer, const SettingsContext *context) { +// score is higher if context is closer match. +static long context_score(const char *path, Language lang, const SettingsContext *context) { long score = 0; - if (buffer_language(buffer) == context->language) { + if (lang == context->language) { score += 100000; } if (context->path) { int i; - for (i = 0; i < TED_PATH_MAX && buffer->filename[i] == context->path[i]; ++i); + for (i = 0; i < TED_PATH_MAX && path[i] == context->path[i]; ++i); score += i; } @@ -293,10 +293,10 @@ static long buffer_context_score(TextBuffer *buffer, const SettingsContext *cont Settings *buffer_settings(TextBuffer *buffer) { Ted *ted = buffer->ted; long best_score = 0; - Settings *settings = ted->settings; - + Settings *settings = ted->default_settings; + Language language = buffer_language(buffer); arr_foreach_ptr(ted->all_settings, Settings, s) { - long score = buffer_context_score(buffer, &s->context); + long score = context_score(buffer->filename, language, &s->context); if (score > best_score) { best_score = score; settings = s; diff --git a/build.c b/build.c index f5b916a..6ec8daf 100644 --- a/build.c +++ b/build.c @@ -81,7 +81,7 @@ static void build_start(Ted *ted) { bool cargo = false, make = false; strbuf_cpy(ted->build_dir, ted->cwd); - Settings *settings = ted->active_buffer ? buffer_settings(ted->active_buffer) : ted->settings; + Settings *settings = ted_active_settings(ted); char *command = settings->build_default_command; diff --git a/command.c b/command.c index eda57f0..58a6004 100644 --- a/command.c +++ b/command.c @@ -31,7 +31,7 @@ char const *arg_get_string(Ted *ted, i64 argument) { void command_execute(Ted *ted, Command c, i64 argument) { TextBuffer *buffer = ted->active_buffer; Node *node = ted->active_node; - Settings *settings = buffer ? buffer_settings(buffer) : ted->settings; + Settings *settings = ted_active_settings(ted); switch (c) { diff --git a/config.c b/config.c index 7a47d23..bf17f54 100644 --- a/config.c +++ b/config.c @@ -42,9 +42,12 @@ static bool context_is_parent(const SettingsContext *parent, const SettingsConte } static void settings_copy(Settings *dest, const Settings *src) { + *dest = *src; context_copy(&dest->context, &src->context); - for (u32 i = 0; i < LANG_COUNT; ++i) - dest->language_extensions[i] = str_dup(src->language_extensions[i]); + for (u32 i = 0; i < LANG_COUNT; ++i) { + if (src->language_extensions[i]) + dest->language_extensions[i] = str_dup(src->language_extensions[i]); + } } static void context_free(SettingsContext *ctx) { @@ -331,6 +334,10 @@ static void parse_section_header(ConfigReader *cfg, char *line, ConfigPart *part } else if (streq(section, "core")) { part->section = SECTION_CORE; } else if (streq(section, "extensions")) { + if (part->context.language != 0 || part->context.path) { + config_err(cfg, "Extensions section cannot be language- or path-specific."); + return; + } part->section = SECTION_EXTENSIONS; } else { config_err(cfg, "Unrecognized section: [%s].", section); @@ -416,6 +423,7 @@ void config_read(Ted *ted, ConfigPart **parts, char const *filename) { if (line[0] == '[') { // a new part! part = arr_addp(*parts); + part->index = (int)arr_len(*parts); part->file = str_dup(filename); part->line = cfg_reader.line_number + 1; parse_section_header(&cfg_reader, line, part); @@ -440,13 +448,12 @@ void config_read(Ted *ted, ConfigPart **parts, char const *filename) { fclose(fp); } - -// REQUIREMENTS FOR THIS FUNCTION: -// - two configs compare equal iff their contexts are identical +// IMPORTANT REQUIREMENT FOR THIS FUNCTION: // - less specific contexts compare as less // (i.e. if context_is_parent(a.context, b.context), then we return -1, and vice versa.) -static int config_part_qsort_cmp(const void *av, const void *bv) { - const ConfigPart *ap = av, *bp = bv; +// if total = true, this gives a total ordering +// if total = false, parts with identical contexts will compare equal. +static int config_part_cmp(const ConfigPart *ap, const ConfigPart *bp, bool total) { const SettingsContext *a = &ap->context, *b = &bp->context; if (a->language == 0 && b->language != 0) return -1; @@ -465,7 +472,20 @@ static int config_part_qsort_cmp(const void *av, const void *bv) { return -1; if (a->language > b->language) return +1; - return strcmp(a_path, b_path); + int cmp = strcmp(a_path, b_path); + if (cmp != 0) return cmp; + if (total) { + if (ap->index < bp->index) + return -1; + if (ap->index > bp->index) + return +1; + } + return 0; + +} + +static int config_part_qsort_cmp(const void *av, const void *bv) { + return config_part_cmp(av, bv, true); } static void config_parse_line(ConfigReader *cfg, Settings *settings, const ConfigPart *part, const char *line) { @@ -699,10 +719,9 @@ void config_parse(Ted *ted, ConfigPart **pparts) { cfg->filename = part->file; cfg->line_number = part->line; - if (part == parts || config_part_qsort_cmp(part, part - 1) != 0) { + if (part == parts || config_part_cmp(part, part - 1, false) != 0) { // new settings settings = arr_addp(ted->all_settings); - context_copy(&settings->context, &part->context); // go backwards to find most specific parent ConfigPart *parent = part; @@ -718,9 +737,13 @@ void config_parse(Ted *ted, ConfigPart **pparts) { break; } } + + context_free(&settings->context); + context_copy(&settings->context, &part->context); } part->settings = settings; + arr_add(part->text, '\0'); // null termination char *line = part->text; while (*line) { @@ -746,7 +769,7 @@ void config_parse(Ted *ted, ConfigPart **pparts) { arr_foreach_ptr(ted->all_settings, Settings, s) { SettingsContext *ctx = &s->context; if (ctx->language == 0 && (!ctx->path || !*ctx->path)) { - ted->settings = s; + ted->default_settings = s; break; } } @@ -766,5 +789,5 @@ void config_free(Ted *ted) { free(ted->strings[i]); } arr_clear(ted->all_settings); - ted->settings = NULL; + ted->default_settings = NULL; } diff --git a/find.c b/find.c index f85255c..5834c04 100644 --- a/find.c +++ b/find.c @@ -70,7 +70,7 @@ static void find_free_pattern(Ted *ted) { static float find_menu_height(Ted *ted) { Font *font = ted->font; float char_height = text_font_char_height(font); - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); float const padding = settings->padding; float const border_thickness = settings->border_thickness; float const line_buffer_height = ted_line_buffer_height(ted); @@ -315,7 +315,7 @@ static void find_menu_frame(Ted *ted, Rect menu_bounds) { Font *font = ted->font, *font_bold = ted->font_bold; float const char_height = text_font_char_height(font); - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); float const padding = settings->padding; float const border_thickness = settings->border_thickness; u32 const *colors = settings->colors; diff --git a/main.c b/main.c index 78e9e72..4579c55 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,6 @@ /* -@TODO: -- make sure [/path//extensions] works - FUTURE FEATURES: -- path-based settings +- [/path//extensions] - custom shaders - texture, time, time since last save - config variables @@ -781,10 +778,9 @@ int main(int argc, char **argv) { Font *font = ted->font; - // default window titlel + // default window title strcpy(ted->window_title, "ted"); - - + { float const padding = ted_active_settings(ted)->padding; float x1 = padding, y = window_height-padding, x2 = window_width-padding; diff --git a/menu.c b/menu.c index 5a0e964..a41da08 100644 --- a/menu.c +++ b/menu.c @@ -107,13 +107,13 @@ static void menu_escape(Ted *ted) { } static float menu_get_width(Ted *ted) { - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); return minf(settings->max_menu_width, ted->window_width - 2.0f * settings->padding); } // returns the rectangle of the screen coordinates of the menu static Rect menu_rect(Ted *ted) { - Settings *settings = ted->settings; + Settings *settings = ted_active_settings(ted); float window_width = ted->window_width, window_height = ted->window_height; float padding = settings->padding; float menu_width = menu_get_width(ted); @@ -125,7 +125,7 @@ static Rect menu_rect(Ted *ted) { static void menu_update(Ted *ted) { Menu menu = ted->menu; - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); u32 const *colors = settings->colors; TextBuffer *line_buffer = &ted->line_buffer; @@ -322,7 +322,7 @@ static void menu_update(Ted *ted) { static void menu_render(Ted *ted) { Menu menu = ted->menu; assert(menu); - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); u32 const *colors = settings->colors; float const window_width = ted->window_width, window_height = ted->window_height; Font *font_bold = ted->font_bold, *font = ted->font; diff --git a/session.c b/session.c index b609310..a443392 100644 --- a/session.c +++ b/session.c @@ -168,7 +168,7 @@ static void session_read_file(Ted *ted, FILE *fp) { } static void session_write(Ted *ted) { - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); if (!settings->restore_session) return; // first we write to a prefixed file so in case something goes wrong we still have the old session. @@ -189,7 +189,7 @@ static void session_write(Ted *ted) { } static void session_read(Ted *ted) { - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); if (settings->restore_session) { char filename[TED_PATH_MAX]; strbuf_printf(filename, "%s/" SESSION_FILENAME, ted->local_data_dir); diff --git a/tags.c b/tags.c index e26ef6d..66ed36e 100644 --- a/tags.c +++ b/tags.c @@ -36,7 +36,7 @@ static bool is_source_file(char const *filename) { static void tags_generate_at_dir(Ted *ted, bool run_in_build_window, const char *dir, int depth) { - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); if (depth >= settings->tags_max_depth) { return; } @@ -385,7 +385,7 @@ static void tag_selector_close(Ted *ted) { // returns tag selected (should be free'd), or NULL if none was. static char *tag_selector_update(Ted *ted) { Selector *sel = &ted->tag_selector; - u32 color = ted->settings->colors[COLOR_TEXT]; + u32 color = ted_color(ted, COLOR_TEXT); sel->enable_cursor = true; // create selector entries based on search term diff --git a/ted.c b/ted.c index a3acfdd..73df785 100644 --- a/ted.c +++ b/ted.c @@ -49,7 +49,7 @@ static void *ted_realloc(Ted *ted, void *p, size_t new_size) { } Settings *ted_active_settings(Ted *ted) { - return ted->active_buffer ? buffer_settings(ted->active_buffer) : ted->settings; + return ted->active_buffer ? buffer_settings(ted->active_buffer) : ted->default_settings; } u32 ted_color(Ted *ted, ColorSetting color) { @@ -206,9 +206,9 @@ static i32 ted_new_node(Ted *ted) { } // how tall is a line buffer? -static float ted_line_buffer_height(Ted const *ted) { +static float ted_line_buffer_height(Ted *ted) { float const char_height = text_font_char_height(ted->font); - return char_height + 2 * ted->settings->border_thickness; + return char_height + 2 * ted_active_settings(ted)->border_thickness; } // switch to this node @@ -386,6 +386,7 @@ void ted_load_configs(Ted *ted, bool reloading) { } config_parse(ted, &parts); + if (reloading) { // reset text size ted_load_fonts(ted); diff --git a/ted.cfg b/ted.cfg index ecafe7c..388d644 100644 --- a/ted.cfg +++ b/ted.cfg @@ -239,7 +239,6 @@ Javascript = .js Java = .java Go = .go - # You can add language-specific settings like this: # [HTML.core] # tab-width = 2 diff --git a/ted.h b/ted.h index 61e19c7..c014103 100644 --- a/ted.h +++ b/ted.h @@ -190,6 +190,7 @@ typedef enum { // this structure is used temporarily when loading settings // it's needed because we want more specific contexts to be dealt with last. typedef struct { + int index; // index in order of which part was read first. SettingsContext context; ConfigSection section; char *file; @@ -329,7 +330,7 @@ typedef struct Ted { TextBuffer *prev_active_buffer; Node *active_node; Settings *all_settings; // dynamic array of Settings. use Settings.context to figure out which one to use. - Settings *settings; // "default" settings + Settings *default_settings; float window_width, window_height; u32 key_modifier; // which of shift, alt, ctrl are down right now. v2 mouse_pos; diff --git a/ui.c b/ui.c index 331dc33..72c5ca2 100644 --- a/ui.c +++ b/ui.c @@ -2,29 +2,29 @@ #include #endif -static float selector_entries_start_y(Ted const *ted, Selector const *s) { - float padding = ted->settings->padding; +static float selector_entries_start_y(Ted *ted, Selector const *s) { + float padding = ted_active_settings(ted)->padding; return s->bounds.pos.y + ted_line_buffer_height(ted) + padding; // make room for line buffer } // number of entries that can be displayed on the screen -static u32 selector_n_display_entries(Ted const *ted, Selector const *s) { +static u32 selector_n_display_entries(Ted *ted, Selector const *s) { float char_height = text_font_char_height(ted->font); float entries_h = rect_y2(s->bounds) - selector_entries_start_y(ted, s); return (u32)(entries_h / char_height); } -static void selector_clamp_scroll(Ted const *ted, Selector *s) { +static void selector_clamp_scroll(Ted *ted, Selector *s) { float max_scroll = (float)s->n_entries - (float)selector_n_display_entries(ted, s); if (max_scroll < 0) max_scroll = 0; s->scroll = clampf(s->scroll, 0, max_scroll); } -static void selector_scroll_to_cursor(Ted const *ted, Selector *s) { +static void selector_scroll_to_cursor(Ted *ted, Selector *s) { u32 n_display_entries = selector_n_display_entries(ted, s); - float scrolloff = ted->settings->scrolloff; + float scrolloff = ted_active_settings(ted)->scrolloff; float min_scroll = (float)s->cursor - ((float)n_display_entries - scrolloff); float max_scroll = (float)s->cursor - scrolloff; s->scroll = clampf(s->scroll, min_scroll, max_scroll); @@ -33,7 +33,7 @@ static void selector_scroll_to_cursor(Ted const *ted, Selector *s) { // where is the ith entry in the selector on the screen? // returns false if it's completely offscreen -static bool selector_entry_pos(Ted const *ted, Selector const *s, u32 i, Rect *r) { +static bool selector_entry_pos(Ted *ted, Selector const *s, u32 i, Rect *r) { Rect bounds = s->bounds; float char_height = text_font_char_height(ted->font); *r = rect(V2(bounds.pos.x, selector_entries_start_y(ted, s) @@ -43,7 +43,7 @@ static bool selector_entry_pos(Ted const *ted, Selector const *s, u32 i, Rect *r return rect_clip_to_rect(r, bounds); } -static void selector_up(Ted const *ted, Selector *s, i64 n) { +static void selector_up(Ted *ted, Selector *s, i64 n) { if (!s->enable_cursor || s->n_entries == 0) { // can't do anything return; @@ -52,7 +52,7 @@ static void selector_up(Ted const *ted, Selector *s, i64 n) { selector_scroll_to_cursor(ted, s); } -static void selector_down(Ted const *ted, Selector *s, i64 n) { +static void selector_down(Ted *ted, Selector *s, i64 n) { selector_up(ted, s, -n); } @@ -111,7 +111,7 @@ static char *selector_update(Ted *ted, Selector *s) { // NOTE: also renders the line buffer static void selector_render(Ted *ted, Selector *s) { - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); u32 const *colors = settings->colors; Font *font = ted->font; @@ -485,7 +485,7 @@ static char *file_selector_update(Ted *ted, FileSelector *fs) { } static void file_selector_render(Ted *ted, FileSelector *fs) { - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); u32 const *colors = settings->colors; Rect bounds = fs->bounds; Font *font = ted->font; @@ -525,12 +525,12 @@ static void file_selector_render(Ted *ted, FileSelector *fs) { } static v2 button_get_size(Ted *ted, char const *text) { - float border_thickness = ted->settings->border_thickness; + float border_thickness = ted_active_settings(ted)->border_thickness; return v2_add_const(text_get_size_v2(ted->font, text), 2 * border_thickness); } static void button_render(Ted *ted, Rect button, char const *text, u32 color) { - u32 const *colors = ted->settings->colors; + u32 const *colors = ted_active_settings(ted)->colors; if (rect_contains_point(button, ted->mouse_pos)) { // highlight button when hovering over it @@ -538,7 +538,7 @@ static void button_render(Ted *ted, Rect button, char const *text, u32 color) { gl_geometry_rect(button, new_color); } - gl_geometry_rect_border(button, ted->settings->border_thickness, colors[COLOR_BORDER]); + gl_geometry_rect_border(button, ted_active_settings(ted)->border_thickness, colors[COLOR_BORDER]); gl_geometry_draw(); v2 pos = rect_center(button); @@ -606,7 +606,7 @@ static void popup_render(Ted *ted, u32 options, char const *title, char const *b Font *font = ted->font; Font *font_bold = ted->font_bold; Rect r, button_yes, button_no, button_cancel; - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); u32 const *colors = settings->colors; float const char_height_bold = text_font_char_height(font_bold); float const padding = settings->padding; @@ -655,7 +655,7 @@ static v2 checkbox_frame(Ted *ted, bool *value, char const *label, v2 pos) { Font *font = ted->font; float char_height = text_font_char_height(font); float checkbox_size = char_height; - Settings const *settings = ted->settings; + Settings const *settings = ted_active_settings(ted); u32 const *colors = settings->colors; float padding = settings->padding; float border_thickness = settings->border_thickness; -- cgit v1.2.3