Files
dotfiles/.config/nvim/lua/c/utils.lua
2025-08-25 18:23:54 -05:00

88 lines
2.5 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- lua/c/utils.lua
local M = {}
-- Find the project root (same markers clangd likes)
local function project_root(buf)
return vim.fs.root(buf or 0, { "compile_commands.json", ".git", "Makefile", "makefile" })
end
local function relpath(abs, root)
if not abs or not root then return nil end
if abs:sub(1, #root) ~= root then return nil end
local r = abs:sub(#root + 1)
if r:sub(1, 1) == "/" then r = r:sub(2) end
return r
end
local function dirpart(p) return p:match("^(.*)/") end
-- Build the alternate path (header <-> source), preserving nested subdirs
local function alternate_rel(rel)
local first = rel:match("^([^/]+)/")
local ext = rel:match("%.([^.]+)$") or ""
local rest = rel:gsub("^" .. (first or "") .. "/", "")
if first == "include" and ext == "h" then
return "src/" .. rest:gsub("%.h$", ".c")
elseif first == "src" and ext == "c" then
return "include/" .. rest:gsub("%.c$", ".h")
end
-- Fallbacks if file isnt directly under include/ or src/
if ext == "h" then
return ("src/" .. rel):gsub("^src/include/", "src/"):gsub("%.h$", ".c")
elseif ext == "c" then
return ("include/" .. rel):gsub("^include/src/", "include/"):gsub("%.c$", ".h")
end
return nil
end
function M.toggle_header_source()
local buf = 0
local abs = vim.api.nvim_buf_get_name(buf)
if abs == "" then
vim.notify("No file name (unsaved buffer).", vim.log.levels.WARN)
return
end
local root = project_root(buf)
if not root then
vim.notify("Couldnt locate project root (no .git/Makefile/compile_commands.json).", vim.log.levels.WARN)
return
end
local rel = relpath(abs, root)
if not rel then
vim.notify("File not under project root: " .. abs, vim.log.levels.WARN)
return
end
local alt_rel = alternate_rel(rel)
if not alt_rel then
vim.notify("Not a .c/.h under include/ or src/: " .. rel, vim.log.levels.WARN)
return
end
local alt_abs = root .. "/" .. alt_rel
if vim.loop.fs_stat(alt_abs) then
vim.cmd.edit(vim.fn.fnameescape(alt_abs))
return
end
-- Prompt to create
local choice = vim.fn.confirm(("Create %s?\n\n%s"):format(alt_rel, alt_abs), "&Yes\n&No", 2)
if choice ~= 1 then return end
-- Ensure dirs exist, then open the new file (unsaved until you write)
local dir = dirpart(alt_abs)
if dir and not vim.loop.fs_stat(dir) then
vim.fn.mkdir(dir, "p")
end
vim.cmd.edit(vim.fn.fnameescape(alt_abs))
-- Optional: write an empty file immediately. Comment out if you prefer unsaved buffer.
-- vim.cmd.write()
end
return M