Skip to content

Commit

Permalink
Extend overseer.nvim, minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Jendker committed Aug 4, 2024
1 parent a4213c1 commit 7a19746
Show file tree
Hide file tree
Showing 10 changed files with 523 additions and 16 deletions.
1 change: 1 addition & 0 deletions nvim/lua/debugging.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ return {
virt_text_pos = 'eol',
},
},
"stevearc/overseer.nvim",
},
keys = {
{ '<F5>', function() require('dap').continue() end, desc = 'Debug: Start/Continue' },
Expand Down
279 changes: 279 additions & 0 deletions nvim/lua/ftplugin.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
---@class FiletypeConfig
---@field abbr? table<string, string> Insert-mode abbreviations
---@field keys? table Buffer-local keymaps
---@field bufvar? table<string, any> Buffer-local variables
---@field callback? fun(bufnr: integer)
---@field opt? table<string, any> Buffer-local or window-local options
---@field compiler? string

local did_setup = false
local M = {}

local function validate_keys(keys)
if not keys then
return
end
vim.validate({
bindings = { keys, "t" },
})
for _, v in ipairs(keys) do
if type(v) ~= "table" then
error("ftplugin keys must be an array of arrays")
end
end
end

---@type table<string, FiletypeConfig>
local configs = {}

---Set the config for a filetype
---@param name string
---@param config FiletypeConfig
M.set = function(name, config)
validate_keys(config.keys)
configs[name] = config
end

---Get a filetype config
---@param name string
---@return FiletypeConfig|nil
M.get = function(name)
return configs[name]
end

local function merge_callbacks(fn1, fn2)
if not fn1 and not fn2 then
return nil
end
if fn1 then
if fn2 then
return function(...)
fn1(...)
fn2(...)
end
else
return fn1
end
else
return fn2
end
end

local function merge_keys(k1, k2)
if not k1 then
return k2
elseif not k2 then
return k1
end
local ret = vim.list_extend({}, k1)
return vim.list_extend(ret, k2)
end

local function coalesce(v1, v2)
if v1 == nil then
return v2
else
return v1
end
end

M.reapply_all_bufs = function()
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
M.apply(vim.bo[bufnr].filetype, bufnr)
end
end

---Extend the configuration for a filetype, overriding values that conflict
---@param name string
---@param new_config FiletypeConfig
M.extend = function(name, new_config)
validate_keys(new_config.keys)
local conf = configs[name] or {}
conf.abbr = vim.tbl_deep_extend("force", conf.abbr or {}, new_config.abbr or {})
conf.opt = vim.tbl_deep_extend("force", conf.opt or {}, new_config.opt or {})
conf.bufvar = vim.tbl_deep_extend("force", conf.bufvar or {}, new_config.bufvar or {})
conf.callback = merge_callbacks(conf.callback, new_config.callback)
conf.keys = merge_keys(conf.keys, new_config.keys)
conf.compiler = coalesce(new_config.compiler, conf.compiler)
configs[name] = conf
if did_setup then
M.reapply_all_bufs()
end
end

---Set many configs all at once
---@param confs table<string, FiletypeConfig>
M.set_all = function(confs)
for k, v in pairs(confs) do
M.set(k, v)
end
end

---Extend many configs all at once
---@param confs table<string, FiletypeConfig>
M.extend_all = function(confs)
for k, v in pairs(confs) do
M.extend(k, v)
end
end

---@param name string
---@param winid integer
local function _apply_win(name, winid)
local conf = configs[name]
if not conf or not conf.opt then
return
end
for k, v in pairs(conf.opt) do
local opt_info = vim.api.nvim_get_option_info2(k, {})
if opt_info.scope == "win" then
local ok, err = pcall(vim.api.nvim_set_option_value, k, v, { scope = "local", win = winid })
if not ok then
vim.notify(
string.format("Error setting window option %s = %s: %s", k, vim.inspect(v), err),
vim.log.levels.ERROR
)
end
end
end
end

---Apply window options
---@param name string
---@param winid integer
M.apply_win = function(name, winid)
local pieces = vim.split(name, ".", { plain = true })
if #pieces > 1 then
for _, ft in ipairs(pieces) do
_apply_win(ft, winid)
end
else
_apply_win(name, winid)
end
end

---Apply all filetype configs for a buffer
---@param name string
---@param bufnr integer
M.apply = function(name, bufnr)
local pieces = vim.split(name, ".", { plain = true })
if #pieces > 1 then
for _, ft in ipairs(pieces) do
M.apply(ft, bufnr)
end
return
end
local conf = configs[name]
if not conf then
return
end
if conf.abbr then
vim.api.nvim_buf_call(bufnr, function()
for k, v in pairs(conf.abbr) do
vim.cmd(string.format("iabbrev <buffer> %s %s", k, v))
end
end)
end
if conf.compiler then
vim.api.nvim_buf_call(bufnr, function()
vim.cmd.compiler({ args = { conf.compiler } })
end)
end
if conf.opt then
for k, v in pairs(conf.opt) do
local opt_info = vim.api.nvim_get_option_info2(k, {})
if opt_info.scope == "buf" then
local ok, err = pcall(vim.api.nvim_set_option_value, k, v, { buf = bufnr })
if not ok then
vim.notify(
string.format("Error setting buffer option %s = %s: %s", k, vim.inspect(v), err),
vim.log.levels.ERROR
)
end
end
end
local winids = vim.tbl_filter(function(win)
return vim.api.nvim_win_get_buf(win) == bufnr
end, vim.api.nvim_list_wins())
for _, winid in ipairs(winids) do
M.apply_win(name, winid)
end
end
if conf.bufvar then
for k, v in pairs(conf.bufvar) do
vim.api.nvim_buf_set_var(bufnr, k, v)
end
end
if conf.keys then
for _, defn in ipairs(conf.keys) do
local mode = defn.mode or "n"
local lhs = defn[1]
local rhs = defn[2]
vim.keymap.set(mode, lhs, rhs, {
buffer = bufnr,
desc = defn.desc,
remap = defn.remap,
replace_keycodes = defn.replace_keycodes,
nowait = defn.nowait,
})
end
end
if conf.callback then
conf.callback(bufnr)
end
end

---@class FiletypeOpts
---@field augroup? string|integer Autogroup to use when creating the autocmds

---Create autocommands that will apply the configs
---@param opts? FiletypeOpts
M.setup = function(opts)
local conf = vim.tbl_deep_extend("keep", opts or {}, {
augroup = nil,
})
if not conf.augroup then
conf.augroup = vim.api.nvim_create_augroup("FiletypePlugin", {})
end

vim.api.nvim_create_autocmd("FileType", {
desc = "Set filetype-specific options",
pattern = "*",
group = conf.augroup,
callback = function(params)
M.apply(params.match, params.buf)
end,
})
vim.api.nvim_create_autocmd("BufWinEnter", {
desc = "Set filetype-specific window options",
pattern = "*",
group = conf.augroup,
callback = function(params)
local winid = vim.api.nvim_get_current_win()
local bufnr = vim.api.nvim_win_get_buf(winid)
local filetype = vim.bo[bufnr].filetype
-- If we're in a terminal buffer, make the filetype "terminal"
if vim.bo[bufnr].buftype == "terminal" then
filetype = "terminal"
end
M.apply_win(filetype, winid)
end,
})
vim.api.nvim_create_autocmd("TermEnter", {
desc = "Set terminal-specific options",
pattern = "*",
group = conf.augroup,
callback = function(params)
local winid = vim.api.nvim_get_current_win()
local bufnr = vim.api.nvim_win_get_buf(winid)
if vim.bo[bufnr].buftype ~= "terminal" then
return
end
M.apply("terminal", bufnr)
M.apply_win("terminal", winid)
end,
})
did_setup = true
end

return M
27 changes: 27 additions & 0 deletions nvim/lua/overseer/template/user/populate_scripts.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local files = require("overseer.files")

return {
generator = function(opts, cb)
vim.notify(opts.dir)
local scripts = vim.tbl_filter(function(filename)
return filename:match("%.sh$")
end, files.list_files(opts.dir))
local ret = {}
for _, filename in ipairs(scripts) do
table.insert(ret, {
name = filename,
params = {
args = { optional = true, type = "list", delimiter = " " },
},
builder = function(params)
return {
cmd = { files.join(opts.dir, filename) },
args = params.args,
}
end,
})
end

cb(ret)
end,
}
21 changes: 21 additions & 0 deletions nvim/lua/overseer/template/user/run_script.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
return {
name = "run script",
builder = function()
local file = vim.fn.expand("%:p")
local cmd = { file }
if vim.bo.filetype == "go" then
cmd = { "go", "run", file }
end
return {
cmd = cmd,
components = {
{ "on_output_quickfix", set_diagnostics = true },
"on_result_diagnostics",
"default",
},
}
end,
condition = {
filetype = { "sh", "python", "go" },
},
}
25 changes: 25 additions & 0 deletions nvim/lua/overseer/template/user/run_script_with_args.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
return {
name = "run script with args",
params = {
args = { type = "string", order = 1 },
},
builder = function(params)
local file = vim.fn.expand("%:p")
local cmd = table.concat({ vim.bo.filetype, file, params.args }, " ")
if vim.bo.filetype == "go" then
cmd = table.concat({ "go", "run", file, params.args }, " ")
end
vim.notify(cmd)
return {
cmd = cmd,
components = {
{ "on_output_quickfix", set_diagnostics = true },
"on_result_diagnostics",
"default",
},
}
end,
condition = {
filetype = { "sh", "python", "go" },
},
}
Loading

0 comments on commit 7a19746

Please sign in to comment.