Skip to content

Commit 4e75c55

Browse files
perf(markup): filter out nodes before matching and do not highlight empty range
1 parent f9a74a4 commit 4e75c55

File tree

7 files changed

+97
-15
lines changed

7 files changed

+97
-15
lines changed

lua/orgmode/colors/highlighter/markup/_meta.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
---@field url? string
3131

3232
---@class OrgMarkupHighlighter
33-
---@field parse_node fun(self: OrgMarkupHighlighter, node: TSNode): OrgMarkupNode | false
33+
---@field parse_node fun(self: OrgMarkupHighlighter, node: TSNode, capture_name: string): OrgMarkupNode | false
3434
---@field is_valid_start_node fun(self: OrgMarkupHighlighter, entry: OrgMarkupNode, bufnr: number): boolean
3535
---@field is_valid_end_node fun(self: OrgMarkupHighlighter, entry: OrgMarkupNode, bufnr: number): boolean
3636
---@field highlight fun(self: OrgMarkupHighlighter, highlights: OrgMarkupHighlight[], bufnr: number)

lua/orgmode/colors/highlighter/markup/dates.lua

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
---@class OrgDatesHighlighter : OrgMarkupHighlighter
22
---@field private markup OrgMarkupHighlighter
3-
local OrgDates = {}
3+
local OrgDates = {
4+
valid_capture_names = {
5+
['date_active.start'] = true,
6+
['date_active.end'] = true,
7+
['date_inactive.start'] = true,
8+
['date_inactive.end'] = true,
9+
},
10+
}
411

512
---@param opts { markup: OrgMarkupHighlighter }
613
function OrgDates:new(opts)
@@ -13,8 +20,12 @@ function OrgDates:new(opts)
1320
end
1421

1522
---@param node TSNode
23+
---@param name string
1624
---@return OrgMarkupNode | false
17-
function OrgDates:parse_node(node)
25+
function OrgDates:parse_node(node, name)
26+
if not self.valid_capture_names[name] then
27+
return false
28+
end
1829
local type = node:type()
1930
if type == '[' or type == '<' then
2031
return self:_parse_start_node(node)
@@ -93,8 +104,9 @@ function OrgDates:_parse_end_node(node)
93104
local prev_sibling = node:prev_sibling()
94105
local next_sibling = node:next_sibling()
95106
local is_prev_sibling_valid = not prev_sibling or prev_sibling:type() == 'str' or prev_sibling:type() == 'num'
96-
-- Ensure it's not a link
97-
local is_next_sibling_valid = not next_sibling or (node_type == ']' and next_sibling:type() ~= ']')
107+
-- Ensure it's not a link or a link alias
108+
local is_next_sibling_valid = not next_sibling
109+
or (node_type == ']' and next_sibling:type() ~= ']' and next_sibling:type() ~= '[')
98110
if is_prev_sibling_valid and is_next_sibling_valid then
99111
local id = table.concat({ 'date', node_type }, '_')
100112
local seek_id = table.concat({ 'date', node_type == ']' and '[' or '<' }, '_')

lua/orgmode/colors/highlighter/markup/emphasis.lua

+25-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,16 @@ local ts_utils = require('orgmode.utils.treesitter')
33

44
---@class OrgEmphasisHighlighter : OrgMarkupHighlighter
55
---@field private markup OrgMarkupHighlighter
6-
local OrgEmphasis = {}
6+
local OrgEmphasis = {
7+
valid_capture_names = {
8+
['bold'] = true,
9+
['italic'] = true,
10+
['underline'] = true,
11+
['strikethrough'] = true,
12+
['code'] = true,
13+
['verbatim'] = true,
14+
},
15+
}
716

817
local valid_pre_marker_chars = { ' ', '(', '-', "'", '"', '{', '*', '/', '_', '+' }
918
local valid_post_marker_chars =
@@ -137,12 +146,26 @@ function OrgEmphasis:prepare_highlights(highlights)
137146
end
138147

139148
---@param node TSNode
149+
---@param name string
140150
---@return OrgMarkupNode | false
141-
function OrgEmphasis:parse_node(node)
151+
function OrgEmphasis:parse_node(node, name)
152+
if not self.valid_capture_names[name] then
153+
return false
154+
end
142155
local node_type = node:type()
143156
if not markers[node_type] then
144157
return false
145158
end
159+
local prev_node = node:prev_sibling()
160+
local next_node = node:next_sibling()
161+
162+
if prev_node and prev_node:type() == node_type then
163+
return false
164+
end
165+
166+
if next_node and next_node:type() == node_type then
167+
return false
168+
end
146169

147170
local id = table.concat({ 'emphasis', node_type }, '_')
148171

lua/orgmode/colors/highlighter/markup/init.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ function OrgMarkup:get_node_highlights(root_node, source, line)
7878
---@type OrgMarkupNode[]
7979
local entries = {}
8080

81-
for _, node in self.query:iter_captures(root_node, source, line, line + 1) do
81+
for capture_id, node in self.query:iter_captures(root_node, source, line, line + 1) do
8282
local entry = nil
8383
for _, parser in pairs(self.parsers) do
84-
entry = parser:parse_node(node)
84+
entry = parser:parse_node(node, self.query.captures[capture_id])
8585
if entry then
8686
table.insert(entries, entry)
8787
break

lua/orgmode/colors/highlighter/markup/latex.lua

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
local ts_utils = require('orgmode.utils.treesitter')
2-
31
---@class OrgLatexHighlighter : OrgMarkupHighlighter
42
---@field private markup OrgMarkupHighlighter
5-
local OrgLatex = {}
3+
local OrgLatex = {
4+
valid_capture_names = {
5+
['latex.plain'] = true,
6+
['latex.bracket.start'] = true,
7+
['latex.bracket.end'] = true,
8+
['latex.curly.start'] = true,
9+
['latex.curly.end'] = true,
10+
['latex.square.start'] = true,
11+
['latex.square.end'] = true,
12+
},
13+
}
614

715
local latex_pairs = {
816
['('] = ')',
@@ -50,7 +58,10 @@ end
5058

5159
---@param node TSNode
5260
---@return OrgMarkupNode | false
53-
function OrgLatex:parse_node(node)
61+
function OrgLatex:parse_node(node, name)
62+
if not self.valid_capture_names[name] then
63+
return false
64+
end
5465
local node_type = node:type()
5566
if node_type ~= 'str' and not latex_pairs[node_type] then
5667
return false

lua/orgmode/colors/highlighter/markup/link.lua

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
---@class OrgLinkHighlighter : OrgMarkupHighlighter
22
---@field private markup OrgMarkupHighlighter
33
---@field private has_extmark_url_support boolean
4-
local OrgLink = {}
4+
local OrgLink = {
5+
valid_capture_names = {
6+
['link.start'] = true,
7+
['link.end'] = true,
8+
},
9+
}
510

611
---@param opts { markup: OrgMarkupHighlighter }
712
function OrgLink:new(opts)
@@ -15,8 +20,12 @@ function OrgLink:new(opts)
1520
end
1621

1722
---@param node TSNode
23+
---@param name string
1824
---@return OrgMarkupNode | false
19-
function OrgLink:parse_node(node)
25+
function OrgLink:parse_node(node, name)
26+
if not self.valid_capture_names[name] then
27+
return false
28+
end
2029
local type = node:type()
2130
if type == '[' then
2231
return self:_parse_start_node(node)

tests/plenary/colors/highlighter_spec.lua

+27
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,33 @@ describe('highlighter', function()
125125
assert_extmark(extmarks[9], { line = 0, start_col = 35, end_col = 36, hl_group = '@org.bold.delimiter' })
126126
end)
127127

128+
it('should not highlight two same emphasis one beside another', function()
129+
local extmarks = get_extmarks({
130+
'I am not italic // text',
131+
})
132+
assert.are.same(0, #extmarks)
133+
extmarks = get_extmarks({
134+
'I am not italic / / text',
135+
})
136+
assert.are.same(0, #extmarks)
137+
extmarks = get_extmarks({
138+
'I am not bold ** text',
139+
})
140+
assert.are.same(0, #extmarks)
141+
extmarks = get_extmarks({
142+
'I am not bold * * text',
143+
})
144+
assert.are.same(0, #extmarks)
145+
extmarks = get_extmarks({
146+
'I am not verbatim == text',
147+
})
148+
assert.are.same(0, #extmarks)
149+
extmarks = get_extmarks({
150+
'I am not verbatim = = text',
151+
})
152+
assert.are.same(0, #extmarks)
153+
end)
154+
128155
it('should conceal markers if org_hide_emphasis_markers is true', function()
129156
config.opts.org_hide_emphasis_markers = true
130157
local extmarks = get_extmarks({

0 commit comments

Comments
 (0)