diff options
-rw-r--r-- | toggler.lua | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/toggler.lua b/toggler.lua new file mode 100644 index 0000000..4b643af --- /dev/null +++ b/toggler.lua @@ -0,0 +1,95 @@ +-- 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) + 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) + vis:map(vis.modes.VISUAL, key, binding, help) +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") + operator_new("<C-x>", toggle(decrement), inner_word, nil, "Toggle/decrement word or selection") + 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) +end) + +return function(config) + local ext_config = require(config) + M = ext_config or M + return M +end |