nvim/lua/keymaps.lua
xfy 9c8deeafc8 Reorganize config modules into lua/plugins/ and add comprehensive docs
- Move lsp.lua, pick.lua, treesitter.lua, git.lua to lua/plugins/
- Update all require() paths in pack.lua and init.lua
- Unify code style: tab indentation, line length control, empty braces
- Add detailed Chinese module documentation to all config files
- Add grug-far.nvim plugin with <leader>sr binding
- Enable vim._core.ui2 for Neovim 0.12+ UI enhancements
- Disable additional built-in plugins to reduce startup overhead

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:42:02 +08:00

179 lines
7.3 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/keymaps.lua)
-- =============================================================================
-- Leader 键设置为 Space所有以 <leader> 开头的映射均使用空格触发。
--
-- 映射模式说明:
-- n - normal 模式(默认)
-- v - visual / select 模式
-- i - insert 模式
-- t - terminal 模式
-- x - visual 模式(不含 select
--
-- 按键分组:
-- <leader> f* → 查找/文件相关(由 pick.lua 补充)
-- <leader> g* → Git 相关(由 git.lua 补充)
-- <leader> b* → Buffer 管理
-- <leader> y* → 复制/粘贴
-- <leader> t* → Terminal/Tab
-- <C-*> → 窗口导航与保存
-- =============================================================================
-- 设置 Leader 键为空格。必须在任何 <leader> 映射之前设置。
vim.g.mapleader = " "
-- 本地别名,简化映射代码
local map = vim.keymap.set
-- ---------------------------------------------------------------------------
-- 基础编辑映射
-- ---------------------------------------------------------------------------
-- 按 Esc 清除搜索高亮(/ ? 搜索后的匹配高亮)
-- silent = true 避免在命令行显示 :nohl 的反馈
map("n", "<Esc>", ":nohl<CR>", { desc = "清除搜索高亮", silent = true })
-- Visual 模式下缩进后保持选区,便于连续多次缩进
map("v", "<", "<gv", { desc = "减少缩进并保持选区" })
map("v", ">", ">gv", { desc = "增加缩进并保持选区" })
-- J合并行时不移动光标。
-- 原理mz 设置标记 zJ 合并行,`z 跳回标记位置。
map("n", "J", "mzJ`z", { desc = "合并行且不移动光标" })
-- ---------------------------------------------------------------------------
-- 搜索与替换
-- ---------------------------------------------------------------------------
-- 快速替换当前光标下的单词(全局替换)。
-- <C-r><C-w> 在命令行插入光标下的单词。
-- 映射展开后形如 :%s/oldword/oldword/gI光标停在末尾可修改替换内容。
map(
"n",
"<leader>ss",
[[:%s/<<C-r><C-w>>/<<C-r><C-w>>/gI<Left><Left><Left>]],
{ desc = "全局替换光标下的单词" }
)
-- Visual 模式下在选区范围内搜索替换
-- \%V 是 Vim 正则中的可视区域限定符,确保替换只在选区内生效
map("v", "<leader>ss", ":s/\\%V", { desc = "在可视选区内搜索替换" })
-- ---------------------------------------------------------------------------
-- 行尾操作符重映射
-- ---------------------------------------------------------------------------
-- 将 $ 映射为 g_行尾最后一个非空白字符
-- 这比 $(真正的行尾,通常包含尾随空格)更符合直觉。
map("n", "$", "g_")
map("v", "$", "g_")
-- 再次映射缩进保持选区(与上方重复,确保可靠性)
map("v", ">", ">gv")
map("v", "<", "<gv")
-- ---------------------------------------------------------------------------
-- 内置撤销树 (Undotree)
-- ---------------------------------------------------------------------------
-- Neovim 0.12+ 内置了 undotree 插件nvim.undotree
-- 这里通过 packadd 按需加载并打开。
vim.keymap.set("n", "<leader>u", function()
vim.cmd.packadd("nvim.undotree")
require("undotree").open()
end, { desc = "打开内置撤销树" })
-- ---------------------------------------------------------------------------
-- 文件操作
-- ---------------------------------------------------------------------------
-- <C-s> 保存当前文件normal 模式)
map("n", "<C-s>", "<cmd>w<CR>", { desc = "保存文件" })
-- <C-c> 复制整行内容到系统剪贴板
map("n", "<C-c>", "<cmd>%y+<CR>", { desc = "复制整个文件内容" })
-- ---------------------------------------------------------------------------
-- Terminal 模式
-- ---------------------------------------------------------------------------
-- Terminal 模式下按 <C-x> 返回 Normal 模式
-- <c-><c-n> 是 Vim 内置的终端转义序列
map("t", "<C-x>", "<c-\\><c-n>", { desc = "从终端模式返回普通模式" })
-- 打开新的终端窗口
map("n", "<leader>tt", ":term<CR>", { desc = "打开新终端" })
-- ---------------------------------------------------------------------------
-- 窗口导航
-- ---------------------------------------------------------------------------
-- 使用 <C-h/j/k/l> 在窗口间快速跳转,替代 <C-w> h/j/k/l 的繁琐操作。
map("n", "<C-h>", "<C-w>h", { desc = "切换到左侧窗口" })
map("n", "<C-j>", "<C-w>j", { desc = "切换到下方窗口" })
map("n", "<C-k>", "<C-w>k", { desc = "切换到上方窗口" })
map("n", "<C-l>", "<C-w>l", { desc = "切换到右侧窗口" })
-- ---------------------------------------------------------------------------
-- Tab 管理
-- ---------------------------------------------------------------------------
map("n", "<leader>tc", ":tabclose<CR>", { desc = "关闭当前标签页" })
map("n", "<leader>tn", ":tabnew<CR>", { desc = "新建标签页" })
map("n", "<leader>]", ":tabnext<CR>", { desc = "下一个标签页" })
map("n", "<leader>[", ":tabprevious<CR>", { desc = "上一个标签页" })
-- ---------------------------------------------------------------------------
-- 复制文件路径
-- ---------------------------------------------------------------------------
-- 复制当前文件的相对路径到系统剪贴板
map("n", "<leader>yp", function()
local path = vim.fn.expand("%")
vim.fn.setreg("+", path)
vim.notify("已复制相对路径: " .. path, vim.log.levels.INFO)
end, { desc = "复制相对文件路径" })
-- 复制当前文件的绝对路径到系统剪贴板
map("n", "<leader>yP", function()
local path = vim.fn.expand("%:p")
vim.fn.setreg("+", path)
vim.notify("已复制绝对路径: " .. path, vim.log.levels.INFO)
end, { desc = "复制绝对文件路径" })
-- ---------------------------------------------------------------------------
-- Buffer 管理
-- ---------------------------------------------------------------------------
-- 关闭当前 Buffer有未保存更改时提示确认。
-- 使用 vim.ui.select 提供交互式选择对话框。
map("n", "<leader>x", function()
local buf = vim.api.nvim_get_current_buf()
if vim.bo[buf].modified then
vim.ui.select({ "", "" }, {
prompt = "Buffer 有未保存的更改,不保存就关闭吗?",
format_item = function(item)
return item
end,
}, function(choice)
if choice == "" then
vim.api.nvim_buf_delete(buf, { force = true })
end
end)
else
vim.cmd.bdelete()
end
end, { desc = "关闭当前 Buffer" })
-- 新建空 Buffer
map("n", "<leader>bn", "<cmd>enew<CR>", { desc = "新建 Buffer" })
-- 关闭除当前 Buffer 外的所有 Buffer。
-- 跳过指定文件类型的 Buffer如文件管理器避免误关闭侧边栏。
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
end, { desc = "关闭其他 Buffer" })