aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--bracketmatch.lua103
-rw-r--r--spellcheck.lua32
3 files changed, 117 insertions, 19 deletions
diff --git a/README.md b/README.md
index 76512b1..d631068 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" }
diff --git a/spellcheck.lua b/spellcheck.lua
index 0c5aca9..bb6f835 100644
--- a/spellcheck.lua
+++ b/spellcheck.lua
@@ -7,27 +7,22 @@ local DocView = require "core.docview"
config.spellcheck_files = { "%.txt$", "%.md$", "%.markdown$" }
config.dictionary_file = "/usr/share/dict/words"
-local inited = false
local words
-local function init_words()
- if inited then return end
- inited = true
- core.add_thread(function()
- local t = {}
- local i = 0
- for line in io.lines(config.dictionary_file) do
- for word in line:gmatch("%a+") do
- t[word:lower()] = true
- end
- i = i + 1
- if i % 1000 == 0 then coroutine.yield() end
+core.add_thread(function()
+ local t = {}
+ local i = 0
+ for line in io.lines(config.dictionary_file) do
+ for word in line:gmatch("%a+") do
+ t[word:lower()] = true
end
- core.log_quiet("Finished loading dictionary file: %s", config.dictionary_file)
- words = t
- core.redraw = true
- end)
-end
+ i = i + 1
+ if i % 1000 == 0 then coroutine.yield() end
+ end
+ words = t
+ core.redraw = true
+ core.log_quiet("Finished loading dictionary file: \"%s\"", config.dictionary_file)
+end)
local function matches_any(filename, ptns)
@@ -42,7 +37,6 @@ local draw_line_text = DocView.draw_line_text
function DocView:draw_line_text(idx, x, y)
draw_line_text(self, idx, x, y)
- init_words()
if not words
or not matches_any(self.doc.filename or "", config.spellcheck_files) then
return