summaryrefslogtreecommitdiffstats
path: root/lua/dotfiles/format.lua
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-06-24 21:24:54 +0200
committerThomas Vanbesien <tvanbesi@proton.me>2026-06-24 21:24:54 +0200
commitd5887f31a416034300a8675d8883d615b31ced83 (patch)
tree7c2b105a8a56ed4c2a9ca6b5d6e9b1b338934f77 /lua/dotfiles/format.lua
parentb0130288e93e00d5f37a5cf70bc8920216600aa7 (diff)
downloadnvim-config-d5887f31a416034300a8675d8883d615b31ced83.tar.gz
nvim-config-d5887f31a416034300a8675d8883d615b31ced83.zip
refactor(nvim): rewrite formatter plugin
Diffstat (limited to 'lua/dotfiles/format.lua')
-rw-r--r--lua/dotfiles/format.lua59
1 files changed, 59 insertions, 0 deletions
diff --git a/lua/dotfiles/format.lua b/lua/dotfiles/format.lua
new file mode 100644
index 0000000..72d0248
--- /dev/null
+++ b/lua/dotfiles/format.lua
@@ -0,0 +1,59 @@
+-- Format engine. Features register a stdin formatter command per filetype; the engine runs the
+-- registered formatter over the buffer on write, when formatting is enabled for it (vim.b.format,
+-- toggled by :FormatToggle). Formatters are registered in plugin/50-format.lua.
+--
+-- API:
+-- register(filetype, cmd) — `cmd` is a command list run with the buffer contents on stdin; its
+-- stdout replaces the buffer. Call once per filetype to share a command.
+
+local M = {}
+
+-- Registered formatter commands, keyed by filetype.
+M.formatters = {}
+
+-- Run `cmd` with `lines` piped on stdin; return its stdout as a list of lines, or nil on failure.
+local function run(cmd, lines)
+ local r = vim.system(cmd, { stdin = lines, text = true }):wait()
+ if r.code ~= 0 then
+ vim.notify(cmd[1] .. " error:\n" .. r.stderr, vim.log.levels.WARN)
+ return nil
+ end
+ return vim.split(r.stdout, "\n", { trimempty = true })
+end
+
+-- Register the stdin formatter command `cmd` for `filetype`.
+function M.register(filetype, cmd)
+ assert(type(filetype) == "string", "format.register: filetype must be a string")
+ assert(type(cmd) == "table", "format.register: cmd must be a command list")
+ M.formatters[filetype] = cmd
+end
+
+-- Format buffer `ev.buf` with its filetype's formatter when formatting is enabled for it.
+-- Meant as a 'BufWritePre' handler; preserves the cursor/window view across the rewrite.
+local function format_buffer(ev)
+ if vim.b[ev.buf].format ~= true then
+ return
+ end
+ local ft = vim.bo[ev.buf].filetype
+ local cmd = M.formatters[ft]
+ if not cmd then
+ vim.notify("No formatter registered for " .. ft, vim.log.levels.ERROR)
+ return
+ end
+ local lines_in = vim.api.nvim_buf_get_lines(ev.buf, 0, -1, false)
+ local lines_out = run(cmd, lines_in)
+ if not lines_out or vim.deep_equal(lines_in, lines_out) then
+ return
+ end
+ local view = vim.fn.winsaveview()
+ vim.api.nvim_buf_set_lines(ev.buf, 0, -1, false, lines_out)
+ vim.fn.winrestview(view)
+end
+
+vim.api.nvim_create_autocmd("BufWritePre", {
+ desc = "Format buffer",
+ group = vim.g.dotfiles.augroup,
+ callback = format_buffer,
+})
+
+return M