1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
-- Author: Georgi Kirilov
--
-- You can contact me via email to the posteo.net domain.
-- The local-part is the Z code for "Place a competent operator on this circuit."
require("vis")
local vis = vis
local M = {}
local lookup = {}
local count
local inner_word = 0
local char_next = 17
local function toggle(func, motion)
return function(file, range, pos)
local word = file:content(range)
local toggled = func(word, count)
if toggled then
file:delete(range)
file:insert(range.start, toggled)
return motion and range.finish or range.start
end
return pos
end
end
local function make_shift(shift)
return function(word, delta)
local number = tonumber(word)
local iter = number and {number} or lookup[word]
if not iter then return end
local binary = iter[2] and #iter[2] == 2
local neighbor, rotate = shift(iter[1], iter[2], delta)
return number and neighbor or iter[2][neighbor] or binary and iter[2][rotate]
end
end
local increment = make_shift(function(i, _, delta) return i + (delta or 1), 1 end)
local decrement = make_shift(function(i, options, delta) return i - (delta or 1), options and #options end)
local function case(str)
return str:gsub("[%l%u]", function(char)
local lower = char:lower()
return char == lower and char:upper() or lower
end)
end
local function operator_new(key, handler, object, motion, help, novisual)
local id = vis:operator_register(handler)
if id < 0 then
return false
end
local function binding()
vis:operator(id)
if vis.mode == vis.modes.OPERATOR_PENDING then
if object then
count = vis.count
vis.count = nil
vis:textobject(object)
elseif motion then
vis:motion(motion)
end
end
end
vis:map(vis.modes.NORMAL, key, binding, help)
if not novisual then
vis:map(vis.modes.VISUAL, key, binding, help)
end
end
local function preprocess(tbl)
local cfg = {}
for _, options in ipairs(tbl) do
for i, key in ipairs(options) do
cfg[key] = {i, options}
end
end
return cfg
end
vis.events.subscribe(vis.events.INIT, function()
operator_new("<C-a>", toggle(increment), inner_word, nil, "Toggle/increment word or selection", true)
operator_new("<C-x>", toggle(decrement), inner_word, nil, "Toggle/decrement word or selection", true)
operator_new("~", toggle(case, true), nil, char_next, "Toggle case of character or selection")
operator_new("g~", toggle(case), nil, nil, "Toggle-case operator")
operator_new("gu", toggle(string.lower), nil, nil, "Lower-case operator")
operator_new("gU", toggle(string.upper), nil, nil, "Upper-case operator")
lookup = preprocess(M)
vis:map(vis.modes.NORMAL, "g~~", "g~il")
vis:map(vis.modes.NORMAL, "guu", "guil")
vis:map(vis.modes.NORMAL, "gUU", "gUil")
vis:map(vis.modes.VISUAL, "u", "gu")
vis:map(vis.modes.VISUAL, "U", "gU")
end)
return function(config)
local ext_config = require(config)
M = ext_config or M
return M
end
|