summaryrefslogtreecommitdiff
path: root/src/dged
diff options
context:
space:
mode:
Diffstat (limited to 'src/dged')
-rw-r--r--src/dged/lang.c2
-rw-r--r--src/dged/s8.c18
-rw-r--r--src/dged/s8.h2
-rw-r--r--src/dged/syntax.c119
4 files changed, 109 insertions, 32 deletions
diff --git a/src/dged/lang.c b/src/dged/lang.c
index d2d7b34..070b96e 100644
--- a/src/dged/lang.c
+++ b/src/dged/lang.c
@@ -46,6 +46,8 @@ void languages_init(bool register_default) {
define_lang("Nix", "nix", "^.*\\.nix$", 2, false);
define_lang("Make", "make", "^.*(Makefile|\\.mk)$", 4, true);
define_lang("Python", "python", "^.*\\.py$", 4, false);
+ define_lang("Markdown", "markdown", "^.*\\.md$", 4, false);
+ define_lang("Javascript", "javascript", "^.*\\.js$", 4, false);
define_lang("Git Commit Message", "gitcommit", "^.*COMMIT_EDITMSG$", 4,
false);
}
diff --git a/src/dged/s8.c b/src/dged/s8.c
index 0566fde..c4544b9 100644
--- a/src/dged/s8.c
+++ b/src/dged/s8.c
@@ -23,3 +23,21 @@ char *s8tocstr(struct s8 s) {
cstr[s.l] = '\0';
return cstr;
}
+
+bool s8startswith(struct s8 s, struct s8 prefix) {
+ if (prefix.l > s.l) {
+ return false;
+ }
+
+ return memcmp(s.s, prefix.s, prefix.l) == 0;
+}
+
+struct s8 s8dup(struct s8 s) {
+ struct s8 new = {0};
+ new.l = s.l;
+
+ new.s = (char *)malloc(s.l);
+ memcpy(new.s, s.s, s.l);
+
+ return new;
+}
diff --git a/src/dged/s8.h b/src/dged/s8.h
index 955a642..76bcc34 100644
--- a/src/dged/s8.h
+++ b/src/dged/s8.h
@@ -14,5 +14,7 @@ struct s8 {
bool s8eq(struct s8 s1, struct s8 s2);
int s8cmp(struct s8 s1, struct s8 s2);
char *s8tocstr(struct s8 s);
+bool s8startswith(struct s8 s, struct s8 prefix);
+struct s8 s8dup(struct s8 s);
#endif
diff --git a/src/dged/syntax.c b/src/dged/syntax.c
index 1544d33..3ee750c 100644
--- a/src/dged/syntax.c
+++ b/src/dged/syntax.c
@@ -121,6 +121,25 @@ static const char *lang_folder(struct buffer *buffer, const char *path) {
return fld;
}
+static bool eval_eq(struct s8 capname, uint32_t argc, struct s8 argv[],
+ struct s8 value, void *data) {
+ const struct s8 *cmp_to = (const struct s8 *)data;
+ if (data == NULL) {
+ return false;
+ }
+
+ return s8eq(value, *cmp_to);
+}
+
+static void cleanup_eq(void *data) {
+ struct s8 *s = (struct s8 *)data;
+ if (s != NULL) {
+ free(s->s);
+ s->l = 0;
+ free(s);
+ }
+}
+
static bool eval_match(struct s8 capname, uint32_t argc, struct s8 argv[],
struct s8 value, void *data) {
regex_t *regex = (regex_t *)data;
@@ -185,6 +204,15 @@ static void create_predicates(struct highlight *h, uint32_t pattern_index) {
}
free(val);
+ } else if (s8eq(args[0], s8("eq?"))) {
+ struct s8 *val = calloc(1, sizeof(struct s8));
+ *val = s8dup(args[1]);
+ VEC_APPEND(&h->predicates, struct predicate * pred);
+ pred->pattern_idx = pattern_index;
+ pred->eval = eval_eq;
+ pred->cleanup = cleanup_eq;
+ pred->argc = 1;
+ pred->data = val;
}
argc = 0;
@@ -217,8 +245,6 @@ static TSQuery *setup_queries(const char *lang_root, TSTree *tree) {
TSQuery *q = ts_query_new(ts_tree_language(tree), (char *)data, len,
&error_offset, &error);
- munmap(data, len);
-
if (error != TSQueryErrorNone) {
const char *msg = "unknown error";
switch (error) {
@@ -235,10 +261,27 @@ static TSQuery *setup_queries(const char *lang_root, TSTree *tree) {
msg = "capture";
break;
}
- message("ts query error at byte offset %d: %s", error_offset, msg);
+
+ // calculate line
+ const char *chars = (const char *)data;
+ uint64_t byteoff = 0;
+ uint32_t lineno = 1;
+ uint32_t colno = 0;
+ while (byteoff < error_offset) {
+ if (chars[byteoff] == '\n') {
+ ++lineno;
+ colno = 0;
+ }
+ ++colno;
+ ++byteoff;
+ }
+ message("ts query error at (%d, %d): %s, %.*s", lineno, colno, msg);
+
+ munmap(data, len);
return NULL;
}
+ munmap(data, len);
return q;
}
@@ -266,6 +309,9 @@ static bool eval_predicates(struct highlight *h, struct text *text,
return true;
}
+#define match_cname(cname, capture) \
+ (s8eq(cname, s8(capture)) || s8startswith(cname, s8(capture ".")))
+
static void update_parser(struct buffer *buffer, void *userdata,
struct location origin, uint32_t width,
uint32_t height) {
@@ -308,50 +354,41 @@ static void update_parser(struct buffer *buffer, void *userdata,
bool highlight = false;
uint32_t color = 0;
- if (s8eq(cname, s8("keyword"))) {
+ if (match_cname(cname, "keyword")) {
highlight = true;
color = Color_Blue;
- } else if (s8eq(cname, s8("operator"))) {
+ } else if (match_cname(cname, "operator")) {
highlight = true;
color = Color_Magenta;
- } else if (s8eq(cname, s8("delimiter"))) {
+ } else if (match_cname(cname, "delimiter")) {
+ highlight = false;
+ } else if (s8eq(cname, s8("text"))) {
highlight = false;
- } else if (s8eq(cname, s8("string")) ||
- s8eq(cname, s8("string.special")) ||
- s8eq(cname, s8("string.special.path")) ||
- s8eq(cname, s8("text.title")) || s8eq(cname, s8("text.uri")) ||
- s8eq(cname, s8("string.special.uri"))) {
+ } else if (match_cname(cname, "string") || match_cname(cname, "text")) {
highlight = true;
color = Color_Green;
- } else if (s8eq(cname, s8("constant"))) {
+ } else if (match_cname(cname, "constant")) {
highlight = true;
color = Color_Yellow;
- } else if (s8eq(cname, s8("attribute"))) {
+ } else if (match_cname(cname, "attribute")) {
highlight = true;
color = Color_Yellow;
- } else if (s8eq(cname, s8("number"))) {
+ } else if (match_cname(cname, "number")) {
highlight = true;
color = Color_Yellow;
- } else if (s8eq(cname, s8("function")) ||
- s8eq(cname, s8("function.macro")) ||
- s8eq(cname, s8("function.method")) ||
- s8eq(cname, s8("function.builtin")) ||
- s8eq(cname, s8("function.signal")) ||
- s8eq(cname, s8("function.special"))) {
+ } else if (match_cname(cname, "function")) {
highlight = true;
color = Color_Yellow;
- } else if (s8eq(cname, s8("property"))) {
+ } else if (match_cname(cname, "property")) {
highlight = false;
- } else if (s8eq(cname, s8("label"))) {
+ } else if (match_cname(cname, "label")) {
highlight = false;
- } else if (s8eq(cname, s8("type")) || s8eq(cname, s8("type.builtin"))) {
+ } else if (match_cname(cname, "type")) {
highlight = true;
color = Color_Cyan;
- } else if (s8eq(cname, s8("variable")) ||
- s8eq(cname, s8("variable.builtin")) ||
- s8eq(cname, s8("variable.parameter"))) {
+ } else if (match_cname(cname, "variable")) {
highlight = false;
- } else if (s8eq(cname, s8("comment"))) {
+ } else if (match_cname(cname, "comment")) {
highlight = true;
color = Color_BrightBlack;
}
@@ -524,6 +561,12 @@ 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);
+ if (hl->query == NULL) {
+ ts_parser_delete(hl->parser);
+ free((void *)lang_root);
+ return;
+ }
+
VEC_INIT(&hl->predicates, 8);
uint32_t npatterns = ts_query_pattern_count(hl->query);
for (uint32_t pi = 0; pi < npatterns; ++pi) {
@@ -549,14 +592,26 @@ void syntax_init(uint32_t grammar_path_len, const char *grammar_path[]) {
treesitter_path[i] = strdup(grammar_path[i]);
}
- // TODO: check that it exists
+ // special-case some of the built-in languages
+ // that have grammar names different from the default
struct language l = lang_from_id("gitcommit");
- lang_setting_set_default(&l, "grammar",
- (struct setting_value){.type = Setting_String,
- .string_value = "gitcommit"});
+ if (!lang_is_fundamental(&l)) {
+ lang_setting_set_default(
+ &l, "grammar",
+ (struct setting_value){.type = Setting_String,
+ .string_value = "gitcommit"});
+ lang_destroy(&l);
+ }
+
+ l = lang_from_id("cxx");
+ if (!lang_is_fundamental(&l)) {
+ lang_setting_set_default(
+ &l, "grammar",
+ (struct setting_value){.type = Setting_String, .string_value = "cpp"});
+ lang_destroy(&l);
+ }
buffer_add_create_hook(create_parser, NULL);
- lang_destroy(&l);
}
void syntax_teardown() {