summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-09-28 00:35:11 -0400
committerpommicket <pommicket@gmail.com>2025-09-28 00:35:11 -0400
commite78bf3013ddb588638a93bed1f6eff4d0beb5106 (patch)
treeabd2a82bdfa2180d46bf41f2241c634f422b36a1
parente2ba8973230902612cb7388eb7b227d9a43a46ed (diff)
Better highlighting for Markdown links
-rw-r--r--main.c7
-rw-r--r--syntax.c29
2 files changed, 28 insertions, 8 deletions
diff --git a/main.c b/main.c
index 9da5c2b..059c5ae 100644
--- a/main.c
+++ b/main.c
@@ -1,11 +1,6 @@
/*
-TODO:
-- highlight <https://example.org> correctly in Markdown
-- highlight (https://example.org) correctly in Markdown (exactly which characters are allowed in links?)
- - what did I mean by this
-- LSP "actions"
-
FUTURE FEATURES:
+- LSP "actions"
- wrap-text command
- path-specific extensions
- more tests
diff --git a/syntax.c b/syntax.c
index f1cd885..e0614c3 100644
--- a/syntax.c
+++ b/syntax.c
@@ -1153,6 +1153,24 @@ static void syntax_highlight_markdown(SyntaxState *state, const char32_t *line,
char_types[i] = SYNTAX_BUILTIN;
}
break;
+ case '<': {
+ u32 end = U32_MAX;
+ bool has_colon = false;
+ for (u32 j = i+1; j < line_len; j++) {
+ char32_t e = line[j];
+ if (e == ' ' || e == '<' || e <= 0x1f)
+ break; // not a link
+ has_colon |= e == ':' && j > i + 2;
+ if (e == '>') {
+ end = j;
+ break;
+ }
+ }
+ if (!has_colon || end == U32_MAX) break;
+ // it's a link!
+ memset(&char_types[i], SYNTAX_LINK, end + 1 - i);
+ i = end;
+ } break;
case ANY_DIGIT:
if (start_of_line) {
size_t spn = str32_ascii_spn(remains, "0123456789");
@@ -1180,9 +1198,16 @@ static void syntax_highlight_markdown(SyntaxState *state, const char32_t *line,
backslashes = 0;
u32 closing_bracket = j;
if (closing_bracket+2 < line_len && line[closing_bracket+1] == '(') {
+ u32 paren_level = 1;
for (j = closing_bracket+2; j < line_len; ++j) {
- if (line[j] == ')' && backslashes % 2 == 0)
- break;
+ if (line[j] == ')' && backslashes % 2 == 0) {
+ paren_level--;
+ if (paren_level == 0)
+ break;
+ }
+ if (line[j] == '(' && backslashes % 2 == 0) {
+ paren_level++;
+ }
if (line[j] == '\\')
++backslashes;
else