summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buffer.c16
-rw-r--r--build.c2
-rw-r--r--command.c2
-rw-r--r--config.c47
-rw-r--r--find.c4
-rw-r--r--main.c10
-rw-r--r--menu.c8
-rw-r--r--session.c4
-rw-r--r--tags.c4
-rw-r--r--ted.c7
-rw-r--r--ted.cfg1
-rw-r--r--ted.h3
-rw-r--r--ui.c32
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 <fcntl.h>
#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;