Unify indentation to tabs and add keymaps/pickers

- Convert 4-space indentation to tabs across all lua files
- Add <C-s> save file and <C-c> copy whole file keymaps
- Add mini.pick keymaps: <leader>fa (find all), <leader>fh (help),
  <leader>fo (oldfiles), <leader>fz (buffer lines)
- Change <leader>fw to grep_live, <leader>vh to <leader>fh
- Fix conform lazy-loading buffer reference

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-28 11:36:26 +08:00
parent a282113ccf
commit 7c5529c400
4 changed files with 248 additions and 227 deletions

View File

@ -11,8 +11,12 @@ map("v", ">", ">gv", { desc = "Indent and keep selection" })
map("n", "J", "mzJ`z", { desc = "Join lines without moving cursor" }) 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>]], map(
{ desc = "Replace word cursor is on globally" }) "n",
"<leader>ss",
[[:%s/\<<C-r><C-w>\>/<C-r><C-w>/gI<Left><Left><Left>]],
{ desc = "Replace word cursor is on globally" }
)
map("v", "<leader>ss", ":s/\\%V", { desc = "Search and replace in visual selection" }) map("v", "<leader>ss", ":s/\\%V", { desc = "Search and replace in visual selection" })
-- general -- general
@ -23,10 +27,13 @@ map("v", "<", "<gv")
-- native undotree -- native undotree
vim.keymap.set("n", "<leader>u", function() vim.keymap.set("n", "<leader>u", function()
vim.cmd.packadd("nvim.undotree") vim.cmd.packadd("nvim.undotree")
require("undotree").open() require("undotree").open()
end, { desc = "Toggle Builtin Undotree" }) end, { desc = "Toggle Builtin Undotree" })
map("n", "<C-s>", "<cmd>w<CR>", { desc = "Save file" })
map("n", "<C-c>", "<cmd>%y+<CR>", { desc = "Copy whole file" })
map("t", "<C-x>", "<c-\\><c-n>", { desc = "Escape termainl" }) map("t", "<C-x>", "<c-\\><c-n>", { desc = "Escape termainl" })
map("n", "<leader>tt", ":term<CR>", { desc = "Open new terminal" }) map("n", "<leader>tt", ":term<CR>", { desc = "Open new terminal" })
@ -38,46 +45,46 @@ map("n", "<leader>[", ":tabprevious<CR>", { desc = "Previous tab" })
-- yank path -- yank path
map("n", "<leader>yp", function() map("n", "<leader>yp", function()
local path = vim.fn.expand("%") local path = vim.fn.expand("%")
vim.fn.setreg("+", path) vim.fn.setreg("+", path)
vim.notify("Copied relative path: " .. path, vim.log.levels.INFO) vim.notify("Copied relative path: " .. path, vim.log.levels.INFO)
end, { desc = "Yank relative file path" }) end, { desc = "Yank relative file path" })
map("n", "<leader>yP", function() map("n", "<leader>yP", function()
local path = vim.fn.expand("%:p") local path = vim.fn.expand("%:p")
vim.fn.setreg("+", path) vim.fn.setreg("+", path)
vim.notify("Copied absolute path: " .. path, vim.log.levels.INFO) vim.notify("Copied absolute path: " .. path, vim.log.levels.INFO)
end, { desc = "Yank absolute file path" }) end, { desc = "Yank absolute file path" })
-- buffer -- buffer
map("n", "<leader>x", function() map("n", "<leader>x", function()
local buf = vim.api.nvim_get_current_buf() local buf = vim.api.nvim_get_current_buf()
if vim.bo[buf].modified then if vim.bo[buf].modified then
vim.ui.select({ "Yes", "No" }, { vim.ui.select({ "Yes", "No" }, {
prompt = "Buffer has unsaved changes. Close without saving?", prompt = "Buffer has unsaved changes. Close without saving?",
format_item = function(item) format_item = function(item)
return item return item
end, end,
}, function(choice) }, function(choice)
if choice == "Yes" then if choice == "Yes" then
vim.api.nvim_buf_delete(buf, { force = true }) vim.api.nvim_buf_delete(buf, { force = true })
end end
end) end)
else else
vim.cmd.bdelete() vim.cmd.bdelete()
end end
end, { desc = "Close current buffer" }) end, { desc = "Close current buffer" })
map("n", "<leader>bn", "<cmd>enew<CR>", { desc = "Buffer new" }) map("n", "<leader>bn", "<cmd>enew<CR>", { desc = "Buffer new" })
map("n", "<leader>bo", function() map("n", "<leader>bo", function()
local current = vim.api.nvim_get_current_buf() local current = vim.api.nvim_get_current_buf()
local skipped_ft = { "NvimTree", "oil", "aerial" } local skipped_ft = { "NvimTree", "oil", "aerial" }
for _, buf in ipairs(vim.api.nvim_list_bufs()) do for _, buf in ipairs(vim.api.nvim_list_bufs()) do
if buf ~= current and vim.api.nvim_buf_is_loaded(buf) then if buf ~= current and vim.api.nvim_buf_is_loaded(buf) then
local ft = vim.bo[buf].filetype local ft = vim.bo[buf].filetype
if not vim.tbl_contains(skipped_ft, ft) then if not vim.tbl_contains(skipped_ft, ft) then
vim.api.nvim_buf_delete(buf, { force = true }) vim.api.nvim_buf_delete(buf, { force = true })
end end
end end
end end
end, { desc = "Close other buffers" }) end, { desc = "Close other buffers" })

View File

@ -2,93 +2,95 @@ local lazy = require("lazy")
-- conform.nvim - BufWritePre 懒加载 -- conform.nvim - BufWritePre 懒加载
local function setup_conform() local function setup_conform()
local function biome_or_prettier() local function biome_or_prettier()
if vim.fs.find({ "biome.json", "biome.jsonc" }, { upward = true, stop = vim.uv.os_homedir() })[1] then if vim.fs.find({ "biome.json", "biome.jsonc" }, { upward = true, stop = vim.uv.os_homedir() })[1] then
return { "biome-check", "biome", stop_after_first = true } return { "biome-check", "biome", stop_after_first = true }
end end
return { "prettier" } return { "prettier" }
end end
require("conform").setup({ require("conform").setup({
formatters_by_ft = { formatters_by_ft = {
lua = { "stylua" }, lua = { "stylua" },
go = { "gofumpt", "goimports" }, go = { "gofumpt", "goimports" },
javascript = biome_or_prettier, javascript = biome_or_prettier,
typescript = biome_or_prettier, typescript = biome_or_prettier,
javascriptreact = biome_or_prettier, javascriptreact = biome_or_prettier,
typescriptreact = biome_or_prettier, typescriptreact = biome_or_prettier,
json = biome_or_prettier, json = biome_or_prettier,
css = { "prettier" }, css = { "prettier" },
html = { "prettier" }, html = { "prettier" },
markdown = { "prettier" }, markdown = { "prettier" },
toml = { "taplo" }, toml = { "taplo" },
}, },
format_on_save = function(bufnr) format_on_save = function(bufnr)
if vim.b[bufnr].autoformat == false or vim.g.autoformat == false then if vim.b[bufnr].autoformat == false or vim.g.autoformat == false then
return nil return nil
end end
return { timeout_ms = 500, lsp_fallback = true } return { timeout_ms = 500, lsp_fallback = true }
end, end,
}) })
end end
lazy.on_event("conform", "BufWritePre", "*", function(args) lazy.on_event("conform", "BufWritePre", "*", function()
setup_conform() setup_conform()
-- 首次保存时手动触发格式化setup 注册的 autocmd 不会在同一次事件中生效) -- conform 的 setup 注册了 BufWritePre但新 autocmd 不会在同一次事件中触发
if vim.b[args.buf].autoformat ~= false and vim.g.autoformat ~= false then -- 所以这里手动调用 format 补偿第一次保存
require("conform").format({ bufnr = args.buf, timeout_ms = 500, lsp_fallback = true }) local bufnr = vim.api.nvim_get_current_buf()
end if vim.b[bufnr].autoformat ~= false and vim.g.autoformat ~= false then
require("conform").format({ bufnr = bufnr, timeout_ms = 500, lsp_fallback = true })
end
end) end)
-- mason + LSP 配置延迟到 VimEnter避免启动时加载 -- mason + LSP 配置延迟到 VimEnter避免启动时加载
lazy.on_event("lsp", "VimEnter", "*", function() lazy.on_event("lsp", "VimEnter", "*", function()
require("mason").setup() require("mason").setup()
local capabilities = vim.lsp.protocol.make_client_capabilities() local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = vim.tbl_deep_extend("force", capabilities, require("mini.completion").get_lsp_capabilities()) capabilities = vim.tbl_deep_extend("force", capabilities, require("mini.completion").get_lsp_capabilities())
vim.lsp.config("*", { capabilities = capabilities }) vim.lsp.config("*", { capabilities = capabilities })
vim.lsp.config("lua_ls", { vim.lsp.config("lua_ls", {
settings = { settings = {
Lua = { Lua = {
diagnostics = { globals = { "vim" } }, diagnostics = { globals = { "vim" } },
}, },
}, },
}) })
vim.lsp.enable({ vim.lsp.enable({
"html", "html",
"cssls", "cssls",
"gopls", "gopls",
"vtsls", "vtsls",
"rust_analyzer", "rust_analyzer",
"lua_ls", "lua_ls",
"taplo", "taplo",
"svelte", "svelte",
"dartls", "dartls",
"kotlin_lsp", "kotlin_lsp",
}) })
end) end)
-- LSP keymaps -- LSP keymaps
vim.keymap.set("n", "gd", vim.lsp.buf.definition, { desc = "Go to definition" }) 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", "gh", vim.lsp.buf.hover, { desc = "Hover" })
vim.keymap.set("n", "<leader>fm", function() vim.keymap.set("n", "<leader>fm", function()
lazy.load("conform", setup_conform) lazy.load("conform", setup_conform)
require("conform").format({ lsp_fallback = true }) require("conform").format({ lsp_fallback = true })
end, { desc = "Format buffer" }) end, { desc = "Format buffer" })
vim.keymap.set("n", "df", vim.diagnostic.open_float, { desc = "Show line diagnostics" }) 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" }) vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, { desc = "Code action" })
local diagnostic_goto = function(next, severity) local diagnostic_goto = function(next, severity)
return function() return function()
vim.diagnostic.jump({ vim.diagnostic.jump({
count = (next and 1 or -1) * vim.v.count1, count = (next and 1 or -1) * vim.v.count1,
severity = severity and vim.diagnostic.severity[severity] or nil, severity = severity and vim.diagnostic.severity[severity] or nil,
float = true, float = true,
}) })
end end
end end
vim.keymap.set("n", "]d", diagnostic_goto(true), { desc = "Next Diagnostic" }) vim.keymap.set("n", "]d", diagnostic_goto(true), { desc = "Next Diagnostic" })

View File

@ -38,10 +38,10 @@ vim.opt.signcolumn = "yes"
vim.opt.termguicolors = true vim.opt.termguicolors = true
vim.api.nvim_create_autocmd("TextYankPost", { vim.api.nvim_create_autocmd("TextYankPost", {
desc = "Highlight when yanking (copying) text", desc = "Highlight when yanking (copying) text",
callback = function() callback = function()
vim.hl.on_yank() vim.hl.on_yank()
end, end,
}) })
vim.opt.foldlevel = 99 -- 打开文件时默认展开所有折叠 vim.opt.foldlevel = 99 -- 打开文件时默认展开所有折叠

View File

@ -1,196 +1,208 @@
local lazy = require("lazy") local lazy = require("lazy")
vim.pack.add({ vim.pack.add({
"https://github.com/nvim-mini/mini.nvim", "https://github.com/nvim-mini/mini.nvim",
"https://github.com/rafamadriz/friendly-snippets", "https://github.com/rafamadriz/friendly-snippets",
{ src = "https://github.com/nvim-treesitter/nvim-treesitter", branch = "main" }, { src = "https://github.com/nvim-treesitter/nvim-treesitter", branch = "main" },
"https://github.com/neovim/nvim-lspconfig", "https://github.com/neovim/nvim-lspconfig",
"https://github.com/mason-org/mason.nvim", "https://github.com/mason-org/mason.nvim",
"https://github.com/stevearc/conform.nvim", "https://github.com/stevearc/conform.nvim",
"https://github.com/tpope/vim-fugitive", "https://github.com/tpope/vim-fugitive",
}) })
-- mini.files - 按键触发 -- mini.files - 按键触发
lazy.on_keys("files", "<leader>-", "n", function() lazy.on_keys("files", "<leader>-", "n", function()
require("mini.files").setup({ require("mini.files").setup({
mappings = { mappings = {
go_in = "<CR>", go_in = "<CR>",
go_in_plus = "L", go_in_plus = "L",
go_out = "_", go_out = "_",
go_out_plus = "H", go_out_plus = "H",
}, },
}) })
end, function() end, function()
require("mini.files").open() require("mini.files").open()
end, { desc = "Toggle mini file explorer" }) end, { desc = "Toggle mini file explorer" })
lazy.on_keys("files", "-", "n", function() lazy.on_keys("files", "-", "n", function()
require("mini.files").setup({ require("mini.files").setup({
mappings = { mappings = {
go_in = "<CR>", go_in = "<CR>",
go_in_plus = "L", go_in_plus = "L",
go_out = "_", go_out = "_",
go_out_plus = "H", go_out_plus = "H",
}, },
}) })
end, function() end, function()
local MiniFiles = require("mini.files") local MiniFiles = require("mini.files")
MiniFiles.open(vim.api.nvim_buf_get_name(0), false) MiniFiles.open(vim.api.nvim_buf_get_name(0), false)
MiniFiles.reveal_cwd() MiniFiles.reveal_cwd()
end, { desc = "Toggle into currently opened file" }) end, { desc = "Toggle into currently opened file" })
-- mini.notify - 启动时加载 -- mini.notify - 启动时加载
lazy.load("notify", function() lazy.load("notify", function()
require("mini.notify").setup({ require("mini.notify").setup({
content = { content = {
format = function(notif) format = function(notif)
return notif.msg return notif.msg
end, end,
}, },
}) })
end) end)
-- mini.cmdline - 启动时加载 -- mini.cmdline - 启动时加载
lazy.load("cmdline", function() lazy.load("cmdline", function()
require("mini.cmdline").setup({ require("mini.cmdline").setup({
autocorrect = { enable = false }, autocorrect = { enable = false },
}) })
end) end)
-- mini.surround - BufReadPost -- mini.surround - BufReadPost
lazy.on_event("surround", "BufReadPost", "*", function() lazy.on_event("surround", "BufReadPost", "*", function()
require("mini.surround").setup() require("mini.surround").setup()
end) end)
-- mini.pick + mini.extra - 按键触发 -- mini.pick + mini.extra - 按键触发
local load_pick = function() local load_pick = function()
lazy.load("pick", function() lazy.load("pick", function()
require("mini.pick").setup() require("mini.pick").setup()
end) end)
lazy.load("extra", function() lazy.load("extra", function()
require("mini.extra").setup() require("mini.extra").setup()
end) end)
end end
lazy.on_keys("pick", "<leader>ff", "n", load_pick, function() lazy.on_keys("pick", "<leader>ff", "n", load_pick, function()
require("mini.pick").builtin.files() require("mini.pick").builtin.files()
end, { desc = "Mini File Picker" }) end, { desc = "Mini File Picker" })
lazy.on_keys("pick", "<leader>fw", "n", load_pick, function() lazy.on_keys("pick", "<leader>fw", "n", load_pick, function()
require("mini.pick").builtin.grep({ pattern = vim.fn.expand("<cword>") }) require("mini.pick").builtin.grep_live()
end, { desc = "Grep word/Search word" }) end, { desc = "Live grep in project" })
lazy.on_keys("pick", "<leader>vh", "n", load_pick, function()
require("mini.pick").builtin.help()
end, { desc = "Mini Help" })
lazy.on_keys("pick", "<leader>ds", "n", load_pick, function() lazy.on_keys("pick", "<leader>ds", "n", load_pick, function()
require("mini.extra").pickers.diagnostic() require("mini.extra").pickers.diagnostic()
end, { desc = "Mini Picker Diagnostics" }) end, { desc = "Mini Picker Diagnostics" })
lazy.on_keys("pick", "<leader>sk", "n", load_pick, function() lazy.on_keys("pick", "<leader>sk", "n", load_pick, function()
require("mini.extra").pickers.keymaps() require("mini.extra").pickers.keymaps()
end, { desc = "Search keymaps" }) end, { desc = "Search keymaps" })
lazy.on_keys("pick", "<leader>fa", "n", load_pick, function()
require("mini.pick").builtin.cli({ command = { "rg", "--files", "--hidden", "--no-ignore", "--color=never" } })
end, { desc = "Find all files (including hidden/ignored)" })
lazy.on_keys("pick", "<leader>fh", "n", load_pick, function()
require("mini.pick").builtin.help()
end, { desc = "Search help tags" })
lazy.on_keys("pick", "<leader>fo", "n", load_pick, function()
require("mini.extra").pickers.oldfiles()
end, { desc = "Search oldfiles" })
lazy.on_keys("pick", "<leader>fz", "n", load_pick, function()
require("mini.extra").pickers.buf_lines({ scope = "current" })
end, { desc = "Search in current buffer" })
-- mini.completion - InsertEnter -- mini.completion - InsertEnter
lazy.on_event("completion", "InsertEnter", "*", function() lazy.on_event("completion", "InsertEnter", "*", function()
require("mini.completion").setup({ require("mini.completion").setup({
lsp_completion = { lsp_completion = {
auto_setup = true, auto_setup = true,
}, },
}) })
end) end)
-- mini.snippets - InsertEnter -- mini.snippets - InsertEnter
lazy.on_event("snippets", "InsertEnter", "*", function() lazy.on_event("snippets", "InsertEnter", "*", function()
local MiniSnippets = require("mini.snippets") local MiniSnippets = require("mini.snippets")
MiniSnippets.setup({ MiniSnippets.setup({
snippets = { snippets = {
MiniSnippets.gen_loader.from_lang(), MiniSnippets.gen_loader.from_lang(),
}, },
}) })
MiniSnippets.start_lsp_server({ match = false }) MiniSnippets.start_lsp_server({ match = false })
end) end)
-- mini.diff - BufReadPost -- mini.diff - BufReadPost
lazy.on_event("diff", "BufReadPost", "*", function() lazy.on_event("diff", "BufReadPost", "*", function()
require("mini.diff").setup({ require("mini.diff").setup({
source = require("mini.diff").gen_source.git({ index = false }), source = require("mini.diff").gen_source.git({ index = false }),
}) })
end) end)
-- vim-fugitive - 按键触发 -- vim-fugitive - 按键触发
lazy.on_keys("fugitive", "<leader>gg", "n", nil, function() lazy.on_keys("fugitive", "<leader>gg", "n", nil, function()
vim.cmd("tabnew | Git | only") vim.cmd("tabnew | Git | only")
end, { desc = "Fugitive Full Page New Tab" }) end, { desc = "Fugitive Full Page New Tab" })
lazy.on_keys("fugitive", "<leader>gd", "n", nil, function() lazy.on_keys("fugitive", "<leader>gd", "n", nil, function()
vim.cmd("Gvdiffsplit") vim.cmd("Gvdiffsplit")
end, { desc = "Git diff split" }) end, { desc = "Git diff split" })
-- mini.pick buffer picker (telescope buffers equivalent) -- mini.pick buffer picker (telescope buffers equivalent)
lazy.on_keys("pick", "<leader><leader>", "n", load_pick, function() lazy.on_keys("pick", "<leader><leader>", "n", load_pick, function()
local MiniPick = require("mini.pick") local MiniPick = require("mini.pick")
local delete_buf = function() local delete_buf = function()
local matches = MiniPick.get_picker_matches() local matches = MiniPick.get_picker_matches()
local item = matches and matches.current local item = matches and matches.current
if not item or not item.bufnr then if not item or not item.bufnr then
return return
end end
local bufnr = item.bufnr local bufnr = item.bufnr
pcall(vim.api.nvim_buf_delete, bufnr, { force = true }) pcall(vim.api.nvim_buf_delete, bufnr, { force = true })
if MiniPick.is_picker_active() then if MiniPick.is_picker_active() then
local items = vim.tbl_filter(function(i) local items = vim.tbl_filter(function(i)
return i.bufnr and vim.api.nvim_buf_is_valid(i.bufnr) return i.bufnr and vim.api.nvim_buf_is_valid(i.bufnr)
end, MiniPick.get_picker_items() or {}) end, MiniPick.get_picker_items() or {})
MiniPick.set_picker_items(items) MiniPick.set_picker_items(items)
end end
end end
local bufs = vim.tbl_filter(function(b) local bufs = vim.tbl_filter(function(b)
return vim.bo[b.bufnr].buftype == "" and b.listed == 1 return vim.bo[b.bufnr].buftype == "" and b.listed == 1
end, vim.fn.getbufinfo()) end, vim.fn.getbufinfo())
table.sort(bufs, function(a, b) table.sort(bufs, function(a, b)
return a.lastused > b.lastused return a.lastused > b.lastused
end) end)
local items = {} local items = {}
for _, info in ipairs(bufs) do for _, info in ipairs(bufs) do
local name = info.name ~= "" and vim.fn.fnamemodify(info.name, ":.") or "[No Name]" local name = info.name ~= "" and vim.fn.fnamemodify(info.name, ":.") or "[No Name]"
table.insert(items, { table.insert(items, {
text = name, text = name,
bufnr = info.bufnr, bufnr = info.bufnr,
}) })
end end
MiniPick.start({ MiniPick.start({
source = { source = {
name = "Buffers", name = "Buffers",
items = items, items = items,
show = function(buf_id, items_arr, query) show = function(buf_id, items_arr, query)
MiniPick.default_show(buf_id, items_arr, query, { show_icons = true }) MiniPick.default_show(buf_id, items_arr, query, { show_icons = true })
end, end,
}, },
mappings = { mappings = {
delete_buffer = { char = "<C-d>", func = delete_buf }, delete_buffer = { char = "<C-d>", func = delete_buf },
}, },
}) })
end, { desc = "Buffers" }) end, { desc = "Buffers" })
-- mini.pick filetype picker -- mini.pick filetype picker
lazy.on_keys("pick", "<leader>ft", "n", load_pick, function() lazy.on_keys("pick", "<leader>ft", "n", load_pick, function()
local MiniPick = require("mini.pick") local MiniPick = require("mini.pick")
local filetypes = vim.fn.getcompletion("", "filetype") local filetypes = vim.fn.getcompletion("", "filetype")
MiniPick.start({ MiniPick.start({
source = { source = {
name = "Filetypes", name = "Filetypes",
items = filetypes, items = filetypes,
choose = function(item) choose = function(item)
vim.bo.filetype = item vim.bo.filetype = item
end, end,
}, },
}) })
end, { desc = "Change filetype" }) end, { desc = "Change filetype" })