diff options
| author | Albert Cervin <albert@acervin.com> | 2024-03-05 09:02:45 +0100 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2024-03-05 09:02:45 +0100 |
| commit | f266c624ad197ea6add738df70702dcbf93cb198 (patch) | |
| tree | a8c2ce9a04ecef065530847108b78ae579b62c0a | |
| parent | 678104121a1aeca7851b91bc536de5548efdf651 (diff) | |
| download | dged-f266c624ad197ea6add738df70702dcbf93cb198.tar.gz dged-f266c624ad197ea6add738df70702dcbf93cb198.tar.xz dged-f266c624ad197ea6add738df70702dcbf93cb198.zip | |
Make syntax path a proper search path
Can be set with the $TREESITTER_GRAMMARS variable, separated by ':'
| -rw-r--r-- | Makefile | 20 | ||||
| -rw-r--r-- | dged.nix | 5 | ||||
| -rw-r--r-- | src/dged/syntax.c | 93 | ||||
| -rw-r--r-- | src/main/main.c | 42 |
4 files changed, 100 insertions, 60 deletions
@@ -69,7 +69,17 @@ FILES = $(DEPS) $(MAIN_OBJS) $(OBJS) dged libdged.a $(TEST_OBJS) $(PLATFORM_OBJS @mkdir -p $(@D) $(CC) $(CFLAGS) -c $< -o $@ -dged: $(MAIN_OBJS) libdged.a +grammars: + if [ -n "$$TREESITTER_GRAMMARS" ]; then \ + IFS=":"; for p in "$$TREESITTER_GRAMMARS"; do \ + cp -rL "$$p"/ grammars; \ + done \ + else \ + @echo "TODO: download and build default set of grammars"; \ + mkdir -p ./grammars; \ + fi + +dged: $(MAIN_OBJS) libdged.a grammars $(CC) $(LDFLAGS) $(MAIN_OBJS) libdged.a -o dged -lm libdged.a: $(OBJS) $(PLATFORM_OBJS) @@ -104,15 +114,13 @@ install: dged install -d $(prefix)/share/man/man1 install -m 644 $(.CURDIR)/dged.1 $(prefix)/share/man/man1/dged.1 - if [ -n "$$TREESITTER_GRAMMARS" ]; then\ - install -d "$(datadir)";\ - cp -rL "$$TREESITTER_GRAMMARS"/ "$(datadir)/grammars";\ - fi + + install -d $(datadir)/grammars + cp -rL $(.OBJDIR)/grammars "$(datadir)/" docs: doxygen $(.CURDIR)/Doxyfile -# in this case we need a separate depend target depend: $(DEPS) @: @@ -49,6 +49,11 @@ stdenv.mkDerivation { rev = "master"; hash = "sha256-q20gLVLs0LpqRpgo/qNRDfExbWXhICWZjM1ux4+AT6M="; }; + # remove broken symlinks + postInstall = '' + unlink "$out/queries/highlights-javascript.scm" + unlink "$out/queries/highlights-typescript.scm" + ''; }; "gitcommit" = tree-sitter.buildGrammar { language = "gitcommit"; diff --git a/src/dged/syntax.c b/src/dged/syntax.c index 7f13b11..61f09c2 100644 --- a/src/dged/syntax.c +++ b/src/dged/syntax.c @@ -21,8 +21,8 @@ #include "text.h" #include "vec.h" -static char *treesitter_path = NULL; -static bool treesitter_path_allocated = false; +static char *treesitter_path[256] = {0}; +static uint32_t treesitter_path_len = 0; static const char *parser_filename = "parser"; static const char *highlight_path = "queries/highlights.scm"; @@ -120,15 +120,14 @@ static const char *grammar_name_from_buffer(struct buffer *buffer) { return buffer->lang.name; } -static const char *lang_folder(struct buffer *buffer) { +static const char *lang_folder(struct buffer *buffer, const char *path) { const char *langname = grammar_name_from_buffer(buffer); - - size_t tspath_len = strlen(treesitter_path); + size_t tspath_len = strlen(path); size_t lang_len = strlen(langname); char *fld = malloc(tspath_len + lang_len + 2); uint32_t idx = 0; - memcpy(&fld[idx], treesitter_path, tspath_len); + memcpy(&fld[idx], path, tspath_len); idx += tspath_len; fld[idx++] = '/'; for (uint32_t i = 0; i < lang_len; ++i) { @@ -489,33 +488,44 @@ static void text_inserted(struct buffer *buffer, struct region inserted, } static void create_parser(struct buffer *buffer, void *userdata) { - const char *lang_root = lang_folder(buffer); - const char *filename = join_path(lang_root, parser_filename); - void *h = dlopen(filename, RTLD_LAZY); - free((void *)filename); - if (h == NULL) { - free((void *)lang_root); - return; - } + TSLanguage *(*langsym)() = NULL; + const char *lang_root = NULL, *langname = NULL; + void *h = NULL; - const char *langname = grammar_name_from_buffer(buffer); - size_t lang_len = strlen(langname); + for (uint32_t i = 0; i < treesitter_path_len && langsym == NULL; ++i) { + const char *path = treesitter_path[i]; + lang_root = lang_folder(buffer, path); + const char *filename = join_path(lang_root, parser_filename); - const char *prefix = "tree_sitter_"; - size_t prefix_len = strlen(prefix); - char *function = malloc(prefix_len + lang_len + 1); - memcpy(function, prefix, prefix_len); - for (uint32_t i = 0; i < lang_len; ++i) { - function[prefix_len + i] = tolower(langname[i]); + h = dlopen(filename, RTLD_LAZY); + free((void *)filename); + if (h == NULL) { + free((void *)lang_root); + continue; + } + + langname = grammar_name_from_buffer(buffer); + size_t lang_len = strlen(langname); + + const char *prefix = "tree_sitter_"; + size_t prefix_len = strlen(prefix); + char *function = malloc(prefix_len + lang_len + 1); + memcpy(function, prefix, prefix_len); + for (uint32_t i = 0; i < lang_len; ++i) { + function[prefix_len + i] = tolower(langname[i]); + } + function[prefix_len + lang_len] = '\0'; + langsym = dlsym(h, function); + + free(function); + if (langsym == NULL) { + free((void *)lang_root); + dlclose(h); + } } - function[prefix_len + lang_len] = '\0'; - TSLanguage *(*langsym)() = dlsym(h, function); - free(function); if (langsym == NULL) { - free((void *)lang_root); - dlclose(h); return; } @@ -550,28 +560,11 @@ static void create_parser(struct buffer *buffer, void *userdata) { buffer_add_destroy_hook(buffer, delete_parser, hl); } -#define xstr(s) str(s) -#define str(s) #s - -void syntax_init() { - treesitter_path = getenv("TREESITTER_GRAMMARS"); - if (treesitter_path == NULL) { - treesitter_path = (char *)join_path(xstr(DATADIR), "grammars"); - treesitter_path_allocated = true; - } +void syntax_init(uint32_t grammar_path_len, const char *grammar_path[]) { - struct stat buffer; - if (stat(treesitter_path, &buffer) != 0) { - minibuffer_echo_timeout(4, - "failed to initialize syntax, TREESITTER_GRAMMARS " - "not set and grammars dir does not exist at %s.", - treesitter_path); - - if (treesitter_path_allocated) { - free(treesitter_path); - } - - return; + treesitter_path_len = grammar_path_len < 256 ? grammar_path_len : 256; + for (uint32_t i = 0; i < treesitter_path_len; ++i) { + treesitter_path[i] = strdup(grammar_path[i]); } // TODO: check that it exists @@ -585,7 +578,7 @@ void syntax_init() { } void syntax_teardown() { - if (treesitter_path_allocated) { - free(treesitter_path); + for (uint32_t i = 0; i < treesitter_path_len; ++i) { + free((void *)treesitter_path[i]); } } diff --git a/src/main/main.c b/src/main/main.c index 348ac1e..e722ed2 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -22,6 +22,9 @@ #ifdef SYNTAX_ENABLE #include "dged/syntax.h" + +#define xstr(s) str(s) +#define str(s) #s #endif #include "bindings.h" @@ -67,6 +70,7 @@ uint64_t calc_frame_time_ns(struct timespec *timers, uint32_t num_timer_pairs) { #define TIMED_SCOPE_BEGIN(timer) clock_gettime(CLOCK_MONOTONIC, &timer##_begin) #define TIMED_SCOPE_END(timer) clock_gettime(CLOCK_MONOTONIC, &timer##_end) +#define INVALID_WATCH -1 struct watched_file { uint32_t watch_id; struct buffer *buffer; @@ -95,7 +99,8 @@ void reload_buffer(struct buffer *buffer) { void update_file_watches(struct reactor *reactor) { // first, find invalid file watches and try to update them VEC_FOR_EACH(&g_watched_files, struct watched_file * w) { - if (w->watch_id == -1) { + if (w->watch_id == INVALID_WATCH) { + message("re-watching: %s", w->buffer->filename); w->watch_id = reactor_watch_file(reactor, w->buffer->filename, FileWritten); reload_buffer(w->buffer); @@ -109,7 +114,8 @@ void update_file_watches(struct reactor *reactor) { VEC_FOR_EACH(&g_watched_files, struct watched_file * w) { if (w->watch_id == ev.id) { if ((ev.mask & LastEvent) != 0) { - w->watch_id = -1; + message("lost watched file: %s", w->buffer->filename); + w->watch_id = INVALID_WATCH; continue; } @@ -222,8 +228,35 @@ int main(int argc, char *argv[]) { minibuffer_init(&minibuffer, &buflist); buffers_add_add_hook(&buflist, watch_file, (void *)reactor); + #ifdef SYNTAX_ENABLE - syntax_init(); + char *treesitter_path_env = getenv("TREESITTER_GRAMMARS"); + const char *builtin_path = join_path(xstr(DATADIR), "grammars"); + + const char *treesitter_path[256] = {0}; + uint32_t treesitter_path_len = 0; + + if (treesitter_path_env != NULL) { + treesitter_path_env = strdup(treesitter_path_env); + char *result = strtok(treesitter_path_env, ":"); + while (result != NULL && treesitter_path_len < 256) { + treesitter_path[treesitter_path_len] = result; + ++treesitter_path_len; + result = strtok(NULL, ":"); + } + } + + if (treesitter_path_len < 256) { + treesitter_path[treesitter_path_len] = builtin_path; + ++treesitter_path_len; + } + + syntax_init(treesitter_path_len, treesitter_path); + + if (treesitter_path_env != NULL) { + free((void *)treesitter_path_env); + } + free((void *)builtin_path); #endif struct buffer initial_buffer = buffer_create("welcome"); @@ -234,7 +267,8 @@ int main(int argc, char *argv[]) { free((void *)filename); free((void *)absfile); } else { - const char *welcome_txt = "Welcome to the editor for datagubbar 👴\n"; + const char *welcome_txt = + "Welcome to the editor for datagubbar and datagummor 👴👵\n"; buffer_set_text(&initial_buffer, (uint8_t *)welcome_txt, strlen(welcome_txt)); } |
