mirror of
https://github.com/cap153/nvim.git
synced 2026-04-16 08:55:43 +08:00
319 lines
9.6 KiB
Lua
319 lines
9.6 KiB
Lua
-- ===
|
||
-- === map function
|
||
-- ===
|
||
|
||
local function mapkey(mode, lhs, rhs, opts)
|
||
vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("force", { silent = true, nowait = true }, opts or {}))
|
||
end
|
||
|
||
local function mapcmd(key, cmd)
|
||
vim.keymap.set("n", key, "<cmd>" .. cmd .. "<cr>", { silent = true })
|
||
end
|
||
|
||
local function maplua(modes, key, action, desc)
|
||
vim.keymap.set(modes, key, action, { silent = true, noremap = true, desc = desc })
|
||
end
|
||
|
||
-- ===
|
||
-- === Basic Mappings
|
||
-- ===
|
||
|
||
-- leader键设置为空格,; as :
|
||
vim.g.mapleader = " "
|
||
mapkey({ "n", "x", "o" }, ";", ":")
|
||
|
||
-- 上/下一个搜索结果以及取消搜索结果高亮
|
||
mapkey({ "n", "x", "o" }, "=", "nzz")
|
||
mapkey({ "n", "x", "o" }, "-", "Nzz")
|
||
mapcmd("<leader><cr>", "nohlsearch")
|
||
|
||
-- 保存和退出
|
||
mapkey({ "n", "x", "o" }, "S", ":wall<cr>")
|
||
mapkey({ "n", "x", "o" }, "Q", ":qall<cr>")
|
||
|
||
-- 撤销与反撤销
|
||
mapkey({ "n", "x", "o" }, "l", "u")
|
||
mapkey({ "n", "x", "o" }, "L", "<c-r>")
|
||
|
||
-- 插入
|
||
mapkey({ "n", "x", "o" }, "k", "i")
|
||
mapkey({ "n", "x", "o" }, "K", "I")
|
||
|
||
mapkey('n', '<C-n>', '<C-o>')
|
||
|
||
-- 折叠
|
||
mapkey({ "n", "x", "o" }, "<leader>o", "za")
|
||
mapkey("x", "<leader>o", "zf") -- 可视模式创造折叠
|
||
-- 读取保存的折叠
|
||
-- mapkey({ "n", "x", "o" }, "<leader>a", ":loadview<cr>")
|
||
|
||
|
||
-- 以下两个映射默认了
|
||
-- make Y to copy till the end of the line
|
||
-- mapkey('','Y','y$')
|
||
|
||
-- make D to delete till the end of the line
|
||
-- mapkey('','D','d$')
|
||
|
||
-- 打开lazygit,已用fm-nvim插件
|
||
-- mapcmd('<c-g>',':tabe<CR>:-tabmove<CR>:term lazygit')
|
||
|
||
-- ===
|
||
-- === treesitter
|
||
-- ===
|
||
|
||
-- 删除i键映射
|
||
vim.api.nvim_create_autocmd("VimEnter", { -- 所有启动脚本、默认脚本都加载完毕后的最后一个事件
|
||
callback = function()
|
||
-- 使用 pcall 忽略如果键位不存在时的报错
|
||
pcall(vim.keymap.del, { "x", "o" }, "in")
|
||
end,
|
||
})
|
||
|
||
local function smart_select(ts_method, lsp_dir)
|
||
return function()
|
||
-- 如果当前不是普通文件(比如 Quickfix、帮助文档、终端等)那么我们直接发送一个原生的 <CR> 按键并退出,恢复回车原本的功能
|
||
if lsp_dir == 1 and vim.bo.buftype ~= "" then
|
||
local cr = vim.api.nvim_replace_termcodes("<CR>", true, false, true)
|
||
vim.api.nvim_feedkeys(cr, "n", false)
|
||
return
|
||
end
|
||
if vim.treesitter.get_parser(nil, nil, { error = false }) then
|
||
require("vim.treesitter._select")[ts_method](vim.v.count1)
|
||
else
|
||
vim.lsp.buf.selection_range(lsp_dir * vim.v.count1)
|
||
end
|
||
end
|
||
end
|
||
-- 扩大范围 (回车键):不断向上寻找父节点 (等价于官方的 an)
|
||
maplua({ "x", "o", "n" }, "<CR>", smart_select("select_parent", 1), "扩大 Treesitter/LSP 范围")
|
||
-- 缩小范围 (退格键):不断向下寻找子节点
|
||
maplua({ "x", "o" }, "<BS>", smart_select("select_child", -1), "缩小 Treesitter/LSP 范围")
|
||
|
||
|
||
|
||
-- ===
|
||
-- === Cursor Movement
|
||
-- ===
|
||
-- New cursor movement (the default arrow keys are used for resizing windows)
|
||
|
||
-- ^
|
||
-- u
|
||
-- < n i >
|
||
-- e
|
||
-- v
|
||
mapkey({ "n", "x", "o" }, "n", "h")
|
||
mapkey({ "n", "x", "o" }, "u", "k")
|
||
mapkey({ "n", "x", "o" }, "e", "j")
|
||
mapkey({ "n", "x", "o" }, "i", "l")
|
||
|
||
-- 更快的导航
|
||
mapkey({ "n", "x", "o" }, "U", "5k")
|
||
mapkey({ "n", "x", "o" }, "E", "5j")
|
||
mapkey({ "n", "x", "o" }, "N", "0")
|
||
mapkey({ "n", "x", "o" }, "I", "$")
|
||
-- 向下滚动半页,<C-u>默认向上滚动半页
|
||
mapkey({ "n", "x", "o" }, "<C-e>", "<C-d>")
|
||
|
||
-- 更快的行导航
|
||
mapkey({ "n", "x", "o" }, "W", "5W")
|
||
mapkey({ "n", "x", "o" }, "B", "5B")
|
||
|
||
-- ===
|
||
-- === Window management
|
||
-- ===
|
||
|
||
-- 使用<space> + 新方向键 在分屏之间移动
|
||
mapkey({ "n", "x", "o" }, "<LEADER>w", "<C-w>w")
|
||
mapkey({ "n", "x", "o" }, "<LEADER>u", "<C-w>k")
|
||
mapkey({ "n", "x", "o" }, "<LEADER>e", "<C-w>j")
|
||
mapkey({ "n", "x", "o" }, "<LEADER>n", "<C-w>h")
|
||
mapkey({ "n", "x", "o" }, "<LEADER>i", "<C-w>l")
|
||
|
||
-- 使用s + 新方向键 进行分屏
|
||
mapcmd("su", "set nosplitbelow<CR>:split<CR>:set splitbelow")
|
||
mapcmd("se", "set splitbelow<CR>:split")
|
||
mapcmd("sn", "set nosplitright<CR>:vsplit<CR>:set splitright")
|
||
mapcmd("si", "set splitright<CR>:vsplit")
|
||
|
||
-- 使用方向键来调整窗口大小
|
||
mapcmd("<up>", "res +5")
|
||
mapcmd("<down>", "res -5")
|
||
mapcmd("<left>", "vertical resize-5")
|
||
mapcmd("<right>", "vertical resize+5")
|
||
|
||
-- 使分屏窗口上下分布
|
||
mapkey({ "n", "x", "o" }, "sh", "<C-w>t<C-w>K")
|
||
-- 使分屏窗口左右分布
|
||
mapkey({ "n", "x", "o" }, "sv", "<C-w>t<C-w>H")
|
||
|
||
-- 按 <SPACE> + q 关闭当前窗口下方的窗口
|
||
mapkey({ "n", "x", "o" }, "<LEADER>q", "<C-w>j:q<CR>")
|
||
|
||
-- ===
|
||
-- === Tab management
|
||
-- ===
|
||
|
||
-- tu创建新标签,已用bufferline.nvim替代
|
||
-- mapcmd("tu", "tabe")
|
||
-- 在标签之间移动
|
||
-- mapcmd('tn','-tabnext')
|
||
-- mapcmd('ti','+tabnext')
|
||
|
||
-- 移动标签的位置
|
||
-- mapcmd('tmn','-tabmove')
|
||
-- mapcmd('tmi','+tabmove')
|
||
|
||
-- 关闭当前标签,已用close-buffers替代
|
||
-- mapcmd('tq','tabc')
|
||
|
||
-- ===
|
||
-- === 批量缩进方法
|
||
-- ===
|
||
-- 操作为,esc从编辑模式退到命令模式,将光标移到需要缩进的行的行首,然后按shift+v,可以看到该行已被选中,且左下角提示为“可视”
|
||
-- 按键盘上的上下方向键,如这里按向下的箭头,选中所有需要批量缩进的行
|
||
-- 按shift+>,是向前缩进一个tab值,按shift+<,则是缩回一个tab值
|
||
|
||
mapkey("x", "<", "<gv")
|
||
mapkey("x", ">", ">gv")
|
||
mapkey("x", "<s-tab>", "<gv")
|
||
mapkey("x", "<tab>", ">gv")
|
||
|
||
-- ===
|
||
-- === 批量替换
|
||
-- ===
|
||
|
||
-- 替换当前目录及子目录下所有文件内容
|
||
local function search_and_replace()
|
||
return function ()
|
||
-- 获取用户输入的查找内容,使用 input() 函数动态输入替换内容
|
||
local search_text = vim.fn.input("Search for: ")
|
||
|
||
-- 获取用户输入的替换内容
|
||
local replace_text = vim.fn.input("Replace with: ")
|
||
|
||
-- 执行替换命令
|
||
if search_text ~= "" and replace_text ~= "" then
|
||
local cmd = 'execute "!grep -rl \\"'
|
||
.. search_text
|
||
.. '\\" ./ | xargs sed -i \\"s/'
|
||
.. search_text
|
||
.. "/"
|
||
.. replace_text
|
||
.. '/g\\""'
|
||
vim.cmd(cmd)
|
||
print("Replaced all occurrences of '" .. search_text .. "' with '" .. replace_text .. "'")
|
||
else
|
||
print("Search or replace text cannot be empty.")
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 替换当前文件内容
|
||
local function search_and_replace_current_file()
|
||
return function()
|
||
-- 获取用户输入的查找内容
|
||
local search_text = vim.fn.input("Search for in current file: ")
|
||
|
||
-- 获取用户输入的替换内容
|
||
local replace_text = vim.fn.input("Replace with: ")
|
||
|
||
-- 执行替换命令
|
||
if search_text ~= "" and replace_text ~= "" then
|
||
-- 使用 sed 替换当前文件中的匹配内容,并正确转义引号
|
||
local cmd = string.format("!sed -i 's/%s/%s/g' %%", search_text, replace_text)
|
||
vim.cmd(cmd)
|
||
print("Replaced all occurrences of '" .. search_text .. "' with '" .. replace_text .. "' in current file.")
|
||
else
|
||
print("Search or replace text cannot be empty.")
|
||
end
|
||
end
|
||
end
|
||
|
||
maplua("n","<leader>sa",search_and_replace(), "替换当前目录及子目录下所有文件内容")
|
||
maplua("n","<leader>sr",search_and_replace_current_file(), "替换当前文件内容")
|
||
|
||
-- ===
|
||
-- === 临时“存档”文件当前的版本,并与后续的修改进行 diff 对比
|
||
-- ===
|
||
|
||
-- 创建 :DiffOrig 自定义命令,这个命令会打开一个垂直分屏,加载当前文件存盘时的版本,并启动 diff 模式
|
||
vim.api.nvim_create_user_command(
|
||
'DiffOrig',
|
||
function()
|
||
-- 在创建新窗口前,先保存当前文件的 filetype
|
||
local original_filetype = vim.bo.filetype
|
||
-- 打开一个垂直分屏,并准备好临时缓冲区
|
||
vim.cmd('vert new | set buftype=nofile')
|
||
-- 在新的临时缓冲区里,设置我们刚才保存的 filetype,这是确保语法高亮的关键!
|
||
vim.bo.filetype = original_filetype
|
||
-- 读取原始文件的磁盘内容,并启动 diff
|
||
vim.cmd('read ++edit # | 0d_ | diffthis | wincmd p | diffthis')
|
||
end,
|
||
{ force = true }
|
||
)
|
||
-- <leader>dd 将会执行 :DiffOrig 命令
|
||
mapcmd('<leader>dd', 'DiffOrig')
|
||
|
||
-- ===
|
||
-- === Other useful stuff
|
||
-- ===
|
||
|
||
-- 打开一个终端窗口
|
||
mapcmd("<LEADER>/", "set splitbelow<CR>:split<CR>:res +10<CR>:term")
|
||
|
||
-- 按两下空格跳转到占位符<++>,并进入插入模式
|
||
mapkey({ "n", "x", "o" }, "<LEADER><LEADER>", "<Esc>/<++><CR>:nohlsearch<CR>c4l")
|
||
|
||
-- 拼写检查
|
||
mapcmd("<LEADER>sc", "set spell!")
|
||
|
||
-- 注释快捷键
|
||
mapkey("n", "<leader>cn", "gcc", { remap = true })
|
||
mapkey("x", "<leader>cn", "gc", { remap = true })
|
||
mapkey("n", "<leader>cu", "gcc", { remap = true })
|
||
mapkey("x", "<leader>cu", "gc", { remap = true })
|
||
mapkey("n", "<c-_>", "gcc", { remap = true })
|
||
mapkey("x", "<c-_>", "gc", { remap = true })
|
||
mapkey("n", "<c-/>", "gcc", { remap = true })
|
||
mapkey("x", "<c-/>", "gc", { remap = true })
|
||
|
||
-- ===
|
||
-- === 运行代码(该功能已经迁移到plugins/coderunner.lua)
|
||
-- ===
|
||
|
||
-- vim.cmd([[
|
||
-- au filetype dart noremap r :wall<cr>:Telescope flutter commands<cr>
|
||
-- au filetype python noremap r :wall<cr>:set splitbelow<cr>:sp<cr>:term uv run %<cr>
|
||
-- au filetype go noremap r :wall<cr>:set splitbelow<cr>:sp<cr>:term go run %<cr>
|
||
-- au filetype markdown noremap r :PeekClose<cr>:PeekOpen<cr>
|
||
-- au filetype rust noremap r :wall<cr>:set splitbelow<cr>:sp<cr>:term cargo run<cr>
|
||
-- ]])
|
||
|
||
|
||
-- ===
|
||
-- === map function external environment
|
||
-- ===
|
||
|
||
-- 下面的函数给外部文件调用的
|
||
-- 使用示例如下
|
||
-- local map = require("core.keymap")
|
||
-- map:cmd('<space>p','PasteImg')
|
||
local map = {}
|
||
function map:key(mode, lhs, rhs)
|
||
vim.keymap.set(mode, lhs, rhs, { silent = true })
|
||
end
|
||
|
||
function map:cmd(key, cmd)
|
||
vim.keymap.set("n", key, "<cmd>" .. cmd .. "<cr>", { silent = true })
|
||
end
|
||
|
||
function map:lua(key, txt_or_func)
|
||
if type(txt_or_func) == "string" then
|
||
vim.keymap.set("n", key, "<cmd>lua " .. txt_or_func .. "<cr>", { silent = true })
|
||
else
|
||
vim.keymap.set("n", key, txt_or_func, { silent = true })
|
||
end
|
||
end
|
||
|
||
return map
|