Files
nvim/lua/config/templates.lua
T

76 lines
2.9 KiB
Lua

--- Snacks picker frontend for template.nvim (<C-f>t).
---
--- <CR>: insert the template at the cursor when the current buffer is a
--- named file whose filetype matches the template's; otherwise fall through
--- to the new-file flow. <C-n>: always prompt (snacks.input) for a new file
--- to create in the cwd and fill with the template.
---
--- template.nvim resolves templates by filetype + basename-without-extension
--- using Lua-pattern substring matching, so template file names must use
--- underscores only and never be substrings of one another.
--- @module config.templates
local M = {}
local function temp_dir() return vim.fs.normalize(require("template").temp_dir) end
local function tpl_name(item) return vim.fn.fnamemodify(item.file, ":t:r") end
--- Insert the template at the cursor of the current buffer.
local function insert(item) require("template"):generate_template { tpl_name(item) } end
--- Prompt for a filename, create it under cwd, and fill it with the template.
local function create(item)
local ext = vim.fn.fnamemodify(item.file, ":e")
require("snacks").input({
prompt = ("New .%s file (created in %s)"):format(ext, vim.fn.fnamemodify(vim.fn.getcwd(), ":~")),
}, function(value)
if not value or value == "" then return end
-- template.nvim detects the file argument by its extension
if not value:find("%.%w+$") then value = value .. "." .. ext end
-- template.nvim opens the file with bare uv.fs_open; make parents first
local parent = vim.fn.fnamemodify(vim.fn.getcwd() .. "/" .. value, ":h")
if vim.fn.isdirectory(parent) == 0 then vim.fn.mkdir(parent, "p") end
require("template"):generate_template { value, tpl_name(item) }
end)
end
--- Open the template picker.
function M.pick()
require "template" -- lazy-loads the plugin so temp_dir is configured
require("snacks").picker.files {
title = "Templates",
cwd = temp_dir(),
actions = {
template_new_file = function(picker, item)
picker:close()
if item then vim.schedule(function() create(item) end) end
end,
},
win = {
input = {
keys = { ["<c-n>"] = { "template_new_file", mode = { "n", "i" } } },
},
},
confirm = function(picker, item)
picker:close()
if not item then return end
-- defer past the picker teardown so the target window is current again
vim.schedule(function()
local buf = vim.api.nvim_get_current_buf()
local named = vim.api.nvim_buf_get_name(buf) ~= "" and vim.bo[buf].buftype == ""
local tpl_ft = vim.filetype.match { filename = vim.fs.joinpath(temp_dir(), item.file) }
-- template.nvim silently no-ops on filetype mismatch, so route
-- non-matching buffers to the new-file flow instead
if named and vim.bo[buf].filetype == tpl_ft then
insert(item)
else
create(item)
end
end)
end,
}
end
return M