diff options
author | Georgi Kirilov <> | 2020-11-22 15:10:49 +0200 |
---|---|---|
committer | Georgi Kirilov <> | 2023-10-04 18:24:59 +0800 |
commit | 1425300e56e500d0cc61b4dfb14e10d59822686b (patch) | |
tree | 80f3ed18c14d0f4fce97ac661c1d6e30f14b5aeb | |
parent | 03fae0a577f4e105aad95744ef1f519386724e40 (diff) | |
download | vis-pairs-1425300e56e500d0cc61b4dfb14e10d59822686b.tar.gz |
Load the whole file only once per action
-rw-r--r-- | pairs.lua | 93 |
1 files changed, 49 insertions, 44 deletions
@@ -110,7 +110,7 @@ local function match_at(str, pattern, pos) end end -local function escaping_context(file, range) +local function escaping_context(data, range) if not vis.win.syntax then return {} end local rules = vis.lexers.lexers[vis.win.syntax]._RULES local p @@ -121,16 +121,16 @@ local function escaping_context(file, range) end if not p then return {} end if not range then return {escape = p} end -- means we are retrying with a "fake" pos - local data = file:content(0, file.size) local e1 = {match_at(data, p, range.start)} local e2 = range.finish - range.start > 1 and {match_at(data, p, range.finish - 1)} or e1 if #e1 == 0 and #e2 == 0 then return {escape = p} end if #e1 == 0 and #e2 > 0 then return {escape = p, newpos = range.start} end if #e2 == 0 and #e1 > 0 then return {escape = p, newpos = range.finish - 1} end p = nil - local escaped_range = {start = e1[1], finish = e1[2]} + local escaped_range = {e1[1] + 1, e1[2]} + local escaped_data = data:sub(e1[1] + 1, e1[2]) for _, level in ipairs({vis.lexers.COMMENT, vis.lexers.STRING}) do - if l.match(rules[level] / 0 * -1, file:content(escaped_range)) then + if l.match(rules[level] / 0 * -1, escaped_data) then for _, name in ipairs(precedence[level]) do if rules[name] then p = p and p + rules[name] / 0 or rules[name] / 0 @@ -141,23 +141,23 @@ local function escaping_context(file, range) end end -local function get_range(key, file, pos) +local function get_range(key, file_data, pos) local d = get_pair(key) if not d then return end local offsets, correction repeat local sel_range = selection_range(pos) - local c = escaping_context(file, sel_range) - local range = c.range or {start = 0, finish = file.size} + local c = escaping_context(file_data, sel_range) + local range = c.range or {1, #file_data} if c.newpos then pos = c.newpos else - pos = pos - range.start + pos = pos - (range[1] - 1) end - correction = range.start + correction = range[1] - 1 local p = d[1] ~= d[2] and symmetric(d[1], d[2], c.escape, pos + 1) or asymmetric(d[1], pos + 1) local skip = c.escape and c.escape + 1 or 1 - local data = file:content(range) + local data = c.range and file_data:sub(unpack(c.range)) or file_data local pattern = l.P{p + skip * (l.V(1) - l.Cmt(l.Cc(pos + 1), past))} local result local start = 1 @@ -167,7 +167,7 @@ local function get_range(key, file, pos) start = result until type(result) == "table" if not result then - pos = range.start - 1 + pos = correction - 1 else offsets = {nth(result)} offsets[3] = nil @@ -185,7 +185,8 @@ end local function get_delimiters(key, pos) local d = get_pair(key) if not d or type(d[1]) == "string" and type(d[2]) == "string" then return d end - local start, finish = get_range(key, vis.win.file, pos) + local content = vis.win.file:content(0, vis.win.file.size) + local start, finish = get_range(key, content, pos) if start and finish then return {vis.win.file:content(start[1], start[2] - start[1]), vis.win.file:content(finish[1], finish[2] - finish[1]), d[3], d[4]} elseif #d > 2 then @@ -193,40 +194,23 @@ local function get_delimiters(key, pos) end end -local done_once - -local function bail_early() - if vis.count and vis.count > 1 then - if done_once then - done_once = nil - return true - else - done_once = true - end - end - return false -end - -local function outer(win, pos) - if bail_early() then return end - local start, finish = get_range(M.key, win.file, pos) +local function outer(content, pos) + local start, finish = get_range(M.key, content, pos) if not (start and finish) then return end return start[1], finish[2] end -local function inner(win, pos) - if bail_early() then return end - local start, finish = get_range(M.key, win.file, pos) +local function inner(content, pos) + local start, finish = get_range(M.key, content, pos) if not (start and finish) then return end return start[2], finish[1] end -local function opening(win, pos) - if bail_early() then return pos end - local start, _ = get_range(M.key, win.file, pos) +local function opening(content, pos) + local start, _ = get_range(M.key, content, pos) if start then if pos == start[2] - 1 then - start, _ = get_range(M.key, win.file, start[1] - 1) + start, _ = get_range(M.key, content, start[1] - 1) end if start then local exclusive = (vis.mode == vis.modes.OPERATOR_PENDING or vis.mode == vis.modes.VISUAL and pos < start[2] - 1) and 1 or 0 @@ -236,12 +220,11 @@ local function opening(win, pos) return pos end -local function closing(win, pos) - if bail_early() then return pos end - local _, finish = get_range(M.key, win.file, pos) +local function closing(content, pos) + local _, finish = get_range(M.key, content, pos) if finish then if pos == finish[1] then - _, finish = get_range(M.key, win.file, finish[2]) + _, finish = get_range(M.key, content, finish[2]) end if finish then local exclusive = (vis.mode == vis.modes.VISUAL and pos > finish[1]) and 1 or 0 @@ -251,6 +234,28 @@ local function closing(win, pos) return pos end +local done_once + +local function bail_early() + if vis.count and vis.count > 1 then + if done_once then + done_once = nil + return true + else + done_once = true + end + end + return false +end + +local function handler(func) + return function(win, pos) + if bail_early() then return pos end + local content = win.file:content(0, win.file.size) + return func(content, pos) + end +end + local function new(execute, register, prefix, handler, help) local id = register(vis, handler) if id < 0 then @@ -284,12 +289,12 @@ end vis.events.subscribe(vis.events.INIT, function() M.motion = { - opening = new(vis.motion, vis.motion_register, M.prefix.opening, opening, "Move cursor to the beginning of a delimited block"), - closing = new(vis.motion, vis.motion_register, M.prefix.closing, closing, "Move cursor to the end of a delimited block"), + opening = new(vis.motion, vis.motion_register, M.prefix.opening, handler(opening), "Move cursor to the beginning of a delimited block"), + closing = new(vis.motion, vis.motion_register, M.prefix.closing, handler(closing), "Move cursor to the end of a delimited block"), } M.textobject = { - inner = new(vis.textobject, vis.textobject_register, M.prefix.inner, inner, "Delimited block (inner variant)"), - outer = new(vis.textobject, vis.textobject_register, M.prefix.outer, outer, "Delimited block (outer variant)"), + inner = new(vis.textobject, vis.textobject_register, M.prefix.inner, handler(inner), "Delimited block (inner variant)"), + outer = new(vis.textobject, vis.textobject_register, M.prefix.outer, handler(outer), "Delimited block (outer variant)"), } local tex_environment = {"\\begin{" * l.Cg(l.R("az", "AZ")^1, "t") * "}", l.Cmt("\\end{" * l.Cb("t") * l.C((1 - l.P"}")^1) * "}", function(_, _, c1, c2) return c1 == c2 end), {"\\begin{\xef\xbf\xbd}", "\\end{\xef\xbf\xbd}"}, "environment name"} |