summaryrefslogtreecommitdiff
path: root/src/dged
diff options
context:
space:
mode:
Diffstat (limited to 'src/dged')
-rw-r--r--src/dged/location.c32
-rw-r--r--src/dged/minibuffer.c20
-rw-r--r--src/dged/syntax.c273
-rw-r--r--src/dged/text.c8
4 files changed, 157 insertions, 176 deletions
diff --git a/src/dged/location.c b/src/dged/location.c
index cac0333..0c7e973 100644
--- a/src/dged/location.c
+++ b/src/dged/location.c
@@ -2,25 +2,19 @@
bool location_is_between(struct location location, struct location start,
struct location end) {
- if (location.line >= start.line && location.line <= end.line) {
- if (location.line == end.line && location.col <= end.col &&
- location.line == start.line && location.col >= start.col) {
- // only one line
- return true;
- } else if (location.line == start.line && location.line != end.line &&
- location.col >= start.col) {
- // we are on the first line
- return true;
- } else if (location.line == end.line && location.line != start.line &&
- location.col <= end.col) {
- // we are on the last line
- return true;
- } else if (location.line != end.line && location.line != start.line) {
- // we are on lines in between
- return true;
- }
- }
- return false;
+ return (location.line >= start.line && location.line <= end.line) &&
+ (
+ // inbetween
+ (location.line != end.line && location.line != start.line) ||
+ // first line
+ (location.line == start.line && location.line != end.line &&
+ location.col >= start.col) ||
+ // last line
+ (location.line == end.line && location.line != start.line &&
+ location.col <= end.col) ||
+ // only one line
+ (location.line == end.line && location.col <= end.col &&
+ location.line == start.line && location.col >= start.col));
}
int location_compare(struct location l1, struct location l2) {
diff --git a/src/dged/minibuffer.c b/src/dged/minibuffer.c
index 634a864..bbe80ed 100644
--- a/src/dged/minibuffer.c
+++ b/src/dged/minibuffer.c
@@ -18,7 +18,6 @@ static struct minibuffer {
char prompt[128];
struct command_ctx prompt_command_ctx;
bool prompt_active;
- bool clear;
struct window *prev_window;
struct buffer *message_buffer;
@@ -65,9 +64,9 @@ int32_t minibuffer_execute() {
}
}
- minibuffer_abort_prompt();
int32_t res = execute_command(c->self, c->commands, c->active_window,
c->buffers, argc, (const char **)argv);
+ minibuffer_abort_prompt();
free(l);
@@ -81,10 +80,8 @@ void update(struct buffer *buffer, void *userdata) {
struct timespec current;
struct minibuffer *mb = (struct minibuffer *)userdata;
clock_gettime(CLOCK_MONOTONIC, &current);
- if ((!mb->prompt_active && current.tv_sec >= mb->expires.tv_sec) ||
- mb->clear) {
- buffer_clear(buffer);
- mb->clear = false;
+ if ((!mb->prompt_active && current.tv_sec >= mb->expires.tv_sec)) {
+ minibuffer_clear();
}
}
@@ -96,7 +93,6 @@ void minibuffer_init(struct buffer *buffer, struct buffers *buffers) {
g_minibuffer.buffer = buffer;
g_minibuffer.expires.tv_sec = 0;
g_minibuffer.expires.tv_nsec = 0;
- g_minibuffer.clear = false;
g_minibuffer.prompt_active = false;
buffer_add_update_hook(g_minibuffer.buffer, update, &g_minibuffer);
@@ -111,7 +107,6 @@ void echo(uint32_t timeout, const char *fmt, va_list args) {
clock_gettime(CLOCK_MONOTONIC, &g_minibuffer.expires);
g_minibuffer.expires.tv_sec += timeout;
- g_minibuffer.clear = false;
static char buff[2048];
size_t nbytes = vsnprintf(buff, 2048, fmt, args);
@@ -188,17 +183,12 @@ static void minibuffer_setup(struct command_ctx command_ctx,
windows_set_active(minibuffer_window());
}
+ minibuffer_clear();
if (initial != NULL) {
buffer_set_text(g_minibuffer.buffer, (uint8_t *)initial, strlen(initial));
- // there might be an earlier clear request but
- // we have sort of taken care of that here
- g_minibuffer.clear = false;
-
// TODO: what to do with these
buffer_view_goto_end_of_line(window_buffer_view(minibuffer_window()));
- } else {
- minibuffer_clear();
}
}
@@ -259,7 +249,7 @@ bool minibuffer_displaying() {
void minibuffer_clear() {
g_minibuffer.expires.tv_sec = 0;
g_minibuffer.expires.tv_nsec = 0;
- g_minibuffer.clear = true;
+ buffer_clear(g_minibuffer.buffer);
}
bool minibuffer_focused() { return g_minibuffer.prompt_active; }
diff --git a/src/dged/syntax.c b/src/dged/syntax.c
index 5f94d60..0935080 100644
--- a/src/dged/syntax.c
+++ b/src/dged/syntax.c
@@ -15,7 +15,6 @@
#include "buffer.h"
#include "display.h"
#include "hash.h"
-#include "hashmap.h"
#include "minibuffer.h"
#include "path.h"
#include "text.h"
@@ -26,13 +25,41 @@ static bool treesitter_path_allocated = false;
static const char *parser_filename = "parser";
static const char *highlight_path = "queries/highlights.scm";
-HASHMAP_ENTRY_TYPE(re_cache_entry, regex_t);
+// TODO: move to own file
+#define s8(s) ((struct s8){s, strlen(s)})
+
+struct s8 {
+ char *s;
+ uint32_t l;
+};
+
+static bool s8eq(struct s8 s1, struct s8 s2) {
+ return s1.l == s2.l && memcmp(s1.s, s2.s, s1.l) == 0;
+}
+
+static char *s8tocstr(struct s8 s) {
+ char *cstr = (char *)malloc(s.l + 1);
+ memcpy(cstr, s.s, s.l);
+ cstr[s.l] = '\0';
+ return cstr;
+}
+
+struct predicate {
+ uint32_t pattern_idx;
+
+ bool (*eval)(struct s8, uint32_t, struct s8[], struct s8, void *);
+ uint32_t argc;
+ struct s8 argv[32];
+ void *data;
+
+ void (*cleanup)(void *);
+};
struct highlight {
TSParser *parser;
TSTree *tree;
TSQuery *query;
- HASHMAP(struct re_cache_entry) re_cache;
+ VEC(struct predicate) predicates;
void *dlhandle;
};
@@ -43,11 +70,13 @@ static void delete_parser(struct buffer *buffer, void *userdata) {
ts_query_delete(highlight->query);
}
- HASHMAP_FOR_EACH(&highlight->re_cache, struct re_cache_entry * entry) {
- regfree(&entry->value);
+ VEC_FOR_EACH(&highlight->predicates, struct predicate * p) {
+ if (p->cleanup != NULL) {
+ p->cleanup(p->data);
+ }
}
- HASHMAP_DESTROY(&highlight->re_cache);
+ VEC_DESTROY(&highlight->predicates);
ts_tree_delete(highlight->tree);
ts_parser_delete(highlight->parser);
@@ -101,6 +130,78 @@ static const char *lang_folder(struct buffer *buffer) {
return fld;
}
+static bool eval_match(struct s8 capname, uint32_t argc, struct s8 argv[],
+ struct s8 value, void *data) {
+ regex_t *regex = (regex_t *)data;
+ if (regex == NULL) {
+ return false;
+ }
+
+ char *text = s8tocstr(value);
+ bool match = regexec(regex, text, 0, NULL, 0) == 0;
+
+ free(text);
+ return match;
+}
+
+static void cleanup_match(void *data) {
+ regex_t *regex = (regex_t *)data;
+ if (regex != NULL) {
+ regfree(regex);
+ free(regex);
+ }
+}
+
+static void create_predicates(struct highlight *h, uint32_t pattern_index) {
+ uint32_t npreds = 0;
+ const TSQueryPredicateStep *predicate_steps =
+ ts_query_predicates_for_pattern(h->query, pattern_index, &npreds);
+
+ struct s8 capname;
+ struct s8 args[32] = {0};
+ uint32_t argc = 0;
+ for (uint32_t predi = 0; predi < npreds; ++predi) {
+ const TSQueryPredicateStep *step = &predicate_steps[predi];
+ switch (step->type) {
+ case TSQueryPredicateStepTypeCapture:
+ capname.s = (char *)ts_query_capture_name_for_id(h->query, step->value_id,
+ &capname.l);
+ break;
+
+ case TSQueryPredicateStepTypeString:
+ args[argc].s = (char *)ts_query_string_value_for_id(
+ h->query, step->value_id, &args[argc].l);
+ ++argc;
+ break;
+
+ case TSQueryPredicateStepTypeDone:
+ if (s8eq(args[0], s8("match?"))) {
+ regex_t *re = calloc(1, sizeof(regex_t));
+ char *val = s8tocstr(args[1]);
+
+ if (regcomp(re, val, 0) == 0) {
+ VEC_APPEND(&h->predicates, struct predicate * pred);
+ pred->pattern_idx = pattern_index;
+ pred->eval = eval_match;
+ pred->cleanup = cleanup_match;
+ pred->argc = 1;
+ pred->data = re;
+
+ memset(pred->argv, 0, sizeof(struct s8) * 32);
+ memcpy(pred->argv, args, sizeof(struct s8));
+ } else {
+ free(re);
+ }
+
+ free(val);
+ }
+
+ argc = 0;
+ break;
+ }
+ }
+}
+
static TSQuery *setup_queries(const char *lang_root, TSTree *tree) {
const char *filename = join_path(lang_root, highlight_path);
@@ -150,123 +251,28 @@ static TSQuery *setup_queries(const char *lang_root, TSTree *tree) {
return q;
}
-#define s8(s) ((struct s8){s, strlen(s)})
-
-struct s8 {
- char *s;
- uint32_t l;
-};
-
-static bool s8eq(struct s8 s1, struct s8 s2) {
- return s1.l == s2.l && memcmp(s1.s, s2.s, s1.l) == 0;
-}
-
-char *s8tocstr(struct s8 s) {
- char *cstr = (char *)malloc(s.l + 1);
- memcpy(cstr, s.s, s.l);
- cstr[s.l] = '\0';
- return cstr;
-}
-
-static bool eval_match(struct s8 capname, uint32_t argc, struct s8 argv[],
- struct s8 value, void *data) {
- regex_t *regex = (regex_t *)data;
- if (regex == NULL) {
- return false;
- }
-
- char *text = s8tocstr(value);
- bool match = regexec(regex, text, 0, NULL, 0) == 0;
-
- free(text);
- return match;
-}
-
-static void cleanup_match(void *data) {
- regex_t *regex = (regex_t *)data;
- if (regex != NULL) {
- regfree(regex);
- free(regex);
- }
-}
-
-struct predicate {
- bool (*fn)(struct s8, uint32_t, struct s8[], struct s8, void *);
- void (*cleanup)(void *);
- uint32_t argc;
- struct s8 argv[32];
- void *data;
-};
-
-typedef VEC(struct predicate) predicate_vec;
-
-static regex_t *compile_re_cached(struct highlight *h, struct s8 expr) {
- char *val = s8tocstr(expr);
- HASHMAP_GET(&h->re_cache, struct re_cache_entry, val, regex_t * re);
- if (re == NULL) {
- regex_t new_re;
- if (regcomp(&new_re, val, 0) == 0) {
- HASHMAP_APPEND(&h->re_cache, struct re_cache_entry, val,
- struct re_cache_entry * new);
- if (new != NULL) {
- new->value = new_re;
- re = &new->value;
+static bool eval_predicates(struct highlight *h, struct text *text,
+ TSPoint start, TSPoint end, uint32_t pattern_index,
+ struct s8 cname) {
+ VEC_FOR_EACH(&h->predicates, struct predicate * p) {
+ if (p->pattern_idx == pattern_index) {
+ struct text_chunk txt =
+ text_get_region(text, start.row, start.column, end.row, end.column);
+ bool result =
+ p->eval(cname, p->argc, p->argv,
+ (struct s8){.s = txt.text, .l = txt.nbytes}, p->data);
+
+ if (txt.allocated) {
+ free(txt.text);
}
- }
- }
- free(val);
- return re;
-}
-
-static predicate_vec create_predicates(struct highlight *h,
- uint32_t pattern_index) {
- predicate_vec predicates;
-
- uint32_t npreds = 0;
- const TSQueryPredicateStep *predicate_steps =
- ts_query_predicates_for_pattern(h->query, pattern_index, &npreds);
-
- VEC_INIT(&predicates, 8);
-
- bool result = true;
- struct s8 capname;
- struct s8 args[32] = {0};
- uint32_t argc = 0;
- for (uint32_t predi = 0; predi < npreds; ++predi) {
- const TSQueryPredicateStep *step = &predicate_steps[predi];
- switch (step->type) {
- case TSQueryPredicateStepTypeCapture:
- capname.s = (char *)ts_query_capture_name_for_id(h->query, step->value_id,
- &capname.l);
- break;
-
- case TSQueryPredicateStepTypeString:
- args[argc].s = (char *)ts_query_string_value_for_id(
- h->query, step->value_id, &args[argc].l);
- ++argc;
- break;
-
- case TSQueryPredicateStepTypeDone:
- if (s8eq(args[0], s8("match?"))) {
- VEC_APPEND(&predicates, struct predicate * pred);
- pred->fn = eval_match;
- pred->cleanup = NULL;
- pred->argc = 1;
-
- // cache the regex
- pred->data = compile_re_cached(h, args[1]);
-
- memset(pred->argv, 0, sizeof(struct s8) * 32);
- memcpy(pred->argv, args, sizeof(struct s8));
+ if (!result) {
+ return false;
}
-
- argc = 0;
- break;
}
}
- return predicates;
+ return true;
}
static void update_parser(struct buffer *buffer, void *userdata,
@@ -284,7 +290,6 @@ static void update_parser(struct buffer *buffer, void *userdata,
}
// take results and set text properties
- // TODO: can reuse the cursor
TSQueryCursor *cursor = ts_query_cursor_new();
uint32_t end_line = origin.line + height >= buffer_num_lines(buffer)
? buffer_num_lines(buffer) - 1
@@ -296,8 +301,6 @@ static void update_parser(struct buffer *buffer, void *userdata,
TSQueryMatch match;
while (ts_query_cursor_next_match(cursor, &match)) {
- predicate_vec predicates = create_predicates(h, match.pattern_index);
-
for (uint32_t capi = 0; capi < match.capture_count; ++capi) {
const TSQueryCapture *cap = &match.captures[capi];
TSPoint start = ts_node_start_point(cap->node);
@@ -307,20 +310,8 @@ static void update_parser(struct buffer *buffer, void *userdata,
cname.s =
(char *)ts_query_capture_name_for_id(h->query, cap->index, &cname.l);
- bool predicates_match = true;
- VEC_FOR_EACH(&predicates, struct predicate * pred) {
- struct text_chunk txt = text_get_region(
- buffer->text, start.row, start.column, end.row, end.column);
- predicates_match &=
- pred->fn(cname, pred->argc, pred->argv,
- (struct s8){.s = txt.text, .l = txt.nbytes}, pred->data);
-
- if (txt.allocated) {
- free(txt.text);
- }
- }
-
- if (!predicates_match) {
+ if (!eval_predicates(h, buffer->text, start, end, match.pattern_index,
+ cname)) {
continue;
}
@@ -388,13 +379,6 @@ static void update_parser(struct buffer *buffer, void *userdata,
},
});
}
-
- VEC_FOR_EACH(&predicates, struct predicate * pred) {
- if (pred->cleanup != NULL) {
- pred->cleanup(pred->data);
- }
- }
- VEC_DESTROY(&predicates);
}
ts_query_cursor_delete(cursor);
@@ -520,8 +504,13 @@ static void create_parser(struct buffer *buffer, void *userdata) {
};
hl->tree = ts_parser_parse(hl->parser, NULL, i);
hl->query = setup_queries(lang_root, hl->tree);
+
+ VEC_INIT(&hl->predicates, 8);
+ uint32_t npatterns = ts_query_pattern_count(hl->query);
+ for (uint32_t pi = 0; pi < npatterns; ++pi) {
+ create_predicates(hl, pi);
+ }
hl->dlhandle = h;
- HASHMAP_INIT(&hl->re_cache, 64, hash_name);
free((void *)lang_root);
diff --git a/src/dged/text.c b/src/dged/text.c
index bc2b1fc..30036a0 100644
--- a/src/dged/text.c
+++ b/src/dged/text.c
@@ -184,10 +184,18 @@ void insert_at(struct text *text, uint32_t line, uint32_t col, uint8_t *data,
}
uint32_t text_line_length(struct text *text, uint32_t lineidx) {
+ if (lineidx >= text_num_lines(text)) {
+ return 0;
+ }
+
return text->lines[lineidx].nchars;
}
uint32_t text_line_size(struct text *text, uint32_t lineidx) {
+ if (lineidx >= text_num_lines(text)) {
+ return 0;
+ }
+
return text->lines[lineidx].nbytes;
}