从零重建 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 glow2. 启动 NvChad 并安装插件
# 重启 NvChad
nvim
# 在 Normal 模式下安装插件
:Lazy install
# 安装 tree-sitter 解析器
:TSInstall all3. 验证核心功能
- Leader 键:按
,e→ 打开文件管理器(逗号是 Leader 键); - IDEAVim 映射:Insert 模式按
Ctrl+a→ 跳转到行首; - Python:打开
.py文件,保存自动格式化(black); - TS:打开
.ts文件,保存自动格式化(Prettier); - Markdown:打开
.md文件,按,mp→ 预览 Markdown。
七、核心总结
- 所有自定义都在
lua/custom:根目录/lua 目录不碰,只改 custom 下的文件; - 通用配置放
general:IDEAVim 快捷键、全局选项、自动命令; - 分语言放
langs:Python/TS/Markdown 专属配置,互不干扰; - 插件放
plugins:通用插件集成你指定的所有功能,适配 IDEAVim 习惯。
这套配置完全适配你的日常开发需求,后续想加 Rust/HTML/CSS 等语言,只需在 langs 下新增文件即可,保持结构清晰、易维护。