aboutsummaryrefslogtreecommitdiffstats
path: root/.claude/skills/nvim-plugin/examples/engine.lua
blob: 9297de8540a1b17b637e165cd2ef65e46e7a9c53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
--[[ Runner engine: run the current buffer's file with a per-filetype command.

Features register a shell command per filetype; the engine runs the current buffer's file with the
registered command and reports the result. Commands are registered in plugin/50-runner.lua.

API:
  register(filetype, cmd) — `cmd` is a command list; `%` in any argument expands to the current file
                            path. Call once per filetype.
  run()                   — run the current buffer with its filetype's command.
]]

local M = {}

-- Registered run commands, keyed by filetype.
M.runners = {}

-- Expand `%` in each argument of `cmd` to `file`, returning a new command list.
local function _expand(cmd, file)
	local out = {}
	for i, arg in ipairs(cmd) do
		out[i] = arg:gsub("%%", file)
	end
	return out
end

--- Register the run command `cmd` for `filetype`.
---@param filetype string
---@param cmd string[]
function M.register(filetype, cmd)
	assert(type(filetype) == "string", "runner.register: filetype must be a string")
	assert(type(cmd) == "table", "runner.register: cmd must be a command list")
	M.runners[filetype] = cmd
end

--- Run the current buffer's file, notifying on a missing command or a non-zero exit.
---@return nil
function M.run()
	local ft = vim.bo.filetype
	local cmd = M.runners[ft]
	if cmd == nil then
		vim.notify("No runner registered for " .. ft, vim.log.levels.ERROR)
		return
	end
	local file = vim.api.nvim_buf_get_name(0)
	-- Spawn the command and wait for it. See <nvim-help://vim.system%28%29>.
	local r = vim.system(_expand(cmd, file), { text = true }):wait()
	if r.code ~= 0 then
		vim.notify(r.stderr, vim.log.levels.WARN)
		return
	end
	vim.notify(r.stdout)
end

return M