Neovim 0.10+ 已经是一流的 IDE 平台:内置 LSP 客户端、Treesitter 语法、
Lua 配置。Lazy.nvim 是事实标准的插件管理器,懒加载 + 锁版本。
下面给一个 < 100 行 Lua、能开箱即用的最小配置。
1. 装 Neovim 0.10+
# Ubuntu 24.04+ apt 自带;老版本用 ppa / appimage / brew
sudo apt install -y neovim
nvim --version # 确认 >= 0.10
2. 目录结构
~/.config/nvim/
├── init.lua
└── lua/
├── options.lua
├── keymaps.lua
├── plugins.lua
└── lsp.lua
3. init.lua
-- 一键 bootstrap lazy.nvim
local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
if not vim.uv.fs_stat(lazypath) then
vim.fn.system({
'git', 'clone', '--filter=blob:none',
'https://github.com/folke/lazy.nvim.git',
'--branch=stable', lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
require('options')
require('keymaps')
require('lazy').setup(require('plugins'))
require('lsp')
4. lua/options.lua
local o = vim.opt
o.number = true
o.relativenumber = true
o.signcolumn = 'yes' -- 给 LSP / git 留位置
o.expandtab = true
o.shiftwidth = 2
o.tabstop = 2
o.smartindent = true
o.wrap = false
o.ignorecase = true
o.smartcase = true
o.termguicolors = true
o.cursorline = true
o.scrolloff = 8
o.updatetime = 250 -- 让 hover / diag 更快
o.clipboard = 'unnamedplus' -- 跟系统剪贴板互通
o.splitright = true
o.splitbelow = true
o.undofile = true -- 跨 session undo
o.mouse = 'a'
5. lua/keymaps.lua
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
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', '<esc>', '<cmd>nohlsearch<cr>')
map('n', '<C-h>', '<C-w>h')
map('n', '<C-j>', '<C-w>j')
map('n', '<C-k>', '<C-w>k')
map('n', '<C-l>', '<C-w>l')
map('v', '<', '<gv') -- 缩进后保持选中
map('v', '>', '>gv')
6. lua/plugins.lua
return {
-- 配色
{ 'catppuccin/nvim', name = 'catppuccin',
config = function() vim.cmd.colorscheme('catppuccin-mocha') end },
-- 文件树
{ 'nvim-tree/nvim-tree.lua',
dependencies = { 'nvim-tree/nvim-web-devicons' },
keys = { { '<leader>e', '<cmd>NvimTreeToggle<cr>', desc = 'File tree' } },
config = function() require('nvim-tree').setup() end,
},
-- 模糊搜索
{ 'nvim-telescope/telescope.nvim',
dependencies = { 'nvim-lua/plenary.nvim' },
keys = {
{ '<leader>f', '<cmd>Telescope find_files<cr>', desc = 'Find files' },
{ '<leader>g', '<cmd>Telescope live_grep<cr>', desc = 'Live grep' },
{ '<leader>b', '<cmd>Telescope buffers<cr>', desc = 'Buffers' },
},
},
-- 语法高亮(Treesitter)
{ 'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate',
config = function()
require('nvim-treesitter.configs').setup({
ensure_installed = { 'lua', 'python', 'javascript', 'typescript',
'tsx', 'go', 'rust', 'bash', 'markdown',
'json', 'yaml', 'html', 'css' },
highlight = { enable = true },
indent = { enable = true },
})
end,
},
-- Git 集成
{ 'lewis6991/gitsigns.nvim',
config = function() require('gitsigns').setup() end },
-- LSP 安装管理
{ 'williamboman/mason.nvim', config = true },
{ 'williamboman/mason-lspconfig.nvim',
dependencies = { 'mason.nvim', 'neovim/nvim-lspconfig' },
config = function()
require('mason-lspconfig').setup({
ensure_installed = { 'pyright', 'ts_ls', 'lua_ls', 'gopls', 'rust_analyzer' },
})
end,
},
-- 补全
{ 'hrsh7th/nvim-cmp',
dependencies = {
'hrsh7th/cmp-nvim-lsp',
'hrsh7th/cmp-buffer',
'hrsh7th/cmp-path',
'L3MON4D3/LuaSnip',
'saadparwaiz1/cmp_luasnip',
},
config = function()
local cmp = require('cmp')
cmp.setup({
snippet = { expand = function(args) require('luasnip').lsp_expand(args.body) end },
mapping = cmp.mapping.preset.insert({
['<C-Space>'] = cmp.mapping.complete(),
['<CR>'] = cmp.mapping.confirm({ select = true }),
['<Tab>'] = cmp.mapping.select_next_item(),
['<S-Tab>'] = cmp.mapping.select_prev_item(),
}),
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
{ name = 'luasnip' },
{ name = 'buffer' },
{ name = 'path' },
}),
})
end,
},
-- 状态栏
{ 'nvim-lualine/lualine.nvim',
config = function() require('lualine').setup() end },
}
7. lua/lsp.lua
local lspconfig = require('lspconfig')
local caps = require('cmp_nvim_lsp').default_capabilities()
local on_attach = function(_, buf)
local map = function(keys, fn, desc)
vim.keymap.set('n', keys, fn, { buffer = buf, desc = desc })
end
map('gd', vim.lsp.buf.definition, 'Go to definition')
map('gr', vim.lsp.buf.references, 'References')
map('K', vim.lsp.buf.hover, 'Hover')
map('<leader>rn', vim.lsp.buf.rename, 'Rename')
map('<leader>ca', vim.lsp.buf.code_action, 'Code action')
map('<leader>d', vim.diagnostic.open_float, 'Show diagnostic')
end
for _, server in ipairs({ 'pyright', 'ts_ls', 'gopls', 'rust_analyzer', 'lua_ls' }) do
lspconfig[server].setup({
on_attach = on_attach,
capabilities = caps,
})
end
-- 保存时自动格式化(如果 LSP 支持)
vim.api.nvim_create_autocmd('BufWritePre', {
callback = function() vim.lsp.buf.format({ async = false }) end,
})
8. 第一次启动
nvim
# Lazy 自动 clone 插件,等几秒
# :Mason ← 进去能看到 LSP 安装状态
9. 升级 / 锁版本
:Lazy update " 升级所有
:Lazy sync " 装新加的、删旧的
:Lazy log " 看更新历史
Lazy 会在 ~/.config/nvim/lazy-lock.json 记录每个插件的 commit hash。
进 git 让别的机器同步到完全一样的版本。
10. 排错
:checkhealth
" 列出每个组件的健康状态
" 缺什么(python3 / npm / node / fd / ripgrep)一目了然
:LspInfo
" 看当前 buffer 的 LSP 状态
踩过的坑
- 不装
ripgrep→ Telescope live_grep 不能用。sudo apt install ripgrep。 - LSP server 装了但没启动:通常因为 root marker 找不到(pyright 找
pyproject.toml/setup.py)。在项目根目录打开 Neovim。 - 自动 format on save 把你刚写的中文注释格式化乱:把不可信的 formatter
关掉,或者:noa w跳过 autocmd。 - 升级 Treesitter parser 时 build 失败:缺 gcc / make。装编译工具链
sudo apt install build-essential。
登录后参与评论。