summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorgi Kirilov <>2020-11-22 15:10:50 +0200
committerGeorgi Kirilov <>2023-10-04 18:24:59 +0800
commitb29dd7d087984b0a9a87509bf86e3ca12f11563a (patch)
tree4514ef41ffa4deea04f7a1caf1a86aa8c3e05475
parent145e6c016810458db727d2e09e4f878caf268503 (diff)
downloadvis-pairs-b29dd7d087984b0a9a87509bf86e3ca12f11563a.tar.gz
Repeatedly calling block objects extends selection
A hopefully better 6a7c70. Almost vim compatible - in vim, vabib == vib, but vis doesn't allow a textobject to shrink the selection.
-rw-r--r--pairs.lua59
1 files changed, 29 insertions, 30 deletions
diff --git a/pairs.lua b/pairs.lua
index 629efe7..4de85d1 100644
--- a/pairs.lua
+++ b/pairs.lua
@@ -60,11 +60,11 @@ local function symmetric(d1, d2, escaped, pos)
return l.P{l.Ct(I * d1 * I * ((skip - d1 - d2) + l.V(1))^0 * I * d2 * I) * l.Cc(pos) / at_pos}
end
-local function nth(t)
+local function nth(t, count)
if type(t) == "table" then
- local start, finish, c = 0, 0, vis.count or 1
+ local start, finish, c = 0, 0, count
if #t == 5 then
- start, finish, c = nth(t[3])
+ start, finish, c = nth(t[3], count)
end
if c then
return {t[1], t[2]}, {t[#t - 1], t[#t]}, c > 1 and c - 1 or nil
@@ -143,7 +143,7 @@ local function escaping_context(win, range, data)
end
end
-local function get_range(key, win, pos, file_data)
+local function get_range(key, win, pos, file_data, count)
local d = get_pair(key, win)
if not d then return end
local offsets, correction
@@ -163,7 +163,7 @@ local function get_range(key, win, pos, file_data)
local data = c.range and file_data:sub(unpack(c.range)) or file_data
local pattern = l.P{l.Cmt(p * l.Cc(can_abut and 1 or 0), any_captures) + skip * l.Cmt(l.Cc(pos + 1), not_past) * l.V(1)}
prev_match = 0
- offsets = {nth(pattern:match(data))}
+ offsets = {nth(pattern:match(data), count or 1)}
offsets[3] = nil
if #offsets == 0 then
pos = correction - 1
@@ -203,11 +203,11 @@ local function barf_linewise(win, content, start, finish)
return start, finish
end
-local function get_delimiters(key, win, pos)
+local function get_delimiters(key, win, pos, count)
local d = get_pair(key, win)
if not d or type(d[1]) == "string" and type(d[2]) == "string" then return d end
local content = win.file:content(0, win.file.size)
- local start, finish = get_range(key, win, pos, content)
+ local start, finish = get_range(key, win, pos, content, count or vis.count)
if start and finish then
return {win.file:content(start[1], start[2] - start[1]), win.file:content(finish[1], finish[2] - finish[1]), d[3], d.prompt}
elseif #d > 2 then
@@ -215,42 +215,32 @@ local function get_delimiters(key, win, pos)
end
end
-local function outer(win, pos, content)
- local start, finish = get_range(M.key, win, pos, content)
+local function outer(win, pos, content, count)
+ local start, finish = get_range(M.key, win, pos, content, count)
if not (start and finish) then return end
return start[1], finish[2]
end
-local function inner(win, pos, content)
- local start, finish = get_range(M.key, win, pos, content)
+local function inner(win, pos, content, count)
+ local start, finish = get_range(M.key, win, pos, content, count)
if not (start and finish) then return end
return barf_linewise(win, content, start[2], finish[1])
end
-local function opening(win, pos, content)
- local start, _ = get_range(M.key, win, pos, content)
+local function opening(win, pos, content, count)
+ local start, _ = get_range(M.key, win, pos, content, count)
if start then
- if pos == start[2] - 1 then
- start, _ = get_range(M.key, win, start[1] - 1, content)
- 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
- return start[2] - 1 + exclusive
- end
+ local exclusive = (vis.mode == vis.modes.OPERATOR_PENDING or vis.mode == vis.modes.VISUAL and pos < start[2] - 1) and 1 or 0
+ return start[2] - 1 + exclusive
end
return pos
end
-local function closing(win, pos, content)
- local _, finish = get_range(M.key, win, pos, content)
+local function closing(win, pos, content, count)
+ local _, finish = get_range(M.key, win, pos, content, count)
if finish then
- if pos == finish[1] then
- _, finish = get_range(M.key, win, finish[2], content)
- end
- if finish then
- local exclusive = (vis.mode == vis.modes.VISUAL and pos > finish[1]) and 1 or 0
- return finish[1] - exclusive
- end
+ local exclusive = (vis.mode == vis.modes.VISUAL and pos > finish[1]) and 1 or 0
+ return finish[1] - exclusive
end
return pos
end
@@ -290,7 +280,16 @@ local function prep(func)
return function(win, pos)
if bail_early() then return pos end
local content = win.file:content(0, win.file.size)
- return func(win, pos, content)
+ local start, finish = func(win, pos, content, vis.count)
+ if not vis.count and vis.mode == vis.modes.VISUAL or start and not finish then
+ local old = selection_range(win, pos)
+ local same_or_smaller = finish and start >= old.start and finish <= old.finish
+ local didnt_move = not finish and start == pos
+ if same_or_smaller or didnt_move then
+ start, finish = func(win, pos, content, 2)
+ end
+ end
+ return start, finish
end
end