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
|
-- increment/decrement number in dec/hex/oct format
local lexer = vis.lexers
local lpeg = vis.lpeg
if not lexer or not lpeg then return end
local Cp = lpeg.Cp()
local dec_num = lpeg.S('+-')^-1 * lexer.dec_num
local pattern = lpeg.P{ Cp * (lexer.hex_num + lexer.oct_num + dec_num) * Cp + 1 * lpeg.V(1) }
local change = function(delta)
local win = vis.win
local file = win.file
local count = vis.count
if not count then count = 1 end
vis.count = nil -- reset count, otherwise it affects next motion
for cursor in win:cursors_iterator() do
-- poor man's continue statement, use break to process next cursor
repeat
local pos = cursor.pos
if not pos then break end
local word = file:text_object_word(pos);
if not word then break end
local data = file:content(word.start, 1024)
if not data then break end
local s, e = pattern:match(data)
if not s then break end
data = string.sub(data, s, e-1)
if #data == 0 then break end
-- align start and end for fileindex
s = word.start + s - 1
e = word.start + e - 1
local base, format, padding = 10, 'd', 0
if lexer.oct_num:match(data) then
base = 8
format = 'o'
padding = #data
elseif lexer.hex_num:match(data) then
base = 16
format = 'x'
padding = #data - #"0x"
end
local number = tonumber(data, base == 8 and 8 or nil)
if not number then
vis:info("Not a number")
break
end
number = number + delta * count
-- string.format does not support negative hex/oct values
if base ~= 10 and number < 0 then number = 0 end
number = string.format((base == 16 and "0x" or "") .. "%0"..padding..format, number)
if base == 8 and string.sub(number, 0, 1) ~= "0" then
number = '0' .. number
end
file:delete(s, e - s)
file:insert(s, number)
cursor.pos = s
until true
end
end
vis:map(vis.modes.NORMAL, "<C-a>", function() change( 1) end, "Increment number")
vis:map(vis.modes.NORMAL, "<C-x>", function() change(-1) end, "Decrement number")
|