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

View File

@ -2,93 +2,95 @@ local lazy = require("lazy")
-- conform.nvim - BufWritePre 懒加载
local function setup_conform()
local function biome_or_prettier()
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 }
end
return { "prettier" }
end
local function biome_or_prettier()
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 }
end
return { "prettier" }
end
require("conform").setup({
formatters_by_ft = {
lua = { "stylua" },
go = { "gofumpt", "goimports" },
javascript = biome_or_prettier,
typescript = biome_or_prettier,
javascriptreact = biome_or_prettier,
typescriptreact = biome_or_prettier,
json = biome_or_prettier,
css = { "prettier" },
html = { "prettier" },
markdown = { "prettier" },
toml = { "taplo" },
},
format_on_save = function(bufnr)
if vim.b[bufnr].autoformat == false or vim.g.autoformat == false then
return nil
end
return { timeout_ms = 500, lsp_fallback = true }
end,
})
require("conform").setup({
formatters_by_ft = {
lua = { "stylua" },
go = { "gofumpt", "goimports" },
javascript = biome_or_prettier,
typescript = biome_or_prettier,
javascriptreact = biome_or_prettier,
typescriptreact = biome_or_prettier,
json = biome_or_prettier,
css = { "prettier" },
html = { "prettier" },
markdown = { "prettier" },
toml = { "taplo" },
},
format_on_save = function(bufnr)
if vim.b[bufnr].autoformat == false or vim.g.autoformat == false then
return nil
end
return { timeout_ms = 500, lsp_fallback = true }
end,
})
end
lazy.on_event("conform", "BufWritePre", "*", function(args)
setup_conform()
-- 首次保存时手动触发格式化setup 注册的 autocmd 不会在同一次事件中生效)
if vim.b[args.buf].autoformat ~= false and vim.g.autoformat ~= false then
require("conform").format({ bufnr = args.buf, timeout_ms = 500, lsp_fallback = true })
end
lazy.on_event("conform", "BufWritePre", "*", function()
setup_conform()
-- conform 的 setup 注册了 BufWritePre但新 autocmd 不会在同一次事件中触发
-- 所以这里手动调用 format 补偿第一次保存
local bufnr = vim.api.nvim_get_current_buf()
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)
-- mason + LSP 配置延迟到 VimEnter避免启动时加载
lazy.on_event("lsp", "VimEnter", "*", function()
require("mason").setup()
require("mason").setup()
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = vim.tbl_deep_extend("force", capabilities, require("mini.completion").get_lsp_capabilities())
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("*", { capabilities = capabilities })
vim.lsp.config("lua_ls", {
settings = {
Lua = {
diagnostics = { globals = { "vim" } },
},
},
})
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",
})
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", function()
lazy.load("conform", setup_conform)
require("conform").format({ lsp_fallback = true })
lazy.load("conform", setup_conform)
require("conform").format({ lsp_fallback = true })
end, { desc = "Format 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" })
local diagnostic_goto = function(next, severity)
return function()
vim.diagnostic.jump({
count = (next and 1 or -1) * vim.v.count1,
severity = severity and vim.diagnostic.severity[severity] or nil,
float = true,
})
end
return function()
vim.diagnostic.jump({
count = (next and 1 or -1) * vim.v.count1,
severity = severity and vim.diagnostic.severity[severity] or nil,
float = true,
})
end
end
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.api.nvim_create_autocmd("TextYankPost", {
desc = "Highlight when yanking (copying) text",
callback = function()
vim.hl.on_yank()
end,
desc = "Highlight when yanking (copying) text",
callback = function()
vim.hl.on_yank()
end,
})
vim.opt.foldlevel = 99 -- 打开文件时默认展开所有折叠

View File

@ -1,196 +1,208 @@
local lazy = require("lazy")
vim.pack.add({
"https://github.com/nvim-mini/mini.nvim",
"https://github.com/rafamadriz/friendly-snippets",
{ src = "https://github.com/nvim-treesitter/nvim-treesitter", branch = "main" },
"https://github.com/neovim/nvim-lspconfig",
"https://github.com/mason-org/mason.nvim",
"https://github.com/stevearc/conform.nvim",
"https://github.com/tpope/vim-fugitive",
"https://github.com/nvim-mini/mini.nvim",
"https://github.com/rafamadriz/friendly-snippets",
{ src = "https://github.com/nvim-treesitter/nvim-treesitter", branch = "main" },
"https://github.com/neovim/nvim-lspconfig",
"https://github.com/mason-org/mason.nvim",
"https://github.com/stevearc/conform.nvim",
"https://github.com/tpope/vim-fugitive",
})
-- 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",
},
})
require("mini.files").setup({
mappings = {
go_in = "<CR>",
go_in_plus = "L",
go_out = "_",
go_out_plus = "H",
},
})
end, function()
require("mini.files").open()
require("mini.files").open()
end, { desc = "Toggle mini file explorer" })
lazy.on_keys("files", "-", "n", function()
require("mini.files").setup({
mappings = {
go_in = "<CR>",
go_in_plus = "L",
go_out = "_",
go_out_plus = "H",
},
})
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()
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 - 启动时加载
lazy.load("notify", function()
require("mini.notify").setup({
content = {
format = function(notif)
return notif.msg
end,
},
})
require("mini.notify").setup({
content = {
format = function(notif)
return notif.msg
end,
},
})
end)
-- mini.cmdline - 启动时加载
lazy.load("cmdline", function()
require("mini.cmdline").setup({
autocorrect = { enable = false },
})
require("mini.cmdline").setup({
autocorrect = { enable = false },
})
end)
-- mini.surround - BufReadPost
lazy.on_event("surround", "BufReadPost", "*", function()
require("mini.surround").setup()
require("mini.surround").setup()
end)
-- 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)
lazy.load("pick", function()
require("mini.pick").setup()
end)
lazy.load("extra", function()
require("mini.extra").setup()
end)
end
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" })
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" })
lazy.on_keys("pick", "<leader>vh", "n", load_pick, function()
require("mini.pick").builtin.help()
end, { desc = "Mini Help" })
require("mini.pick").builtin.grep_live()
end, { desc = "Live grep in project" })
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" })
lazy.on_keys("pick", "<leader>sk", "n", load_pick, function()
require("mini.extra").pickers.keymaps()
require("mini.extra").pickers.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
lazy.on_event("completion", "InsertEnter", "*", function()
require("mini.completion").setup({
lsp_completion = {
auto_setup = true,
},
})
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 })
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 }),
})
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")
vim.cmd("tabnew | Git | only")
end, { desc = "Fugitive Full Page New Tab" })
lazy.on_keys("fugitive", "<leader>gd", "n", nil, function()
vim.cmd("Gvdiffsplit")
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 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
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 })
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
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 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
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 },
},
})
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,
},
})
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" })