335 lines
6.8 KiB
Lua
335 lines
6.8 KiB
Lua
-- This is the runtime for my custom nix-based neovim configuration system
|
|
|
|
local M = {}
|
|
local H = {}
|
|
M.helpers = H
|
|
|
|
-- {{{ General helpers
|
|
function H.with_default(default, given)
|
|
if given == nil then
|
|
return default
|
|
else
|
|
return given
|
|
end
|
|
end
|
|
|
|
-- {{{ Strings
|
|
function H.string_chars(str)
|
|
local chars = {}
|
|
for i = 1, #str do
|
|
table.insert(chars, str:sub(i, i))
|
|
end
|
|
return chars
|
|
end
|
|
|
|
function H.split(text, sep)
|
|
---@diagnostic disable-next-line: redefined-local
|
|
local sep, fields = sep or ":", {}
|
|
local pattern = string.format("([^%s]+)", sep)
|
|
text:gsub(pattern, function(c)
|
|
fields[#fields + 1] = c
|
|
end)
|
|
return fields
|
|
end
|
|
-- }}}
|
|
-- {{{ Tables
|
|
function H.mergeTables(t1, t2)
|
|
local t3 = {}
|
|
|
|
if t1 ~= nil then
|
|
for k, v in pairs(t1) do
|
|
t3[k] = v
|
|
end
|
|
end
|
|
|
|
if t2 ~= nil then
|
|
for k, v in pairs(t2) do
|
|
t3[k] = v
|
|
end
|
|
end
|
|
|
|
return t3
|
|
end
|
|
-- }}}
|
|
-- }}}
|
|
-- {{{ API wrappers
|
|
-- {{{ Keymaps
|
|
function M.set_keymap(opts, context)
|
|
if context == nil then
|
|
context = {}
|
|
end
|
|
|
|
local buffer = nil
|
|
|
|
if context.bufnr ~= nil then
|
|
buffer = context.bufnr
|
|
end
|
|
|
|
local action = opts.action
|
|
|
|
if type(opts.action) == "function" then
|
|
action = function()
|
|
opts.action(context)
|
|
end
|
|
end
|
|
|
|
vim.keymap.set(
|
|
H.string_chars(H.with_default("n", opts.mode)),
|
|
opts.mapping,
|
|
action,
|
|
{
|
|
desc = opts.desc,
|
|
buffer = H.with_default(buffer, opts.buffer),
|
|
expr = opts.expr,
|
|
silent = H.with_default(true, opts.silent),
|
|
}
|
|
)
|
|
end
|
|
-- }}}
|
|
-- {{{ Autocmds
|
|
function M.create_autocmd(opts)
|
|
local callback
|
|
|
|
if type(opts.action) == "function" then
|
|
callback = opts.action
|
|
end
|
|
|
|
if type(opts.action) == "table" then
|
|
callback = function(event)
|
|
M.configure(opts.action, event)
|
|
end
|
|
end
|
|
|
|
vim.api.nvim_create_autocmd(opts.event, {
|
|
group = vim.api.nvim_create_augroup(opts.group, {}),
|
|
pattern = H.with_default("*", opts.pattern),
|
|
callback = callback,
|
|
})
|
|
end
|
|
-- }}}
|
|
-- }}}
|
|
-- {{{ Main config runtime
|
|
local function recursive_assign(source, destination)
|
|
for key, value in pairs(source) do
|
|
if type(value) == "table" and type(destination[key]) == "table" then
|
|
recursive_assign(value, destination[key])
|
|
else
|
|
destination[key] = value
|
|
end
|
|
end
|
|
end
|
|
|
|
function M.configure(opts, context)
|
|
-- {{{ Construct opts & context
|
|
if type(opts) == "function" then
|
|
opts = opts(context)
|
|
end
|
|
|
|
if type(opts) ~= "table" then
|
|
-- TODO: throw
|
|
return
|
|
end
|
|
|
|
if type(opts.mkContext) == "function" then
|
|
context = opts.mkContext(context)
|
|
end
|
|
-- }}}
|
|
|
|
if
|
|
opts.cond == false
|
|
or type(opts.cond) == "function" and opts.cond(context) == false
|
|
then
|
|
return
|
|
end
|
|
|
|
if type(opts.vim) == "table" then
|
|
recursive_assign(opts.vim, vim)
|
|
end
|
|
|
|
-- {{{ Keybinds
|
|
if type(opts.keys) == "function" then
|
|
opts.keys = opts.keys(context)
|
|
end
|
|
|
|
if type(opts.keys) == "table" then
|
|
local keys = opts.keys
|
|
|
|
-- Detect single key passed instead of array
|
|
if keys.mapping ~= nil then
|
|
keys = { keys }
|
|
end
|
|
|
|
for _, keymap in ipairs(keys) do
|
|
M.set_keymap(keymap, context)
|
|
end
|
|
end
|
|
-- }}}
|
|
-- {{{ Autocmds
|
|
if type(opts.autocmds) == "function" then
|
|
opts.autocmds = opts.autocmds(context)
|
|
end
|
|
|
|
if type(opts.autocmds) == "table" then
|
|
local autocmds = opts.autocmds
|
|
|
|
-- Detect single autocmd passed instead of array
|
|
if autocmds.event ~= nil then
|
|
autocmds = { autocmds }
|
|
end
|
|
|
|
for _, autocmd in ipairs(autocmds) do
|
|
M.create_autocmd(autocmd)
|
|
end
|
|
end
|
|
-- }}}
|
|
-- {{{ .setup calls
|
|
if type(opts.setup) == "table" then
|
|
for key, arg in pairs(opts.setup) do
|
|
require(key).setup(arg)
|
|
end
|
|
end
|
|
|
|
if
|
|
type(context) == "table"
|
|
and context.lazy ~= nil
|
|
and context.opts ~= nil
|
|
and vim.inspect(context.opts) ~= "{}"
|
|
then
|
|
-- This is a terrible way to do it :/
|
|
local status, module = pcall(require, context.lazy.name)
|
|
if status then
|
|
module.setup(context.opts)
|
|
end
|
|
end
|
|
-- }}}
|
|
-- {{{ Callbacks
|
|
if type(opts.callback) == "function" then
|
|
opts.callback(context)
|
|
end
|
|
|
|
if type(opts.callback) == "table" then
|
|
M.configure(opts.callback, context)
|
|
end
|
|
-- }}}
|
|
end
|
|
|
|
function M.configureMany(specs, context)
|
|
for _, spec in ipairs(specs) do
|
|
M.configure(spec, context)
|
|
end
|
|
end
|
|
-- }}}
|
|
-- {{{ Neovim env handling
|
|
local envs = {
|
|
vscode = vim.g.vscode ~= nil,
|
|
neovide = vim.g.neovide ~= nil or vim.g.nix_neovim_app == "neovide",
|
|
firenvim = vim.g.started_by_firenvim ~= nil
|
|
or vim.g.nix_neovim_app == "firenvim",
|
|
}
|
|
|
|
M.blacklist = function(list)
|
|
if type(list) == "string" then
|
|
list = { list }
|
|
end
|
|
|
|
for _, key in pairs(list) do
|
|
if envs[key] then
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
M.whitelist = function(list)
|
|
if type(list) == "string" then
|
|
list = { list }
|
|
end
|
|
|
|
for _, key in pairs(list) do
|
|
if not envs[key] then
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
-- }}}
|
|
-- {{{ Other misc thingies
|
|
function M.withSavedCursor(callback)
|
|
local cursor = vim.api.nvim_win_get_cursor(0)
|
|
callback()
|
|
vim.api.nvim_win_set_cursor(0, cursor)
|
|
end
|
|
-- }}}
|
|
-- {{{ Fixup lazy spec generated by nix
|
|
function M.prepareLazySpec(spec)
|
|
for _, module in ipairs(spec) do
|
|
if module.package ~= nil then
|
|
module[1] = module.package
|
|
module.package = nil
|
|
end
|
|
|
|
local configType = type(module.config)
|
|
if configType == "function" or configType == "table" then
|
|
local previousConfig = module.config
|
|
module.config = function(lazy, opts)
|
|
M.configure(previousConfig, { lazy = lazy, opts = opts })
|
|
end
|
|
end
|
|
|
|
local initType = type(module.init)
|
|
if initType == "function" or initType == "table" then
|
|
local previousInit = module.init
|
|
module.init = function(lazy, opts)
|
|
M.configure(previousInit, { lazy = lazy, opts = opts })
|
|
end
|
|
end
|
|
|
|
if module.keys ~= nil then
|
|
if type(module.keys) == "string" or module.keys.mapping ~= nil then
|
|
module.keys = { module.keys }
|
|
end
|
|
|
|
for _, key in ipairs(module.keys) do
|
|
if type(key) ~= "string" then
|
|
key[1] = key.mapping
|
|
key.mapping = nil
|
|
if key.mode ~= nil then
|
|
key.mode = H.string_chars(key.mode)
|
|
end
|
|
if key.action ~= nil then
|
|
key[2] = key.action
|
|
key.action = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if type(module.cond) == "table" then
|
|
local final = true
|
|
for _, cond in ipairs(module.cond) do
|
|
final = final and cond
|
|
end
|
|
module.cond = final
|
|
end
|
|
end
|
|
end
|
|
-- }}}
|
|
-- {{{ Theming
|
|
local theme = vim.g.nix_theme
|
|
|
|
M.theme = theme
|
|
|
|
function M.theme_contains(name)
|
|
return string.find(theme.name, name) ~= nil
|
|
end
|
|
|
|
function M.theme_variant(name)
|
|
-- +1 for 1-indexed strings and +1 for the space between name and variant
|
|
return string.lower(string.sub(theme.name, string.len(name) + 2))
|
|
end
|
|
-- }}}
|
|
|
|
return M
|