From b01f94be0a7056349ec25d3490e5d7a5e7abe211 Mon Sep 17 00:00:00 2001 From: newbieQQ Date: Thu, 11 Jun 2026 16:16:45 +0800 Subject: [PATCH] docs: add README and key config comments --- README.md | 171 +++++++++++++++++++++++++++++++++++ init.lua | 4 +- lua/G.lua | 2 + lua/lsp/basedpyright.lua | 1 + lua/lsp/go.lua | 1 + lua/options.lua | 5 +- lua/plugs/dev.lua | 2 +- lua/plugs/edit-plugs.lua | 6 +- lua/plugs/mason.lua | 2 +- lua/plugs/nvim-cmp.lua | 8 +- lua/plugs/nvim-lspconfig.lua | 2 + lua/plugs/treesitter.lua | 4 +- 12 files changed, 199 insertions(+), 9 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..4dd55c2 --- /dev/null +++ b/README.md @@ -0,0 +1,171 @@ +# Neovim 配置 + +基于 Neovim 0.12+,lazy.nvim 管理插件,支持原生和 VSCode Neovim 双模式。 + +## 目录结构 + +``` +init.lua # 入口:安装 lazy.nvim → keymaps → 分支判断 +lua/ + G.lua # 全局工具单例(vim API 别名 + 映射/命令/自动命令封装) + keymap.lua # 基础快捷键 + options.lua # vim.opt 基础设置 + vsc.lua # VSCode Neovim 模式下的精简启动(仅编辑插件) + plugs.lua # 插件聚合器(10 个模块) + plugs/ + nvim-lspconfig.lua # LSP 核心:7 个 server 注册 + LSP 快捷键 + mason.lua # LSP server 自动安装(Mason) + nvim-cmp.lua # 补全引擎(nvim-cmp + vsnip + lspkind + 命令行补全) + treesitter.lua # 语法高亮 + 自动安装 parser + symbols-outline.lua # 代码大纲侧边栏 + winbar.lua # 顶部文件路径 + 函数标签 + nvimtree.lua # 文件树 + theme.lua # 主题(tokyonight)+ 状态栏(lualine)+ 标签栏(tabline) + edit-plugs.lua # 编辑增强(fzf/surround/wildfire/多光标/对齐/Copilot/折叠/hop) + dev.lua # 开发工具(colorizer/go.nvim/conda/toggleterm) + lsp/ + lua.lua # Lua LSP(LuaJIT + 全局变量声明) + c.lua # C/C++ LSP(clangd)+ :R 编译运行 + bash.lua # Bash LSP + :R 运行 + go.lua # Go LSP(gopls)+ :R / :Rgin 运行 + basedpyright.lua # Python LSP(basedpyright)+ :R 运行 + yaml.lua # YAML LSP + GitHub Workflow schema + json.lua # JSON LSP +snippets/ # 代码片段(C/Go/JSON/Lua) +``` + +## 启动流程 + +``` +G.lua → 克隆/定位 lazy.nvim → keymap.lua → + 若 VSCode 环境 → vsc.lua(仅编辑插件) + 若原生 Neovim → options.lua → lazy.setup(plugs.lua) +``` + +## 插件总表(~28 个) + +| 分类 | 插件 | 用途 | +|------|------|------| +| LSP | nvim-lspconfig | LSP 客户端配置 | +| LSP | Mason + mason-lspconfig | LSP server 自动下载 | +| LSP | lua_ls, clangd, bashls, gopls, basedpyright, yamlls, jsonls | 7 种语言 LSP | +| 补全 | nvim-cmp + cmp-nvim-lsp + cmp-buffer + cmp-path + cmp-cmdline | 补全引擎 | +| 补全 | vim-vsnip + cmp-vsnip | 代码片段引擎 | +| 补全 | lspkind-nvim | 补全图标 | +| 语法 | nvim-treesitter | 语法高亮 + 缩进检测 | +| 语法 | nvim-autopairs | 自动括号配对 | +| 语法 | nvim-hlchunk | 括号层级和缩进色块 | +| 主题 | tokyonight.nvim | 配色方案 | +| UI | lualine.nvim | 状态栏 | +| UI | tabline.nvim | 顶部标签栏 | +| UI | winbar.nvim | 顶部文件名 + 函数路径 | +| UI | nvim-tree.lua | 侧边文件树 | +| UI | symbols-outline.nvim | 代码大纲 | +| UI | colorizer | 颜色值可视化 | +| 编辑 | nvim-fzf | 模糊搜索 | +| 编辑 | vim-surround | 环绕字符操作(cs/ds/ys) | +| 编辑 | wildfire.vim | 选区自动扩大/缩小 | +| 编辑 | vim-multiple-cursors | 多光标编辑 | +| 编辑 | vim-easy-align | 对齐排版 | +| 编辑 | hop.nvim | 快速跳转(替代 f/F/t/T) | +| 编辑 | nvim-ufo | 现代折叠(treesitter 驱动) | +| AI | copilot.vim | GitHub Copilot 行内补全 | +| 语言 | go.nvim | Go 开发增强(test/coverage 等) | +| 语言 | nvim-conda | Conda 环境切换 | +| 终端 | toggleterm.nvim | 浮层终端 | + +## 快捷键速查 + +### 基础操作 + +| 键 | 模式 | 功能 | +|----|------|------| +| `nh` | n | 清除搜索高亮 | +| `rp` | n | 全局替换 `:%s/` | +| `y` / `p` / `v` | n | 全文件复制/粘贴/全选 | +| `` / `` | n | 切换左右标签页 | +| `` | n | 窗口间跳转 | +| `` / `` | n | 关闭窗口 / 强制关闭 | +| `` | n | sudo 强制保存 | +| `` | v | 复制到系统剪切板 | +| `` | n | 文件树开关 | +| `` | n | 代码大纲开关 | +| `` | n/i | 终端开关 | +| `` | n | 调整窗口大小 | + +### LSP + +| 键 | 模式 | 功能 | +|----|------|------| +| `gd` | n | 跳转到定义 | +| `gh` | n | 悬浮文档 | +| `gD` | n | 跳转到声明 | +| `gi` | n | 跳转到实现 | +| `gr` | n | 查找引用 | +| `` | n | 重命名符号 | +| `` | n | 代码格式化 | + +### 语言运行 `:R` + +| 语言 | 命令 | +|------|------| +| C/C++ | 编译 → 运行 → 删二进制 | +| Bash | `sh %` | +| Go | `go run %`;`:Rgin` 运行 `main.go` | +| Python | `python3 %` | + +### 补全(插入模式) + +| 键 | 功能 | +|----|------| +| `` / `` | 选择补全项 / snippet 占位跳转 | +| ``(未选择时) | 换行 | +| ``(选择后) | 确认补全 | +| `Tab` | Copilot 接受建议 | + +### 命令栏 / 搜索栏补全 + +| 键 | 功能 | +|----|------| +| `Tab` / `S-Tab` | 选择补全项 | +| ``(未选择时) | 直接执行命令/搜索 | +| ``(选择后) | 确认补全 | + +### 编辑 + +| 键 | 模式 | 功能 | +|----|------|------| +| `f` / `F` / `t` / `T` | n | hop 行内跳转(覆盖原生) | +| `` | n | hop 双字符跳转 | +| `ga` / `=` | v | EasyAlign 对齐 | +| `gc` / `gcc` | n | 注释切换(Neovim 0.12 内置) | +| `zc` / `zo` / `za` / `zR` | n | 折叠(ufo) | + +### 文件树内 + +| 键 | 功能 | +|----|------| +| `v` | 垂直分屏打开 | +| `s` | 水平分屏打开 | + +## LSP 说明 + +- 使用 Neovim 0.11+ 新 API:`vim.lsp.config` / `vim.lsp.enable` +- `capabilities` 由 `cmp_nvim_lsp` 统一在 `nvim-lspconfig.lua` 注入,各语言文件不重复 require +- `basedpyright` 替代了 `pyright`(类型检查更强) +- Mason 自动安装:bashls、lua_ls、jsonls、yamlls(basedpyright 需手动装) +- Treesitter 关闭了 txt parser,禁用了 Go(恢复中由 go.nvim 处理) + +## 安装 + +```bash +# 克隆到 Neovim 配置目录 +git clone https://git.qyhhh.top/newbie/nvim.git ~/.config/nvim + +# 首次启动会自动安装 lazy.nvim 及全部插件 +nvim +``` + +## 许可 + +MIT diff --git a/init.lua b/init.lua index 96411f5..3504cc5 100644 --- a/init.lua +++ b/init.lua @@ -1,6 +1,6 @@ G = require('G') --- 安装/定位 lazy.nvim(VSCode 和原生 Neovim 都需要) +-- lazy.nvim 必须在 VSCode 和原生环境都可用:原生用它装插件,VSCode 的 vsc.lua 也需要 require('lazy') local lazypath = G.fn.stdpath('data') .. '/lazy/lazy.nvim' if not G.loop.fs_stat(lazypath) then G.fn.system({ @@ -14,9 +14,11 @@ if not G.loop.fs_stat(lazypath) then end G.opt.rtp:prepend(lazypath) +-- keymap 在两个环境都加载(基础键位都不依赖插件) require('keymap') if G.g.vscode then + -- VSCode Neovim 模式:只加载编辑插件,不加载 LSP/补全/主题/选项 require('vscode') else require('options') diff --git a/lua/G.lua b/lua/G.lua index 0212ddd..70eaf76 100644 --- a/lua/G.lua +++ b/lua/G.lua @@ -13,6 +13,7 @@ G.lb = vim.lsp.buf G.dic = vim.diagnostic G.cgp = vim.nvim_create_augroup +-- 批量设置键映射,3 元素自动加 { noremap = true },4 元素用传入的 opts function G.map(maps) for _, map in pairs(maps) do vim.keymap.set(map[1], map[2], map[3], map[4] or { noremap = true }) @@ -41,6 +42,7 @@ function G.au(even, opts) return G.api.nvim_create_autocmd(even, opts) end +-- :R 命令工厂:在下方分屏开终端运行指定命令,省去 5 个 LSP 文件的重复代码 function G.run_cmd(cmd) return function() G.cmd [[set splitbelow | sp]] diff --git a/lua/lsp/basedpyright.lua b/lua/lsp/basedpyright.lua index 873421c..fa32aee 100644 --- a/lua/lsp/basedpyright.lua +++ b/lua/lsp/basedpyright.lua @@ -1,4 +1,5 @@ return { + -- basedpyright:pyright 的增强分支,类型检查更强。capabilities 由 nvim-lspconfig.lua 统一注入 settings = { basedpyright = { analysis = { diff --git a/lua/lsp/go.lua b/lua/lsp/go.lua index e5d19ca..52a9b61 100644 --- a/lua/lsp/go.lua +++ b/lua/lsp/go.lua @@ -1,4 +1,5 @@ return { + -- gopls + :R(go run %)+ :Rgin(go run ./main.go,主入口专用) on_attach = function() G.api.nvim_create_user_command('R', G.run_cmd('go run %'), {}) G.api.nvim_create_user_command('Rgin', G.run_cmd('go run ./main.go'), {}) diff --git a/lua/options.lua b/lua/options.lua index 8b7ff08..d6bafc5 100644 --- a/lua/options.lua +++ b/lua/options.lua @@ -36,10 +36,11 @@ G.opt.wrap = false -- 文件判断 G.cmd("filetype plugin indent on") --- 取消换行注释 +-- 取消换行注释:o 和 O 不自动续注释;回车继续续注释(一次设定,formatoptions 不会变) G.opt.formatoptions = G.opt.formatoptions - "o" + "r" +-- 进入插入模式时自动关搜索高亮(个人偏好:打字时不想被高亮干扰) G.au({ "InsertEnter" }, { pattern = { "*" }, callback = function() @@ -47,6 +48,7 @@ G.au({ "InsertEnter" }, { end, }) +-- .code-snippets 文件强制识别为 JSON(方便编辑,否则无法语法高亮) G.au({ "VimEnter", "BufEnter" }, { pattern = { "*.code-snippets" }, callback = function() @@ -55,6 +57,7 @@ G.au({ "VimEnter", "BufEnter" }, { }) +-- 自动检测 Conda Python 环境,优先用 conda 里的 python local function isempty(s) return s == nil or s == "" end diff --git a/lua/plugs/dev.lua b/lua/plugs/dev.lua index 6d6fe05..1ee3e5b 100644 --- a/lua/plugs/dev.lua +++ b/lua/plugs/dev.lua @@ -9,7 +9,7 @@ return { -- end -- }, { - -- go开发 + -- go 开发:只对 go/gomod 文件加载,build 时检测是否装了 Go(无 Go 环境静默跳过) "ray-x/go.nvim", dependencies = { "ray-x/guihua.lua", diff --git a/lua/plugs/edit-plugs.lua b/lua/plugs/edit-plugs.lua index a209b64..b8a3026 100644 --- a/lua/plugs/edit-plugs.lua +++ b/lua/plugs/edit-plugs.lua @@ -23,11 +23,12 @@ return { }) end }, - -- 注释插件(neovim 0.12 内置 gc,用 treesitter,先注释测试) + -- 注释插件:Neovim 0.12 内置 treesitter gc/gcc 注释切换,暂注释掉此插件测试 -- { -- 'tpope/vim-commentary', -- }, { + -- Copilot 懒加载:只在插入模式需要(和 nvim-cmp 共用 Tab 键,cmp 改用 C-n/C-p 避让) 'github/copilot.vim', -- github copilot event = "InsertEnter", }, @@ -58,7 +59,8 @@ return { end }, { - -- hop + -- hop 快速跳转:用 f/F/t/T 做行内单字符跳转, 做双字符跳转 + -- 注意:这会覆盖 Vim 原生的 f/F/t/T "phaazon/hop.nvim", branch = "v2", keys = { diff --git a/lua/plugs/mason.lua b/lua/plugs/mason.lua index 019c3e1..831b658 100644 --- a/lua/plugs/mason.lua +++ b/lua/plugs/mason.lua @@ -18,7 +18,7 @@ return { require("mason-lspconfig").setup({ ensure_installed = { "bashls", - -- "basedpyright", + -- "basedpyright", -- Python LSP 需手动装(有的机器不用 Python) "lua_ls", "jsonls", "yamlls", diff --git a/lua/plugs/nvim-cmp.lua b/lua/plugs/nvim-cmp.lua index 191a2e9..60bd2a4 100644 --- a/lua/plugs/nvim-cmp.lua +++ b/lua/plugs/nvim-cmp.lua @@ -33,6 +33,7 @@ return { vim.fn["vsnip#anonymous"](args.body) end, }, + -- 补全来源优先级:LSP > 片段 > buffer > 路径 sources = cmp.config.sources({ { name = 'nvim_lsp' }, { name = 'vsnip' }, @@ -40,8 +41,10 @@ return { { name = 'buffer' }, { name = 'path' } ), + -- 插入模式映射:C-n/C-p 选择,CR 未选时换行(避免冲突 Copilot 的 Tab) mapping = cmp.mapping.preset.insert({ + -- 回车:手动选择后确认,未选时 fallback 到换行 [""] = cmp.mapping({ i = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false }), c = function(fallback) @@ -53,6 +56,7 @@ return { end, }), + -- C-n:选下一个补全项 / 展开 vsnip 占位 / 手动触发补全 [""] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_next_item() @@ -103,7 +107,7 @@ return { } require('cmp').setup(cmp_opt) - -- 命令栏补全(Tab 导航,回车无选择时直接执行) + -- 命令栏补全:Tab 导航,回车时若有手动选择则确认,否则直接执行命令(不卡住) require('cmp').setup.cmdline(':', { mapping = { [''] = cmp.mapping(cmp.mapping.select_next_item(), { 'c' }), @@ -113,7 +117,7 @@ return { if cmp.visible() and cmp.get_active_entry() then cmp.confirm({ select = false }) else - fallback() + fallback() -- 没选的时候 fallback = 直接执行命令 end end, }), diff --git a/lua/plugs/nvim-lspconfig.lua b/lua/plugs/nvim-lspconfig.lua index ddfb22d..f19e1cb 100644 --- a/lua/plugs/nvim-lspconfig.lua +++ b/lua/plugs/nvim-lspconfig.lua @@ -19,6 +19,8 @@ return { jsonls = require('lsp.json'), } + -- capabilities 在此处统一注入,各 lsp/*.lua 不单独 require cmp_nvim_lsp + -- 避免模块层面 require 带来的隐式依赖 local capabilities = require('cmp_nvim_lsp').default_capabilities() for server, config in pairs(servers) do config.capabilities = capabilities diff --git a/lua/plugs/treesitter.lua b/lua/plugs/treesitter.lua index 4da2bfd..d4a0f56 100644 --- a/lua/plugs/treesitter.lua +++ b/lua/plugs/treesitter.lua @@ -1,6 +1,6 @@ return { { - -- 语法高亮 -- + -- 语法高亮:auto_install=true 自动装 parser,ignore_install 跳过 txt 'nvim-treesitter/nvim-treesitter', config = function() local treesitter_opt = { @@ -12,6 +12,7 @@ return { auto_install = true, highlight = { enable = true, + -- 大于 100KB 的文件关闭 treesitter 高亮(性能优化) disable = function(_, buf) local max_filesize = 100 * 1024 -- 100 KB local ok, stats = pcall(G.loop.fs_stat, G.api.nvim_buf_get_name(buf)) @@ -21,6 +22,7 @@ return { end, additional_vim_regex_highlighting = false, }, + -- 自定义 Vue parser:上游 tree-sitter-html 不识别 .vue 单文件组件 parsers = { vue = { install_info = {