diff options
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | bracketmatch.lua | 103 | ||||
-rw-r--r-- | spellcheck.lua | 32 |
3 files changed, 117 insertions, 19 deletions
@@ -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 |