aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrxi <rxi@users.noreply.github.com>2020-04-23 18:57:15 +0100
committerrxi <rxi@users.noreply.github.com>2020-04-23 18:57:15 +0100
commit8e321f68aba76da51f1ea2de7fef3588ddc763ad (patch)
tree9e0a47fc611e6ffe6a42c7862f1d5d5a45c7cac0
parent5b6ab581e9fcdd554f0b914dd51338f7c2bc3cfd (diff)
downloadlite-xl-plugins-8e321f68aba76da51f1ea2de7fef3588ddc763ad.tar.gz
lite-xl-plugins-8e321f68aba76da51f1ea2de7fef3588ddc763ad.zip
Added plugin `bracketmatch`
-rw-r--r--README.md1
-rw-r--r--bracketmatch.lua103
2 files changed, 104 insertions, 0 deletions
diff --git a/README.md b/README.md
index 92bd2e3..2215849 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ otherwise the plugin file itself can be submitted.*
Plugin | Description
-------|-----------------------------------------
[`autowrap`](autowrap.lua?raw=1) | Automatically hardwraps lines when typing
+[`bracketmatch`](bracketmatch.lua?raw=1) | [Underlines](https://user-images.githubusercontent.com/3920290/80132745-0c863f00-8594-11ea-8875-c455c6fd7eae.png) matching right-bracket of left-bracket under caret
[`gofmt`](gofmt.lua?raw=1) | Auto-formats the current go file, adds the missing imports and the missing return cases
[`indentguide`](indentguide.lua?raw=1) | Adds [indent guides](https://user-images.githubusercontent.com/3920290/79640716-f9860000-818a-11ea-9c3b-26d10dd0e0c0.png)
[`language_fe`](language_fe.lua?raw=1) | Syntax for the [fe](https://github.com/rxi/fe) programming language
diff --git a/bracketmatch.lua b/bracketmatch.lua
new file mode 100644
index 0000000..b05e8ab
--- /dev/null
+++ b/bracketmatch.lua
@@ -0,0 +1,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" }