summaryrefslogtreecommitdiffstats
path: root/pairs.lua
diff options
context:
space:
mode:
authorGeorgi Kirilov <>2020-11-22 15:10:49 +0200
committerGeorgi Kirilov <>2023-10-04 18:24:58 +0800
commite2a571588c141120286912147892b401a066b5cd (patch)
tree62d405f6f45d6dcb6cfd99df06a345b41dd98a98 /pairs.lua
parentc4cc47a8e5fc3192d5a178c4c3edba17451a0b97 (diff)
downloadvis-pairs-e2a571588c141120286912147892b401a066b5cd.tar.gz
DRY fixes
Diffstat (limited to 'pairs.lua')
-rw-r--r--pairs.lua91
1 files changed, 40 insertions, 51 deletions
diff --git a/pairs.lua b/pairs.lua
index 2ac429f..773aa12 100644
--- a/pairs.lua
+++ b/pairs.lua
@@ -8,25 +8,33 @@ local l = require("lpeg")
local M
-local builtins = {
+local builtin_textobjects = {
["["] = { "[" , "]" },
["{"] = { "{" , "}" },
["<"] = { "<" , ">" },
["("] = { "(" , ")" },
+ ['"'] = { '"' , '"' },
+ ["'"] = { "'" , "'" },
+ ["`"] = { "`" , "`" },
+}
+
+local builtin_motions = {
+ ["["] = { ["("] = true, ["{"] = true },
+ ["]"] = { [")"] = true, ["}"] = true },
}
local aliases = {}
-for _, pair in pairs(builtins) do aliases[pair[2]] = pair end
-for key, pair in pairs(aliases) do builtins[key] = pair end
-for key, pair in pairs({
+for key, pair in pairs(builtin_textobjects) do aliases[pair[2]] = key ~= pair[2] and pair or nil end
+for alias, pair in pairs(aliases) do builtin_textobjects[alias] = pair end
+for alias, key in pairs({
B = "{",
b = "(",
-}) do builtins[key] = builtins[pair] end
+}) do builtin_textobjects[alias] = builtin_textobjects[key] end
local function get_pair(key)
return M.map[vis.win.syntax] and M.map[vis.win.syntax][key]
or M.map[1] and M.map[1][key]
- or builtins[key]
+ or builtin_textobjects[key]
or not key:match("%w") and {key, key}
end
@@ -76,6 +84,14 @@ local function get_range(key, file, pos)
return nth(l.match(pattern, file:content(0, file.size)))
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)
+ if not (start and finish) then return end
+ return {vis.win.file:content(start[1], start[2] - start[1]), vis.win.file:content(finish[1], finish[2] - finish[1])}
+end
+
local function outer(win, pos)
local start, finish = get_range(M.key, win.file, pos)
if not (start and finish) then return end
@@ -88,38 +104,6 @@ local function inner(win, pos)
return start[2], finish[1]
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)
- if not (start and finish) then return end
- return {vis.win.file:content(start[1], start[2] - start[1]), vis.win.file:content(finish[1], finish[2] - finish[1])}
-end
-
-local function textobject_new(prefix, textobject, help)
- local id = vis:textobject_register(textobject)
- if id < 0 then
- return false
- end
- if prefix then
- for _, o in ipairs({"[", "]", "{", "}", "<", ">", "(", ")", "b", "B", '"', "'", "`", "i"}) do
- vis:unmap(vis.modes.VISUAL, prefix..o)
- vis:unmap(vis.modes.OPERATOR_PENDING, prefix..o)
- end
- local binding = function(keys)
- if #keys < 1 then return -1 end
- if #keys == 1 then
- M.key = keys
- vis:textobject(id)
- end
- return #keys
- end
- vis:map(vis.modes.VISUAL, prefix, binding, help)
- vis:map(vis.modes.OPERATOR_PENDING, prefix, binding, help)
- end
- return id
-end
-
local function opening(win, pos)
local start, _ = get_range(M.key, win.file, pos)
if start then
@@ -146,40 +130,45 @@ local function closing(win, pos)
return pos
end
-local function motion_new(prefix, motion, help)
- local id = vis:motion_register(motion)
+local function new(execute, register, prefix, handler, help)
+ local id = register(vis, handler)
if id < 0 then
return false
end
if prefix then
- for _, o in ipairs({"{", "}", "(", ")"}) do
- vis:unmap(vis.modes.NORMAL, prefix..o)
- vis:unmap(vis.modes.VISUAL, prefix..o)
- vis:unmap(vis.modes.OPERATOR_PENDING, prefix..o)
- end
local binding = function(keys)
if #keys < 1 then return -1 end
if #keys == 1 then
M.key = keys
- vis:motion(id)
+ execute(vis, id)
end
return #keys
end
- vis:map(vis.modes.NORMAL, prefix, binding, help)
+ if execute ~= vis.textobject then
+ vis:map(vis.modes.NORMAL, prefix, binding, help)
+ end
vis:map(vis.modes.VISUAL, prefix, binding, help)
vis:map(vis.modes.OPERATOR_PENDING, prefix, binding, help)
+ local builtin = execute == vis.motion and builtin_motions[prefix] or builtin_textobjects
+ for key, _ in pairs(builtin) do
+ if execute ~= vis.textobject then
+ vis:unmap(vis.modes.NORMAL, prefix..key)
+ end
+ vis:unmap(vis.modes.VISUAL, prefix..key)
+ vis:unmap(vis.modes.OPERATOR_PENDING, prefix..key)
+ end
end
return id
end
vis.events.subscribe(vis.events.INIT, function()
M.motion = {
- opening = motion_new(M.prefix.opening, opening, "Move cursor to the opening delimiter inside a pair of delimiters"),
- closing = motion_new(M.prefix.closing, closing, "Move cursor to the closing delimiter inside a pair of delimiters"),
+ opening = new(vis.motion, vis.motion_register, M.prefix.opening, opening, "Move cursor to the opening delimiter inside a pair of delimiters"),
+ closing = new(vis.motion, vis.motion_register, M.prefix.closing, closing, "Move cursor to the closing delimiter inside a pair of delimiters"),
}
M.textobject = {
- inner = textobject_new(M.prefix.inner, inner, "Delimited block (inner variant)"),
- outer = textobject_new(M.prefix.outer, outer, "Delimited block (outer variant)"),
+ 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)"),
}
local tag = {"<" * l.Cg(l.C((1 - l.S" />")^1), "t") * (1 - l.P">")^0 * (">" - l.B" /"), l.Cmt("</" * l.Cb("t") * l.C((1 - l.P">")^1) * ">", function(_, _, c1, c2) return c1 == c2 end)}
M.map.html = {t = tag}