Add lazy loading for all plugins

- Create lua/lazy.lua helper with load/on_event/on_keys
- Rewrite pack.lua: lazy load all mini modules + fugitive
- Defer treesitter.install() with vim.defer_fn
- Defer mason + LSP config to VimEnter
- Move mini.pick keymaps from keymaps.lua to pack.lua
- Keep mini.notify and mini.cmdline eager (startup needed)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-28 11:04:08 +08:00
parent a45929aff6
commit 077ec08dc1
5 changed files with 283 additions and 207 deletions

View File

@ -2,8 +2,7 @@ vim.g.mapleader = " "
local map = vim.keymap.set
map("x", "p", [["_dP]], { desc = "Paste over selection without losing yanked text" })
-- map({ "n", "v" }, "<leader>d", [["_d]], { desc = "Delete without yanking" })
map("x", "p", [[_dP]], { desc = "Paste over selection without losing yanked text" })
map("n", "<Esc>", ":nohl<CR>", { desc = "Clear search highlighting", silent = true })
@ -14,7 +13,6 @@ map("n", "J", "mzJ`z", { desc = "Join lines without moving cursor" })
map("n", "<leader>ss", [[:%s/\<<C-r><C-w>\>/<C-r><C-w>/gI<Left><Left><Left>]],
{ desc = "Replace word cursor is on globally" })
-- search
map("v", "<leader>ss", ":s/\\%V", { desc = "Search and replace in visual selection" })
-- general
@ -38,7 +36,6 @@ map("n", "<leader>tn", ":tabnew<CR>", { desc = "New tab" })
map("n", "<leader>]", ":tabnext<CR>", { desc = "Next tab" })
map("n", "<leader>[", ":tabprevious<CR>", { desc = "Previous tab" })
-- yank path
map("n", "<leader>yp", function()
local path = vim.fn.expand("%")
@ -84,71 +81,3 @@ map("n", "<leader>bo", function()
end
end
end, { desc = "Close other buffers" })
-- mini.pick buffer picker (telescope buffers equivalent)
map("n", "<leader><leader>", function()
local MiniPick = require("mini.pick")
local delete_buf = function()
local matches = MiniPick.get_picker_matches()
local item = matches and matches.current
if not item or not item.bufnr then return end
local bufnr = item.bufnr
-- 先删除 bufferpcall 保护,避免删除当前窗口 buffer 时出错)
pcall(vim.api.nvim_buf_delete, bufnr, { force = true })
-- 刷新列表:只保留仍然有效的 buffer
if MiniPick.is_picker_active() then
local items = vim.tbl_filter(function(i)
return i.bufnr and vim.api.nvim_buf_is_valid(i.bufnr)
end, MiniPick.get_picker_items() or {})
MiniPick.set_picker_items(items)
end
end
-- 收集所有 buffer过滤特殊类型和未列出的按最近使用排序
local bufs = vim.tbl_filter(function(b)
return vim.bo[b.bufnr].buftype == "" and b.listed == 1
end, vim.fn.getbufinfo())
table.sort(bufs, function(a, b)
return a.lastused > b.lastused
end)
local items = {}
for _, info in ipairs(bufs) do
local name = info.name ~= "" and vim.fn.fnamemodify(info.name, ":.") or "[No Name]"
table.insert(items, {
text = name,
bufnr = info.bufnr,
})
end
MiniPick.start({
source = {
name = "Buffers",
items = items,
show = function(buf_id, items_arr, query)
MiniPick.default_show(buf_id, items_arr, query, { show_icons = true })
end,
},
mappings = {
delete_buffer = { char = "<C-d>", func = delete_buf },
},
})
end, { desc = "Buffers" })
-- mini.pick filetype picker
map("n", "<leader>ft", function()
local MiniPick = require("mini.pick")
local filetypes = vim.fn.getcompletion("", "filetype")
MiniPick.start({
source = {
name = "Filetypes",
items = filetypes,
choose = function(item)
vim.bo.filetype = item
end,
},
})
end, { desc = "Change filetype" })

34
lua/lazy.lua Normal file
View File

@ -0,0 +1,34 @@
local M = {}
M._loaded = {}
M.load = function(name, fn)
if M._loaded[name] then
return
end
M._loaded[name] = true
fn()
end
M.on_event = function(name, event, pattern, fn)
vim.api.nvim_create_autocmd(event, {
pattern = pattern or "*",
once = true,
callback = function()
M.load(name, fn)
end,
})
end
M.on_keys = function(name, keys, mode, fn, action, opts)
mode = mode or "n"
opts = opts or {}
vim.keymap.set(mode, keys, function()
M.load(name, fn)
if action then
action()
end
end, { desc = opts.desc, buffer = opts.buffer })
end
return M

View File

@ -1,7 +1,39 @@
require("mason").setup()
local lazy = require("lazy")
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { desc = "Go to definition" })
vim.keymap.set('n', 'gh', vim.lsp.buf.hover, { desc = "Hover" })
-- mason + LSP 配置延迟到 VimEnter避免启动时加载
lazy.on_event("lsp", "VimEnter", "*", function()
require("mason").setup()
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = vim.tbl_deep_extend("force", capabilities, require("mini.completion").get_lsp_capabilities())
vim.lsp.config("*", { capabilities = capabilities })
vim.lsp.config("lua_ls", {
settings = {
Lua = {
diagnostics = { globals = { "vim" } },
},
},
})
vim.lsp.enable({
"html",
"cssls",
"gopls",
"vtsls",
"rust_analyzer",
"lua_ls",
"taplo",
"svelte",
"dartls",
"kotlin_lsp",
})
end)
-- LSP keymaps
vim.keymap.set("n", "gd", vim.lsp.buf.definition, { desc = "Go to definition" })
vim.keymap.set("n", "gh", vim.lsp.buf.hover, { desc = "Hover" })
vim.keymap.set("n", "<leader>fm", vim.lsp.buf.format, { desc = "Format Local buffer" })
vim.keymap.set("n", "df", vim.diagnostic.open_float, { desc = "Show line diagnostics" })
vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, { desc = "Code action" })
@ -24,29 +56,3 @@ vim.keymap.set("n", "]w", diagnostic_goto(true, "WARN"), { desc = "Next Warning"
vim.keymap.set("n", "[w", diagnostic_goto(false, "WARN"), { desc = "Prev Warning" })
vim.diagnostic.config({ virtual_text = true })
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = vim.tbl_deep_extend("force", capabilities, require("mini.completion").get_lsp_capabilities())
vim.lsp.config("*", { capabilities = capabilities })
vim.lsp.config("lua_ls", {
settings = {
Lua = {
diagnostics = { globals = { "vim" } },
},
},
})
vim.lsp.enable({
"html",
"cssls",
"gopls",
"vtsls",
"rust_analyzer",
"lua_ls",
"taplo",
"svelte",
"dartls",
"kotlin_lsp"
})

View File

@ -1,3 +1,5 @@
local lazy = require("lazy")
vim.pack.add({
"https://github.com/nvim-mini/mini.nvim",
"https://github.com/rafamadriz/friendly-snippets",
@ -7,85 +9,187 @@ vim.pack.add({
"https://github.com/tpope/vim-fugitive",
})
-- mini files ----
local MiniFiles = require("mini.files")
MiniFiles.setup({
mappings = {
go_in = "<CR>",
go_in_plus = "L",
go_out = "_",
go_out_plus = "H",
},
})
-- mini.files - 按键触发
lazy.on_keys("files", "<leader>-", "n", function()
require("mini.files").setup({
mappings = {
go_in = "<CR>",
go_in_plus = "L",
go_out = "_",
go_out_plus = "H",
},
})
end, function()
require("mini.files").open()
end, { desc = "Toggle mini file explorer" })
vim.keymap.set("n", "<leader>-", "<cmd>lua MiniFiles.open()<CR>", { desc = "Toggle mini file explorer" })
vim.keymap.set("n", "-", function()
lazy.on_keys("files", "-", "n", function()
require("mini.files").setup({
mappings = {
go_in = "<CR>",
go_in_plus = "L",
go_out = "_",
go_out_plus = "H",
},
})
end, function()
local MiniFiles = require("mini.files")
MiniFiles.open(vim.api.nvim_buf_get_name(0), false)
MiniFiles.reveal_cwd()
end, { desc = "Toggle into currently opened file" })
---- mini notify ----
require("mini.notify").setup({
-- only show messages
content = {
format = function(notif)
return notif.msg
end,
},
})
-- mini.notify - 启动时加载
lazy.load("notify", function()
require("mini.notify").setup({
content = {
format = function(notif)
return notif.msg
end,
},
})
end)
--- mini cmdline completion ---
require("mini.cmdline").setup({
autocorrect = { enable = false }
})
-- mini.cmdline - 启动时加载
lazy.load("cmdline", function()
require("mini.cmdline").setup({
autocorrect = { enable = false },
})
end)
--- mini surround ---
require("mini.surround").setup()
-- Default Keymaps
-- | `sa` | Add surrounding or Direct with 'saiw' |
-- | `sd` | Delete surrounding |
-- | `sr` | Replace surrounding |
-- | `sf` | Find surrounding (right) |
-- | `sF` | Find surrounding (left) |
-- | `sh` | Highlight surrounding |
-- | `sn` | Update n_lines |
-- | `l` / `n` | as suffix for prev/next |
-- mini.surround - BufReadPost
lazy.on_event("surround", "BufReadPost", "*", function()
require("mini.surround").setup()
end)
--- mini picker ---
local MiniPick = require("mini.pick")
local MiniExtra = require("mini.extra")
MiniPick.setup()
MiniExtra.setup()
-- mini.pick + mini.extra - 按键触发
local load_pick = function()
lazy.load("pick", function()
require("mini.pick").setup()
end)
lazy.load("extra", function()
require("mini.extra").setup()
end)
end
-- keymaps
vim.keymap.set("n", "<leader>ff", function() MiniPick.builtin.files() end, { desc = "Mini File Picker" })
vim.keymap.set("n", "<leader>fw", function() MiniPick.builtin.grep({ pattern = vim.fn.expand("<cword>") }) end, { desc = "Grep word/Search word" })
vim.keymap.set("n", "<leader>vh", function() MiniPick.builtin.help() end, { desc = "Mini Help" })
lazy.on_keys("pick", "<leader>ff", "n", load_pick, function()
require("mini.pick").builtin.files()
end, { desc = "Mini File Picker" })
vim.keymap.set("n", "<leader>ds", function() MiniExtra.pickers.diagnostic() end, { desc = "Mini Picker Diagnostics" })
vim.keymap.set("n", "<leader>sk", function() MiniExtra.pickers.keymaps() end, { desc = 'Search keymaps' })
lazy.on_keys("pick", "<leader>fw", "n", load_pick, function()
require("mini.pick").builtin.grep({ pattern = vim.fn.expand("<cword>") })
end, { desc = "Grep word/Search word" })
--- mini completions ---
require("mini.completion").setup({
lsp_completion = {
auto_setup = true,
}
})
lazy.on_keys("pick", "<leader>vh", "n", load_pick, function()
require("mini.pick").builtin.help()
end, { desc = "Mini Help" })
--- mini snippets ---
local MiniSnippets = require("mini.snippets")
MiniSnippets.setup({
snippets = {
MiniSnippets.gen_loader.from_lang(), -- loads friendly-snippets
},
})
MiniSnippets.start_lsp_server({ match = false })
lazy.on_keys("pick", "<leader>ds", "n", load_pick, function()
require("mini.extra").pickers.diagnostic()
end, { desc = "Mini Picker Diagnostics" })
--- mini diff and fugitive ---
local MiniDiff = require("mini.diff")
MiniDiff.setup({
source = MiniDiff.gen_source.git({ index = false }),
})
lazy.on_keys("pick", "<leader>sk", "n", load_pick, function()
require("mini.extra").pickers.keymaps()
end, { desc = "Search keymaps" })
vim.keymap.set("n", "<leader>gg", "<cmd>tabnew | Git | only<cr>", { desc = "Fugitive Full Page New Tab" })
vim.keymap.set("n", "<leader>gd", "<cmd>Gvdiffsplit<CR>", { desc = "Git diff split", })
-- mini.completion - InsertEnter
lazy.on_event("completion", "InsertEnter", "*", function()
require("mini.completion").setup({
lsp_completion = {
auto_setup = true,
},
})
end)
-- mini.snippets - InsertEnter
lazy.on_event("snippets", "InsertEnter", "*", function()
local MiniSnippets = require("mini.snippets")
MiniSnippets.setup({
snippets = {
MiniSnippets.gen_loader.from_lang(),
},
})
MiniSnippets.start_lsp_server({ match = false })
end)
-- mini.diff - BufReadPost
lazy.on_event("diff", "BufReadPost", "*", function()
require("mini.diff").setup({
source = require("mini.diff").gen_source.git({ index = false }),
})
end)
-- vim-fugitive - 按键触发
lazy.on_keys("fugitive", "<leader>gg", "n", nil, function()
vim.cmd("tabnew | Git | only")
end, { desc = "Fugitive Full Page New Tab" })
lazy.on_keys("fugitive", "<leader>gd", "n", nil, function()
vim.cmd("Gvdiffsplit")
end, { desc = "Git diff split" })
-- mini.pick buffer picker (telescope buffers equivalent)
lazy.on_keys("pick", "<leader><leader>", "n", load_pick, function()
local MiniPick = require("mini.pick")
local delete_buf = function()
local matches = MiniPick.get_picker_matches()
local item = matches and matches.current
if not item or not item.bufnr then
return
end
local bufnr = item.bufnr
pcall(vim.api.nvim_buf_delete, bufnr, { force = true })
if MiniPick.is_picker_active() then
local items = vim.tbl_filter(function(i)
return i.bufnr and vim.api.nvim_buf_is_valid(i.bufnr)
end, MiniPick.get_picker_items() or {})
MiniPick.set_picker_items(items)
end
end
local bufs = vim.tbl_filter(function(b)
return vim.bo[b.bufnr].buftype == "" and b.listed == 1
end, vim.fn.getbufinfo())
table.sort(bufs, function(a, b)
return a.lastused > b.lastused
end)
local items = {}
for _, info in ipairs(bufs) do
local name = info.name ~= "" and vim.fn.fnamemodify(info.name, ":.") or "[No Name]"
table.insert(items, {
text = name,
bufnr = info.bufnr,
})
end
MiniPick.start({
source = {
name = "Buffers",
items = items,
show = function(buf_id, items_arr, query)
MiniPick.default_show(buf_id, items_arr, query, { show_icons = true })
end,
},
mappings = {
delete_buffer = { char = "<C-d>", func = delete_buf },
},
})
end, { desc = "Buffers" })
-- mini.pick filetype picker
lazy.on_keys("pick", "<leader>ft", "n", load_pick, function()
local MiniPick = require("mini.pick")
local filetypes = vim.fn.getcompletion("", "filetype")
MiniPick.start({
source = {
name = "Filetypes",
items = filetypes,
choose = function(item)
vim.bo.filetype = item
end,
},
})
end, { desc = "Change filetype" })

View File

@ -1,49 +1,52 @@
local treesitter = require("nvim-treesitter")
local ensure_installed = {
"lua",
"vim",
"vimdoc",
-- Web
"javascript",
"typescript",
"tsx",
"jsdoc",
"json",
"html",
"css",
"yaml",
-- Backend
"c",
"rust",
"toml",
"go",
"gomod",
"gosum",
"gowork",
-- Infra
"dockerfile",
"make",
"lua",
"vim",
"vimdoc",
-- Web
"javascript",
"typescript",
"tsx",
"jsdoc",
"json",
"html",
"css",
"yaml",
-- Backend
"c",
"rust",
"toml",
"go",
"gomod",
"gosum",
"gowork",
-- Infra
"dockerfile",
"make",
}
treesitter.install(ensure_installed)
-- 延迟安装 parser避免启动时阻塞
vim.defer_fn(function()
treesitter.install(ensure_installed)
end, 100)
vim.api.nvim_create_autocmd("FileType", {
pattern = "*",
callback = function(args)
local buf = args.buf
local ft = vim.bo[buf].filetype
pattern = "*",
callback = function(args)
local buf = args.buf
local ft = vim.bo[buf].filetype
local lang = vim.treesitter.language.get_lang(ft)
if not lang then
return
end
local lang = vim.treesitter.language.get_lang(ft)
if not lang then
return
end
local ok_add = pcall(vim.treesitter.language.add, lang)
if not ok_add then
return
end
local ok_add = pcall(vim.treesitter.language.add, lang)
if not ok_add then
return
end
pcall(vim.treesitter.start, buf, lang)
end,
pcall(vim.treesitter.start, buf, lang)
end,
})