跳转至

Neovim 现代配置

为什么要学 Neovim 现代配置

Neovim 已经从传统 Vim 的继承者演变为一个现代化的可编程编辑器平台。通过 Lua 配置和丰富的插件生态,Neovim 可以提供媲美 VS Code 的开发体验(LSP 自动补全、模糊搜索、Git 集成、调试器),同时保持终端原生的高效操作。掌握 Neovim 现代配置,意味着你在任何服务器、任何终端中都能拥有一个高效的 IDE 级开发环境。


核心概念

概念白话解释用途
Lua ConfigLua 配置替代 VimScript 的现代配置语言
LSP语言服务协议代码补全、诊断、跳转
Treesitter语法树解析精确的语法高亮和代码分析
Plugin Manager插件管理器安装和管理插件(lazy.nvim)
Telescope模糊搜索文件、内容、符号的快速查找
MasonLSP 安装器一键安装语言服务器
Which-key快捷键提示显示可用的按键绑定

安装配置

安装 Neovim

# Ubuntu (最新版)
sudo add-apt-repository ppa:neovim-ppa/unstable
sudo apt update && sudo apt install neovim

# macOS
brew install neovim

# 从源码编译(获取最新版)
git clone https://github.com/neovim/neovim.git
cd neovim && make CMAKE_BUILD_TYPE=Release
sudo make install

配置目录结构

~/.config/nvim/
├── init.lua                 # 入口文件
├── lua/
│   ├── config/
│   │   ├── options.lua      # 基础设置
│   │   ├── keymaps.lua      # 快捷键
│   │   ├── autocmds.lua     # 自动命令
│   │   └── lazy.lua         # 插件管理器初始化
│   └── plugins/
│       ├── lsp.lua          # LSP 配置
│       ├── treesitter.lua   # Treesitter 配置
│       ├── telescope.lua    # 搜索配置
│       ├── completion.lua   # 补全配置
│       └── ui.lua           # UI 插件配置

基础设置

-- lua/config/options.lua
local opt = vim.opt

opt.number = true            -- 行号
opt.relativenumber = true    -- 相对行号
opt.tabstop = 2              -- Tab 宽度
opt.shiftwidth = 2           -- 缩进宽度
opt.expandtab = true         -- Tab 转空格
opt.smartindent = true       -- 智能缩进
opt.wrap = false             -- 不折行
opt.ignorecase = true        -- 搜索忽略大小写
opt.smartcase = true         -- 有大写时区分大小写
opt.termguicolors = true     -- 24位色
opt.signcolumn = "yes"       -- 始终显示标记列
opt.clipboard = "unnamedplus" -- 系统剪贴板
opt.scrolloff = 8            -- 滚动时保留行数
opt.updatetime = 250         -- 减少延迟
opt.undofile = true          -- 持久化撤销
opt.splitright = true        -- 右侧分屏
opt.splitbelow = true        -- 下方分屏

vim.g.mapleader = " "        -- Leader 键为空格

快速上手

插件管理器 lazy.nvim

-- lua/config/lazy.lua
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.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("lazy").setup("plugins")  -- 加载 lua/plugins/ 目录

核心插件配置

-- lua/plugins/ui.lua
return {
  -- 主题
  {
    "catppuccin/nvim",
    name = "catppuccin",
    priority = 1000,
    config = function()
      vim.cmd.colorscheme("catppuccin-mocha")
    end,
  },
  -- 状态栏
  {
    "nvim-lualine/lualine.nvim",
    dependencies = { "nvim-tree/nvim-web-devicons" },
    config = function()
      require("lualine").setup({ options = { theme = "catppuccin" } })
    end,
  },
  -- 文件树
  {
    "nvim-neo-tree/neo-tree.nvim",
    dependencies = { "nvim-lua/plenary.nvim", "nvim-tree/nvim-web-devicons", "MunifTanjim/nui.nvim" },
    keys = { { "<leader>e", "<cmd>Neotree toggle<cr>", desc = "文件树" } },
  },
}

LSP 配置

-- lua/plugins/lsp.lua
return {
  {
    "neovim/nvim-lspconfig",
    dependencies = {
      "williamboman/mason.nvim",
      "williamboman/mason-lspconfig.nvim",
    },
    config = function()
      require("mason").setup()
      require("mason-lspconfig").setup({
        ensure_installed = {
          "lua_ls", "pyright", "ts_ls", "rust_analyzer", "gopls",
        },
      })

      local lspconfig = require("lspconfig")
      local capabilities = require("cmp_nvim_lsp").default_capabilities()

      -- 通用 on_attach
      local on_attach = function(_, bufnr)
        local map = function(keys, func, desc)
          vim.keymap.set("n", keys, func, { buffer = bufnr, desc = desc })
        end
        map("gd", vim.lsp.buf.definition, "跳转定义")
        map("gr", vim.lsp.buf.references, "查看引用")
        map("K", vim.lsp.buf.hover, "悬浮文档")
        map("<leader>rn", vim.lsp.buf.rename, "重命名")
        map("<leader>ca", vim.lsp.buf.code_action, "代码操作")
      end

      -- 配置各语言服务
      local servers = { "pyright", "ts_ls", "rust_analyzer", "gopls" }
      for _, server in ipairs(servers) do
        lspconfig[server].setup({
          capabilities = capabilities,
          on_attach = on_attach,
        })
      end
    end,
  },
}

快捷键

-- lua/config/keymaps.lua
local map = vim.keymap.set

-- 文件操作
map("n", "<leader>w", "<cmd>w<cr>", { desc = "保存" })
map("n", "<leader>q", "<cmd>q<cr>", { desc = "退出" })

-- 窗口导航
map("n", "<C-h>", "<C-w>h", { desc = "左窗口" })
map("n", "<C-l>", "<C-w>l", { desc = "右窗口" })
map("n", "<C-j>", "<C-w>j", { desc = "下窗口" })
map("n", "<C-k>", "<C-w>k", { desc = "上窗口" })

-- 搜索
map("n", "<leader>ff", "<cmd>Telescope find_files<cr>", { desc = "查找文件" })
map("n", "<leader>fg", "<cmd>Telescope live_grep<cr>", { desc = "全局搜索" })
map("n", "<leader>fb", "<cmd>Telescope buffers<cr>", { desc = "切换缓冲区" })

-- 代码
map("n", "<leader>cf", vim.lsp.buf.format, { desc = "格式化" })

进阶用法

Telescope 深度配置

return {
  "nvim-telescope/telescope.nvim",
  dependencies = {
    "nvim-lua/plenary.nvim",
    { "nvim-telescope/telescope-fzf-native.nvim", build = "make" },
  },
  config = function()
    local telescope = require("telescope")
    telescope.setup({
      defaults = {
        file_ignore_patterns = { "node_modules", ".git/", "target/" },
        layout_strategy = "horizontal",
        layout_config = { preview_width = 0.6 },
      },
      pickers = {
        find_files = { hidden = true },
      },
    })
    telescope.load_extension("fzf")
  end,
}

自动补全

return {
  "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")
    local luasnip = require("luasnip")

    cmp.setup({
      snippet = {
        expand = function(args) 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(function(fallback)
          if cmp.visible() then cmp.select_next_item()
          elseif luasnip.expand_or_jumpable() then luasnip.expand_or_jump()
          else fallback() end
        end, { "i", "s" }),
      }),
      sources = cmp.config.sources({
        { name = "nvim_lsp" },
        { name = "luasnip" },
      }, {
        { name = "buffer" },
        { name = "path" },
      }),
    })
  end,
}

常见问题

Q: 配置太复杂不想自己写?

使用预配置方案: - LazyVim:最推荐,开箱即用 - NvChad:美观,配置清晰 - AstroNvim:功能全面

Q: 插件冲突怎么解决?

  • 使用 :Lazy profile 检查加载顺序
  • 确认 dependencies 声明正确
  • 使用 lazy = true 延迟加载减少冲突

Q: LSP 不工作?

:LspInfo          " 查看当前 LSP 状态
:Mason            " 检查语言服务器安装
:checkhealth lsp  " 健康检查

参考资源

  • Neovim 官方:https://neovim.io/
  • lazy.nvim:https://github.com/folke/lazy.nvim
  • LazyVim:https://www.lazyvim.org/
  • 插件搜索:https://dotfyle.com/
  • Neovim Craft:https://neovimcraft.com/