diff --git a/lua/core/keymap.lua b/lua/core/keymap.lua index d396b2e..2f7f49d 100644 --- a/lua/core/keymap.lua +++ b/lua/core/keymap.lua @@ -3,11 +3,13 @@ -- === local function mapkey(mode, lhs, rhs, opts) - vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("force", { silent = true, nowait = true }, opts or {})) + 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 .. "", { silent = true }) + vim.keymap.set("n", key, function() + vim.cmd(cmd) + end, { silent = true }) end local function maplua(modes, key, action, desc) @@ -180,58 +182,55 @@ mapkey("x", "", "", ">gv") -- === --- === 批量替换 +-- === 批量替换 (修复 Shell 逃逸与正则符冲突版) -- === -- 替换当前目录及子目录下所有文件内容 local function search_and_replace() - return function () - -- 获取用户输入的查找内容,使用 input() 函数动态输入替换内容 - local search_text = vim.fn.input("Search for: ") + return function() + local search_text = vim.fn.input("Search for: ") + if search_text == "" then return end + local replace_text = vim.fn.input("Replace with: ") - -- 获取用户输入的替换内容 - local replace_text = vim.fn.input("Replace with: ") + -- 为 sed 转义分隔符 '/',防止 s/a/b/g 出现语法错误 + local sed_search = vim.fn.escape(search_text, '/') + local sed_replace = vim.fn.escape(replace_text, '/') - -- 执行替换命令 - if search_text ~= "" and replace_text ~= "" then - local cmd = 'execute "!grep -rl \\"' - .. search_text - .. '\\" ./ | xargs sed -i \\"s/' - .. search_text - .. "/" - .. replace_text - .. '/g\\""' + -- 利用内核自动转义并生成安全的单引号包裹 + local grep_arg = vim.fn.shellescape(search_text) + local sed_arg = vim.fn.shellescape('s/' .. sed_search .. '/' .. sed_replace .. '/g') + + -- 执行拼接:grep 增加 -F 参数表示“固定字符串”,彻底无视正则符号(如括号、星号) + local cmd = '!grep -rlF ' .. grep_arg .. ' ./ | xargs sed -i ' .. sed_arg vim.cmd(cmd) - print("Replaced all occurrences of '" .. search_text .. "' with '" .. replace_text .. "'") - else - print("Search or replace text cannot be empty.") - end + -- 强制 Neovim 检查文件在外部的改动并立即刷新 UI + vim.cmd("checktime") + print("\n✅ Replaced occurrences of '" .. search_text .. "' in workspace.") end end -- 替换当前文件内容 local function search_and_replace_current_file() return function() - -- 获取用户输入的查找内容 local search_text = vim.fn.input("Search for in current file: ") - - -- 获取用户输入的替换内容 + if search_text == "" then return end 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 + local sed_search = vim.fn.escape(search_text, '/') + local sed_replace = vim.fn.escape(replace_text, '/') + local sed_arg = vim.fn.shellescape('s/' .. sed_search .. '/' .. sed_replace .. '/g') + + -- % 代表当前文件 + local cmd = '!sed -i ' .. sed_arg .. ' %' + vim.cmd(cmd) + + vim.cmd("checktime") + print("\n✅ Replaced occurrences in current file.") end end -maplua("n","sa",search_and_replace(), "替换当前目录及子目录下所有文件内容") -maplua("n","sr",search_and_replace_current_file(), "替换当前文件内容") +maplua("n", "sa", search_and_replace(), "替换当前目录及子目录下所有文件内容") +maplua("n", "sr", search_and_replace_current_file(), "替换当前文件内容") -- === -- === 临时“存档”文件当前的版本,并与后续的修改进行 diff 对比 @@ -305,7 +304,9 @@ function map:key(mode, lhs, rhs) end function map:cmd(key, cmd) - vim.keymap.set("n", key, "" .. cmd .. "", { silent = true }) + vim.keymap.set("n", key, function() + vim.cmd(cmd) + end, { silent = true }) end function map:lua(key, txt_or_func) diff --git a/lua/pack/configs/conform.lua b/lua/pack/configs/conform.lua index 8f8366c..113908d 100644 --- a/lua/pack/configs/conform.lua +++ b/lua/pack/configs/conform.lua @@ -41,7 +41,7 @@ local function get_ensure_installed_for_ft(ft, ft_table) end -- 快捷键纯懒加载:只在按下快捷键时激活 -vim.keymap.set({ "n", "v" }, "f", function() +vim.keymap.set({ "n", "x" }, "f", function() PackUtils.load(P, function() require("conform").setup({ -- At a minimum, you will need to set up some formatters by filetype formatters_by_ft = formatters_by_ft diff --git a/lua/pack/configs/outline.lua b/lua/pack/configs/outline.lua new file mode 100644 index 0000000..e3142a7 --- /dev/null +++ b/lua/pack/configs/outline.lua @@ -0,0 +1,55 @@ +-- === outline大纲 === +if vim.g.vscode then return end + +local P = { + name = "outline.nvim", +} + +vim.keymap.set({ "n", "x" }, "v", function() + PackUtils.load(P, function() + require("outline").setup({ + outline_window = { + position = "left", + width = 20, + }, + keymaps = { + show_help = "?", + close = { "", "q" }, + -- Jump to symbol under cursor. + -- It can auto close the outline window when triggered, see + -- 'auto_close' option above. + goto_location = "", + -- Jump to symbol under cursor but keep focus on outline window. + peek_location = "o", + -- Visit location in code and close outline immediately + goto_and_close = "", + -- Change cursor position of outline window to match current location in code. + -- 'Opposite' of goto/peek_location. + restore_location = "", + -- Open LSP/provider-dependent symbol hover information + hover_symbol = "", + -- Preview location code of the symbol under cursor + toggle_preview = "K", + rename_symbol = "r", + code_actions = "a", + -- These fold actions are collapsing tree nodes, not code folding + fold = "n", + unfold = "i", + fold_toggle = "", + -- Toggle folds for all nodes. + -- If at least one node is folded, this action will fold all nodes. + -- If all nodes are folded, this action will unfold all nodes. + fold_toggle_all = "", + fold_all = "N", + unfold_all = "I", + fold_reset = "R", + -- Move down/up by one line and peek_location immediately. + -- You can also use outline_window.auto_jump=true to do this for any + -- j/k//. + down_and_jump = "", + up_and_jump = "", + }, + }) + end) + vim.cmd("Outline") +end, { desc = "Toggle outline" }) diff --git a/lua/pack/configs/tv.lua b/lua/pack/configs/tv.lua index f27e52b..c7af234 100644 --- a/lua/pack/configs/tv.lua +++ b/lua/pack/configs/tv.lua @@ -35,7 +35,7 @@ local function load_plugin() end) end -vim.keymap.set({ "n", "v" }, "", function() +vim.keymap.set({ "n", "x" }, "", function() load_plugin() if vim.fs.root(0, '.git') then vim.cmd('Tv git-files') @@ -44,7 +44,7 @@ vim.keymap.set({ "n", "v" }, "", function() end end, { desc = "Smart Tv: git-files or files" }) -vim.keymap.set({ "n", "v" }, "", function() +vim.keymap.set({ "n", "x" }, "", function() load_plugin() vim.cmd('Tv text') end, { desc = "模糊查找字符串" }) diff --git a/lua/pack/configs/yazi.lua b/lua/pack/configs/yazi.lua index b6d1989..b876774 100644 --- a/lua/pack/configs/yazi.lua +++ b/lua/pack/configs/yazi.lua @@ -15,7 +15,7 @@ local P = { } -- 快捷键触发懒加载 -vim.keymap.set({ "n", "v" }, "tt", function() +vim.keymap.set({ "n", "x" }, "tt", function() -- 核心:直接调用引擎,把配置逻辑传进去 PackUtils.load(P, function() require("yazi").setup({ diff --git a/lua/pack/plugins.lua b/lua/pack/plugins.lua index db24a6b..444261e 100644 --- a/lua/pack/plugins.lua +++ b/lua/pack/plugins.lua @@ -27,6 +27,10 @@ local specs = { "https://github.com/nvim-treesitter/nvim-treesitter-context", -- bufferline.lua 顶部状态栏 'https://github.com/akinsho/bufferline.nvim', + -- lualine.lua 底部状态栏 + "https://github.com/nvim-lualine/lualine.nvim", + -- outline.lua 大纲、函数变量结构 + "https://github.com/hedyhli/outline.nvim", -- noice.lua 取代消息、命令行和弹出菜单的 UI "https://github.com/folke/noice.nvim", "https://github.com/MunifTanjim/nui.nvim", @@ -44,8 +48,6 @@ local specs = { 'https://github.com/cap153/peek.nvim', -- yazi.lua 文件管理器 'https://github.com/mikavilpas/yazi.nvim', - -- lualine.lua 底部状态栏 - "https://github.com/nvim-lualine/lualine.nvim", -- sudo权限保存文件 "https://github.com/lambdalisue/vim-suda", -- 查看可用键位 diff --git a/nvim-pack-lock.json b/nvim-pack-lock.json index 7389f23..dda2e4e 100644 --- a/nvim-pack-lock.json +++ b/nvim-pack-lock.json @@ -80,6 +80,10 @@ "rev": "6e76c5e47e957fbf080b1fdac165c66dbd2e7cfb", "src": "https://github.com/nvim-tree/nvim-web-devicons" }, + "outline.nvim": { + "rev": "c293eb56db880a0539bf9d85b4a27816960b863e", + "src": "https://github.com/hedyhli/outline.nvim" + }, "peek.nvim": { "rev": "803815d18689b8f9e69d433b08ed767d7555128c", "src": "https://github.com/cap153/peek.nvim" diff --git a/snippets/lua.json b/snippets/lua.json index 49028f1..3a0dd01 100644 --- a/snippets/lua.json +++ b/snippets/lua.json @@ -45,7 +45,7 @@ "\t\tend)", "\tend", "})", - "-- vim.keymap.set({ \"n\", \"v\" }, \"${8:<++>}\", function()", + "-- vim.keymap.set({ \"n\", \"x\" }, \"${8:<++>}\", function()", "-- \tPackUtils.load(P, function()", "-- \t\t$9", "-- \tend)",