diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt index 94eafaa400eb24..e1549a110e8e1e 100644 --- a/runtime/doc/if_lua.txt +++ b/runtime/doc/if_lua.txt @@ -148,6 +148,43 @@ lua/charblob.lua: > encode = charblob_encode, } +------------------------------------------------------------------------------ +The plugin table *lua-plugin_table* + +To create a new plugin, call |vim.helpers.new_plugin|, passing the plugin +name. It returns a table representing the plugin, containing some information +on the plugin and some methods on the plugin table itself. + +Information in the plugin table *lua-plugin_table_information* + + Key:~ + `ns` The namespace for the addon. It is uniquely identified by the name + given when calling |vim.helpers.new_plugin|. Don't change it, and don't + make assumptions about its type. + `name` The name of the plugin, as passed to |vim.helpers.new_plugin|. + +Methods in the plugin table *lua-plugin_table_functions* + +plugin:map({keys}, {fn}) *lua-plugin:map* + Provides an interface to |map-cmd|. Note the mode-agnostic nature. if + you want to provide functionality only for certain modes, check + for the mode in the function body. + + Parameters: + {keys} String. The keys to be mapped. + {fn} Function. The lua function to be executed by the keys. + +plugin:map({args}) *lua-plugin:map_table* + Provides an interface to |map-cmd|. Note the mode-agnostic nature. if + you want to provide functionality only for certain modes, check + for the mode in the function body. + + Parameters: + {args} Table. Mandatory keys are `keys` and `fn` as in + |lua-plugin:map|. Optionally, set any of `buffer`, `nowait`, + `silent` or `unique` to `true` to use it as a special + argument as in |:map-arguments|. + ============================================================================== Commands *lua-commands* @@ -346,6 +383,15 @@ vim.helpers.deepcopy({object}) *vim.helpers.deepcopy* Performs a deep copy of the given object, and returns that copy. For a non-table object, that just means a usual copy of the object, while for a table all subtables are copied recursively. + +vim.helpers.new_plugin({string}) *vim.helpers.new_plugin* + Declare a new plugin namespace. + + Parameters:~ + {string} The name of the plugin + + Return:~ + A table representing the plugin. See |lua-plugin_table|. ------------------------------------------------------------------------------ vim.lua_api.* utility functions diff --git a/runtime/lua/helpers.lua b/runtime/lua/helpers.lua deleted file mode 100644 index c614df32aa679f..00000000000000 --- a/runtime/lua/helpers.lua +++ /dev/null @@ -1,104 +0,0 @@ -local nvim_eval = vim.api.nvim_eval - -local os_name = nil -local function osname() - if not os_name then - if nvim_eval('has("win32")') == 1 then - os_name = 'windows' - elseif nvim_eval('has("macunix")') == 1 then - os_name = 'osx' - else - os_name = 'unix' - end - end - return os_name -end - -local function gsplit(s, sep, plain) - assert(type(s) == "string") - assert(type(sep) == "string") - assert(type(plain) == "boolean" or type(plain) == "nil") - - local start = 1 - local done = false - - local function pass(i, j, ...) - if i then - assert(j+1 > start, "Infinite loop detected") - local seg = s:sub(start, i - 1) - start = j + 1 - return seg, ... - else - done = true - return s:sub(start) - end - end - - return function() - if done then - return - end - if sep == '' then - if start == #s then - done = true - end - return pass(start+1, start) - end - return pass(s:find(sep, start, plain)) - end -end - -local function split(s,sep,plain) - local t={} for c in gsplit(s, sep, plain) do table.insert(t,c) end - return t -end - -local inspect = require('inspect') - -local function trim(s) - assert(type(s) == "string", "Only strings can be trimmed") - return s:gsub("^%s+", ""):gsub("%s+$", "") -end - -local function deepcopy(orig) - local copy - if type(orig) == 'table' then - copy = {} - for k, v in pairs(orig) do - copy[deepcopy(k)] = deepcopy(v) - end - setmetatable(copy, deepcopy(getmetatable(orig))) - else -- number, string, boolean, etc - copy = orig - end - return copy -end - -if not vim.helpers then vim.helpers = {} end -if not vim.lua_api then vim.lua_api = {} end - -vim.lua_api.osname = osname -vim.helpers.split = split -vim.helpers.gsplit = gsplit -vim.helpers.inspect = inspect -vim.helpers.trim = trim -vim.helpers.deepcopy = deepcopy - -local module ={ - osname = osname, - split = split, - gsplit = gsplit, - inspect = inspect, - trim = trim, - deepcopy = deepcopy, -} - -vim.api.nvim_command("let lua = {}") - -vim.api.nvim_command([[ - function lua.osname() dict - return luaeval('require("helpers").osname()', {}) - endfunction -]]) - -return module diff --git a/runtime/lua/helpers/deepcopy.lua b/runtime/lua/helpers/deepcopy.lua new file mode 100644 index 00000000000000..1342d61ed51315 --- /dev/null +++ b/runtime/lua/helpers/deepcopy.lua @@ -0,0 +1,17 @@ +local function deepcopy(orig) + local copy + if type(orig) == 'table' then + copy = {} + for k, v in pairs(orig) do + copy[deepcopy(k)] = deepcopy(v) + end + setmetatable(copy, deepcopy(getmetatable(orig))) + else -- number, string, boolean, etc + copy = orig + end + return copy +end + +return { + deepcopy = deepcopy, +} diff --git a/runtime/lua/helpers/init.lua b/runtime/lua/helpers/init.lua new file mode 100644 index 00000000000000..bce2036b389865 --- /dev/null +++ b/runtime/lua/helpers/init.lua @@ -0,0 +1,43 @@ +local nvim_eval = vim.api.nvim_eval + +local osname = require('helpers.os').osname +local gsplit = require('helpers.stringstuff').gsplit +local trim = require('helpers.stringstuff').trim +local split = require('helpers.stringstuff').split + +local inspect = require('helpers.inspect') + +local deepcopy = require('helpers.deepcopy').deepcopy + +local new_plugin = require('helpers.plugin').new_plugin + +if not vim.helpers then vim.helpers = {} end +if not vim.lua_api then vim.lua_api = {} end + +vim.lua_api.osname = osname +vim.helpers.split = split +vim.helpers.gsplit = gsplit +vim.helpers.inspect = inspect +vim.helpers.trim = trim +vim.helpers.deepcopy = deepcopy +vim.helpers.new_plugin = new_plugin + +local module ={ + osname = osname, + split = split, + gsplit = gsplit, + inspect = inspect, + trim = trim, + deepcopy = deepcopy, + new_plugin = new_plugin, +} + +vim.api.nvim_command("let lua = {}") + +vim.api.nvim_command([[ + function lua.osname() dict + return luaeval('require("helpers").osname()', {}) + endfunction +]]) + +return module diff --git a/runtime/lua/inspect.lua b/runtime/lua/helpers/inspect.lua similarity index 100% rename from runtime/lua/inspect.lua rename to runtime/lua/helpers/inspect.lua diff --git a/runtime/lua/helpers/os.lua b/runtime/lua/helpers/os.lua new file mode 100644 index 00000000000000..8d3a9f278b7aa7 --- /dev/null +++ b/runtime/lua/helpers/os.lua @@ -0,0 +1,21 @@ +-- luacheck: globals unpack vim.api +local nvim = vim.api +local eval = nvim.nvim_eval + +local os_name = nil +local function osname() + if not os_name then + if eval('has("win32")') == 1 then + os_name = 'windows' + elseif eval('has("macunix")') == 1 then + os_name = 'osx' + else + os_name = 'unix' + end + end + return os_name +end + +return { + osname = osname, +} diff --git a/runtime/lua/helpers/plugin/init.lua b/runtime/lua/helpers/plugin/init.lua new file mode 100644 index 00000000000000..9365ca4382a519 --- /dev/null +++ b/runtime/lua/helpers/plugin/init.lua @@ -0,0 +1,20 @@ +-- luacheck: globals unpack vim.api +local nvim = vim.api +local map = require('helpers.plugin.map').map +local functions = require('helpers.plugin.map').functions + +local function new_plugin(name) + -- TODO(KillTheMule): This code assumes that subsequent calls with the same + -- name return the same ns. Make sure of that, or adapt + local ns = nvim.nvim_create_namespace(name) + + -- Should be redundant after the comment above has ben ascertained + assert(functions[ns] == nil, "Namspace "..tostring(ns).." already exists") + + functions[ns] = {} + return { ns = ns, name = name, map = map } +end + +return { + new_plugin = new_plugin, +} diff --git a/runtime/lua/tycho/init.lua b/runtime/lua/helpers/plugin/map.lua similarity index 67% rename from runtime/lua/tycho/init.lua rename to runtime/lua/helpers/plugin/map.lua index 196f5f476c2e19..4d112077dcfce9 100644 --- a/runtime/lua/tycho/init.lua +++ b/runtime/lua/helpers/plugin/map.lua @@ -1,28 +1,18 @@ -- luacheck: globals unpack vim.api local nvim = vim.api - local command = nvim.nvim_command -local messages = {} local functions = {} local function map_to_ns(keys, ns, opts) local keys_rhs = keys:gsub("<", "") - local rhs = "lua require('tycho').functions[".. + local rhs = "lua require('helpers.plugin.map').functions[".. tostring(ns).."]['"..keys_rhs.."']()" opts = (opts and opts.." ") or "" - table.insert(messages, { rhs = rhs, opts = opts }) command("map "..opts..keys.." "..rhs.."") end -local function debug() - nvim.nvim_set_var("tycho_msgs", require('inspect')(messages)) - nvim.nvim_set_var("tycho_fns", require('inspect')(functions)) - command("put =tycho_msgs") - command("put =tycho_fns") -end - local allowed_map_opts = { buffer = true, nowait = true, silent = true, unique = true } local function destructure_map_args(table) @@ -67,26 +57,13 @@ local function map(self, arg1, arg2) keys, fn, opts = arg1, arg2, nil end - assert(functions[ns][keys] == nil, "Keys already mapped from tycho") + assert(functions[ns][keys] == nil, "Keys already mapped from namespace "..tostring(ns)) functions[ns][keys] = fn map_to_ns(keys, ns, opts) end -local function new_plugin(name) - -- TODO(KillTheMule): This code assumes that subsequent calls with the same - -- name return the same ns. Make sure of that, or adapt - local ns = nvim.nvim_create_namespace(name) - - -- Should be redundant after the comment above has ben ascertained - assert(functions[ns] == nil, "Namspace already exists in tycho") - - functions[ns] = {} - return { ns = ns, name = name, map = map } -end - return { - debug = debug, - new_plugin = new_plugin, + map = map, functions = functions, } diff --git a/runtime/lua/helpers/stringstuff.lua b/runtime/lua/helpers/stringstuff.lua new file mode 100644 index 00000000000000..6a5c3663c61227 --- /dev/null +++ b/runtime/lua/helpers/stringstuff.lua @@ -0,0 +1,50 @@ +local function gsplit(s, sep, plain) + assert(type(s) == "string") + assert(type(sep) == "string") + assert(type(plain) == "boolean" or type(plain) == "nil") + + local start = 1 + local done = false + + local function pass(i, j, ...) + if i then + assert(j+1 > start, "Infinite loop detected") + local seg = s:sub(start, i - 1) + start = j + 1 + return seg, ... + else + done = true + return s:sub(start) + end + end + + return function() + if done then + return + end + if sep == '' then + if start == #s then + done = true + end + return pass(start+1, start) + end + return pass(s:find(sep, start, plain)) + end +end + +local function split(s,sep,plain) + local t={} for c in gsplit(s, sep, plain) do table.insert(t,c) end + return t +end + + +local function trim(s) + assert(type(s) == "string", "Only strings can be trimmed") + return s:gsub("^%s+", ""):gsub("%s+$", "") +end + +return { + trim = trim, + gsplit = gsplit, + split = split +} diff --git a/runtime/lua/testplugin.lua b/runtime/lua/testplugin.lua index 88478d285fe11c..adff2765ea5a5b 100644 --- a/runtime/lua/testplugin.lua +++ b/runtime/lua/testplugin.lua @@ -1,8 +1,7 @@ -local tycho = require('tycho') local nvim = vim.api +local helpers = require('helpers') - -local plugin = tycho.new_plugin("testplugin") +local plugin = helpers.new_plugin("testplugin") local function stuff() local curbuf = nvim.nvim_get_current_buf()