309 lines
6.8 KiB
Lua
309 lines
6.8 KiB
Lua
-- Bring vim into local scope.
|
|
local vim = vim
|
|
local api = vim.api
|
|
local inspect = vim.inspect
|
|
|
|
local function extend(t, o)
|
|
local mt = getmetatable(t)
|
|
for k, v in pairs(o) do
|
|
rawset(mt, k, v)
|
|
end
|
|
return t
|
|
end
|
|
|
|
-- Equivalent to `echo vim.inspect(...)`
|
|
local function nvim_print(...)
|
|
if select("#", ...) == 1 then
|
|
api.nvim_out_write(inspect((...)))
|
|
else
|
|
api.nvim_out_write(inspect({ ... }))
|
|
end
|
|
api.nvim_out_write("\n")
|
|
end
|
|
|
|
--- Equivalent to `echo` EX command
|
|
local function nvim_echo(...)
|
|
for i = 1, select("#", ...) do
|
|
local part = select(i, ...)
|
|
api.nvim_out_write(tostring(part))
|
|
-- vim.api.nvim_out_write("\n")
|
|
api.nvim_out_write(" ")
|
|
end
|
|
api.nvim_out_write("\n")
|
|
end
|
|
|
|
local window_options = {
|
|
arab = true,
|
|
arabic = true,
|
|
breakindent = true,
|
|
breakindentopt = true,
|
|
bri = true,
|
|
briopt = true,
|
|
cc = true,
|
|
cocu = true,
|
|
cole = true,
|
|
colorcolumn = true,
|
|
concealcursor = true,
|
|
conceallevel = true,
|
|
crb = true,
|
|
cuc = true,
|
|
cul = true,
|
|
cursorbind = true,
|
|
cursorcolumn = true,
|
|
cursorline = true,
|
|
diff = true,
|
|
fcs = true,
|
|
fdc = true,
|
|
fde = true,
|
|
fdi = true,
|
|
fdl = true,
|
|
fdm = true,
|
|
fdn = true,
|
|
fdt = true,
|
|
fen = true,
|
|
fillchars = true,
|
|
fml = true,
|
|
fmr = true,
|
|
foldcolumn = true,
|
|
foldenable = true,
|
|
foldexpr = true,
|
|
foldignore = true,
|
|
foldlevel = true,
|
|
foldmarker = true,
|
|
foldmethod = true,
|
|
foldminlines = true,
|
|
foldnestmax = true,
|
|
foldtext = true,
|
|
lbr = true,
|
|
lcs = true,
|
|
linebreak = true,
|
|
list = true,
|
|
listchars = true,
|
|
nu = true,
|
|
number = true,
|
|
numberwidth = true,
|
|
nuw = true,
|
|
previewwindow = true,
|
|
pvw = true,
|
|
relativenumber = true,
|
|
rightleft = true,
|
|
rightleftcmd = true,
|
|
rl = true,
|
|
rlc = true,
|
|
rnu = true,
|
|
scb = true,
|
|
scl = true,
|
|
scr = true,
|
|
scroll = true,
|
|
scrollbind = true,
|
|
signcolumn = true,
|
|
spell = true,
|
|
statusline = true,
|
|
stl = true,
|
|
wfh = true,
|
|
wfw = true,
|
|
winbl = true,
|
|
winblend = true,
|
|
winfixheight = true,
|
|
winfixwidth = true,
|
|
winhighlight = true,
|
|
winhl = true,
|
|
wrap = true,
|
|
}
|
|
|
|
local function validate(conf)
|
|
assert(type(conf) == "table")
|
|
local type_names = {
|
|
t = "table",
|
|
s = "string",
|
|
n = "number",
|
|
b = "boolean",
|
|
f = "function",
|
|
c = "callable",
|
|
["table"] = "table",
|
|
["string"] = "string",
|
|
["number"] = "number",
|
|
["boolean"] = "boolean",
|
|
["function"] = "function",
|
|
["callable"] = "callable",
|
|
["nil"] = "nil",
|
|
["thread"] = "thread",
|
|
["userdata"] = "userdata",
|
|
}
|
|
for k, v in pairs(conf) do
|
|
if not (v[3] and v[1] == nil) and type(v[1]) ~= type_names[v[2]] then
|
|
error(string.format("validation_failed: %q: expected %s, received %s", k, type_names[v[2]], type(v[1])))
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
local function make_meta_accessor(get, set, del)
|
|
validate({
|
|
get = { get, "f" },
|
|
set = { set, "f" },
|
|
del = { del, "f", true },
|
|
})
|
|
local mt = {}
|
|
if del then
|
|
function mt:__newindex(k, v)
|
|
if v == nil then
|
|
return del(k)
|
|
end
|
|
return set(k, v)
|
|
end
|
|
else
|
|
function mt:__newindex(k, v)
|
|
return set(k, v)
|
|
end
|
|
end
|
|
function mt:__index(k)
|
|
return get(k)
|
|
end
|
|
return setmetatable({}, mt)
|
|
end
|
|
|
|
local function pcall_ret(status, ...)
|
|
if status then
|
|
return ...
|
|
end
|
|
end
|
|
|
|
local function nil_wrap(fn)
|
|
return function(...)
|
|
return pcall_ret(pcall(fn, ...))
|
|
end
|
|
end
|
|
|
|
local fn = setmetatable({}, {
|
|
__index = function(t, k)
|
|
local f = function(...)
|
|
return api.nvim_call_function(k, { ... })
|
|
end
|
|
rawset(t, k, f)
|
|
return f
|
|
end,
|
|
})
|
|
|
|
local function getenv(k)
|
|
local v = fn.getenv(k)
|
|
if v == vim.NIL then
|
|
return nil
|
|
end
|
|
return v
|
|
end
|
|
|
|
local function new_win_accessor(winnr)
|
|
local function get(k)
|
|
if winnr == nil and type(k) == "number" then
|
|
return new_win_accessor(k)
|
|
end
|
|
return api.nvim_win_get_var(winnr or 0, k)
|
|
end
|
|
local function set(k, v)
|
|
return api.nvim_win_set_var(winnr or 0, k, v)
|
|
end
|
|
local function del(k)
|
|
return api.nvim_win_del_var(winnr or 0, k)
|
|
end
|
|
return make_meta_accessor(nil_wrap(get), set, del)
|
|
end
|
|
|
|
local function new_win_opt_accessor(winnr)
|
|
local function get(k)
|
|
if winnr == nil and type(k) == "number" then
|
|
return new_win_opt_accessor(k)
|
|
end
|
|
return api.nvim_win_get_option(winnr or 0, k)
|
|
end
|
|
local function set(k, v)
|
|
return api.nvim_win_set_option(winnr or 0, k, v)
|
|
end
|
|
return make_meta_accessor(nil_wrap(get), set)
|
|
end
|
|
|
|
local function new_buf_accessor(bufnr)
|
|
local function get(k)
|
|
if bufnr == nil and type(k) == "number" then
|
|
return new_buf_accessor(k)
|
|
end
|
|
return api.nvim_buf_get_var(bufnr or 0, k)
|
|
end
|
|
local function set(k, v)
|
|
return api.nvim_buf_set_var(bufnr or 0, k, v)
|
|
end
|
|
local function del(k)
|
|
return api.nvim_buf_del_var(bufnr or 0, k)
|
|
end
|
|
return make_meta_accessor(nil_wrap(get), set, del)
|
|
end
|
|
|
|
local function new_buf_opt_accessor(bufnr)
|
|
local function get(k)
|
|
if window_options[k] then
|
|
return api.nvim_err_writeln(k .. " is a window option, not a buffer option")
|
|
end
|
|
if bufnr == nil and type(k) == "number" then
|
|
return new_buf_opt_accessor(k)
|
|
end
|
|
return api.nvim_buf_get_option(bufnr or 0, k)
|
|
end
|
|
local function set(k, v)
|
|
if window_options[k] then
|
|
return api.nvim_err_writeln(k .. " is a window option, not a buffer option")
|
|
end
|
|
return api.nvim_buf_set_option(bufnr or 0, k, v)
|
|
end
|
|
return make_meta_accessor(nil_wrap(get), set)
|
|
end
|
|
|
|
-- `nvim.$method(...)` redirects to `nvim.api.nvim_$method(...)`
|
|
-- `nvim.fn.$method(...)` redirects to `vim.api.nvim_call_function($method, {...})`
|
|
-- TODO `nvim.ex.$command(...)` is approximately `:$command {...}.join(" ")`
|
|
-- `nvim.print(...)` is approximately `echo vim.inspect(...)`
|
|
-- `nvim.echo(...)` is approximately `echo table.concat({...}, '\n')`
|
|
-- Both methods cache the inital lookup in the metatable, but there is api small overhead regardless.
|
|
return setmetatable({
|
|
print = nvim_print,
|
|
echo = nvim_echo,
|
|
fn = rawget(vim, "fn") or fn,
|
|
validate = validate,
|
|
g = rawget(vim, "g") or make_meta_accessor(nil_wrap(api.nvim_get_var), api.nvim_set_var, api.nvim_del_var),
|
|
v = rawget(vim, "v") or make_meta_accessor(nil_wrap(api.nvim_get_vvar), api.nvim_set_vvar),
|
|
o = rawget(vim, "o") or make_meta_accessor(api.nvim_get_option, api.nvim_set_option),
|
|
w = new_win_accessor(nil),
|
|
b = new_buf_accessor(nil),
|
|
env = rawget(vim, "env") or make_meta_accessor(getenv, fn.setenv),
|
|
wo = rawget(vim, "wo") or new_win_opt_accessor(nil),
|
|
bo = rawget(vim, "bo") or new_buf_opt_accessor(nil),
|
|
buf = {
|
|
line = api.nvim_get_current_line,
|
|
nr = api.nvim_get_current_buf,
|
|
},
|
|
ex = setmetatable({}, {
|
|
__index = function(t, k)
|
|
local command = k:gsub("_$", "!")
|
|
local f = function(...)
|
|
local flattened = nil
|
|
if vim.iter then
|
|
flattened = vim.iter({ command, ... }):flatten():totable()
|
|
else
|
|
flattened = vim.tbl_flatten({ command, ... })
|
|
end
|
|
return api.nvim_command(table.concat(flattened, " "))
|
|
end
|
|
rawset(t, k, f)
|
|
return f
|
|
end,
|
|
}),
|
|
}, {
|
|
__index = function(t, k)
|
|
local f = api["nvim_" .. k]
|
|
if f then
|
|
rawset(t, k, f)
|
|
end
|
|
return f
|
|
end,
|
|
})
|
|
-- vim:et ts=2 sw=2
|