From 5a4ec36070aed439d509870b793a008fee24a48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Wed, 1 Mar 2017 22:00:05 +0100 Subject: lua: let number increment/decrement handle next number Operate on the next number to the right of the cursor, for now the matches are not restricted to the current line. Based on a patch from Denis Warsow. Close #509 --- lua/plugins/number-inc-dec.lua | 84 +++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 37 deletions(-) (limited to 'lua') diff --git a/lua/plugins/number-inc-dec.lua b/lua/plugins/number-inc-dec.lua index a165b5a..e2f5f2e 100644 --- a/lua/plugins/number-inc-dec.lua +++ b/lua/plugins/number-inc-dec.lua @@ -1,6 +1,11 @@ -- increment/decrement number in dec/hex/oct format local lexer = vis.lexers -if not lexer then return end +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) @@ -8,45 +13,50 @@ local change = function(delta) local file = win.file local count = vis.count if not count then count = 1 end - vis.count = nil -- reset count + vis.count = nil -- reset count, otherwise it affects next motion for cursor in win:cursors_iterator() do - local pos = cursor.pos - local word = file:text_object_word(pos); - local s, e = word.start, word.finish; - if s then - local data = file:content(s, e - s) - if data and #data > 0 then - 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 number then - number = number + delta * count - if base ~= 10 and number < 0 then - -- string.format does not handle negative hex/oct values - -- should we wrap around? - 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 - else - vis:info("Not a number") - end + -- 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 - end + file:delete(s, e - s) + file:insert(s, number) + cursor.pos = s + until true end end -- cgit v1.2.3