完美!我们按这个顺序来,先搞定 完整的通用插件配置


📁 通用插件配置(完整版)

目录结构

~/.config/nvim/
├── chadrc.lua
└── lua/
    └── core/
        ├── keymaps.lua
        ├── options.lua  
        └── plugins.lua

🔧 1. chadrc.lua(主配置)

-- ~/.config/nvim/chadrc.lua
local M = {}
 
M.ui = { theme = "catppuccin" }
 
M.options = {
  configs = {
    "core.options",   -- 通用选项
    "core.keymaps",   -- 统一快捷键
  }
}
 
-- 加载通用插件 + 环境插件
M.plugins = function()
  local env_file = vim.fn.stdpath("config") .. "/.nvim-env"
  local env = "writer"  -- 默认环境
  
  if vim.fn.filereadable(env_file) == 1 then
    env = vim.fn.readfile(env_file)[1]
  end
  
  return {
    "core.plugins",    -- 通用插件(所有环境都加载)
    "envs." .. env,    -- 环境专用插件
  }
end
 
return M

⚙️ 2. lua/core/options.lua(通用选项)

-- ~/.config/nvim/lua/core/options.lua
local opt = vim.opt
 
-- 基础设置
opt.number = true
opt.relativenumber = true
opt.cursorline = true
opt.showmode = false
opt.hidden = true        -- 允许切换缓冲区而不保存
opt.splitright = true    -- 新窗口在右侧
opt.splitbelow = true    -- 新窗口在下方
opt.mouse = "a"          -- 启用鼠标
 
-- 缩进和制表符
opt.tabstop = 2
opt.softtabstop = 2
opt.shiftwidth = 2
opt.expandtab = true     -- 使用空格代替制表符
opt.autoindent = true
opt.smartindent = true
 
-- 搜索
opt.ignorecase = true
opt.smartcase = true
opt.hlsearch = true
opt.incsearch = true
 
-- 折叠(基于 Tree-sitter)
opt.foldmethod = "expr"
opt.foldexpr = "nvim_treesitter#foldexpr()"
opt.foldlevel = 99       -- 默认展开所有
opt.foldlevelstart = 99
opt.foldenable = true
 
-- 其他
opt.termguicolors = true -- 真彩色支持
opt.updatetime = 300     -- 插件更新频率
opt timeoutlen = 400     -- 快捷键超时

🔌 3. lua/core/plugins.lua(通用插件 - 完整版)

-- ~/.config/nvim/lua/core/plugins.lua
return {
  -- 🌳 Tree-sitter(语法解析核心)
  {
    "nvim-treesitter/nvim-treesitter",
    build = ":TSUpdate",
    config = function()
      require("nvim-treesitter.configs").setup({
        ensure_installed = {
          "python", "typescript", "tsx", "javascript", "rust", 
          "html", "css", "json", "yaml", "toml", "markdown", "bash", "lua"
        },
        auto_install = true,
        highlight = { enable = true },
        indent = { enable = true },
        incremental_selection = {
          enable = true,
          keymaps = {
            init_selection = "<CR>",
            node_incremental = "<CR>",
            scope_incremental = "<S-CR>",
            node_decremental = "<BS>",
          },
        },
        textobjects = {
          select = {
            enable = true,
            lookahead = true,
            keymaps = {
              ["af"] = "@function.outer",
              ["if"] = "@function.inner",
              ["ac"] = "@class.outer", 
              ["ic"] = "@class.inner",
            },
          },
          move = {
            enable = true,
            set_jumps = true,
            goto_next_start = { ["]m"] = "@function.outer", ["]]"] = "@class.outer" },
            goto_next_end = { ["]M"] = "@function.outer", ["]["] = "@class.outer" },
            goto_previous_start = { ["[m"] = "@function.outer", ["[["] = "@class.outer" },
            goto_previous_end = { ["[M"] = "@function.outer", ["[]"] = "@class.outer" },
          },
        },
      })
    end,
  },
 
  -- 🎯 Flash(快速定位)
  {
    "folke/flash.nvim",
    dependencies = "nvim-treesitter/nvim-treesitter",
    config = function()
      require("flash").setup({
        modes = {
          char = { enabled = true, keys = { "f", "F", "t", "T" } },
        },
        labels = "abcdefghijklmnopqrstuvwxyz",
        jump = { autojump = true },
        highlight = {
          groups = { match = { bg = "#3c3836", fg = "#fabd2f" } },
        },
      })
    end,
  },
 
  -- 💬 智能注释
  {
    "numToStr/Comment.nvim",
    config = function()
      require("Comment").setup({
        toggler = { line = "gcc", block = "gbc" },
        opleader = { line = "gc", block = "gb" },
        mappings = { basic = true, extra = true },
      })
    end,
  },
 
  -- 🧩 括号处理
  {
    "windwp/nvim-autopairs",
    config = function()
      require("nvim-autopairs").setup({
        disable_filetype = { "TelescopePrompt", "vim" },
        fast_wrap = {
          map = "<M-e>",
          chars = { "{", "[", "(", '"', "'" },
          pattern = string.gsub([[ [%'%"%)%>%]%)%}%,] ]], "%s+", ""),
          end_key = "$",
          keys = "qwertyuiopzxcvbnmasdfghjkl",
          check_comma = true,
          highlight = "PmenuSel",
          highlight_grey = "LineNr",
        },
      })
    end,
  },
  {
    "HiPhish/rainbow-delimiters.nvim",
    config = function()
      require("rainbow-delimiters.setup").setup({
        strategy = {
          [""] = rainbow_delimiters.strategy["global"],
          vim = rainbow_delimiters.strategy["local"],
        },
      })
    end,
  },
 
  -- 🧩 代码片段
  {
    "L3MON4D3/LuaSnip",
    dependencies = {
      "saadparwaiz1/cmp_luasnip",
      "rafamadriz/friendly-snippets",
    },
    config = function()
      require("luasnip.loaders.from_vscode").lazy_load()
      require("luasnip").config.set_config({
        history = true,
        update_events = "TextChanged,TextChangedI",
      })
    end,
  },
 
  -- 🔍 文件导航
  {
    "nvim-telescope/telescope.nvim",
    dependencies = { "nvim-lua/plenary.nvim" },
    cmd = "Telescope",
    config = function()
      local actions = require("telescope.actions")
      require("telescope").setup({
        defaults = {
          prompt_prefix = "🔍 ",
          selection_caret = "➤ ",
          path_display = { "truncate" },
          sorting_strategy = "ascending",
          layout_strategy = "horizontal",
          layout_config = {
            horizontal = { width = 0.9, height = 0.8 },
          },
          mappings = {
            i = {
              ["<C-j>"] = actions.move_selection_next,
              ["<C-k>"] = actions.move_selection_previous,
              ["<C-c>"] = actions.close,
            },
          },
        },
      })
    end,
  },
 
  -- 📊 状态栏
  {
    "nvim-lualine/lualine.nvim",
    config = function()
      require("lualine").setup({
        options = {
          theme = "catppuccin",
          section_separators = "",
          component_separators = "",
        },
        sections = {
          lualine_a = { "mode" },
          lualine_b = { "branch" },
          lualine_c = { "filename" },
          lualine_x = { "encoding", "fileformat", "filetype" },
          lualine_y = { "progress" },
          lualine_z = { "location" },
        },
      })
    end,
  },
 
  -- 📁 项目管理
  {
    "ahmedkhalf/project.nvim",
    config = function()
      require("project_nvim").setup({
        detection_methods = { "lsp", "pattern" },
        patterns = { ".git", "package.json", "pyproject.toml", "Cargo.toml", "Makefile" },
        manual_mode = false,
      })
    end,
  },
 
  -- 🖥️ 终端集成
  {
    "akinsho/toggleterm.nvim",
    version = "*",
    config = function()
      require("toggleterm").setup({
        size = 15,
        open_mapping = [[<C-\>]],
        hide_numbers = true,
        shade_filetypes = {},
        shade_terminals = false,
        start_in_insert = true,
        persist_size = true,
        direction = "float",
        close_on_exit = true,
      })
    end,
  },
 
  -- 📦 Git 集成
  {
    "lewis6991/gitsigns.nvim",
    config = function()
      require("gitsigns").setup({
        signs = {
          add = { text = "│" },
          change = { text = "│" },
          delete = { text = "_" },
          topdelete = { text = "‾" },
          changedelete = { text = "~" },
        },
        on_attach = function(bufnr)
          local gs = package.loaded.gitsigns
          local function map(mode, l, r, opts)
            opts = opts or {}
            opts.buffer = bufnr
            vim.keymap.set(mode, l, r, opts)
          end
          map('n', ']c', "&diff ? g] : ]c", { expr=true })
          map('n', '[c', "&diff ? g[ : [c", { expr=true })
          map('n', '<leader>hs', ':Gitsigns stage_hunk<CR>')
          map('n', '<leader>hr', ':Gitsigns reset_hunk<CR>')
        end
      })
    end,
  },
}

⌨️ 4. lua/core/keymaps.lua(统一快捷键 - 完整版)

-- ~/.config/nvim/lua/core/keymaps.lua
local map = vim.keymap.set
 
-- 🌐 全局通用
map("n", "<leader>w", "<cmd>w<cr>", { desc = "Save" })
map("n", "<leader>q", "<cmd>q<cr>", { desc = "Quit" })
map("n", "<leader>h", "<cmd>nohlsearch<cr>", { desc = "Clear highlights" })
 
-- 🔍 Telescope 导航
map("n", "<leader>ff", "<cmd>Telescope find_files<cr>", { desc = "Find Files" })
map("n", "<leader>fg", "<cmd>Telescope live_grep<cr>", { desc = "Live Grep" })
map("n", "<leader>fb", "<cmd>Telescope buffers<cr>", { desc = "Buffers" })
map("n", "<leader>fh", "<cmd>Telescope help_tags<cr>", { desc = "Help" })
map("n", "<leader>pp", "<cmd>Telescope projects<cr>", { desc = "Projects" })
 
-- 🎯 Flash 快速定位
if package.loaded["flash"] then
  map({ "n", "x", "o" }, "s", "<cmd>lua require('flash').jump()<cr>", { desc = "Flash Jump" })
  map({ "n", "x", "o" }, "S", "<cmd>lua require('flash').treesitter()<cr>", { desc = "Flash Treesitter" })
  map({ "n", "x", "o" }, "r", "<cmd>lua require('flash').remote()<cr>", { desc = "Flash Remote" })
  map({ "n", "x", "o" }, "f", "<cmd>lua require('flash').jump({ char = 'f' })<cr>", { desc = "Flash f" })
  map({ "n", "x", "o" }, "F", "<cmd>lua require('flash').jump({ char = 'F' })<cr>", { desc = "Flash F" })
  map({ "n", "x", "o" }, "t", "<cmd>lua require('flash').jump({ char = 't' })<cr>", { desc = "Flash t" })
  map({ "n", "x", "o" }, "T", "<cmd>lua require('flash').jump({ char = 'T' })<cr>", { desc = "Flash T" })
end
 
-- 💬 注释
if package.loaded["Comment"] then
  map("n", "gcc", "<cmd>lua require('Comment.api').toggle.linewise.current()<cr>", { desc = "Comment Line" })
  map("v", "gc", "<cmd>lua require('Comment.api').toggle.linewise(vim.fn.visualmode())<cr>", { desc = "Comment Visual" })
  map("n", "gbc", "<cmd>lua require('Comment.api').toggle.blockwise.current()<cr>", { desc = "Comment Block" })
  map("v", "gb", "<cmd>lua require('Comment.api').toggle.blockwise(vim.fn.visualmode())<cr>", { desc = "Comment Block Visual" })
end
 
-- 🧩 括号快速包裹
if package.loaded["nvim-autopairs"] then
  map("n", "<M-e>", "<cmd>lua require('nvim-autopairs.fast_wrap')()<cr>", { desc = "Fast Wrap" })
end
 
-- 🧩 代码片段
if package.loaded["luasnip"] then
  map("i", "<C-j>", "<cmd>lua require('luasnip').jump(1)<cr>", { desc = "Snippet Next" })
  map("i", "<C-k>", "<cmd>lua require('luasnip').jump(-1)<cr>", { desc = "Snippet Prev" })
  map("i", "<C-l>", "<cmd>lua require('luasnip').expand_or_jump()<cr>", { desc = "Snippet Expand" })
end
 
-- 🌳 Tree-sitter 增量选择
map("n", "<CR>", "<cmd>lua require('nvim-treesitter.incremental_selection').init_selection()<cr>", { desc = "TS Select Init" })
map("n", "<S-CR>", "<cmd>lua require('nvim-treesitter.incremental_selection').scope_incremental()<cr>", { desc = "TS Select Scope" })
 
-- 📂 代码折叠
map("n", "zM", "<cmd>set foldlevel=0<cr>", { desc = "Fold All" })
map("n", "zR", "<cmd>set foldlevel=99<cr>", { desc = "Unfold All" })
map("n", "za", "<cmd>normal! za<cr>", { desc = "Toggle Fold" })
 
-- 📊 LSP 通用
map("n", "<leader>gd", "<cmd>lua vim.lsp.buf.definition()<cr>", { desc = "Go to Definition" })
map("n", "<leader>gr", "<cmd>lua vim.lsp.buf.references()<cr>", { desc = "References" })
map("n", "<leader>gR", "<cmd>lua vim.lsp.buf.rename()<cr>", { desc = "Rename" })
map("n", "<leader>ca", "<cmd>lua vim.lsp.buf.code_action()<cr>", { desc = "Code Action" })
map("n", "<leader>fd", "<cmd>lua vim.lsp.buf.format({ async = true })<cr>", { desc = "Format Document" })
 
-- 📁 Git
if package.loaded["gitsigns"] then
  map("n", "<leader>gs", "<cmd>Gitsigns stage_hunk<cr>", { desc = "Git Stage" })
  map("n", "<leader>gr", "<cmd>Gitsigns reset_hunk<cr>", { desc = "Git Reset" })
  map("n", "]c", "&diff ? g] : ]c", { expr = true, desc = "Next Git hunk" })
  map("n", "[c", "&diff ? g[ : [c", { expr = true, desc = "Prev Git hunk" })
end
 
-- 🖥️ 终端
map("n", "<C-\\>", "<cmd>ToggleTerm<cr>", { desc = "Toggle Terminal" })
 
-- ✍️ 写作环境专用
if vim.fn.filereadable(vim.fn.stdpath("config") .. "/.nvim-env-writer") == 1 then
  map("n", "<leader>h1", "<cmd>put =repeat('#', 1) . ' '<cr>", { desc = "Header 1" })
  map("n", "<leader>h2", "<cmd>put =repeat('#', 2) . ' '<cr>", { desc = "Header 2" })
  map("n", "<leader>ul", "<cmd>put = '- '<cr>", { desc = "Unordered List" })
  map("n", "]s", "]s", { desc = "Next misspelling" })
  map("n", "[s", "[s", { desc = "Prev misspelling" })
  map("n", "z=", "z=", { desc = "Spelling suggestions" })
end

🚀 部署脚本

# 创建目录
mkdir -p ~/.config/nvim/lua/core
 
# 部署通用配置
# (将上面四个文件的内容分别保存到对应位置)
 
echo "✅ 通用插件配置部署完成!"
echo "📝 接下来可以逐个部署环境专用配置"

✅ 通用功能验证清单

  • Tree-sitter: 打开文件,检查语法高亮是否精准
  • Flash: 按 s 测试多字符跳转
  • Comment: 按 gcc 测试行注释
  • Autopairs: 输入 { 测试自动补全
  • Telescope: 按 <leader>ff 测试文件查找
  • Git: 修改文件,查看行号旁的 Git 标记
  • 折叠: 按 zM / zR 测试代码折叠
  • 终端: 按 <C-\> 测试内置终端

现在你有了一个 完整的通用插件基础!接下来我们可以逐个生成环境专用配置:

  1. Python 环境
  2. TypeScript 环境
  3. Web 环境
  4. Rust 环境
  5. Writer 环境

你想先从哪个环境开始?