1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
local core = require "core"
local style = require "core.style"
local config = require "core.config"
local command = require "core.command"
local keymap = require "core.keymap"
local DocView = require "core.docview"
local bracket_map = { ["["] = "]", ["("] = ")", ["{"] = "}" }
local state = {}
local function update_state(line_limit)
line_limit = line_limit or math.huge
-- reset if we don't have a document (eg. DocView isn't focused)
local doc = core.active_view.doc
if not doc then
state = {}
return
end
-- early exit if nothing has changed since the last call
local line, col = doc:get_selection()
if state.doc == doc and state.line == line and state.col == col
and state.limit == line_limit then
return
end
-- find matching rbracket if we have an lbracket
local line2, col2
local chr = doc:get_text(line, col - 1, line, col)
local rbracket = bracket_map[chr]
if rbracket then
local ptn = "[%" .. chr .. "%" .. rbracket .. "]"
local offset = col - 1
local depth = 1
for i = line, math.min(#doc.lines, line + line_limit) do
while offset do
local n = doc.lines[i]:find(ptn, offset + 1)
if n then
local match = doc.lines[i]:sub(n, n)
if match == chr then
depth = depth + 1
elseif match == rbracket then
depth = depth - 1
if depth == 0 then line2, col2 = i, n end
end
end
offset = n
end
if line2 then break end
offset = 0
end
end
-- update
state = {
doc = doc,
line = line,
col = col,
line2 = line2,
col2 = col2,
limit = line_limit,
}
end
local update = DocView.update
function DocView:update(...)
update(self, ...)
update_state(100)
end
local draw_line_text = DocView.draw_line_text
function DocView:draw_line_text(idx, x, y)
draw_line_text(self, idx, x, y)
if self.doc == state.doc and idx == state.line2 then
local color = style.bracketmatch_color or style.syntax["function"]
local x1 = x + self:get_col_x_offset(idx, state.col2)
local x2 = x + self:get_col_x_offset(idx, state.col2 + 1)
local h = style.divider_size
renderer.draw_rect(x1, y + self:get_line_height() - h, x2 - x1, h, color)
end
end
command.add("core.docview", {
["bracket-match:move-to-matching"] = function()
update_state()
if state.line2 then
core.active_view.doc:set_selection(state.line2, state.col2)
end
end,
})
keymap.add { ["ctrl+m"] = "bracket-match:move-to-matching" }
|