从零重建 NvChad 自定义配置(全量放 custom 目录)

完全按你的需求:所有自定义配置仅放在 lua/custom 目录,适配 IDEAVim 快捷键习惯(通用映射放 general),聚焦 Python/TypeScript/Markdown 三种语言(放 langs),集成你指定的所有通用插件,一步到位、开箱即用。

一、第一步:重建标准化 custom 目录结构

先清空之前的错误配置,按以下结构创建目录(终端一键执行,不用手动建):

# 先进入 NvChad 根目录
cd ~/.config/nvim
 
# 删除 custom 下的旧配置(清空重来)
rm -rf lua/custom/*
 
# 创建标准化目录结构
mkdir -p lua/custom/{general,langs,plugins}
 
# 创建通用配置文件(IDEAVim 映射、全局选项、自动命令)
touch lua/custom/general/{keymaps.lua,options.lua,autocmds.lua}
 
# 创建分语言配置文件(Python/TS/Markdown)
touch lua/custom/langs/{python.lua,typescript.lua,markdown.lua}
 
# 创建插件配置文件(通用插件入口+具体插件配置)
touch lua/custom/plugins/{init.lua,core.lua,tree-sitter.lua}
 
# 创建 custom 核心配置文件(覆盖 Leader 键、加载自定义)
touch lua/custom/chadrc.lua

最终 custom 目录结构(清晰无冗余):

lua/custom/
├── chadrc.lua          # NvChad 核心覆盖配置(Leader 键、加载自定义)
├── general/            # 通用配置(IDEAVim 习惯)
│   ├── keymaps.lua     # 全局快捷键(适配 IDEAVim)
│   ├── options.lua     # 全局 Vim 选项(缩进、显示等)
│   └── autocmds.lua    # 全局自动命令(保存格式化、文件类型适配)
├── langs/              # 分语言配置
│   ├── python.lua      # Python 专属(LSP、格式化、调试)
│   ├── typescript.lua  # TS 专属(LSP、Bun、ESLint/Prettier)
│   └── markdown.lua    # Markdown 专属(预览、表格、语法高亮)
└── plugins/            # 通用插件配置
    ├── init.lua        # 插件加载入口(统一加载所有插件)
    ├── core.lua        # 通用插件(flash、Comment、telescope 等)
    └── tree-sitter.lua # 语法解析(支持你指定的所有语言)

二、第二步:配置 custom 核心(chadrc.lua)

这是 NvChad 加载自定义的“总开关”,只负责覆盖默认配置+指定加载路径

-- lua/custom/chadrc.lua
local M = {}
 
-- 1. 覆盖默认配置(适配 IDEAVim 习惯,Leader 键设为逗号)
M.options = {
  leader = ",",          -- Leader 键 = 逗号(和 IDEAVim 一致)
  localleader = "\\",    -- 本地 Leader 键(插件内快捷键)
  relativenumber = true, -- 显示相对行号(IDEAVim 常用)
  number = true,         -- 显示绝对行号
  expandtab = true,      -- 空格代替制表符
  tabstop = 2,           -- 制表符宽度 2 空格
  shiftwidth = 2,        -- 缩进宽度 2 空格
}
 
-- 2. 指定插件加载路径(加载 custom/plugins 下的所有插件)
M.plugins = "custom.plugins"
 
-- 3. 加载通用配置(启动时自动加载 general 下的映射/选项/自动命令)
M.ui = {
  theme = "catppuccin",  -- 可选:配个舒服的主题(IDEAVim 风格)
}
 
return M

三、第三步:通用配置(适配 IDEAVim 习惯)

1. 全局快捷键(general/keymaps.lua)

完全复刻 IDEAVim 常用快捷键,保留你之前的核心需求(行首/行尾/移动):

-- lua/custom/general/keymaps.lua
local map = function(mode, lhs, rhs, desc)
  vim.keymap.set(mode, lhs, rhs, { noremap = true, silent = true, desc = desc })
end
 
-- ==================== IDEAVim 核心映射(Insert 模式) ====================
map("i", "<C-a>", "<ESC>^i", "跳转到行首(IDEAVim 习惯)")
map("i", "<C-e>", "<ESC>$a", "跳转到行尾(IDEAVim 习惯)")
map("i", "<C-h>", "<Left>", "向左移动(替代删除,IDEAVim 习惯)")
map("i", "<C-l>", "<Right>", "向右移动(IDEAVim 习惯)")
map("i", "<C-j>", "<Down>", "向下移动(IDEAVim 习惯)")
map("i", "<C-k>", "<Up>", "向上移动(IDEAVim 习惯)")
map("i", "<C-z>", "<ESC>ua", "撤销输入(IDEAVim 习惯)")
map("i", "<C-y>", "<ESC><C-r>a", "恢复撤销(IDEAVim 习惯)")
 
-- ==================== IDEAVim 核心映射(Normal 模式) ====================
-- 窗口管理(IDEAVim 常用)
map("n", "<leader>wv", "<C-w>v", "垂直分屏(IDEAVim 习惯)")
map("n", "<leader>wh", "<C-w>s", "水平分屏(IDEAVim 习惯)")
map("n", "<leader>wc", "<C-w>c", "关闭当前分屏(IDEAVim 习惯)")
map("n", "<leader>wo", "<C-w>o", "关闭其他分屏(IDEAVim 习惯)")
map("n", "<leader>wj", "<C-w>j", "跳转到下方分屏(IDEAVim 习惯)")
map("n", "<leader>wk", "<C-w>k", "跳转到上方分屏(IDEAVim 习惯)")
map("n", "<leader>wl", "<C-w>l", "跳转到右侧分屏(IDEAVim 习惯)")
map("n", "<leader>wh", "<C-w>h", "跳转到左侧分屏(IDEAVim 习惯)")
 
-- 搜索/替换(IDEAVim 习惯)
map("n", "<leader>nh", ":nohl<CR>", "关闭搜索高亮(IDEAVim 习惯)")
map("n", "<leader>rf", ":%s///g<Left><Left>", "全局替换(IDEAVim 快捷)")
 
-- 复制粘贴(系统剪贴板,IDEAVim 习惯)
map("n", "<leader>y", '"+y', "复制到系统剪贴板")
map("n", "<leader>p", '"+p', "粘贴系统剪贴板")
map("v", "<leader>y", '"+y', "复制选中内容到系统剪贴板")
map("v", "<leader>p", '"+p', "粘贴系统剪贴板到选中位置")
 
-- 文件操作(IDEAVim 习惯)
map("n", "<leader>w", ":w<CR>", "保存文件")
map("n", "<leader>q", ":qa!<CR>", "强制退出所有窗口")
map("n", "<leader>fn", ":enew<CR>", "新建文件")
 
-- 快速跳转(IDEAVim 习惯)
map("n", "H", "^", "跳转到行首(跳过空白)")
map("n", "L", "$", "跳转到行尾")
map("n", "<leader>l", ":Lazy<CR>", "打开插件管理")
 
-- ==================== IDEAVim 核心映射(Visual 模式) ====================
map("v", "<", "<gv", "向左缩进(不取消选中,IDEAVim 习惯)")
map("v", ">", ">gv", "向右缩进(不取消选中,IDEAVim 习惯)")
map("v", "J", ":m '>+1<CR>gv=gv", "向下移动选中内容(IDEAVim 习惯)")
map("v", "K", ":m '<-2<CR>gv=gv", "向上移动选中内容(IDEAVim 习惯)")
 
return {}

2. 全局选项(general/options.lua)

适配 IDEAVim 习惯的全局配置,通用且不区分语言:

-- lua/custom/general/options.lua
local opt = vim.opt
 
-- 编码/文件(IDEAVim 通用)
opt.encoding = "utf-8"        -- 默认编码
opt.fileencoding = "utf-8"    -- 文件编码
opt.autoread = true           -- 外部修改后自动重读(IDEAVim 同步)
 
-- 缩进(通用,语言专属缩进在 autocmds.lua 中覆盖)
opt.expandtab = true          -- 空格代替制表符
opt.shiftwidth = 2            -- 通用缩进 2 空格
opt.tabstop = 2               -- 制表符 2 空格
opt.softtabstop = 2           -- 软制表符 2 空格
opt.smartindent = true        -- 智能缩进(适配代码语法)
 
-- 显示(IDEAVim 习惯)
opt.number = true             -- 显示绝对行号
opt.relativenumber = true     -- 显示相对行号(方便跳转)
opt.wrap = true               -- 换行显示(Markdown 必备)
opt.linebreak = true          -- 按单词换行(不截断)
opt.signcolumn = "yes"        -- 显示符号列(LSP 提示不挤代码)
opt.cursorline = true         -- 高亮当前行(IDEAVim 习惯)
opt.termguicolors = true      -- 开启真彩色(主题正常显示)
opt.scrolloff = 5             -- 光标距离顶部/底部 5 行(IDEAVim 习惯)
 
-- 搜索(IDEAVim 习惯)
opt.ignorecase = true         -- 搜索忽略大小写
opt.smartcase = true          -- 包含大写时区分大小写
opt.hlsearch = true           -- 高亮搜索结果
opt.incsearch = true          -- 实时搜索
 
-- 编辑(IDEAVim 习惯)
opt.backup = false            -- 关闭备份文件
opt.swapfile = false          -- 关闭交换文件
opt.undofile = true           -- 持久化撤销(跨会话,IDEAVim 同步)
opt.undodir = vim.fn.stdpath("data") .. "/undo"  -- 撤销文件目录
 
return {}

3. 全局自动命令(general/autocmds.lua)

适配语言专属缩进、保存格式化等,兼容 IDEAVim 习惯:

-- lua/custom/general/autocmds.lua
local augroup = vim.api.nvim_create_augroup("IDEAVimCustom", { clear = true })
 
-- 1. 保存时自动去除行尾空格(IDEAVim 习惯)
vim.api.nvim_create_autocmd("BufWritePre", {
  group = augroup,
  pattern = "*",
  callback = function()
    vim.cmd([[%s/\s\+$//e]])
  end,
  desc = "保存时去除行尾空格",
})
 
-- 2. Python 专属缩进(覆盖通用 2 空格,改为 4 空格,IDEAVim 适配)
vim.api.nvim_create_autocmd("FileType", {
  group = augroup,
  pattern = "python",
  callback = function()
    vim.opt_local.shiftwidth = 4
    vim.opt_local.tabstop = 4
    vim.opt_local.softtabstop = 4
  end,
  desc = "Python 文件缩进 4 空格",
})
 
-- 3. Markdown 专属显示(关闭相对行号,IDEAVim 写作习惯)
vim.api.nvim_create_autocmd("FileType", {
  group = augroup,
  pattern = "markdown",
  callback = function()
    vim.opt_local.relativenumber = false
    vim.opt_local.wrap = true
    vim.opt_local.linebreak = true
  end,
  desc = "Markdown 写作优化",
})
 
-- 4. TS/JS 专属缩进(保持 2 空格,IDEAVim 前端习惯)
vim.api.nvim_create_autocmd("FileType", {
  group = augroup,
  pattern = { "typescript", "javascript", "tsx", "jsx" },
  callback = function()
    vim.opt_local.shiftwidth = 2
    vim.opt_local.tabstop = 2
  end,
  desc = "TS/JS 缩进 2 空格",
})
 
return {}

四、第四步:通用插件配置(plugins)

1. 插件加载入口(plugins/init.lua)

统一加载所有通用插件+分语言插件:

-- lua/custom/plugins/init.lua
return {
  -- 通用插件
  { import = "custom.plugins.core" },
  { import = "custom.plugins.tree-sitter" },
  -- 分语言插件
  { import = "custom.langs.python" },
  { import = "custom.langs.typescript" },
  { import = "custom.langs.markdown" },
}

2. 核心通用插件(plugins/core.lua)

集成你指定的所有通用插件(flash、Comment、autopairs 等),适配 IDEAVim 习惯:

-- lua/custom/plugins/core.lua
return {
  -- 1. 快速跳转(flash.nvim,IDEAVim 增强)
  {
    "folke/flash.nvim",
    opts = {
      labels = "asdfghjklqwertyuiopzxcvbnm", -- IDEAVim 常用键位
      modes = {
        search = { enabled = false },
        char = { enabled = true },
      },
    },
    keys = {
      { "s", mode = { "n", "x", "o" }, "<cmd>Flash<CR>", desc = "Flash 快速跳转(IDEAVim 习惯)" },
      { "S", mode = { "n", "x", "o" }, "<cmd>Flash treesitter<CR>", desc = "Flash 语法节点跳转" },
    },
  },
 
  -- 2. 代码注释(Comment.nvim,IDEAVim 兼容)
  {
    "numToStr/Comment.nvim",
    opts = {
      toggler = { line = "gcc", block = "gbc" },
      opleader = { line = "gc", block = "gb" },
    },
    keys = {
      { "gcc", mode = "n", desc = "切换行注释(IDEAVim 习惯)" },
      { "gbc", mode = "n", desc = "切换块注释(IDEAVim 习惯)" },
      { "gc", mode = "v", desc = "切换选中注释" },
    },
  },
 
  -- 3. 自动括号(nvim-autopairs,IDEAVim 增强)
  {
    "windwp/nvim-autopairs",
    event = "InsertEnter",
    opts = {
      check_ts = true, -- 结合 tree-sitter 智能配对
      ts_config = {
        python = { "string", "comment" },
        typescript = { "string", "template_string" },
        markdown = { "string" },
      },
      fast_wrap = { map = "<M-e>" }, -- IDEAVim 快捷包裹
    },
    config = function(_, opts)
      require("nvim-autopairs").setup(opts)
      -- 配合补全插件自动配对
      local cmp_autopairs = require("nvim-autopairs.completion.cmp")
      local cmp = require("cmp")
      cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done())
    end,
  },
 
  -- 4. 彩虹括号(rainbow-delimiters.nvim,IDEAVim 增强)
  {
    "hiphish/rainbow-delimiters.nvim",
    event = "BufReadPost",
    config = function()
      local rainbow_delimiters = require("rainbow-delimiters")
      vim.g.rainbow_delimiters = {
        strategy = { [""] = rainbow_delimiters.strategy["global"] },
        query = {
          [""] = "rainbow-delimiters",
          lua = "rainbow-blocks",
          python = "rainbow-blocks",
          tsx = "rainbow-delimiters-react",
        },
        highlight = {
          "RainbowDelimiterRed",
          "RainbowDelimiterYellow",
          "RainbowDelimiterBlue",
          "RainbowDelimiterGreen",
          "RainbowDelimiterPurple",
          "RainbowDelimiterCyan",
          "RainbowDelimiterOrange",
        },
      }
    end,
  },
 
  -- 5. 代码片段(LuaSnip,IDEAVim 兼容)
  {
    "L3MON4D3/LuaSnip",
    version = "v2.*",
    build = "make install_jsregexp",
    dependencies = { "rafamadriz/friendly-snippets" },
    opts = {
      history = true,
      delete_check_events = "TextChanged",
      snippet_dirs = { vim.fn.stdpath("config") .. "/lua/custom/snippets" },
    },
    keys = {
      {
        "<tab>",
        function()
          return require("luasnip").jumpable(1) and "<Plug>luasnip-jump-next" or "<tab>"
        end,
        expr = true,
        silent = true,
        mode = "i",
      },
    },
    config = function(_, opts)
      require("luasnip").setup(opts)
      require("luasnip.loaders.from_vscode").lazy_load() -- 加载友好片段
    end,
  },
 
  -- 6. 模糊搜索(telescope.nvim,IDEAVim 增强)
  {
    "nvim-telescope/telescope.nvim",
    dependencies = { "nvim-lua/plenary.nvim" },
    opts = {
      defaults = {
        prompt_prefix = "   ",
        selection_caret = "  ",
        path_display = { "truncate" },
        sorting_strategy = "ascending",
        layout_config = {
          horizontal = { prompt_position = "top", preview_width = 0.55 },
          vertical = { mirror = false },
          width = 0.87,
          height = 0.80,
        },
      },
    },
    keys = {
      { "<leader>ff", "<cmd>Telescope find_files<CR>", desc = "搜索文件(IDEAVim 习惯)" },
      { "<leader>fg", "<cmd>Telescope live_grep<CR>", desc = "搜索文本(IDEAVim 习惯)" },
      { "<leader>fr", "<cmd>Telescope oldfiles<CR>", desc = "搜索最近文件" },
      { "<leader>fb", "<cmd>Telescope buffers<CR>", desc = "搜索缓冲区" },
      { "<leader>fh", "<cmd>Telescope help_tags<CR>", desc = "搜索帮助" },
    },
  },
 
  -- 7. 状态栏(lualine.nvim,IDEAVim 风格)
  {
    "nvim-lualine/lualine.nvim",
    dependencies = { "nvim-tree/nvim-web-devicons" },
    opts = {
      options = {
        theme = "catppuccin",
        component_separators = { left = "", right = "" },
        section_separators = { left = "", right = "" },
        disabled_filetypes = { "NvimTree" },
      },
      sections = {
        lualine_a = { "mode" },
        lualine_b = { "branch", "diff", "diagnostics" },
        lualine_c = { "filename" },
        lualine_x = { "encoding", "fileformat", "filetype" },
        lualine_y = { "progress" },
        lualine_z = { "location" },
      },
    },
  },
 
  -- 8. 项目管理(project.nvim,IDEAVim 增强)
  {
    "ahmedkhalf/project.nvim",
    opts = {
      detection_methods = { "pattern", "lsp" },
      patterns = { ".git", "pyproject.toml", "package.json", "README.md" },
      ignore_lsp = { "null-ls", "lua_ls" },
    },
    config = function(_, opts)
      require("project_nvim").setup(opts)
      require("telescope").load_extension("projects")
    end,
    keys = {
      { "<leader>fp", "<cmd>Telescope projects<CR>", desc = "切换项目(IDEAVim 习惯)" },
    },
  },
 
  -- 9. 终端(toggleterm.nvim,IDEAVim 兼容)
  {
    "akinsho/toggleterm.nvim",
    version = "*",
    opts = {
      size = 15,
      open_mapping = [[<c-\>]], -- IDEAVim 终端快捷键
      hide_numbers = true,
      shade_filetypes = {},
      shade_terminals = true,
      shading_factor = 2,
      start_in_insert = true,
      insert_mappings = true,
      persist_size = true,
      direction = "horizontal",
      close_on_exit = true,
      shell = vim.o.shell,
    },
    keys = {
      { "<C-\\>", "<cmd>ToggleTerm<CR>", desc = "切换终端(IDEAVim 习惯)" },
      { "<leader>tt", "<cmd>ToggleTerm<CR>", desc = "切换终端" },
    },
  },
 
  -- 10. Git 提示(gitsigns.nvim,IDEAVim 增强)
  {
    "lewis6991/gitsigns.nvim",
    event = "BufReadPre",
    opts = {
      signs = {
        add = { text = "│" },
        change = { text = "│" },
        delete = { text = "_" },
        topdelete = { text = "‾" },
        changedelete = { text = "~" },
        untracked = { text = "┆" },
      },
      signcolumn = true,
      numhl = false,
      linehl = false,
      watch_gitdir = { interval = 1000, follow_files = true },
      attach_to_untracked = true,
      current_line_blame = false,
      sign_priority = 6,
      update_debounce = 100,
      status_formatter = nil,
    },
    keys = {
      { "<leader>gh", "<cmd>Gitsigns preview_hunk<CR>", desc = "预览 Git 变更(IDEAVim 习惯)" },
      { "<leader>gr", "<cmd>Gitsigns reset_hunk<CR>", desc = "重置 Git 变更" },
      { "<leader>gb", "<cmd>Gitsigns blame_line<CR>", desc = "Git 行注释" },
    },
  },
 
  -- 11. 文件图标(nvim-web-devicons,依赖插件)
  {
    "nvim-tree/nvim-web-devicons",
    opts = {
      override = {
        lua = { icon = "", color = "#51a0cf", name = "Lua" },
        py = { icon = "", color = "#3776ab", name = "Python" },
        ts = { icon = "", color = "#3178c6", name = "TypeScript" },
        md = { icon = "", color = "#ffffff", name = "Markdown" },
      },
    },
  },
 
  -- 12. 文件管理器(nvim-tree.lua,IDEAVim 兼容)
  {
    "nvim-tree/nvim-tree.lua",
    opts = {
      view = { width = 35 },
      renderer = { indent_markers = { enable = true } },
      actions = { open_file = { quit_on_open = true } },
    },
    keys = { { "<leader>e", "<cmd>NvimTreeToggle<CR>", desc = "打开文件管理器(IDEAVim 习惯)" } },
  },
}

3. 语法解析(plugins/tree-sitter.lua)

集成你指定的所有语言,适配 Python/TS/Markdown:

-- lua/custom/plugins/tree-sitter.lua
return {
  "nvim-treesitter/nvim-treesitter",
  build = ":TSUpdate",
  opts = {
    ensure_installed = {
      -- 通用解析器
      "lua", "vim", "regex", "bash", "json", "yaml", "toml",
      -- 核心语言解析器(你指定的)
      "python", "typescript", "javascript", "tsx", "rust",
      "html", "css", "markdown", "markdown_inline",
    },
    sync_install = false,  -- 异步安装
    highlight = { enable = true },  -- 语法高亮
    indent = { enable = true },     -- 语法缩进
    incremental_selection = {
      enable = true,
      keymaps = {
        init_selection = "<CR>",
        node_incremental = "<CR>",
        node_decremental = "<BS>",
      },
    },
    autotag = { enable = true }, -- 自动闭合标签(TSX/HTML)
  },
  config = function(_, opts)
    require("nvim-treesitter.configs").setup(opts)
    -- 修复 Markdown 高亮
    vim.treesitter.language.register("markdown", "md")
    -- 修复 TSX 高亮
    vim.treesitter.language.register("typescript", "tsx")
  end,
}

五、第五步:分语言配置(langs)

1. Python 配置(langs/python.lua)

聚焦日常开发(LSP、格式化、调试):

-- lua/custom/langs/python.lua
return {
  -- 1. Python LSP(pyright,IDEAVim 兼容)
  {
    "neovim/nvim-lspconfig",
    opts = {
      servers = {
        pyright = {
          settings = {
            python = {
              analysis = {
                autoImportCompletions = true,
                typeCheckingMode = "basic",
                useLibraryCodeForTypes = true,
                diagnosticMode = "openFilesOnly",
              },
            },
          },
        },
      },
    },
  },
 
  -- 2. Python 格式化(black,IDEAVim 自动格式化)
  {
    "psf/black",
    ft = "python",
    config = function()
      vim.api.nvim_create_autocmd("BufWritePre", {
        pattern = "*.py",
        callback = function()
          vim.cmd("Black")
        end,
        desc = "Python 保存自动格式化(black)",
      })
    end,
  },
 
  -- 3. Python 调试(debugpy,IDEAVim 调试习惯)
  {
    "mfussenegger/nvim-dap",
    dependencies = { "rcarriga/nvim-dap-ui", "theHamsta/nvim-dap-virtual-text" },
    ft = "python",
    config = function()
      local dap = require("dap")
      local dapui = require("dapui")
 
      -- 初始化调试 UI
      dapui.setup()
      require("nvim-dap-virtual-text").setup()
 
      -- Python 调试适配器
      dap.adapters.python = {
        type = "executable",
        command = "python3",
        args = { "-m", "debugpy.adapter" },
      }
 
      -- Python 调试配置
      dap.configurations.python = {
        {
          type = "python",
          request = "launch",
          name = "Run current file",
          program = "${file}",
          pythonPath = function()
            local cwd = vim.fn.getcwd()
            if vim.fn.executable(cwd .. "/venv/bin/python") == 1 then
              return cwd .. "/venv/bin/python"
            elseif vim.fn.executable(cwd .. "/.venv/bin/python") == 1 then
              return cwd .. "/.venv/bin/python"
            else
              return "python3"
            end
          end,
        },
        {
          type = "python",
          request = "launch",
          name = "Run selected test",
          program = "${file}",
          args = { "-m", "pytest", "-x", "${file}" },
          pythonPath = "python3",
        },
      }
 
      -- 调试快捷键(IDEAVim 习惯)
      vim.keymap.set("n", "<leader>dp", dap.continue, { desc = "Python 调试启动" })
      vim.keymap.set("n", "<leader>db", dap.toggle_breakpoint, { desc = "Python 切换断点" })
      vim.keymap.set("n", "<leader>dn", dap.step_over, { desc = "Python 单步跳过" })
      vim.keymap.set("n", "<leader>di", dap.step_into, { desc = "Python 单步进入" })
      vim.keymap.set("n", "<leader>do", dap.step_out, { desc = "Python 单步退出" })
      vim.keymap.set("n", "<leader>du", dapui.toggle, { desc = "Python 调试 UI 切换" })
    end,
  },
}

2. TypeScript 配置(langs/typescript.lua)

适配 Bun 环境、ESLint/Prettier:

-- lua/custom/langs/typescript.lua
return {
  -- 1. TS LSP(tsserver,适配 Bun)
  {
    "neovim/nvim-lspconfig",
    opts = {
      servers = {
        tsserver = {
          cmd = { "typescript-language-server", "--stdio" },
          settings = {
            typescript = {
              format = {
                indentSize = 2,
                convertTabsToSpaces = true,
              },
              inlayHints = {
                includeInlayParameterNameHints = "all",
                includeInlayParameterNameHintsWhenArgumentMatchesName = false,
                includeInlayFunctionParameterTypeHints = true,
                includeInlayVariableTypeHints = true,
              },
            },
            javascript = {
              format = { indentSize = 2 },
              inlayHints = { enable = true },
            },
          },
          root_dir = function(fname)
            return require("lspconfig.util").root_pattern("package.json", "tsconfig.json", "jsconfig.json", ".git")(fname)
          end,
        },
      },
    },
  },
 
  -- 2. Bun 集成(适配 Bun 运行环境)
  {
    "OmniSharp/omnisharp-vim", -- 辅助 Bun 识别
    ft = { "typescript", "javascript", "tsx" },
    config = function()
      vim.g.omnisharp_bun_enabled = 1 -- 启用 Bun 支持
    end,
  },
 
  -- 3. TS/JS 格式化(Prettier,IDEAVim 自动格式化)
  {
    "MunifTanjim/prettier.nvim",
    dependencies = { "jose-elias-alvarez/null-ls.nvim" },
    ft = { "typescript", "javascript", "tsx", "jsx", "json", "yaml" },
    config = function()
      local null_ls = require("null-ls")
      null_ls.setup({
        sources = {
          null_ls.builtins.formatting.prettier.with({
            extra_args = { "--single-quote", "--tab-width", "2" },
            runtime_condition = function(params)
              return vim.fn.executable("bun") == 1 or vim.fn.executable("prettier") == 1
            end,
          }),
          null_ls.builtins.diagnostics.eslint.with({
            runtime_condition = function(params)
              return vim.fn.executable("eslint") == 1
            end,
          }),
        },
      })
 
      -- 保存自动格式化
      vim.api.nvim_create_autocmd("BufWritePre", {
        pattern = { "*.ts", "*.js", "*.tsx", "*.jsx" },
        callback = function()
          vim.cmd("Prettier")
        end,
        desc = "TS/JS 保存自动格式化(Prettier)",
      })
    end,
  },
}

3. Markdown 配置(langs/markdown.lua)

聚焦写作(预览、表格、语法高亮):

-- lua/custom/langs/markdown.lua
return {
  -- 1. Markdown 预览(glow.nvim,IDEAVim 写作习惯)
  {
    "ellisonleao/glow.nvim",
    ft = "markdown",
    opts = {
      border = "rounded",
      width = 120,
      height = 30,
      style = "dark",
    },
    keys = {
      { "<leader>mp", "<cmd>Glow<CR>", desc = "Markdown 预览(IDEAVim 习惯)" },
      { "<leader>mc", "<cmd>Glow!<CR>", desc = "关闭 Markdown 预览" },
    },
  },
 
  -- 2. Markdown 表格(markdown-table-mode.nvim)
  {
    "dhruvasagar/vim-table-mode",
    ft = "markdown",
    keys = {
      { "<leader>mt", "<cmd>TableModeToggle<CR>", desc = "Markdown 表格模式切换" },
    },
    config = function()
      vim.g.table_mode_corner = "|" -- 表格边框风格
      vim.g.table_mode_header_fillchar = "-"
    end,
  },
 
  -- 3. Markdown 链接跳转(markdown-links.nvim)
  {
    "antonk52/markdown-links.nvim",
    ft = "markdown",
    keys = {
      { "<leader>ml", "<cmd>MarkdownLinks<CR>", desc = "Markdown 链接跳转" },
    },
    config = function()
      require("markdown-links").setup({})
    end,
  },
}

六、第六步:启动 & 验证

1. 安装依赖(终端执行)

# 安装 tree-sitter 依赖(可选)
brew install tree-sitter
 
# 安装 Python/TS 格式化工具
pip3 install black
npm install -g prettier eslint typescript-language-server
 
# 安装 Markdown 预览依赖
brew install glow

2. 启动 NvChad 并安装插件

# 重启 NvChad
nvim
 
# 在 Normal 模式下安装插件
:Lazy install
 
# 安装 tree-sitter 解析器
:TSInstall all

3. 验证核心功能

  • Leader 键:按 ,e → 打开文件管理器(逗号是 Leader 键);
  • IDEAVim 映射:Insert 模式按 Ctrl+a → 跳转到行首;
  • Python:打开 .py 文件,保存自动格式化(black);
  • TS:打开 .ts 文件,保存自动格式化(Prettier);
  • Markdown:打开 .md 文件,按 ,mp → 预览 Markdown。

七、核心总结

  1. 所有自定义都在 lua/custom:根目录/lua 目录不碰,只改 custom 下的文件;
  2. 通用配置放 general:IDEAVim 快捷键、全局选项、自动命令;
  3. 分语言放 langs:Python/TS/Markdown 专属配置,互不干扰;
  4. 插件放 plugins:通用插件集成你指定的所有功能,适配 IDEAVim 习惯。

这套配置完全适配你的日常开发需求,后续想加 Rust/HTML/CSS 等语言,只需在 langs 下新增文件即可,保持结构清晰、易维护。