diff --git a/NVIM_GUIDE.md b/NVIM_GUIDE.md new file mode 100644 index 0000000..8b6cddb --- /dev/null +++ b/NVIM_GUIDE.md @@ -0,0 +1,366 @@ +# Neovim 配置使用手册 + +> **Leader 键 = `Space`(空格)** +> 任何时候按住 `Space` 稍等,**which-key** 会弹出所有可用提示菜单。 + +--- + +## 🚀 第一次启动 + +1. 打开 Neovim:`nvim` +2. lazy.nvim 自动安装所有插件(等待完成) +3. 重启 nvim,再运行 `:Lazy sync` +4. `:Mason` 查看工具安装状态 +5. `:checkhealth` 检查环境健康 + +--- + +## 📁 文件树(neo-tree) + +| 快捷键 | 功能 | +|--------|------| +| `e` | **打开/关闭文件树** | +| `o` | 聚焦到文件树 | +| `ge` | 浮动显示 Git 状态树 | + +**文件树内操作:** + +| 按键 | 功能 | +|------|------| +| `Enter` / `l` | 打开文件/展开目录 | +| `h` | 折叠目录 | +| `a` | 新建文件(末尾加 `/` 则创建目录) | +| `d` | 删除 | +| `r` | 重命名 | +| `y` | 复制 | +| `x` | 剪切 | +| `p` | 粘贴 | +| `q` | 关闭文件树 | + +--- + +## 🔍 查找 / 搜索 + +| 快捷键 | 功能 | +|--------|------| +| `ff` | **查找文件** | +| `fr` | 最近打开的文件 | +| `fb` | 已打开的缓冲区 | +| `fg` | **全局内容搜索(grep)** | +| `fw` | 搜索光标下的单词 | +| `fh` | 搜索帮助文档 | +| `fk` | 查看所有快捷键 | +| `fs` | 当前文件符号 | +| `fS` | 工作区符号 | +| `fd` | 诊断错误 | +| `ft` | TODO 注释 | +| `sr` | **项目范围搜索替换**(grug-far) | + +--- + +## 💡 LSP 代码智能 + +| 快捷键 | 功能 | +|--------|------| +| `gd` | **跳转到定义** | +| `gD` | 跳转到声明 | +| `gr` | 查看所有引用 | +| `gI` | 跳转到实现 | +| `gy` | 跳转到类型定义 | +| `K` | **悬浮显示文档** | +| `gK` | 函数签名帮助 | +| `` | 签名帮助(插入模式) | +| `ca` | **代码操作**(自动修复、重构) | +| `cr` | **重命名符号**(实时预览) | +| `cd` | 显示当前行诊断详情 | +| `cl` | LSP 状态信息 | +| `cf` | **格式化**(文件或选中范围) | +| `uf` | 切换当前缓冲区自动格式化 | +| `uF` | 切换全局自动格式化 | +| `uh` | 切换 Inlay Hints | +| `]d` / `[d` | 跳到下/上一个诊断 | + +--- + +## 🔴 诊断列表(Trouble) + +| 快捷键 | 功能 | +|--------|------| +| `xx` | 工作区所有诊断 | +| `xX` | 当前文件诊断 | +| `xs` | 符号列表 | +| `xL` | 位置列表 | +| `xQ` | Quickfix 列表 | +| `]q` / `[q` | 在 Trouble 列表内跳转 | + +--- + +## ✍️ 文本编辑增强 + +### 包围操作(mini.surround,前缀 `gs`) + +| 快捷键 | 功能 | 示例 | +|--------|------|------| +| `gsa` | 添加包围 | `gsaiw"` = 用 `"` 包围单词 | +| `gsd` | 删除包围 | `gsd"` = 删除 `"` | +| `gsr` | 替换包围 | `gsr"'` = `"` 替换为 `'` | +| `gsf` | 向前查找包围 | | +| `gsh` | 高亮包围 | | + +### 文本对象(mini.ai,在 d/c/y/v 后使用) + +> `a` = around(含包围符号),`i` = inner(仅内容) + +| 对象 | 说明 | +|------|------| +| `af` / `if` | 函数 | +| `ac` / `ic` | 类 | +| `aa` / `ia` | 参数 | +| `ab` / `ib` | 代码块 | +| `ae` / `ie` | 整个文件 | +| `aq` / `iq` | 引号 | +| `at` / `it` | HTML/JSX 标签 | + +示例:`daf` 删除整个函数,`vif` 选中函数体,`caa` 修改整个参数 + +### 注释(`gc` 系列) + +| 快捷键 | 功能 | +|--------|------| +| `gcc` | 行注释切换 | +| `gbc` | 块注释切换 | +| `gc{motion}` | 注释 motion 范围 | +| `gcO` / `gco` | 在上/下方插入注释 | + +### 多光标(vim-visual-multi) + +| 快捷键 | 功能 | +|--------|------| +| `` | 选中光标下的词(重复按继续选下一个) | +| `` | 向下/上添加光标 | +| `q` | 跳过当前,选下一个 | +| `` | 退出多光标 | + +--- + +## 🐛 调试(DAP) + +| 快捷键 | 功能 | +|--------|------| +| `dc` | **开始/继续调试** | +| `db` | 切换断点 | +| `dB` | 条件断点 | +| `di` | 单步进入 | +| `do` | 单步跳出 | +| `dO` | 单步跳过 | +| `dC` | 运行到光标处 | +| `dt` | 终止调试 | +| `du` | 调试 UI 面板 | +| `dw` | 悬浮查看变量值 | +| `dr` | 打开 REPL | +| `dl` | 重新运行上次调试 | + +--- + +## 🐹 Go 开发 + +| 快捷键 | 功能 | +|--------|------| +| `gr` | 运行 | +| `gb` | 构建 | +| `gv` | go vet | +| `gi` | 实现接口 | +| `gge` | 生成 if err 错误处理 | +| `ggf` | 填充结构体字段 | +| `ggs` | 填充 switch case | +| `gts` | 切换测试/实现文件 | +| `gtt` | 运行测试 | +| `gtf` | 测试当前函数 | +| `gtc` | 查看测试覆盖率 | +| `gta` | 添加 struct tag | +| `dtg` | 调试当前 Go 测试 | + +--- + +## 🦀 Rust 开发 + +| 快捷键 | 功能 | +|--------|------| +| `rr` | 运行目标列表 | +| `rt` | 测试目标列表 | +| `rd` | 调试目标列表 | +| `re` | 解释错误 | +| `rm` | 展开宏 | +| `rc` | 打开 Cargo.toml | +| `rp` | 跳转到父模块 | +| `rx` | 打开外部文档 | +| `rcu` | 升级所有 crate 依赖 | +| `rco` | 查看 crate 信息 | + +--- + +## 🐍 Python 开发 + +| 快捷键 | 功能 | +|--------|------| +| `pt` | 运行测试 | +| `pT` | 运行当前文件全部测试 | +| `pd` | DAP 调试测试 | +| `ps` | 停止测试 | +| `po` | 查看测试输出 | +| `pO` | 测试输出面板 | +| `pS` | 测试摘要面板 | +| `dpm` | 调试当前方法 | +| `dpc` | 调试当前类 | + +--- + +## 📘 TypeScript/JavaScript 开发 + +| 快捷键 | 功能 | +|--------|------| +| `to` | 整理 import | +| `ta` | 添加缺失 import | +| `tu` | 删除未使用 import | +| `tf` | 修复所有问题 | +| `tr` | 重命名文件(自动更新引用) | +| `tR` | 查看文件引用 | + +--- + +## 🌿 Git 操作 + +| 快捷键 | 功能 | +|--------|------| +| `gg` | **打开 LazyGit** | +| `gl` | Git 日志 | +| `gf` | 当前文件 Git 历史 | +| `gs` | 暂存当前 hunk | +| `gr` | 重置当前 hunk | +| `gS` | 暂存整个文件 | +| `gR` | 重置整个文件 | +| `gu` | 取消暂存 hunk | +| `gp` | 预览变更 hunk | +| `gb` | 查看当前行 blame | +| `gB` | 开关行 blame 显示 | +| `gd` | 文件 diff | +| `]h` / `[h` | 跳到下/上一个 hunk | +| `ih` | 选中 hunk(Visual/Operator 模式) | + +--- + +## 🖥️ 终端 + +| 快捷键 | 功能 | +|--------|------| +| `` | 切换终端(浮动) | +| `tf` | 浮动终端 | +| `th` | 水平终端 | +| `tv` | 垂直终端 | +| `Esc` 或 `jk` | 退出终端模式 | + +--- + +## ⚡ 快速跳转(Flash) + +| 快捷键 | 功能 | +|--------|------| +| `s` | 字符跳转(高亮标记) | +| `S` | Treesitter 节点跳转 | +| `f/F/t/T` | 行内增强跳转 | +| `r` (operator) | Flash 远程操作 | + +--- + +## 📑 缓冲区管理 + +| 快捷键 | 功能 | +|--------|------| +| `` | 上一个缓冲区 | +| `` | 下一个缓冲区 | +| `bd` | 关闭当前缓冲区 | +| `bD` | 强制关闭 | +| `bo` | 关闭其他缓冲区 | +| `bp` | 标记/取消固定缓冲区 | +| `br` / `bl` | 关闭右/左侧缓冲区 | + +--- + +## 🪟 窗口管理 + +| 快捷键 | 功能 | +|--------|------| +| `` | 切换窗口 | +| `sv` | 垂直分割 | +| `sh` | 水平分割 | +| `se` | 均分窗口 | +| `sx` | 关闭当前窗口 | +| `` | 调整窗口大小 | + +--- + +## 🔢 代码折叠(UFO) + +| 快捷键 | 功能 | +|--------|------| +| `zR` | 展开所有折叠 | +| `zM` | 折叠所有 | +| `zr` | 展开一级 | +| `zm` | 折叠一级 | +| `zp` | 预览折叠内容 | + +--- + +## 🗂️ 会话管理 + +| 快捷键 | 功能 | +|--------|------| +| `qs` | 恢复上次会话 | +| `ql` | 恢复最后会话 | +| `qd` | 退出不保存会话 | + +--- + +## 🔔 通知 + +| 快捷键 | 功能 | +|--------|------| +| `nh` | 通知历史 | +| `nd` | 关闭所有通知 | +| `snl` | 最后一条消息 | +| `snh` | Noice 历史 | + +--- + +## ⚙️ 通用编辑技巧 + +| 快捷键 | 功能 | +|--------|------| +| `w` | 保存文件 | +| `q` | 退出 | +| `Q` | 退出全部 | +| `h` | 清除搜索高亮 | +| `r` | 替换光标下单词(全文) | +| `jk` | Insert 模式退出 | +| `` | 翻页并保持光标居中 | +| `n/N` | 搜索跳转并居中 | +| `J/K` (Visual) | 上下移动选中文本 | +| `>/<` (Visual) | 缩进并保持选中 | +| `p` (Visual) | 粘贴不覆盖寄存器 | +| `]]` / `[[` | 跳到下/上一个同名引用 | +| `]w` / `[w` | 跳到下/上一个引用词 | +| `]t` / `[t` | 跳到下/上一个 TODO | + +--- + +## 🛠️ 常用命令 + +``` +:Lazy 插件管理(S=同步更新,U=更新全部) +:Mason LSP/工具管理 +:LspInfo 当前 LSP 状态 +:ConformInfo 格式化工具状态 +:checkhealth 环境健康检查 +:TSInstall 安装 Treesitter 语法 +:noa w 保存(跳过格式化) +``` diff --git a/nvim/lazy-lock.json b/nvim/lazy-lock.json index 7d40b2f..2caa06f 100644 --- a/nvim/lazy-lock.json +++ b/nvim/lazy-lock.json @@ -1,74 +1,66 @@ { "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, - "LuaSnip": { "branch": "master", "commit": "776a29c3e1ac61029ac3f57ac6b5937df2340162" }, - "alpha-nvim": { "branch": "main", "commit": "a35468cd72645dbd52c0624ceead5f301c566dff" }, - "animation.nvim": { "branch": "main", "commit": "fb77091ab72ec9971aee0562e7081182527aaa6a" }, - "avante.nvim": { "branch": "main", "commit": "d80b7966c0505809e83e408353bbe8cb3394936d" }, + "LuaSnip": { "branch": "master", "commit": "642b0c595e11608b4c18219e93b88d7637af27bc" }, + "SchemaStore.nvim": { "branch": "main", "commit": "6d0329adb9c8cbe51b9a28299890a5eb104db7dc" }, + "avante.nvim": { "branch": "main", "commit": "8c84af0f09e5d9058362ac58401a8e7b047d826e" }, + "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, - "catppuccin": { "branch": "main", "commit": "a0c769bc7cd04bbbf258b3d5f01e2bdce744108d" }, - "cmp-buffer": { "branch": "main", "commit": "3022dbc9166796b644a841a02de8dd1cc1d311fa" }, - "cmp-cmdline": { "branch": "main", "commit": "d250c63aa13ead745e3a40f61fdd3470efde3923" }, - "cmp-nvim-lsp": { "branch": "main", "commit": "39e2eda76828d88b773cc27a3f61d2ad782c922d" }, - "cmp-path": { "branch": "main", "commit": "c6635aae33a50d6010bf1aa756ac2398a2d54c32" }, - "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, - "conform.nvim": { "branch": "master", "commit": "b529dd4897c85c3188cc787084089a9d55843093" }, + "catppuccin": { "branch": "main", "commit": "426dbebe06b5c69fd846ceb17b42e12f890aedf1" }, + "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, + "crates.nvim": { "branch": "main", "commit": "0f536967abd097d9a4275087483f15d012418740" }, "dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" }, - "fidget.nvim": { "branch": "legacy", "commit": "2f7c08f45639a64a5c0abcf67321d52c3f499ae6" }, - "flash.nvim": { "branch": "main", "commit": "3c942666f115e2811e959eabbdd361a025db8b63" }, - "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, - "gitsigns.nvim": { "branch": "main", "commit": "def49e48c6329527e344d0c99a0d2cd9fdf6bb84" }, - "go.nvim": { "branch": "master", "commit": "a3455f48cff718a86275115523dcc735535a13aa" }, - "guihua.lua": { "branch": "master", "commit": "87bea7b98429405caf2a0ce4d029b027bb017c70" }, + "fidget.nvim": { "branch": "main", "commit": "889e2e96edef4e144965571d46f7a77bcc4d0ddf" }, + "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "gitsigns.nvim": { "branch": "main", "commit": "0d797daee85366bc242580e352a4f62d67557b84" }, + "go.nvim": { "branch": "master", "commit": "c97cac0cd9e56b44ae5d4b95034d414cedb20145" }, + "grug-far.nvim": { "branch": "main", "commit": "6f8c2097ab4422976063fefe0f29331e12a32334" }, + "guihua.lua": { "branch": "master", "commit": "c4f1b5ee1a66dbcef0b2c5ee26e42b9757684f61" }, "img-clip.nvim": { "branch": "main", "commit": "b6ddfb97b5600d99afe3452d707444afda658aca" }, - "indent-blankline.nvim": { "branch": "master", "commit": "d98f537c3492e87b6dc6c2e3f66ac517528f406f" }, - "lazy.nvim": { "branch": "main", "commit": "bc620783663ab09d16bff9fdecc07da65b2a1528" }, - "lazygit.nvim": { "branch": "main", "commit": "a04ad0dbc725134edbee3a5eea29290976695357" }, - "legendary.nvim": { "branch": "master", "commit": "6de819bc285eb8c420e49e82c21d5bb696b5a727" }, - "lualine.nvim": { "branch": "master", "commit": "0a5a66803c7407767b799067986b4dc3036e1983" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "37a336b653f8594df75c827ed589f1c91d91ff6c" }, - "mason-null-ls.nvim": { "branch": "main", "commit": "de19726de7260c68d94691afb057fa73d3cc53e7" }, - "mason-tool-installer.nvim": { "branch": "main", "commit": "93a9ff9b34c91c0cb0f7de8d5f7e4abce51d8903" }, - "mason.nvim": { "branch": "main", "commit": "0950b15060067f752fde13a779a994f59516ce3d" }, - "middleclass": { "branch": "master", "commit": "9fab4d5bca67262614960960ca35c4740eb2be2c" }, - "mini.bufremove": { "branch": "main", "commit": "66019ecebdc5bc0759e04747586994e2e3f98416" }, - "neo-tree.nvim": { "branch": "v3.x", "commit": "f481de16a0eb59c985abac8985e3f2e2f75b4875" }, - "neodev.nvim": { "branch": "main", "commit": "02893eeb9d6e8503817bd52385e111cba9a90500" }, - "noice.nvim": { "branch": "main", "commit": "0427460c2d7f673ad60eb02b35f5e9926cf67c59" }, - "none-ls.nvim": { "branch": "main", "commit": "db2a48b79cfcdab8baa5d3f37f21c78b6705c62e" }, - "nui.nvim": { "branch": "main", "commit": "7cd18e73cfbd70e1546931b7268b3eebaeff9391" }, - "nvim-autopairs": { "branch": "master", "commit": "c15de7e7981f1111642e7e53799e1211d4606cb9" }, - "nvim-cmp": { "branch": "main", "commit": "a110e12d0b58eefcf5b771f533fc2cf3050680ac" }, - "nvim-dap": { "branch": "master", "commit": "e771e86a69a8ba60cffb16609773522eafb9f41a" }, - "nvim-dap-go": { "branch": "main", "commit": "8763ced35b19c8dc526e04a70ab07c34e11ad064" }, - "nvim-dap-python": { "branch": "master", "commit": "261ce649d05bc455a29f9636dc03f8cdaa7e0e2c" }, - "nvim-dap-ui": { "branch": "master", "commit": "73a26abf4941aa27da59820fd6b028ebcdbcf932" }, + "inc-rename.nvim": { "branch": "main", "commit": "0074b551a17338ccdcd299bd86687cc651bcb33d" }, + "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, + "lualine.nvim": { "branch": "master", "commit": "8811f3f3f4dc09d740c67e9ce399e7a541e2e5b2" }, + "luvit-meta": { "branch": "main", "commit": "cc9b2d412d2fbd30b94a70cfc214c2a3be27a0a2" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "25f609e7fca78af7cede4f9fa3af8a94b1c4950b" }, + "mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" }, + "mason.nvim": { "branch": "main", "commit": "b03fb0f20bc1d43daf558cda981a2be22e73ac42" }, + "mini.ai": { "branch": "main", "commit": "43eb2074843950a3a25aae56a5f41362ec043bfa" }, + "mini.bufremove": { "branch": "main", "commit": "8603490905fdfa31943cf2ede7ef4475e3dbac9a" }, + "mini.surround": { "branch": "main", "commit": "2715e04bea3ec9244f15b421dc5b18c0fe326210" }, + "neo-tree.nvim": { "branch": "v3.x", "commit": "84c75e7a7e443586f60508d12fc50f90d9aee14e" }, + "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, + "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-autopairs": { "branch": "master", "commit": "59bce2eef357189c3305e25bc6dd2d138c1683f5" }, + "nvim-dap": { "branch": "master", "commit": "45a69eba683a2c448dd9ecfc4de89511f0646b5f" }, + "nvim-dap-go": { "branch": "main", "commit": "b4421153ead5d726603b02743ea40cf26a51ed5f" }, + "nvim-dap-python": { "branch": "master", "commit": "1808458eba2b18f178f990e01376941a42c7f93b" }, + "nvim-dap-ui": { "branch": "master", "commit": "1a66cabaa4a4da0be107d5eda6d57242f0fe7e49" }, "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, - "nvim-lint": { "branch": "master", "commit": "bcd1a44edbea8cd473af7e7582d3f7ffc60d8e81" }, - "nvim-lspconfig": { "branch": "master", "commit": "5c33bf1f708ac8cb839469e1a03d45987fec305c" }, + "nvim-lint": { "branch": "master", "commit": "4b03656c09c1561f89b6aa0665c15d292ba9499d" }, + "nvim-lspconfig": { "branch": "master", "commit": "bedca8b426b2fee0ccac596d167d71bbe971253f" }, "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, - "nvim-notify": { "branch": "master", "commit": "b5825cf9ee881dd8e43309c93374ed5b87b7a896" }, - "nvim-treesitter": { "branch": "master", "commit": "4bbd2e72f877ce6835c8ccc1b588ed465446c6ab" }, - "nvim-treesitter-textobjects": { "branch": "master", "commit": "34867c69838078df7d6919b130c0541c0b400c47" }, - "nvim-ufo": { "branch": "main", "commit": "3c7a3570e9c9dc198a2ad4491b0b0e51c4d4ba08" }, - "nvim-web-devicons": { "branch": "master", "commit": "c0cfc1738361b5da1cd0a962dd6f774cc444f856" }, - "oil.nvim": { "branch": "master", "commit": "5b6068aad7d2057dd399fac73b7fb2cdf23ccd6e" }, - "persistence.nvim": { "branch": "main", "commit": "166a79a55bfa7a4db3e26fc031b4d92af71d0b51" }, - "plenary.nvim": { "branch": "master", "commit": "a3e3bc82a3f95c5ed0d7201546d5d2c19b20d683" }, - "project.nvim": { "branch": "main", "commit": "8c6bad7d22eef1b71144b401c9f74ed01526a4fb" }, + "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, + "nvim-treesitter-textobjects": { "branch": "main", "commit": "93d60a475f0b08a8eceb99255863977d3a25f310" }, + "nvim-ts-context-commentstring": { "branch": "main", "commit": "6141a40173c6efa98242dc951ed4b6f892c97027" }, + "nvim-ufo": { "branch": "main", "commit": "ab3eb124062422d276fae49e0dd63b3ad1062cfc" }, + "nvim-web-devicons": { "branch": "master", "commit": "95b7a002d5dba1a42eb58f5fac5c565a485eefd0" }, + "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, + "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, "promise-async": { "branch": "main", "commit": "119e8961014c9bfaf1487bf3c2a393d254f337e2" }, - "rainbow-delimiters.nvim": { "branch": "master", "commit": "607a438d8c647a355749973fd295e33505afafde" }, - "snacks.nvim": { "branch": "main", "commit": "bc0630e43be5699bb94dadc302c0d21615421d93" }, - "sniprun": { "branch": "master", "commit": "a90c65846c3c18efc3f799d8b6dc26af9d4a69ed" }, - "telescope-fzf-native.nvim": { "branch": "main", "commit": "1f08ed60cafc8f6168b72b80be2b2ea149813e55" }, - "telescope.nvim": { "branch": "master", "commit": "c392f1b78eaaf870ca584bd698e78076ed301b26" }, - "todo-comments.nvim": { "branch": "main", "commit": "51e10f838e84b4756c16311d0b1ef0972c6482d2" }, - "toggleterm.nvim": { "branch": "main", "commit": "fee58a0473fd92b28c34f8f724e4918b15ba30a3" }, - "tokyonight.nvim": { "branch": "main", "commit": "81c867c5f638597a82c82094dcb90ed42444dabc" }, - "trouble.nvim": { "branch": "main", "commit": "85bedb7eb7fa331a2ccbecb9202d8abba64d37b3" }, - "ts-comments.nvim": { "branch": "main", "commit": "1bd9d0ba1d8b336c3db50692ffd0955fe1bb9f0c" }, - "venv-selector.nvim": { "branch": "main", "commit": "f212a424fb29949cb5e683928bdd4038bbe0062d" }, + "rainbow-delimiters.nvim": { "branch": "master", "commit": "aab6caaffd79b8def22ec4320a5344f7c42f58d2" }, + "rustaceanvim": { "branch": "main", "commit": "e9c5aaba16fead831379d5f44617547a90b913c7" }, + "snacks.nvim": { "branch": "main", "commit": "ad9ede6a9cddf16cedbd31b8932d6dcdee9b716e" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, + "telescope.nvim": { "branch": "master", "commit": "7ef4d6dccb78ee71e552bbd866176762ad328afa" }, + "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "toggleterm.nvim": { "branch": "main", "commit": "50ea089fc548917cc3cc16b46a8211833b9e3c7c" }, + "tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" }, + "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, + "typescript-tools.nvim": { "branch": "master", "commit": "c2f5910074103705661e9651aa841e0d7eea9932" }, + "venv-selector.nvim": { "branch": "regexp", "commit": "d2326e7433fdeb10f7d0d1237c18b91b353f9f8b" }, "vim-illuminate": { "branch": "master", "commit": "0d1e93684da00ab7c057410fecfc24f434698898" }, "vim-visual-multi": { "branch": "master", "commit": "a6975e7c1ee157615bbc80fc25e4392f71c344d4" }, - "which-key.nvim": { "branch": "main", "commit": "fcbf4eea17cb299c02557d576f0d568878e354a4" }, - "windows.nvim": { "branch": "main", "commit": "c7492552b23d0ab30325e90b56066ec51242adc8" } -} \ No newline at end of file + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } +} diff --git a/nvim/lua/config/autocmds.lua b/nvim/lua/config/autocmds.lua index 872ad56..3c23587 100644 --- a/nvim/lua/config/autocmds.lua +++ b/nvim/lua/config/autocmds.lua @@ -1,9 +1,8 @@ -- autocmds.lua - 自动命令配置 --- 创建自动命令组 local augroup = vim.api.nvim_create_augroup("MyCustomGroup", { clear = true }) --- 自动设置光标行 +-- 插入模式进出切换光标行高亮 vim.api.nvim_create_autocmd({ "InsertLeave", "WinEnter" }, { pattern = "*", group = augroup, @@ -33,20 +32,7 @@ vim.api.nvim_create_autocmd("TextYankPost", { end, }) --- 自动切换工作目录 -vim.api.nvim_create_autocmd({ "BufEnter" }, { - pattern = "*", - group = augroup, - desc = "自动切换到文件所在目录", - callback = function() - local buftype = vim.bo.buftype - if buftype ~= "terminal" and buftype ~= "nofile" and buftype ~= "prompt" then - vim.cmd("silent! lcd %:p:h") - end - end, -}) - --- 自动恢复光标位置 +-- 恢复光标位置 vim.api.nvim_create_autocmd("BufReadPost", { group = augroup, desc = "恢复光标位置", @@ -59,18 +45,12 @@ vim.api.nvim_create_autocmd("BufReadPost", { end, }) --- 自动关闭某些窗口的 q 键 +-- 特定文件类型用 q 关闭 vim.api.nvim_create_autocmd("FileType", { pattern = { - "qf", - "help", - "man", - "notify", - "lspinfo", - "startuptime", - "tsplayground", - "spectre_panel", - "PlenaryTestPopup", + "qf", "help", "man", "notify", "lspinfo", "startuptime", + "tsplayground", "spectre_panel", "PlenaryTestPopup", + "checkhealth", "neotest-output", "neotest-summary", }, group = augroup, callback = function(event) @@ -79,28 +59,43 @@ vim.api.nvim_create_autocmd("FileType", { end, }) --- 在保存时自动删除行尾空白字符 +-- 保存时删除行尾空白(markdown 使用尾部空格表示换行,需跳过) vim.api.nvim_create_autocmd("BufWritePre", { pattern = "*", group = augroup, - desc = "删除行尾空白字符", + desc = "删除行尾空白", callback = function() - -- 保存当前位置 + local ft = vim.bo.filetype + if ft == "markdown" or ft == "text" or ft == "diff" then return end local cursor_pos = vim.api.nvim_win_get_cursor(0) - -- 保存搜索寄存器 local search = vim.fn.getreg("/") - - -- 替换所有行尾空白字符 vim.cmd([[%s/\s\+$//e]]) - - -- 恢复搜索寄存器 vim.fn.setreg("/", search) - -- 恢复光标位置 vim.api.nvim_win_set_cursor(0, cursor_pos) end, }) --- 自动设置文件类型的选项 +-- 在外部更改时自动重新加载文件 +vim.api.nvim_create_autocmd({ "FocusGained", "BufEnter", "CursorHold", "CursorHoldI" }, { + pattern = "*", + group = augroup, + callback = function() + if vim.fn.mode() ~= "c" and not vim.bo.readonly then + vim.cmd("checktime") + end + end, +}) + +vim.api.nvim_create_autocmd("FileChangedShellPost", { + pattern = "*", + group = augroup, + callback = function() + vim.notify("文件已被外部修改,缓冲区已重新加载", vim.log.levels.WARN) + end, +}) + +-- ========== 语言专用设置 ========== + vim.api.nvim_create_autocmd("FileType", { pattern = "python", group = augroup, @@ -109,7 +104,7 @@ vim.api.nvim_create_autocmd("FileType", { vim.opt_local.shiftwidth = 4 vim.opt_local.tabstop = 4 vim.opt_local.softtabstop = 4 - vim.opt_local.textwidth = 88 -- 符合 black 格式化 + vim.opt_local.textwidth = 88 vim.opt_local.colorcolumn = "88" end, }) @@ -121,11 +116,25 @@ vim.api.nvim_create_autocmd("FileType", { vim.opt_local.expandtab = false vim.opt_local.shiftwidth = 4 vim.opt_local.tabstop = 4 + vim.opt_local.softtabstop = 4 end, }) vim.api.nvim_create_autocmd("FileType", { - pattern = { "javascript", "typescript", "javascriptreact", "typescriptreact", "json", "html", "css", "yaml", "markdown" }, + pattern = "rust", + group = augroup, + callback = function() + vim.opt_local.expandtab = true + vim.opt_local.shiftwidth = 4 + vim.opt_local.tabstop = 4 + vim.opt_local.softtabstop = 4 + vim.opt_local.textwidth = 100 + vim.opt_local.colorcolumn = "100" + end, +}) + +vim.api.nvim_create_autocmd("FileType", { + pattern = { "javascript", "typescript", "javascriptreact", "typescriptreact", "json", "jsonc", "html", "css", "scss", "yaml", "markdown" }, group = augroup, callback = function() vim.opt_local.expandtab = true @@ -142,71 +151,3 @@ vim.api.nvim_create_autocmd("FileType", { vim.opt_local.expandtab = false end, }) - --- 为新文件创建模板 -vim.api.nvim_create_autocmd("BufNewFile", { - pattern = "*.py", - group = augroup, - callback = function() - local lines = { - "#!/usr/bin/env python3", - "# -*- coding: utf-8 -*-", - "\"\"\"", - "Description: ", - "\"\"\"", - "", - "", - "def main():", - " pass", - "", - "", - "if __name__ == \"__main__\":", - " main()", - "", - } - vim.api.nvim_buf_set_lines(0, 0, 0, false, lines) - vim.api.nvim_win_set_cursor(0, { 4, 13 }) - end, -}) - -vim.api.nvim_create_autocmd("BufNewFile", { - pattern = "*.go", - group = augroup, - callback = function() - local package_name = vim.fn.fnamemodify(vim.fn.expand("%:p:h:t"), ":r") - - local lines = { - "package " .. package_name, - "", - "import (", - "\t\"fmt\"", - ")", - "", - "// TODO: Add description here", - "", - "", - } - vim.api.nvim_buf_set_lines(0, 0, 0, false, lines) - vim.api.nvim_win_set_cursor(0, { 7, 27 }) - end, -}) - --- 在外部更改时自动重新加载文件 -vim.api.nvim_create_autocmd({ "FocusGained", "BufEnter", "CursorHold", "CursorHoldI" }, { - pattern = "*", - group = augroup, - callback = function() - if vim.fn.mode() ~= "c" and not vim.bo.readonly then - vim.cmd("checktime") - end - end, -}) - --- 当 checktime 检测到文件已更改时通知 -vim.api.nvim_create_autocmd("FileChangedShellPost", { - pattern = "*", - group = augroup, - callback = function() - vim.notify("File changed on disk. Buffer reloaded!", vim.log.levels.WARN) - end, -}) \ No newline at end of file diff --git a/nvim/lua/config/keymaps.lua b/nvim/lua/config/keymaps.lua index f893706..6abeb88 100644 --- a/nvim/lua/config/keymaps.lua +++ b/nvim/lua/config/keymaps.lua @@ -1,24 +1,9 @@ -- keymaps.lua - 键位映射配置 --- 设置局部变量 local map = vim.keymap.set local opts = { noremap = true, silent = true } ---[[ -模式说明: - n: 普通模式 - i: 插入模式 - v: 可视模式 - x: 可视块模式 - t: 终端模式 - c: 命令行模式 -]]-- - ------------------ --- 基础键位映射 -- ------------------ - --- 使用 jk 从插入模式返回普通模式 +-- 插入模式退出 map("i", "jk", "", opts) -- 保存和退出 @@ -29,89 +14,60 @@ map("n", "Q", "qa", { desc = "退出全部" }) -- 清除搜索高亮 map("n", "h", "nohlsearch", { desc = "清除搜索高亮" }) --- 更好的缩进 +-- 缩进保持选中 map("v", "<", "", ">gv", opts) --- 上下移动选中的文本 -map("v", "J", ":m '>+1gv=gv", { desc = "向下移动选中文本" }) -map("v", "K", ":m '<-2gv=gv", { desc = "向上移动选中文本" }) +-- 上下移动选中文本 +map("v", "J", ":m '>+1gv=gv", { desc = "向下移动选中" }) +map("v", "K", ":m '<-2gv=gv", { desc = "向上移动选中" }) --- 保持复制内容在粘贴后 +-- 粘贴不覆盖寄存器 map("x", "p", [["_dP]], { desc = "粘贴不覆盖寄存器" }) -- 删除到黑洞寄存器 map({ "n", "v" }, "d", [["_d]], { desc = "删除到黑洞寄存器" }) --- 快速移动 -map("n", "J", "mzJ`z", { desc = "连接行保持光标位置" }) -map("n", "", "zz", { desc = "向下移动保持光标居中" }) -map("n", "", "zz", { desc = "向上移动保持光标居中" }) -map("n", "n", "nzzzv", { desc = "下一个搜索结果并居中" }) -map("n", "N", "Nzzzv", { desc = "上一个搜索结果并居中" }) +-- 快速移动(保持居中) +map("n", "J", "mzJ`z", { desc = "连接行" }) +map("n", "", "zz", { desc = "向下翻页居中" }) +map("n", "", "zz", { desc = "向上翻页居中" }) +map("n", "n", "nzzzv", { desc = "下一个结果居中" }) +map("n", "N", "Nzzzv", { desc = "上一个结果居中" }) -------------------------- --- 窗口和缓冲区管理 -- -------------------------- - --- 窗口间导航 -map("n", "", "h", { desc = "移动到左窗口" }) -map("n", "", "j", { desc = "移动到下窗口" }) -map("n", "", "k", { desc = "移动到上窗口" }) -map("n", "", "l", { desc = "移动到右窗口" }) - --- 缓冲区导航 -map("n", "", "bprevious", { desc = "上一个缓冲区" }) -map("n", "", "bnext", { desc = "下一个缓冲区" }) -map("n", "bd", "bdelete", { desc = "关闭当前缓冲区" }) -map("n", "ba", "bufdo bd", { desc = "关闭所有缓冲区" }) +-- 窗口导航 +map("n", "", "h", { desc = "左窗口" }) +map("n", "", "j", { desc = "下窗口" }) +map("n", "", "k", { desc = "上窗口" }) +map("n", "", "l", { desc = "右窗口" }) -- 窗口分割 map("n", "sv", "vsplit", { desc = "垂直分割" }) map("n", "sh", "split", { desc = "水平分割" }) -map("n", "se", "=", { desc = "使所有窗口等宽" }) -map("n", "sx", "close", { desc = "关闭当前窗口" }) +map("n", "se", "=", { desc = "均分窗口" }) +map("n", "sx", "close", { desc = "关闭窗口" }) -- 调整窗口大小 -map("n", "", "resize +2", { desc = "增加窗口高度" }) -map("n", "", "resize -2", { desc = "减小窗口高度" }) -map("n", "", "vertical resize -2", { desc = "减小窗口宽度" }) -map("n", "", "vertical resize +2", { desc = "增加窗口宽度" }) +map("n", "", "resize +2", { desc = "增加高度" }) +map("n", "", "resize -2", { desc = "减少高度" }) +map("n", "", "vertical resize -2", { desc = "减少宽度" }) +map("n", "", "vertical resize +2", { desc = "增加宽度" }) -------------------------- --- 终端模式映射 -- -------------------------- - --- 退出终端模式 +-- 终端模式 map("t", "", "", { desc = "退出终端模式" }) map("t", "jk", "", { desc = "退出终端模式" }) +map("t", "", "h", opts) +map("t", "", "j", opts) +map("t", "", "k", opts) +map("t", "", "l", opts) --- 终端窗口导航 -map("t", "", "h", { desc = "终端模式下向左移动" }) -map("t", "", "j", { desc = "终端模式下向下移动" }) -map("t", "", "k", { desc = "终端模式下向上移动" }) -map("t", "", "l", { desc = "终端模式下向右移动" }) - -------------------------- --- 实用功能 -- -------------------------- - --- 全文快速替换当前单词 +-- 实用工具 map("n", "r", [[:%s/\<\>//gI]], { desc = "替换当前单词" }) +map("n", "x", "!chmod +x %", { desc = "使文件可执行", silent = true }) --- 使当前文件可执行 -map("n", "x", "!chmod +x %", { desc = "使当前文件可执行", silent = true }) - --- 打开一个新的终端 -map("n", "t", "terminal", { desc = "打开终端" }) - --- 快速编辑配置文件 -map("n", "ev", "e $MYVIMRC", { desc = "编辑init.lua" }) -map("n", "sv", "source $MYVIMRC", { desc = "重新加载配置" }) - --- 更简单的命令行历史导航 -map("c", "", "", { desc = "下一个命令历史" }) -map("c", "", "", { desc = "上一个命令历史" }) +-- 命令行历史 +map("c", "", "", { desc = "下一条命令" }) +map("c", "", "", { desc = "上一条命令" }) -- 更好的搜索 -map("n", "g/", "/\\<\\>", { desc = "搜索单词" }) \ No newline at end of file +map("n", "g/", "/\\<\\>", { desc = "搜索单词" }) diff --git a/nvim/lua/config/lazy.lua b/nvim/lua/config/lazy.lua index 13d8ce8..3227a17 100644 --- a/nvim/lua/config/lazy.lua +++ b/nvim/lua/config/lazy.lua @@ -21,8 +21,8 @@ vim.opt.rtp:prepend(lazypath) require("lazy").setup({ -- 插件列表 spec = { - -- 导入插件模块 { import = "plugins" }, + { import = "plugins.lang" }, }, -- 默认配置 diff --git a/nvim/lua/config/options.lua b/nvim/lua/config/options.lua index f6984df..479ae0d 100644 --- a/nvim/lua/config/options.lua +++ b/nvim/lua/config/options.lua @@ -8,9 +8,7 @@ opt.termguicolors = true -- 使用终端真彩色 opt.number = true -- 显示行号 opt.relativenumber = true -- 相对行号 opt.cursorline = true -- 高亮当前行 -opt.cursorcolumn = true -- 高亮当前列 -opt.signcolumn = "auto:1" -- 显示标记列 -opt.showmatch = true -- 高亮匹配的括号 +opt.signcolumn = "yes" -- 始终显示标记列(避免每次出现符号时布局跳动) opt.showmode = false -- 不显示模式,由状态栏插件替代 opt.laststatus = 3 -- 全局状态栏 opt.cmdheight = 1 -- 命令行高度 @@ -25,7 +23,6 @@ opt.listchars = { -- 设置不可见字符的显示方式 extends = "›", precedes = "‹", nbsp = "␣", - eol = "↴" } opt.fillchars:append({ -- 分隔符符号设置 vert = "│", -- 窗口分隔符 @@ -41,7 +38,6 @@ opt.shiftwidth = 4 -- 缩进宽度 opt.expandtab = true -- 使用空格替代Tab opt.smartindent = true -- 智能缩进 opt.autoindent = true -- 自动缩进 -opt.cindent = true -- C语言缩进规则 opt.textwidth = 120 -- 文本宽度 opt.formatoptions = "jcroqlnt" -- 格式化选项 opt.foldenable = false @@ -56,7 +52,7 @@ opt.incsearch = true -- 增量搜索 -- 性能设置 opt.hidden = true -- 允许切换未保存的缓冲区 -opt.history = 500 -- 历史记录数 +opt.history = 1000 -- 历史记录数 opt.updatetime = 100 -- 更新时间(ms) opt.timeout = true -- 启用超时 opt.timeoutlen = 300 -- 键映射超时时间(ms) @@ -83,6 +79,8 @@ opt.completeopt = "menu,menuone,noselect" -- 补全选项 opt.pumheight = 10 -- 弹出菜单高度 opt.confirm = true -- 显示确认对话框 opt.autoread = true -- 自动重新加载文件 +-- 减少消息噪音(W=写入/I=intro/c=补全消息/C=扫描消息) +opt.shortmess:append("WIcC") -- 加载 .nvimrc, .exrc 等本地配置 opt.exrc = true -- 启用 .exrc diff --git a/nvim/lua/plugins/avante.lua b/nvim/lua/plugins/ai.lua similarity index 100% rename from nvim/lua/plugins/avante.lua rename to nvim/lua/plugins/ai.lua diff --git a/nvim/lua/plugins/blink.lua b/nvim/lua/plugins/blink.lua new file mode 100644 index 0000000..9c5322d --- /dev/null +++ b/nvim/lua/plugins/blink.lua @@ -0,0 +1,99 @@ +-- blink.lua - blink.cmp 补全引擎(替换 nvim-cmp) + +return { + { + "saghen/blink.cmp", + version = "*", + event = "InsertEnter", + dependencies = { + "rafamadriz/friendly-snippets", + { "L3MON4D3/LuaSnip", version = "v2.*" }, + }, + opts = { + keymap = { + preset = "default", + [""] = { "show", "show_documentation", "hide_documentation" }, + [""] = { "hide" }, + [""] = { "accept", "fallback" }, + [""] = { "snippet_forward", "fallback" }, + [""] = { "snippet_backward", "fallback" }, + [""] = { "select_next", "fallback" }, + [""] = { "select_prev", "fallback" }, + [""] = { "scroll_documentation_up", "fallback" }, + [""] = { "scroll_documentation_down", "fallback" }, + }, + + appearance = { + nerd_font_variant = "mono", + }, + + snippets = { + expand = function(snippet) + require("luasnip").lsp_expand(snippet) + end, + active = function(filter) + if filter and filter.direction then + return require("luasnip").jumpable(filter.direction) + end + return require("luasnip").in_snippet() + end, + jump = function(direction) + require("luasnip").jump(direction) + end, + }, + + sources = { + default = { "lsp", "path", "snippets", "buffer" }, + providers = { + lsp = { score_offset = 100 }, + path = { score_offset = 50 }, + snippets = { score_offset = 40 }, + buffer = { score_offset = 10 }, + }, + }, + + completion = { + accept = { auto_brackets = { enabled = true } }, + menu = { + border = "rounded", + draw = { + treesitter = { "lsp" }, + columns = { + { "label", "label_description", gap = 1 }, + { "kind_icon", "kind" }, + }, + }, + }, + documentation = { + auto_show = true, + auto_show_delay_ms = 200, + window = { border = "rounded" }, + }, + ghost_text = { enabled = true }, + }, + + signature = { + enabled = true, + window = { border = "rounded" }, + }, + }, + + config = function(_, opts) + -- LuaSnip 加载 vscode 风格的代码片段 + require("luasnip.loaders.from_vscode").lazy_load() + require("blink.cmp").setup(opts) + end, + }, + + -- LuaSnip 代码片段引擎 + { + "L3MON4D3/LuaSnip", + version = "v2.*", + build = "make install_jsregexp", + dependencies = { "rafamadriz/friendly-snippets" }, + opts = { + history = true, + delete_check_events = "TextChanged", + }, + }, +} diff --git a/nvim/lua/plugins/cmp.lua b/nvim/lua/plugins/cmp.lua deleted file mode 100644 index 142cb92..0000000 --- a/nvim/lua/plugins/cmp.lua +++ /dev/null @@ -1,34 +0,0 @@ --- cmp.lua - 自动补全配置 -return { - { - "hrsh7th/nvim-cmp", - dependencies = { - "hrsh7th/cmp-nvim-lsp", - "hrsh7th/cmp-buffer", - "hrsh7th/cmp-path", - "L3MON4D3/LuaSnip", - "saadparwaiz1/cmp_luasnip", - }, - event = "InsertEnter", - opts = function() - local cmp = require("cmp") - return { - snippet = { - expand = function(args) - require("luasnip").lsp_expand(args.body) - end, - }, - mapping = cmp.mapping.preset.insert({ - [""] = cmp.mapping.complete(), - [""] = cmp.mapping.confirm({ select = true }), - }), - sources = cmp.config.sources({ - { name = "nvim_lsp" }, - { name = "luasnip" }, - { name = "buffer" }, - { name = "path" }, - }), - } - end, - }, -} diff --git a/nvim/lua/plugins/coding.lua b/nvim/lua/plugins/coding.lua deleted file mode 100644 index 54107f2..0000000 --- a/nvim/lua/plugins/coding.lua +++ /dev/null @@ -1,621 +0,0 @@ --- coding.lua - 代码增强插件配置 - -return { - -- LSP 配置 - { - "neovim/nvim-lspconfig", - event = { "BufReadPre", "BufNewFile" }, - dependencies = { - -- LSP 管理器 - { "williamboman/mason.nvim" }, - { "williamboman/mason-lspconfig.nvim" }, - - -- 自动安装 LSP - { "WhoIsSethDaniel/mason-tool-installer.nvim" }, - - -- 显示 LSP 进度 - { "j-hui/fidget.nvim", opts = {} }, - - -- 额外 LSP 功能 - { "folke/neodev.nvim", opts = {} }, - }, - opts = { - -- LSP 服务器诊断设置 - diagnostics = { - underline = true, - update_in_insert = false, - virtual_text = { - spacing = 4, - source = "if_many", - prefix = "●", - }, - severity_sort = true, - signs = { - text = { - [vim.diagnostic.severity.ERROR] = "✘", - [vim.diagnostic.severity.WARN] = "▲", - [vim.diagnostic.severity.HINT] = "⚑", - [vim.diagnostic.severity.INFO] = "»", - }, - }, - }, - - -- 自动格式化 - format = { - formatting_options = nil, - timeout_ms = 1000, - }, - - -- LSP 服务器设置 - servers = { - -- 根据语言配置服务器 - lua_ls = { - settings = { - Lua = { - completion = { - callSnippet = "Replace", - }, - workspace = { - checkThirdParty = false, - }, - telemetry = { - enable = false, - }, - diagnostics = { - globals = { "vim" }, - }, - }, - }, - }, - - -- Python 服务器 - pyright = { - settings = { - python = { - analysis = { - typeCheckingMode = "basic", - autoSearchPaths = true, - useLibraryCodeForTypes = true, - diagnosticMode = "workspace", - }, - }, - }, - }, - ruff_lsp = { - -- Ruff 会处理导入和排序 - init_options = { - settings = { - args = {}, - }, - }, - }, - - -- Go 服务器 - gopls = { - settings = { - gopls = { - gofumpt = true, - codelenses = { - gc_details = true, - generate = true, - regenerate_cgo = true, - run_govulncheck = true, - test = true, - tidy = true, - upgrade_dependency = true, - vendor = true, - }, - hints = { - assignVariableTypes = true, - compositeLiteralFields = true, - compositeLiteralTypes = true, - constantValues = true, - functionTypeParameters = true, - parameterNames = true, - rangeVariableTypes = true, - }, - analyses = { - fieldalignment = true, - nilness = true, - unusedparams = true, - unusedwrite = true, - useany = true, - shadow = true, - }, - usePlaceholders = true, - completeUnimported = true, - staticcheck = true, - directoryFilters = { "-.git", "-.vscode", "-.idea", "-.vscode-test", "-node_modules" }, - semanticTokens = true, - }, - }, - }, - }, - }, - config = function(_, opts) - -- 设置诊断标志 - for name, icon in pairs(opts.diagnostics.signs.text) do - name = "DiagnosticSign" .. name - vim.fn.sign_define(name, { text = icon, texthl = name, numhl = "" }) - end - - -- 配置诊断 - vim.diagnostic.config(vim.deepcopy(opts.diagnostics)) - - -- 设置 LSP 的键绑定和自动命令 - vim.api.nvim_create_autocmd("LspAttach", { - callback = function(args) - local buffer = args.buf - local client = vim.lsp.get_client_by_id(args.data.client_id) - - -- 设置 LSP 键绑定 - local map = function(mode, l, r, opts_) - opts_ = opts_ or {} - opts_.silent = true - opts_.buffer = buffer - vim.keymap.set(mode, l, r, opts_) - end - - -- 导航键绑定 - map("n", "gd", "Telescope lsp_definitions", { desc = "转到定义" }) - map("n", "gr", "Telescope lsp_references", { desc = "查找引用" }) - map("n", "gD", vim.lsp.buf.declaration, { desc = "转到声明" }) - map("n", "gI", "Telescope lsp_implementations", { desc = "转到实现" }) - map("n", "gt", "Telescope lsp_type_definitions", { desc = "转到类型定义" }) - map("n", "K", vim.lsp.buf.hover, { desc = "显示悬停信息" }) - map("n", "gK", vim.lsp.buf.signature_help, { desc = "显示签名帮助" }) - - -- 代码操作键绑定 - map("n", "ca", vim.lsp.buf.code_action, { desc = "代码操作" }) - map("n", "cr", vim.lsp.buf.rename, { desc = "重命名" }) - - -- 诊断键绑定 - map("n", "]d", vim.diagnostic.goto_next, { desc = "下一个诊断" }) - map("n", "[d", vim.diagnostic.goto_prev, { desc = "上一个诊断" }) - map("n", "cd", vim.diagnostic.open_float, { desc = "行诊断" }) - map("n", "cl", "LspInfo", { desc = "LSP 信息" }) - - -- 格式化文档(如果服务器支持) - if client and client.supports_method("textDocument/formatting") then - map("n", "cf", vim.lsp.buf.format, { desc = "格式化代码" }) - end - end, - }) - - -- 设置 LSP 服务器 - local capabilities = vim.tbl_deep_extend( - "force", - {}, - vim.lsp.protocol.make_client_capabilities(), - require("cmp_nvim_lsp").default_capabilities(), - opts.capabilities or {} - ) - - -- 为 Lua 开发环境配置 - require("neodev").setup({ - library = { - plugins = { "nvim-dap-ui" }, - types = true, - }, - }) - - -- 设置 mason-lspconfig - require("mason").setup() - - local ensure_installed = {} -- 要安装的服务器列表 - - -- 收集需要安装的服务器 - for server, server_opts in pairs(opts.servers) do - if server_opts then - server_opts = server_opts == true and {} or server_opts - -- 将服务器添加到安装列表 - ensure_installed[#ensure_installed + 1] = server - end - end - - -- 设置 mason-lspconfig - require("mason-lspconfig").setup({ - ensure_installed = vim.tbl_keys(ensure_installed), - automatic_installation = true, - }) - - -- 设置工具安装程序 - require("mason-tool-installer").setup({ - ensure_installed = { - -- Python 工具 - "black", - "isort", - "mypy", - "ruff", - "debugpy", - - -- Go 工具 - "gofumpt", - "goimports", - "golangci-lint", - "delve", - - -- 通用工具 - "stylua", - "shfmt", - }, - }) - - -- 启动服务器 - require("mason-lspconfig").setup_handlers({ - function(server) - local server_opts = vim.tbl_deep_extend("force", { - capabilities = vim.deepcopy(capabilities), - }, opts.servers[server] or {}) - - -- 特殊设置钩子 - if server == "ruff_lsp" then - -- 使用 LspAttach 自动命令来配置 ruff_lsp - vim.api.nvim_create_autocmd("LspAttach", { - callback = function(args) - local client = vim.lsp.get_client_by_id(args.data.client_id) - -- 禁用 ruff 格式化功能,由 conform 处理 - if client and client.name == "ruff_lsp" then - client.server_capabilities.documentFormattingProvider = false - end - end, - }) - end - - -- 启动服务器 - require("lspconfig")[server].setup(server_opts) - end, - }) - end, - }, - - -- 自动完成 - { - "hrsh7th/nvim-cmp", - version = false, - event = "InsertEnter", - dependencies = { - "hrsh7th/cmp-nvim-lsp", - "hrsh7th/cmp-buffer", - "hrsh7th/cmp-path", - "saadparwaiz1/cmp_luasnip", - "hrsh7th/cmp-cmdline", - }, - opts = function() - vim.api.nvim_set_hl(0, "CmpGhostText", { link = "Comment", default = true }) - local cmp = require("cmp") - local luasnip = require("luasnip") - - local function has_words_before() - unpack = unpack or table.unpack - local line, col = unpack(vim.api.nvim_win_get_cursor(0)) - return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil - end - - return { - completion = { - completeopt = "menu,menuone,noinsert", - }, - snippet = { - expand = function(args) - luasnip.lsp_expand(args.body) - end, - }, - mapping = cmp.mapping.preset.insert({ - [""] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }), - [""] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }), - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.scroll_docs(4), - [""] = cmp.mapping.complete(), - [""] = cmp.mapping.abort(), - [""] = cmp.mapping.confirm({ select = true }), - [""] = cmp.mapping.confirm({ - behavior = cmp.ConfirmBehavior.Replace, - select = true, - }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_next_item() - elseif luasnip.expand_or_jumpable() then - luasnip.expand_or_jump() - elseif has_words_before() then - cmp.complete() - else - fallback() - end - end, { "i", "s" }), - [""] = cmp.mapping(function(fallback) - if cmp.visible() then - cmp.select_prev_item() - elseif luasnip.jumpable(-1) then - luasnip.jump(-1) - else - fallback() - end - end, { "i", "s" }), - }), - sources = cmp.config.sources({ - { name = "nvim_lsp", priority = 1000 }, - { name = "luasnip", priority = 750 }, - { name = "buffer", priority = 500 }, - { name = "path", priority = 250 }, - }), - formatting = { - format = function(entry, vim_item) - -- 添加源信息 - vim_item.menu = ({ - nvim_lsp = "[LSP]", - luasnip = "[Snip]", - buffer = "[Buf]", - path = "[Path]", - })[entry.source.name] - - -- 设置最大宽度 - local MAX_LABEL_WIDTH = 50 - if #vim_item.abbr > MAX_LABEL_WIDTH then - vim_item.abbr = vim_item.abbr:sub(1, MAX_LABEL_WIDTH) .. "..." - end - - return vim_item - end, - }, - experimental = { - ghost_text = { - hl_group = "CmpGhostText", - }, - }, - } - end, - config = function(_, opts) - -- 设置 nvim-cmp - local cmp = require("cmp") - cmp.setup(opts) - - -- 为命令行设置完成 - cmp.setup.cmdline(":", { - mapping = cmp.mapping.preset.cmdline(), - sources = cmp.config.sources({ - { name = "path" }, - { name = "cmdline" }, - }), - }) - - -- 为搜索设置完成 - cmp.setup.cmdline("/", { - mapping = cmp.mapping.preset.cmdline(), - sources = cmp.config.sources({ - { name = "buffer" }, - }), - }) - end, - }, - - -- 代码格式化和 Linting - { - "stevearc/conform.nvim", - event = { "BufReadPre", "BufNewFile" }, - cmd = { "ConformInfo" }, - keys = { - { - "cf", - function() - require("conform").format({ lsp_fallback = true, async = false }) - end, - mode = { "n", "v" }, - desc = "格式化代码", - }, - }, - opts = { - formatters_by_ft = { - lua = { "stylua" }, - python = { "isort", "black" }, - go = { "goimports", "gofumpt" }, - javascript = { "prettierd" }, - typescript = { "prettierd" }, - javascriptreact = { "prettierd" }, - typescriptreact = { "prettierd" }, - json = { "prettierd" }, - html = { "prettierd" }, - css = { "prettierd" }, - yaml = { "prettierd" }, - markdown = { "prettierd" }, - sh = { "shfmt" }, - }, - - -- 每个格式化工具的设置 - formatters = { - black = { - args = { "--line-length", "88", "--fast", "-" }, - }, - isort = { - args = { "--stdout", "--profile", "black", "--line-length", "88", "-" }, - }, - stylua = { - args = { "--indent-type", "Spaces", "--indent-width", "2", "-" }, - }, - }, - - -- 保存时自动格式化 - format_on_save = function(bufnr) - if vim.b[bufnr].disable_autoformat or vim.g.disable_autoformat then - return - end - return { timeout_ms = 500, lsp_fallback = true } - end, - - -- 格式化超时时间 - format_after_save = function(bufnr) - if vim.b[bufnr].disable_autoformat or vim.g.disable_autoformat then - return - end - return { lsp_fallback = true } - end, - }, - init = function() - -- 添加用户命令以切换格式化 - vim.api.nvim_create_user_command("FormatToggle", function(args) - if args.bang then - -- FormatToggle! 将为当前缓冲区切换格式化 - vim.b.disable_autoformat = not vim.b.disable_autoformat - vim.notify(string.format("Buffer autoformatting %s", vim.b.disable_autoformat and "disabled" or "enabled")) - else - -- FormatToggle 将全局切换格式化 - vim.g.disable_autoformat = not vim.g.disable_autoformat - vim.notify(string.format("Global autoformatting %s", vim.g.disable_autoformat and "disabled" or "enabled")) - end - end, { desc = "切换自动格式化", bang = true }) - end, - }, - - -- 调试支持 - { - "mfussenegger/nvim-dap", - dependencies = { - -- UI 相关 - { - "rcarriga/nvim-dap-ui", - dependencies = { "nvim-neotest/nvim-nio" }, - keys = { - { "du", function() require("dapui").toggle() end, desc = "Dap UI" }, - }, - opts = {}, - config = function(_, opts) - local dap = require("dap") - local dapui = require("dapui") - dapui.setup(opts) - dap.listeners.after.event_initialized["dapui_config"] = function() - dapui.open() - end - dap.listeners.before.event_terminated["dapui_config"] = function() - dapui.close() - end - dap.listeners.before.event_exited["dapui_config"] = function() - dapui.close() - end - end, - }, - -- 虚拟文本支持 - { - "theHamsta/nvim-dap-virtual-text", - opts = {}, - }, - -- Python 调试支持 - { - "mfussenegger/nvim-dap-python", - config = function() - local path = require("mason-registry").get_package("debugpy"):get_install_path() - require("dap-python").setup(path .. "/venv/bin/python") - end, - }, - -- Go 调试支持 - { - "leoluz/nvim-dap-go", - config = true, - }, - }, - keys = { - { "dB", function() require("dap").set_breakpoint(vim.fn.input('断点条件: ')) end, desc = "条件断点" }, - { "db", function() require("dap").toggle_breakpoint() end, desc = "切换断点" }, - { "dc", function() require("dap").continue() end, desc = "继续执行" }, - { "da", function() require("dap").continue({ before = get_args }) end, desc = "带参数运行" }, - { "dC", function() require("dap").run_to_cursor() end, desc = "运行到光标处" }, - { "dg", function() require("dap").goto_() end, desc = "跳转到行" }, - { "di", function() require("dap").step_into() end, desc = "单步进入" }, - { "dj", function() require("dap").down() end, desc = "下栈帧" }, - { "dk", function() require("dap").up() end, desc = "上栈帧" }, - { "dl", function() require("dap").run_last() end, desc = "运行最后的配置" }, - { "do", function() require("dap").step_out() end, desc = "单步跳出" }, - { "dO", function() require("dap").step_over() end, desc = "单步跳过" }, - { "dp", function() require("dap").pause() end, desc = "暂停执行" }, - { "dr", function() require("dap").repl.toggle() end, desc = "切换 REPL" }, - { "ds", function() require("dap").session() end, desc = "获取会话" }, - { "dt", function() require("dap").terminate() end, desc = "终止调试" }, - { "dw", function() require("dap.ui.widgets").hover() end, desc = "小部件" }, - }, - config = function() - local icons = { - dap = { - Stopped = { "󰁕 ", "DiagnosticWarn", "DapStoppedLine" }, - Breakpoint = " ", - BreakpointCondition = " ", - BreakpointRejected = { " ", "DiagnosticError" }, - LogPoint = ".>", - }, - } - - vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" }) - - for name, sign in pairs(icons.dap) do - sign = type(sign) == "table" and sign or { sign } - vim.fn.sign_define( - "Dap" .. name, - { text = sign[1], texthl = sign[2] or "DiagnosticInfo", linehl = sign[3], numhl = sign[3] } - ) - end - end, - }, - - -- 问题检测器 - { - "folke/trouble.nvim", - cmd = { "TroubleToggle", "Trouble" }, - opts = { - use_diagnostic_signs = true, - action_keys = { - close = "q", - cancel = "", - refresh = "r", - jump = { "", "", "<2-leftmouse>" }, - open_split = { "" }, - open_vsplit = { "" }, - open_tab = { "" }, - jump_close = { "o" }, - toggle_mode = "m", - switch_severity = "s", - toggle_preview = "P", - hover = "K", - preview = "p", - close_folds = { "zM", "zm" }, - open_folds = { "zR", "zr" }, - toggle_fold = { "zA", "za" }, - previous = "k", - next = "j", - help = "?", - }, - }, - keys = { - { "xx", "TroubleToggle document_diagnostics", desc = "文档诊断" }, - { "xX", "TroubleToggle workspace_diagnostics", desc = "工作区诊断" }, - { "xL", "TroubleToggle loclist", desc = "位置列表" }, - { "xQ", "TroubleToggle quickfix", desc = "快速修复" }, - { - "[q", - function() - if require("trouble").is_open() then - require("trouble").previous({ skip_groups = true, jump = true }) - else - local ok, err = pcall(vim.cmd.cprev) - if not ok then - vim.notify(err, vim.log.levels.ERROR) - end - end - end, - desc = "上一个问题", - }, - { - "]q", - function() - if require("trouble").is_open() then - require("trouble").next({ skip_groups = true, jump = true }) - else - local ok, err = pcall(vim.cmd.cnext) - if not ok then - vim.notify(err, vim.log.levels.ERROR) - end - end - end, - desc = "下一个问题", - }, - }, - }, -} \ No newline at end of file diff --git a/nvim/lua/plugins/colorscheme.lua b/nvim/lua/plugins/colorscheme.lua index d9953fc..d9a1f71 100644 --- a/nvim/lua/plugins/colorscheme.lua +++ b/nvim/lua/plugins/colorscheme.lua @@ -1,101 +1,63 @@ -- colorscheme.lua - 主题配置 return { - -- 主题:Tokyo Night { "folke/tokyonight.nvim", - lazy = false, -- 不延迟加载主题 - priority = 1000, -- 确保先加载主题 - config = function() - require("tokyonight").setup({ - style = "night", -- 可选值:"storm", "moon", "night", "day" - transparent = false, -- 启用背景透明 - terminal_colors = true, -- 设置终端颜色 - styles = { - comments = { italic = true }, - keywords = { italic = true }, - functions = {}, - variables = {}, - sidebars = "dark", - floats = "dark", - }, - sidebars = { "qf", "help", "terminal", "packer", "NvimTree", "Trouble" }, - dim_inactive = false, -- 非活动窗口变暗 - lualine_bold = true, -- 在状态栏中使用粗体 - - on_highlights = function(hl, c) - -- 自定义高亮组 - hl.CursorLineNr = { fg = c.orange, bold = true } - hl.LineNr = { fg = c.orange, bold = false } - hl.LineNrAbove = { fg = c.fg_gutter } - hl.LineNrBelow = { fg = c.fg_gutter } - - -- 浮动窗口 - hl.NormalFloat = { bg = c.bg_dark } - hl.FloatBorder = { bg = c.bg_dark, fg = c.blue } - end, - }) - - -- 加载主题 + lazy = false, + priority = 1000, + opts = { + style = "night", + transparent = false, + terminal_colors = true, + styles = { + comments = { italic = true }, + keywords = { italic = true }, + functions = {}, + variables = {}, + sidebars = "dark", + floats = "dark", + }, + sidebars = { "qf", "help", "terminal", "Trouble", "neo-tree" }, + dim_inactive = false, + lualine_bold = true, + on_highlights = function(hl, c) + hl.CursorLineNr = { fg = c.orange, bold = true } + hl.LineNr = { fg = c.orange, bold = false } + hl.LineNrAbove = { fg = c.fg_gutter } + hl.LineNrBelow = { fg = c.fg_gutter } + hl.NormalFloat = { bg = c.bg_dark } + hl.FloatBorder = { bg = c.bg_dark, fg = c.blue } + end, + }, + config = function(_, opts) + require("tokyonight").setup(opts) vim.cmd.colorscheme("tokyonight") - end + end, }, - - -- 替代主题:Catppuccin + { "catppuccin/nvim", name = "catppuccin", - lazy = true, -- 懒加载此主题 + lazy = true, opts = { - flavour = "mocha", -- 风格: latte, frappe, macchiato, mocha + flavour = "mocha", term_colors = true, transparent_background = false, - styles = { - comments = { "italic" }, - conditionals = { "italic" }, - loops = {}, - functions = {}, - keywords = {}, - strings = {}, - variables = {}, - numbers = {}, - booleans = {}, - properties = {}, - types = {}, - operators = {}, - }, integrations = { cmp = true, gitsigns = true, - nvimtree = true, treesitter = true, mason = true, - telescope = { - enabled = true, - style = "nvchad", - }, - native_lsp = { - enabled = true, - virtual_text = { - errors = { "italic" }, - hints = { "italic" }, - warnings = { "italic" }, - information = { "italic" }, - }, - underlines = { - errors = { "underline" }, - hints = { "underline" }, - warnings = { "underline" }, - information = { "underline" }, - }, - }, + telescope = { enabled = true }, + native_lsp = { enabled = true }, + blink_cmp = true, }, }, }, - - -- 图标支持 + { "nvim-tree/nvim-web-devicons", lazy = true, }, -} \ No newline at end of file +} + \ No newline at end of file diff --git a/nvim/lua/plugins/dap.lua b/nvim/lua/plugins/dap.lua index 16a30c6..58976f0 100644 --- a/nvim/lua/plugins/dap.lua +++ b/nvim/lua/plugins/dap.lua @@ -1,23 +1,82 @@ --- dap.lua - 调试支持 +-- dap.lua - 调试适配器协议(通用配置) + return { { "mfussenegger/nvim-dap", - event = "VeryLazy", - }, - { - "leoluz/nvim-dap-go", - ft = "go", - dependencies = { "mfussenegger/nvim-dap" }, + dependencies = { + { + "rcarriga/nvim-dap-ui", + dependencies = { "nvim-neotest/nvim-nio" }, + opts = { + icons = { expanded = "▾", collapsed = "▸", current_frame = "▸" }, + layouts = { + { + elements = { + { id = "scopes", size = 0.25 }, + { id = "breakpoints", size = 0.25 }, + { id = "stacks", size = 0.25 }, + { id = "watches", size = 0.25 }, + }, + size = 40, + position = "left", + }, + { + elements = { + { id = "repl", size = 0.5 }, + { id = "console", size = 0.5 }, + }, + size = 15, + position = "bottom", + }, + }, + floating = { border = "rounded" }, + }, + config = function(_, opts) + local dap = require("dap") + local dapui = require("dapui") + dapui.setup(opts) + dap.listeners.after.event_initialized["dapui_config"] = dapui.open + dap.listeners.before.event_terminated["dapui_config"] = dapui.close + dap.listeners.before.event_exited["dapui_config"] = dapui.close + end, + }, + { + "theHamsta/nvim-dap-virtual-text", + opts = { commented = true }, + }, + }, + keys = { + { "dB", function() require("dap").set_breakpoint(vim.fn.input("断点条件: ")) end, desc = "条件断点" }, + { "db", function() require("dap").toggle_breakpoint() end, desc = "切换断点" }, + { "dc", function() require("dap").continue() end, desc = "继续/启动" }, + { "dC", function() require("dap").run_to_cursor() end, desc = "运行到光标" }, + { "di", function() require("dap").step_into() end, desc = "单步进入" }, + { "do", function() require("dap").step_out() end, desc = "单步跳出" }, + { "dO", function() require("dap").step_over() end, desc = "单步跳过" }, + { "dl", function() require("dap").run_last() end, desc = "重新运行" }, + { "dt", function() require("dap").terminate() end, desc = "终止调试" }, + { "dr", function() require("dap").repl.toggle() end, desc = "REPL" }, + { "du", function() require("dapui").toggle() end, desc = "调试 UI" }, + { "dw", function() require("dap.ui.widgets").hover() end, desc = "悬浮变量" }, + }, config = function() - require("dap-go").setup() - end, - }, - { - "mfussenegger/nvim-dap-python", - ft = "python", - dependencies = { "mfussenegger/nvim-dap" }, - config = function() - require("dap-python").setup("python") + vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" }) + local signs = { + Stopped = { "󰁕 ", "DiagnosticWarn", "DapStoppedLine" }, + Breakpoint = " ", + BreakpointCondition = " ", + BreakpointRejected = { " ", "DiagnosticError" }, + LogPoint = ".>", + } + for name, sign in pairs(signs) do + sign = type(sign) == "table" and sign or { sign } + vim.fn.sign_define("Dap" .. name, { + text = sign[1], + texthl = sign[2] or "DiagnosticInfo", + linehl = sign[3], + numhl = sign[3], + }) + end end, }, } diff --git a/nvim/lua/plugins/editor.lua b/nvim/lua/plugins/editor.lua index aa2da88..a8d43a9 100644 --- a/nvim/lua/plugins/editor.lua +++ b/nvim/lua/plugins/editor.lua @@ -1,27 +1,10 @@ -- editor.lua - 编辑器增强插件配置 +-- 包含:telescope, gitsigns, flash, todo-comments, which-key, mini.bufremove, +-- autopairs, illuminate, ufo(折叠), rainbow-delimiters, toggleterm, +-- trouble(v3), persistence, luasnip, ts-comments, vim-visual-multi return { - -- LazyGit 集成 - { - "kdheepak/lazygit.nvim", - cmd = { - "LazyGit", - "LazyGitConfig", - "LazyGitCurrentFile", - "LazyGitFilter", - "LazyGitFilterCurrentFile", - }, - dependencies = { - "nvim-lua/plenary.nvim", - }, - keys = { - { "gg", "LazyGit", desc = "打开 LazyGit" }, - { "gf", "LazyGitCurrentFile", desc = "当前文件 Git 历史" }, - { "gc", "LazyGitConfig", desc = "LazyGit 配置" }, - }, - }, - - -- 模糊搜索 + -- 模糊搜索(保留 telescope 作为备选/LSP 操作入口) { "nvim-telescope/telescope.nvim", cmd = "Telescope", @@ -35,34 +18,7 @@ return { }, }, keys = { - -- 文件查找 - { "ff", "Telescope find_files", desc = "查找文件" }, - { "fr", "Telescope oldfiles", desc = "最近文件" }, - { "fb", "Telescope buffers", desc = "查找缓冲区" }, - - -- 内容搜索 - { "fg", "Telescope live_grep", desc = "全局搜索" }, - { "fw", "Telescope grep_string", desc = "搜索当前单词" }, - - -- 其他功能 - { "fh", "Telescope help_tags", desc = "帮助标签" }, - { "fm", "Telescope marks", desc = "跳转到书签" }, - { "fc", "Telescope commands", desc = "命令" }, - { "fk", "Telescope keymaps", desc = "快捷键" }, - - -- 工作区相关 - { "ws", "Telescope lsp_workspace_symbols", desc = "工作区符号" }, - - -- LSP 相关 - { "cs", "Telescope lsp_document_symbols", desc = "文档符号" }, - { "cr", "Telescope lsp_references", desc = "引用" }, - { "ci", "Telescope lsp_implementations", desc = "实现" }, - { "cd", "Telescope lsp_definitions", desc = "定义" }, - { "ct", "Telescope lsp_type_definitions", desc = "类型定义" }, - - -- 诊断 - { "xx", "Telescope diagnostics bufnr=0", desc = "当前文件诊断" }, - { "xw", "Telescope diagnostics", desc = "工作区诊断" }, + { "fp", "Telescope projects", desc = "项目" }, }, opts = { defaults = { @@ -70,228 +26,230 @@ return { selection_caret = " ", mappings = { i = { - [""] = function(...) - return require("telescope.actions").move_selection_next(...) - end, - [""] = function(...) - return require("telescope.actions").move_selection_previous(...) - end, - [""] = function(...) - return require("telescope.actions").cycle_history_next(...) - end, - [""] = function(...) - return require("telescope.actions").cycle_history_prev(...) - end, - [""] = function(...) - return require("telescope.actions").close(...) - end, - [""] = function(...) - return require("telescope.actions").preview_scrolling_up(...) - end, - [""] = function(...) - return require("telescope.actions").preview_scrolling_down(...) - end, - }, - n = { - ["q"] = function(...) - return require("telescope.actions").close(...) - end, + [""] = function(...) return require("telescope.actions").move_selection_next(...) end, + [""] = function(...) return require("telescope.actions").move_selection_previous(...) end, + [""] = function(...) return require("telescope.actions").close(...) end, }, + n = { ["q"] = function(...) return require("telescope.actions").close(...) end }, }, }, pickers = { - find_files = { - -- 默认包含隐藏文件 - find_command = { "rg", "--files", "--hidden", "--glob", "!.git" }, - }, + find_files = { find_command = { "rg", "--files", "--hidden", "--glob", "!.git" } }, }, }, config = function(_, opts) local telescope = require("telescope") telescope.setup(opts) - - -- 加载扩展 pcall(telescope.load_extension, "fzf") end, }, - - -- LazyGit 集成 + + -- Git 变更标记 { - "kdheepak/lazygit.nvim", - cmd = { - "LazyGit", - "LazyGitConfig", - "LazyGitCurrentFile", - "LazyGitFilter", - "LazyGitFilterCurrentFile", - }, - dependencies = { - "nvim-lua/plenary.nvim", - }, - keys = { - { "gg", "LazyGit", desc = "打开 LazyGit" }, - { "gf", "LazyGitCurrentFile", desc = "当前文件 Git 历史" }, - { "gc", "LazyGitConfig", desc = "LazyGit 配置" }, + "lewis6991/gitsigns.nvim", + event = { "BufReadPre", "BufNewFile" }, + opts = { + signs = { + add = { text = "▎" }, change = { text = "▎" }, delete = { text = "" }, + topdelete = { text = "" }, changedelete = { text = "▎" }, untracked = { text = "▎" }, + }, + on_attach = function(buffer) + local gs = package.loaded.gitsigns + local function map(mode, l, r, desc) + vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc }) + end + map("n", "]h", gs.next_hunk, "下一个变更") + map("n", "[h", gs.prev_hunk, "上一个变更") + map({ "n", "v" }, "gs", ":Gitsigns stage_hunk", "暂存变更") + map({ "n", "v" }, "gr", ":Gitsigns reset_hunk", "重置变更") + map("n", "gS", gs.stage_buffer, "暂存文件") + map("n", "gu", gs.undo_stage_hunk, "取消暂存变更") + map("n", "gR", gs.reset_buffer, "重置文件") + map("n", "gp", gs.preview_hunk, "预览变更") + map("n", "gb", function() gs.blame_line({ full = true }) end, "查看责任") + map("n", "gB", gs.toggle_current_line_blame, "开关行责任") + map("n", "gd", gs.diffthis, "文件差异") + map({ "o", "x" }, "ih", ":Gitsigns select_hunk", "选择变更") + end, }, }, - -- 高级语法高亮 + -- 快速跳转 { - "nvim-treesitter/nvim-treesitter", - build = ":TSUpdate", - event = { "BufReadPost", "BufNewFile" }, - dependencies = { - "nvim-treesitter/nvim-treesitter-textobjects", - }, + "folke/flash.nvim", + event = "VeryLazy", opts = { - -- 自动安装的语法 - ensure_installed = { - "bash", - "c", - "cmake", - "comment", - "cpp", - "css", - "dockerfile", - "gitignore", - "go", - "gomod", - "gowork", - "html", - "http", - "java", - "javascript", - "json", - "kotlin", - "lua", - "make", - "markdown", - "markdown_inline", - "python", - "regex", - "ruby", - "rust", - "sql", - "toml", - "tsx", - "typescript", - "vim", - "vimdoc", - "xml", - "yaml", - }, - - -- 启用特性 - highlight = { enable = true }, - indent = { enable = true }, - incremental_selection = { - enable = true, - keymaps = { - init_selection = "", - node_incremental = "", - scope_incremental = false, - node_decremental = "", - }, - }, - - -- 文本对象 - textobjects = { - select = { - enable = true, - lookahead = true, - keymaps = { - ["af"] = "@function.outer", - ["if"] = "@function.inner", - ["ac"] = "@class.outer", - ["ic"] = "@class.inner", - ["aa"] = "@parameter.outer", - ["ia"] = "@parameter.inner", - }, - }, - move = { - enable = true, - set_jumps = true, - goto_next_start = { - ["]f"] = "@function.outer", - ["]c"] = "@class.outer", - }, - goto_next_end = { - ["]F"] = "@function.outer", - ["]C"] = "@class.outer", - }, - goto_previous_start = { - ["[f"] = "@function.outer", - ["[c"] = "@class.outer", - }, - goto_previous_end = { - ["[F"] = "@function.outer", - ["[C"] = "@class.outer", - }, - }, + search = { multi_window = false, wrap = true }, + modes = { char = { enabled = true, keys = { "f", "F", "t", "T", ";", "," } } }, + }, + keys = { + { "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash 跳转" }, + { "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" }, + { "r", mode = "o", function() require("flash").remote() end, desc = "Flash 远程" }, + { "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Flash Treesitter 搜索" }, + }, + }, + + -- TODO 注释高亮 + { + "folke/todo-comments.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + event = "BufReadPost", + opts = { signs = true }, + keys = { + { "]t", function() require("todo-comments").jump_next() end, desc = "下一个 TODO" }, + { "[t", function() require("todo-comments").jump_prev() end, desc = "上一个 TODO" }, + { "ft", "TodoTelescope", desc = "TODO 列表" }, + }, + }, + + -- which-key 按键提示 + { + "folke/which-key.nvim", + event = "VeryLazy", + opts = { + plugins = { + marks = true, registers = true, + spelling = { enabled = true, suggestions = 20 }, + presets = { operators = true, motions = true, text_objects = true, windows = true, nav = true, z = true, g = true }, }, + icons = { breadcrumb = "»", separator = "➜", group = "+" }, + win = { border = "rounded" }, + show_help = true, }, config = function(_, opts) - require("nvim-treesitter.configs").setup(opts) + local wk = require("which-key") + wk.setup(opts) + wk.add({ + { "b", group = "缓冲区" }, + { "c", group = "代码" }, + { "d", group = "调试" }, + { "f", group = "查找/文件" }, + { "g", group = "Git" }, + { "n", group = "通知" }, + { "q", group = "退出/会话" }, + { "r", group = "Rust" }, + { "s", group = "搜索" }, + { "t", group = "TypeScript/终端" }, + { "u", group = "UI 切换" }, + { "x", group = "诊断" }, + { "p", group = "Python" }, + { "gt", group = "Go 测试" }, + { "gg", group = "Go 生成" }, + { "dt", group = "调试 - 测试" }, + { "dp", group = "调试 - Python" }, + { "rc", group = "Rust Crate" }, + { "sn", group = "Noice" }, + }) end, }, - - -- 代码注释 + + -- Trouble v3 - 诊断列表 { - "numToStr/Comment.nvim", + "folke/trouble.nvim", + cmd = "Trouble", opts = { - padding = true, -- 在注释分隔符后添加空格 - sticky = true, -- 注释时光标不移动 - toggler = { - line = "gcc", -- 行注释切换 - block = "gbc", -- 块注释切换 - }, - opleader = { - line = "gc", -- 行注释操作 - block = "gb", -- 块注释操作 - }, - extra = { - above = "gcO", -- 在当前行上方添加注释 - below = "gco", -- 在当前行下方添加注释 - eol = "gcA", -- 在当前行尾添加注释 - }, - mappings = { - basic = true, -- 基本映射 - extra = true, -- 额外映射 + modes = { + lsp = { + win = { position = "right" }, + }, }, }, keys = { - { "gcc", mode = "n", desc = "行注释" }, - { "gbc", mode = "n", desc = "块注释" }, - { "gc", mode = { "n", "o" }, desc = "行注释操作" }, - { "gb", mode = { "n", "o" }, desc = "块注释操作" }, + { "xx", "Trouble diagnostics toggle", desc = "诊断" }, + { "xX", "Trouble diagnostics toggle filter.buf=0", desc = "当前文件诊断" }, + { "xL", "Trouble loclist toggle", desc = "位置列表" }, + { "xQ", "Trouble qflist toggle", desc = "快速修复" }, + { "xs", "Trouble symbols toggle", desc = "符号" }, + { + "[q", + function() + if require("trouble").is_open() then + require("trouble").prev({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cprev) + if not ok then vim.notify(err, vim.log.levels.ERROR) end + end + end, + desc = "上一个问题", + }, + { + "]q", + function() + if require("trouble").is_open() then + require("trouble").next({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cnext) + if not ok then vim.notify(err, vim.log.levels.ERROR) end + end + end, + desc = "下一个问题", + }, }, }, - - -- 代码折叠 + + -- 缓冲区删除(保留分割窗口) { - "kevinhwang91/nvim-ufo", - dependencies = { - "kevinhwang91/promise-async", + "echasnovski/mini.bufremove", + keys = { + { "bd", function() require("mini.bufremove").delete(0, false) end, desc = "关闭缓冲区" }, + { "bD", function() require("mini.bufremove").delete(0, true) end, desc = "强制关闭缓冲区" }, }, + }, + + -- 自动括号配对 + { + "windwp/nvim-autopairs", + event = "InsertEnter", + opts = { + check_ts = true, + ts_config = { + lua = { "string", "source" }, + javascript = { "string", "template_string" }, + }, + fast_wrap = { map = "" }, + }, + }, + + -- 高亮相同单词 + { + "RRethy/vim-illuminate", event = "BufReadPost", opts = { - provider_selector = function() - return { "treesitter", "indent" } - end, + delay = 200, + large_file_cutoff = 2000, + large_file_overrides = { providers = { "lsp" } }, + }, + config = function(_, opts) + require("illuminate").configure(opts) + local function map(key, dir, buffer) + vim.keymap.set("n", key, function() + require("illuminate")["goto_" .. dir .. "_reference"](false) + end, { desc = dir .. " 引用", buffer = buffer }) + end + map("]]", "next") + map("[[", "prev") + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(args) + map("]]", "next", args.buf) + map("[[", "prev", args.buf) + end, + }) + end, + keys = { { "]]", desc = "下一个引用" }, { "[[", desc = "上一个引用" } }, + }, + + -- 代码折叠(基于 LSP/treesitter) + { + "kevinhwang91/nvim-ufo", + dependencies = { "kevinhwang91/promise-async" }, + event = "BufReadPost", + opts = { + provider_selector = function() return { "treesitter", "indent" } end, open_fold_hl_timeout = 150, - close_fold_kinds_for_ft = {}, preview = { - win_config = { - border = { "", "─", "", "", "", "─", "", "" }, - winhighlight = "Normal:Folded", - winblend = 0, - }, - mappings = { - scrollU = "", - scrollD = "", - jumpTop = "[", - jumpBot = "]", - }, + win_config = { border = { "", "─", "", "", "", "─", "", "" }, winhighlight = "Normal:Folded", winblend = 0 }, + mappings = { scrollU = "", scrollD = "", jumpTop = "[", jumpBot = "]" }, }, }, init = function() @@ -303,12 +261,29 @@ return { keys = { { "zR", function() require("ufo").openAllFolds() end, desc = "打开所有折叠" }, { "zM", function() require("ufo").closeAllFolds() end, desc = "关闭所有折叠" }, - { "zr", function() require("ufo").openFoldsExceptKinds() end, desc = "打开一级折叠" }, - { "zm", function() require("ufo").closeFoldsWith() end, desc = "关闭一级折叠" }, - { "zp", function() require("ufo").peekFoldedLinesUnderCursor() end, desc = "预览当前折叠" }, + { "zr", function() require("ufo").openFoldsExceptKinds() end, desc = "展开一级" }, + { "zm", function() require("ufo").closeFoldsWith() end, desc = "折叠一级" }, + { "zp", function() require("ufo").peekFoldedLinesUnderCursor() end, desc = "预览折叠" }, }, }, - + + -- 彩虹括号 + { + "HiPhish/rainbow-delimiters.nvim", + event = "BufReadPost", + config = function() + local rd = require("rainbow-delimiters") + vim.g.rainbow_delimiters = { + strategy = { [""] = rd.strategy["global"], vim = rd.strategy["local"] }, + query = { [""] = "rainbow-delimiters", lua = "rainbow-blocks" }, + highlight = { + "RainbowDelimiterRed", "RainbowDelimiterYellow", "RainbowDelimiterBlue", + "RainbowDelimiterOrange", "RainbowDelimiterGreen", "RainbowDelimiterViolet", "RainbowDelimiterCyan", + }, + } + end, + }, + -- 终端集成 { "akinsho/toggleterm.nvim", @@ -317,222 +292,126 @@ return { { "tf", "ToggleTerm direction=float", desc = "浮动终端" }, { "th", "ToggleTerm direction=horizontal", desc = "水平终端" }, { "tv", "ToggleTerm direction=vertical size=40", desc = "垂直终端" }, - { "tt", "ToggleTerm", desc = "切换终端" }, + { "", "ToggleTerm", desc = "切换终端" }, }, opts = { size = function(term) - if term.direction == "horizontal" then - return 15 - elseif term.direction == "vertical" then - return vim.o.columns * 0.4 + if term.direction == "horizontal" then return 15 + elseif term.direction == "vertical" then return vim.o.columns * 0.4 end end, open_mapping = [[]], - hide_numbers = true, - shade_filetypes = {}, - autochdir = true, - shade_terminals = true, - shading_factor = 2, - start_in_insert = true, - insert_mappings = true, - terminal_mappings = true, - persist_size = true, - persist_mode = true, direction = "float", + float_opts = { border = "curved", winblend = 3 }, + autochdir = true, + start_in_insert = true, close_on_exit = true, - shell = vim.o.shell, - float_opts = { - border = "curved", - winblend = 3, - highlights = { - border = "Normal", - background = "Normal", - }, - }, }, }, - - -- 代码片段 + + -- 会话管理 { - "L3MON4D3/LuaSnip", - dependencies = { - "rafamadriz/friendly-snippets", - config = function() - require("luasnip.loaders.from_vscode").lazy_load() - end, - }, + "folke/persistence.nvim", + event = "BufReadPre", opts = { - history = true, - delete_check_events = "TextChanged", + dir = vim.fn.expand(vim.fn.stdpath("state") .. "/sessions/"), + options = { "buffers", "curdir", "tabpages", "winsize" }, }, keys = { - { - "", - function() - return require("luasnip").jumpable(1) and "luasnip-jump-next" or "" - end, - expr = true, silent = true, mode = "i", - }, - { "", function() require("luasnip").jump(1) end, mode = "s" }, - { "", function() require("luasnip").jump(-1) end, mode = { "i", "s" } }, + { "qs", function() require("persistence").load() end, desc = "恢复上次会话" }, + { "ql", function() require("persistence").load({ last = true }) end, desc = "恢复最后会话" }, + { "qd", function() require("persistence").stop() end, desc = "不保存会话" }, }, }, - - -- 自动括号配对 - { - "windwp/nvim-autopairs", - event = "InsertEnter", - opts = { - check_ts = true, -- 检查 treesitter - ts_config = { - lua = { "string", "source" }, - javascript = { "string", "template_string" }, - java = false, - }, - fast_wrap = { - map = "", - chars = { "{", "[", "(", '"', "'" }, - pattern = string.gsub([[ [%'%"%)%>%]%)%}%,] ]], "%s+", ""), - offset = 0, - end_key = "$", - keys = "qwertyuiopzxcvbnmasdfghjkl", - check_comma = true, - highlight = "PmenuSel", - highlight_grey = "LineNr", - }, - }, - }, - - -- Git 集成 - { - "lewis6991/gitsigns.nvim", - event = { "BufReadPre", "BufNewFile" }, - opts = { - signs = { - add = { text = "▎" }, - change = { text = "▎" }, - delete = { text = "▁" }, - topdelete = { text = "▔" }, - changedelete = { text = "▎" }, - untracked = { text = "▎" }, - }, - on_attach = function(buffer) - local gs = package.loaded.gitsigns - - local function map(mode, l, r, desc) - vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc }) - end - - -- 导航 - map("n", "]h", gs.next_hunk, "下一个变更") - map("n", "[h", gs.prev_hunk, "上一个变更") - - -- 操作 - map({ "n", "v" }, "gs", ":Gitsigns stage_hunk", "暂存变更") - map({ "n", "v" }, "gr", ":Gitsigns reset_hunk", "重置变更") - map("n", "gS", gs.stage_buffer, "暂存文件") - map("n", "gu", gs.undo_stage_hunk, "取消暂存变更") - map("n", "gR", gs.reset_buffer, "重置文件") - map("n", "gp", gs.preview_hunk, "预览变更") - map("n", "gb", function() gs.blame_line({ full = true }) end, "查看责任") - map("n", "gB", gs.toggle_current_line_blame, "开关行责任") - map("n", "gd", gs.diffthis, "文件差异") - map("n", "gD", function() gs.diffthis("~") end, "与HEAD差异") - map("n", "gt", gs.toggle_deleted, "开关显示删除") - - -- 文本对象 - map({ "o", "x" }, "ih", ":Gitsigns select_hunk", "选择变更") - end, - }, - }, - - -- 多光标编辑 + + -- 多光标( 选择当前词, 添加光标) { "mg979/vim-visual-multi", event = "BufReadPost", init = function() vim.g.VM_leader = ";" + -- 使用默认 而非覆盖 已用于滚动) vim.g.VM_maps = { - ["Find Under"] = "", - ["Find Subword Under"] = "", + ["Find Under"] = "", + ["Find Subword Under"] = "", } end, }, - - -- 高亮相同单词 + + -- TypeScript/JSX 注释增强 { - "RRethy/vim-illuminate", + "JoosepAlviste/nvim-ts-context-commentstring", + lazy = true, + opts = { enable_autocmd = false }, + }, + + -- 注释插件(支持 context commentstring) + { + "numToStr/Comment.nvim", event = "BufReadPost", opts = { - delay = 200, - large_file_cutoff = 2000, - large_file_overrides = { - providers = { "lsp" }, + padding = true, + sticky = true, + toggler = { line = "gcc", block = "gbc" }, + opleader = { line = "gc", block = "gb" }, + extra = { above = "gcO", below = "gco", eol = "gcA" }, + pre_hook = function() + return require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook()() + end, + }, + }, + + -- 增强文本对象(mini.ai) + -- af/if=函数, ac/ic=类, aa/ia=参数, ab/ib=块, aq/iq=引号, at/it=标签 + { + "echasnovski/mini.ai", + event = "VeryLazy", + opts = { + n_lines = 500, + custom_textobjects = { + -- 整个文件 + e = function() + local from = { line = 1, col = 1 } + local to = { line = vim.fn.line("$"), col = math.max(vim.fn.getline("$"):len(), 1) } + return { from = from, to = to } + end, }, }, - config = function(_, opts) - require("illuminate").configure(opts) - - local function map(key, dir, buffer) - vim.keymap.set("n", key, function() - require("illuminate")["goto_" .. dir .. "_reference"](false) - end, { desc = dir:sub(1, 1):upper() .. dir:sub(2) .. " 引用", buffer = buffer }) - end - - -- 下一个/上一个引用导航 - map("]]", "next") - map("[[", "prev") - - -- 同时也是 LSP 附加时设置键绑定 - vim.api.nvim_create_autocmd("LspAttach", { - callback = function(args) - local buffer = args.buf - map("]]", "next", buffer) - map("[[", "prev", buffer) + }, + + -- 括号/引号包围操作(mini.surround) + -- saiw" = 用 " 包围单词, sd" = 删除 ", sr"' = 替换 " 为 ' + { + "echasnovski/mini.surround", + event = "VeryLazy", + opts = { + mappings = { + add = "gsa", -- 添加包围 + delete = "gsd", -- 删除包围 + find = "gsf", -- 向前查找包围 + find_left = "gsF", -- 向后查找包围 + highlight = "gsh", -- 高亮包围 + replace = "gsr", -- 替换包围 + update_n_lines = "gsn", -- 更新搜索范围 + }, + }, + }, + + -- 项目范围搜索替换(grug-far) + { + "MagicDuck/grug-far.nvim", + cmd = "GrugFar", + keys = { + { + "sr", + function() + local ext = vim.bo.filetype ~= "" and ("." .. vim.bo.filetype) or "" + require("grug-far").open({ prefills = { filesFilter = "*" .. ext } }) end, - }) - end, - keys = { - { "]]", desc = "下一个引用" }, - { "[[", desc = "上一个引用" }, + mode = { "n", "v" }, + desc = "搜索替换(项目范围)", + }, }, + opts = { headerMaxWidth = 80 }, }, - - -- 缓冲区删除 - { - "echasnovski/mini.bufremove", - keys = { - { "bd", function() require("mini.bufremove").delete(0, false) end, desc = "删除缓冲区" }, - { "bD", function() require("mini.bufremove").delete(0, true) end, desc = "强制删除缓冲区" }, - }, - }, - - -- 括号高亮配对 - { - "HiPhish/rainbow-delimiters.nvim", - event = "BufReadPost", - config = function() - local rainbow_delimiters = require("rainbow-delimiters") - - vim.g.rainbow_delimiters = { - strategy = { - [""] = rainbow_delimiters.strategy["global"], - vim = rainbow_delimiters.strategy["local"], - }, - query = { - [""] = "rainbow-delimiters", - lua = "rainbow-blocks", - }, - highlight = { - "RainbowDelimiterRed", - "RainbowDelimiterYellow", - "RainbowDelimiterBlue", - "RainbowDelimiterOrange", - "RainbowDelimiterGreen", - "RainbowDelimiterViolet", - "RainbowDelimiterCyan", - }, - } - end, - }, -} \ No newline at end of file +} diff --git a/nvim/lua/plugins/flash.lua b/nvim/lua/plugins/flash.lua deleted file mode 100644 index f52abc6..0000000 --- a/nvim/lua/plugins/flash.lua +++ /dev/null @@ -1 +0,0 @@ -return {"folke/flash.nvim", opts={}} \ No newline at end of file diff --git a/nvim/lua/plugins/formatting.lua b/nvim/lua/plugins/formatting.lua new file mode 100644 index 0000000..640eb26 --- /dev/null +++ b/nvim/lua/plugins/formatting.lua @@ -0,0 +1,78 @@ +-- formatting.lua - 代码格式化(conform.nvim) + +return { + { + "stevearc/conform.nvim", + event = { "BufReadPre", "BufNewFile" }, + cmd = { "ConformInfo" }, + keys = { + { + "cf", + function() + require("conform").format({ async = true, lsp_format = "fallback" }) + end, + mode = { "n", "v" }, + desc = "格式化代码", + }, + { + "uf", + function() + vim.b.disable_autoformat = not vim.b.disable_autoformat + vim.notify( + "当前缓冲区自动格式化 " .. (vim.b.disable_autoformat and "已禁用" or "已启用"), + vim.log.levels.INFO + ) + end, + desc = "切换当前缓冲区自动格式化", + }, + { + "uF", + function() + vim.g.disable_autoformat = not vim.g.disable_autoformat + vim.notify( + "全局自动格式化 " .. (vim.g.disable_autoformat and "已禁用" or "已启用"), + vim.log.levels.INFO + ) + end, + desc = "切换全局自动格式化", + }, + }, + opts = { + formatters_by_ft = { + lua = { "stylua" }, + go = { "goimports", "gofumpt" }, + rust = { "rustfmt" }, + python = { "isort", "ruff_format" }, + javascript = { "prettierd", "prettier", stop_after_first = true }, + typescript = { "prettierd", "prettier", stop_after_first = true }, + javascriptreact = { "prettierd", "prettier", stop_after_first = true }, + typescriptreact = { "prettierd", "prettier", stop_after_first = true }, + json = { "prettierd" }, + jsonc = { "prettierd" }, + html = { "prettierd" }, + css = { "prettierd" }, + scss = { "prettierd" }, + yaml = { "prettierd" }, + markdown = { "prettierd" }, + sh = { "shfmt" }, + bash = { "shfmt" }, + }, + + formatters = { + stylua = { + args = { "--indent-type", "Spaces", "--indent-width", "2", "-" }, + }, + shfmt = { + args = { "-i", "2", "-" }, + }, + }, + + format_on_save = function(bufnr) + if vim.b[bufnr].disable_autoformat or vim.g.disable_autoformat then + return + end + return { timeout_ms = 3000, lsp_format = "fallback" } + end, + }, + }, +} diff --git a/nvim/lua/plugins/go.lua b/nvim/lua/plugins/go.lua deleted file mode 100644 index 243002b..0000000 --- a/nvim/lua/plugins/go.lua +++ /dev/null @@ -1,285 +0,0 @@ --- go.lua - Go 开发专用配置 - -return { - -- Go 专用插件 - { - "ray-x/go.nvim", - dependencies = { - "ray-x/guihua.lua", - "neovim/nvim-lspconfig", - "nvim-treesitter/nvim-treesitter", - }, - ft = { "go", "gomod", "gowork", "gotmpl" }, - build = ':lua require("go.install").update_all_sync()', -- 同步更新所有解析器 - opts = { - -- 日志级别: 可以是 'trace', 'debug', 'info', 'warn', 'error', 'fatal' - lsp_cfg = { - settings = { - gopls = { - gofumpt = true, - codelenses = { - gc_details = true, - generate = true, - regenerate_cgo = true, - run_govulncheck = true, - test = true, - tidy = true, - upgrade_dependency = true, - vendor = true, - }, - hints = { - assignVariableTypes = true, - compositeLiteralFields = true, - constantValues = true, - functionTypeParameters = true, - parameterNames = true, - rangeVariableTypes = true, - }, - analyses = { - fieldalignment = true, - nilness = true, - unusedparams = true, - unusedwrite = true, - useany = true, - shadow = true, - }, - usePlaceholders = true, - completeUnimported = true, - staticcheck = true, - directoryFilters = { "-.git", "-.vscode", "-.idea", "-.vscode-test", "-node_modules" }, - semanticTokens = true, - }, - }, - }, - lsp_on_attach = function(client, bufnr) - -- 启用自动格式化 - vim.api.nvim_buf_set_option(bufnr, "formatexpr", "v:lua.vim.lsp.formatexpr()") - - -- 设置键映射 - local map = function(mode, lhs, rhs, desc) - if desc then - desc = desc - end - vim.keymap.set(mode, lhs, rhs, { silent = true, desc = desc, buffer = bufnr, noremap = true }) - end - - -- Go 特定映射 - map("n", "gfs", "GoFillStruct", "填充结构体") - map("n", "gfa", "GoAddTag", "添加标签") - map("n", "gfr", "GoRmTag", "移除标签") - map("n", "gcl", "GoClearTag", "清除标签") - map("n", "ge", "GoIfErr", "生成错误处理") - - -- 代码生成 - map("n", "ggt", "GoTest", "生成测试") - map("n", "ggf", "GoTestFunc", "生成函数测试") - map("n", "ggc", "GoCoverage", "显示测试覆盖率") - map("n", "ggC", "GoCoverageClear", "清除测试覆盖率") - map("n", "ggb", "GoBuild", "构建") - map("n", "ggr", "GoRun", "运行") - - -- 代码操作 - map("n", "gil", "GoImport", "导入包") - map("n", "gia", "GoImportAll", "导入所有") - map("n", "gif", "GoImpl", "实现接口") - map("n", "gid", "GoDoc", "查看文档") - - -- 代码移动 - map("n", "gca", "GoCodeAction", "代码操作") - map("n", "gfd", "GoFixDocumentation", "修复文档") - map("n", "gsf", "GoFillSwitch", "填充 switch") - map("n", "gsj", "GoAddErrCheck", "添加错误检查") - - -- 调试和测试 - map("n", "gtc", "GoCmt", "生成注释") - map("n", "gts", "GoAlt", "在实现和测试间切换") - end, - lsp_codelens = true, - -- 控制 gopls 设置 - lsp_keymaps = false, -- 我们手动设置键映射 - lsp_diag_hdlr = true, - lsp_diag_virtual_text = { space = 0, prefix = "" }, - lsp_diag_signs = true, - lsp_diag_update_in_insert = false, - lsp_document_formatting = true, - -- 代码格式化设置 - formatter = "gofumpt", -- gofmt, gofumpt, golines - formatter_extra_args = { "-s" }, - -- 测试设置 - test_runner = "go", -- richgo, go test, richgo, dlv, ginkgo - run_in_floaterm = true, - -- 调试设置 - dap_debug = true, - dap_debug_gui = true, - dap_debug_vt = true, - dap_port = 38697, - dap_timeout = 15, - -- 其他设置 - textobjects = true, - gofmt = true, -- 设置 gofmt 和 goimports - goimport = "gopls", -- goimport, gopls - diagnostic = { - hdlr = true, - underline = true, - virtual_text = { space = 0, prefix = "" }, - signs = true, - update_in_insert = false, - }, - tag_transform = "snakecase", - -- 路径设置 - verbose = false, - trouble = true, - lsp_inlay_hints = { - enable = true, - -- 使用 LSP 内联提示而不是 virtualtypes - only_current_line = false, - only_current_line_autocmd = "CursorHold", - show_parameter_hints = true, - show_variable_name = true, - parameter_hints_prefix = " ", - other_hints_prefix = " ", - highlight = "LspInlayHint", - }, - }, - config = function(_, opts) - require("go").setup(opts) - - -- 设置自动命令 - local gogroup = vim.api.nvim_create_augroup("GoGroup", { clear = true }) - - vim.api.nvim_create_autocmd("BufWritePre", { - pattern = "*.go", - group = gogroup, - callback = function() - require("go.format").goimport() - end, - }) - - vim.api.nvim_create_autocmd("FileType", { - pattern = "go", - group = gogroup, - callback = function() - -- 将 tab 宽度设置为 Go 的标准 - vim.bo.tabstop = 4 - vim.bo.shiftwidth = 4 - vim.bo.softtabstop = 4 - vim.bo.expandtab = false - end, - }) - end, - keys = { - -- 测试 - { "gts", "GoAlt", desc = "切换测试/实现文件" }, - { "gtt", "GoTest", desc = "运行包测试" }, - { "gtf", "GoTestFunc", desc = "测试函数" }, - { "gtc", "GoCoverage", desc = "测试覆盖率" }, - { "gtC", "GoCoverageClear", desc = "清除测试覆盖率" }, - - -- 格式化 - { "gff", "GoFormat", desc = "格式化" }, - { "gfi", "GoImport", desc = "导入" }, - { "gfI", "GoImportAll", desc = "导入所有" }, - - -- 模板 - { "gge", "GoIfErr", desc = "生成错误处理" }, - { "ggf", "GoFillStruct", desc = "填充结构体" }, - { "ggs", "GoFillSwitch", desc = "填充 switch" }, - - -- 标签 - { "gta", "GoAddTag", desc = "添加标签" }, - { "gtr", "GoRmTag", desc = "移除标签" }, - { "gtc", "GoClearTag", desc = "清除标签" }, - - -- 运行和构建 - { "gr", "GoRun", desc = "运行" }, - { "gb", "GoBuild", desc = "构建" }, - - -- 工具 - { "gi", "GoImpl", desc = "实现接口" }, - { "gd", "GoDoc", desc = "查看文档" }, - { "gl", "GoLint", desc = "运行 golint" }, - { "gv", "GoVet", desc = "运行 go vet" }, - }, - }, - - -- 格式化集成 - { - "stevearc/conform.nvim", - optional = true, - opts = { - formatters_by_ft = { - go = { "goimports", "gofumpt" }, - }, - }, - }, - - -- 调试支持 - { - "mfussenegger/nvim-dap", - optional = true, - dependencies = { - { - "leoluz/nvim-dap-go", - config = true, - }, - }, - keys = { - { "dgr", function() require("dap-go").debug_test() end, desc = "调试当前测试" }, - { "dgl", function() require("dap-go").debug_last_test() end, desc = "调试上一个测试" }, - }, - }, - - -- 单元测试 - { - "nvim-neotest/neotest", - optional = true, - dependencies = { - "nvim-neotest/neotest-go", - }, - opts = { - adapters = { - ["neotest-go"] = { - -- 使用 gotest 作为测试器 - args = { "-count=1", "-timeout=30s", "-v" }, - }, - }, - }, - }, - - -- 工具安装程序 - { - "williamboman/mason.nvim", - optional = true, - opts = function(_, opts) - -- 添加 Go 工具到确保安装列表 - if type(opts.ensure_installed) == "table" then - vim.list_extend(opts.ensure_installed, { - "gopls", - "gofumpt", - "goimports", - "golangci-lint", - "gomodifytags", - "gotests", - "impl", - "delve", - }) - end - end, - }, - - -- Treesitter 集成 - { - "nvim-treesitter/nvim-treesitter", - opts = function(_, opts) - -- 添加 Go 相关的解析器 - if type(opts.ensure_installed) == "table" then - vim.list_extend(opts.ensure_installed, { - "go", - "gomod", - "gowork", - "gosum", - }) - end - end, - }, -} \ No newline at end of file diff --git a/nvim/lua/plugins/lang/go.lua b/nvim/lua/plugins/lang/go.lua new file mode 100644 index 0000000..4a4bbb8 --- /dev/null +++ b/nvim/lua/plugins/lang/go.lua @@ -0,0 +1,121 @@ +-- lang/go.lua - Go 开发专用配置 + +return { + -- ray-x/go.nvim - Go 全功能插件 + { + "ray-x/go.nvim", + dependencies = { + "ray-x/guihua.lua", + "neovim/nvim-lspconfig", + "nvim-treesitter/nvim-treesitter", + }, + ft = { "go", "gomod", "gowork", "gotmpl" }, + build = ':lua require("go.install").update_all_sync()', + opts = { + lsp_cfg = false, -- LSP 由 lsp.lua 的 gopls 配置统一管理 + lsp_keymaps = false, + lsp_codelens = true, + lsp_inlay_hints = { + enable = true, + only_current_line = false, + show_parameter_hints = true, + parameter_hints_prefix = " ", + other_hints_prefix = " ", + }, + formatter = "gofumpt", + goimport = "gopls", + gofmt = true, + test_runner = "go", + run_in_floaterm = true, + dap_debug = true, + dap_debug_gui = true, + dap_debug_vt = true, + textobjects = true, + trouble = true, + diagnostic = { + hdlr = true, + underline = true, + virtual_text = { space = 0, prefix = "" }, + signs = true, + update_in_insert = false, + }, + tag_transform = "snakecase", + verbose = false, + }, + config = function(_, opts) + require("go").setup(opts) + + local gogroup = vim.api.nvim_create_augroup("GoGroup", { clear = true }) + + vim.api.nvim_create_autocmd("BufWritePre", { + pattern = "*.go", + group = gogroup, + callback = function() + require("go.format").goimport() + end, + }) + end, + keys = { + { "gts", "GoAlt", ft = "go", desc = "切换测试/实现" }, + { "gtt", "GoTest", ft = "go", desc = "运行测试" }, + { "gtf", "GoTestFunc", ft = "go", desc = "测试当前函数" }, + { "gtc", "GoCoverage", ft = "go", desc = "测试覆盖率" }, + { "gtC", "GoCoverageClear", ft = "go", desc = "清除覆盖率" }, + { "gge", "GoIfErr", ft = "go", desc = "生成错误处理" }, + { "ggf", "GoFillStruct", ft = "go", desc = "填充结构体" }, + { "ggs", "GoFillSwitch", ft = "go", desc = "填充 switch" }, + { "gta", "GoAddTag", ft = "go", desc = "添加标签" }, + { "gtr", "GoRmTag", ft = "go", desc = "移除标签" }, + { "gr", "GoRun", ft = "go", desc = "运行" }, + { "gb", "GoBuild", ft = "go", desc = "构建" }, + { "gi", "GoImpl", ft = "go", desc = "实现接口" }, + { "gdc", "GoDoc", ft = "go", desc = "查看文档" }, + { "gv", "GoVet", ft = "go", desc = "go vet" }, + }, + }, + + -- Go DAP 支持 + { + "leoluz/nvim-dap-go", + ft = "go", + dependencies = { "mfussenegger/nvim-dap" }, + config = function() + require("dap-go").setup({ dap_configurations = { + { type = "go", name = "调试文件", request = "launch", program = "${file}" }, + { type = "go", name = "调试包", request = "launch", program = "${fileDirname}" }, + { type = "go", name = "调试测试", request = "launch", mode = "test", program = "${file}" }, + }}) + end, + keys = { + { "dtg", function() require("dap-go").debug_test() end, ft = "go", desc = "调试当前测试" }, + { "dtl", function() require("dap-go").debug_last_test() end, ft = "go", desc = "调试上次测试" }, + }, + }, + + -- neotest Go 适配器 + { + "nvim-neotest/neotest", + optional = true, + dependencies = { "nvim-neotest/neotest-go" }, + opts = { + adapters = { + ["neotest-go"] = { + args = { "-count=1", "-timeout=30s", "-v" }, + }, + }, + }, + }, + + -- Mason Go 工具 + { + "williamboman/mason.nvim", + optional = true, + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { + "gopls", "gofumpt", "goimports", "golangci-lint", + "gomodifytags", "gotests", "impl", "delve", + }) + end, + }, +} diff --git a/nvim/lua/plugins/lang/python.lua b/nvim/lua/plugins/lang/python.lua new file mode 100644 index 0000000..03bc949 --- /dev/null +++ b/nvim/lua/plugins/lang/python.lua @@ -0,0 +1,95 @@ +-- lang/python.lua - Python 开发专用配置 + +return { + -- 虚拟环境选择器 + { + "linux-cultist/venv-selector.nvim", + branch = "regexp", + cmd = "VenvSelect", + ft = "python", + dependencies = { "neovim/nvim-lspconfig", "nvim-telescope/telescope.nvim" }, + opts = { + settings = { + options = { + notify_user_on_venv_activation = true, + }, + }, + }, + keys = { + { "pv", "VenvSelect", ft = "python", desc = "选择虚拟环境" }, + }, + }, + + -- Python DAP 支持 + { + "mfussenegger/nvim-dap-python", + ft = "python", + dependencies = { "mfussenegger/nvim-dap" }, + config = function() + local ok, mason_registry = pcall(require, "mason-registry") + local python_path = "python3" + if ok and mason_registry.is_installed("debugpy") then + python_path = mason_registry.get_package("debugpy"):get_install_path() .. "/venv/bin/python" + end + require("dap-python").setup(python_path) + require("dap-python").test_runner = "pytest" + + -- 带参数启动 + table.insert(require("dap").configurations.python, { + type = "python", request = "launch", + name = "带参数启动", + program = "${file}", + args = function() + return vim.split(vim.fn.input("命令行参数: "), " ") + end, + console = "integratedTerminal", + }) + end, + keys = { + { "dpm", function() require("dap-python").test_method() end, ft = "python", desc = "调试当前方法" }, + { "dpc", function() require("dap-python").test_class() end, ft = "python", desc = "调试当前类" }, + }, + }, + + -- neotest Python 适配器 + { + "nvim-neotest/neotest", + optional = true, + dependencies = { "nvim-neotest/neotest-python" }, + opts = function(_, opts) + opts.adapters = opts.adapters or {} + table.insert(opts.adapters, require("neotest-python")({ + runner = "pytest", + args = { "--color=yes", "-v" }, + python = function() + if vim.env.VIRTUAL_ENV then + return vim.env.VIRTUAL_ENV .. "/bin/python" + end + return "python3" + end, + })) + return opts + end, + keys = { + { "pt", function() require("neotest").run.run() end, ft = "python", desc = "运行最近测试" }, + { "pT", function() require("neotest").run.run(vim.fn.expand("%")) end, ft = "python", desc = "运行文件测试" }, + { "pd", function() require("neotest").run.run({ strategy = "dap" }) end, ft = "python", desc = "调试测试" }, + { "ps", function() require("neotest").run.stop() end, ft = "python", desc = "停止测试" }, + { "po", function() require("neotest").output.open() end, ft = "python", desc = "测试输出" }, + { "pO", function() require("neotest").output_panel.toggle() end, ft = "python", desc = "输出面板" }, + { "pS", function() require("neotest").summary.toggle() end, ft = "python", desc = "摘要窗口" }, + }, + }, + + -- Mason Python 工具 + { + "williamboman/mason.nvim", + optional = true, + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { + "pyright", "ruff", "isort", "debugpy", + }) + end, + }, +} diff --git a/nvim/lua/plugins/lang/rust.lua b/nvim/lua/plugins/lang/rust.lua new file mode 100644 index 0000000..9046aae --- /dev/null +++ b/nvim/lua/plugins/lang/rust.lua @@ -0,0 +1,111 @@ +-- lang/rust.lua - Rust 开发专用配置(rustaceanvim + codelldb) + +return { + -- rustaceanvim - Rust 全功能插件(接管 rust-analyzer LSP) + { + "mrcjkb/rustaceanvim", + version = "^5", + ft = "rust", + opts = { + server = { + on_attach = function(_, bufnr) + local map = function(mode, lhs, rhs, desc) + vim.keymap.set(mode, lhs, rhs, { buffer = bufnr, silent = true, desc = desc }) + end + -- Rust 专用操作 + map("n", "rr", function() vim.cmd.RustLsp("runnables") end, "Rust 运行目标") + map("n", "rt", function() vim.cmd.RustLsp("testables") end, "Rust 测试目标") + map("n", "rd", function() vim.cmd.RustLsp("debuggables") end, "Rust 调试目标") + map("n", "re", function() vim.cmd.RustLsp("explainError") end, "解释错误") + map("n", "rc", function() vim.cmd.RustLsp("openCargo") end, "打开 Cargo.toml") + map("n", "rp", function() vim.cmd.RustLsp("parentModule") end, "父模块") + map("n", "rm", function() vim.cmd.RustLsp("expandMacro") end, "展开宏") + map("n", "rx", function() vim.cmd.RustLsp("externalDocs") end, "外部文档") + map("n", "K", function() vim.cmd.RustLsp({ "hover", "actions" }) end, "悬浮操作") + map("n", "ca", function() vim.cmd.RustLsp("codeAction") end, "代码操作") + end, + default_settings = { + ["rust-analyzer"] = { + cargo = { + allFeatures = true, + loadOutDirsFromCheck = true, + runBuildScripts = true, + }, + checkOnSave = { + allFeatures = true, + command = "clippy", + extraArgs = { "--no-deps" }, + }, + procMacro = { + enable = true, + ignored = { + ["async-trait"] = { "async_trait" }, + ["napi-derive"] = { "napi" }, + ["async-recursion"] = { "async_recursion" }, + }, + }, + inlayHints = { + bindingModeHints = { enable = false }, + chainingHints = { enable = true }, + closingBraceHints = { enable = true, minLines = 25 }, + closureReturnTypeHints = { enable = "never" }, + lifetimeElisionHints = { enable = "never" }, + parameterHints = { enable = false }, + typeHints = { enable = true, hideClosureInitialization = false, hideNamedConstructor = false }, + }, + }, + }, + }, + -- DAP 配置(codelldb) + dap = {}, + }, + config = function(_, opts) + -- 延迟设置 DAP adapter(需在 rustaceanvim 加载后才能 require) + local ok_mason, mason_registry = pcall(require, "mason-registry") + if ok_mason and mason_registry.is_installed("codelldb") then + local codelldb_path = mason_registry.get_package("codelldb"):get_install_path() + local codelldb = codelldb_path .. "/codelldb" + local liblldb = codelldb_path .. "/extension/lldb/lib/liblldb.dylib" + if vim.fn.has("linux") == 1 then + liblldb = codelldb_path .. "/extension/lldb/lib/liblldb.so" + end + opts.dap = opts.dap or {} + opts.dap.adapter = require("rustaceanvim.config").get_codelldb_adapter(codelldb, liblldb) + end + vim.g.rustaceanvim = vim.tbl_deep_extend("keep", vim.g.rustaceanvim or {}, opts) + end, + }, + + -- crates.nvim - Cargo.toml 依赖管理 + { + "saecki/crates.nvim", + event = { "BufRead Cargo.toml" }, + opts = { + completion = { + cmp = { enabled = false }, + crates = { enabled = true, max_results = 8, min_chars = 3 }, + }, + lsp = { + enabled = true, + on_attach = function() end, + actions = true, + completion = true, + hover = true, + }, + }, + keys = { + { "rcu", function() require("crates").upgrade_all_crates() end, ft = "toml", desc = "升级所有依赖" }, + { "rco", function() require("crates").show_popup() end, ft = "toml", desc = "Crate 信息" }, + }, + }, + + -- Mason Rust 工具 + { + "williamboman/mason.nvim", + optional = true, + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { "codelldb" }) + end, + }, +} diff --git a/nvim/lua/plugins/lang/typescript.lua b/nvim/lua/plugins/lang/typescript.lua new file mode 100644 index 0000000..d77eca5 --- /dev/null +++ b/nvim/lua/plugins/lang/typescript.lua @@ -0,0 +1,99 @@ +-- lang/typescript.lua - TypeScript/JavaScript 开发专用配置 + +return { + -- typescript-tools.nvim - 高性能 TypeScript LSP(直接对接 tsserver 协议) + { + "pmizio/typescript-tools.nvim", + dependencies = { "nvim-lua/plenary.nvim", "neovim/nvim-lspconfig" }, + ft = { "javascript", "javascriptreact", "typescript", "typescriptreact", "vue" }, + opts = { + on_attach = function(_, bufnr) + local map = function(mode, lhs, rhs, desc) + vim.keymap.set(mode, lhs, rhs, { buffer = bufnr, silent = true, desc = desc }) + end + map("n", "to", "TSToolsOrganizeImports", "整理 Import") + map("n", "ta", "TSToolsAddMissingImports", "添加缺失 Import") + map("n", "tu", "TSToolsRemoveUnusedImports", "删除未使用 Import") + map("n", "tf", "TSToolsFixAll", "修复所有") + map("n", "tr", "TSToolsRenameFile", "重命名文件") + map("n", "tR", "TSToolsFileReferences", "文件引用") + end, + settings = { + separate_diagnostic_server = true, + publish_diagnostic_on = "insert_leave", + expose_as_code_action = "all", + tsserver_path = nil, + tsserver_plugins = {}, + tsserver_max_memory = "auto", + tsserver_format_options = { + allowIncompleteCompletions = false, + allowRenameOfImportPath = false, + }, + tsserver_file_preferences = { + includeInlayParameterNameHints = "all", + includeInlayParameterNameHintsWhenArgumentMatchesName = false, + includeInlayFunctionParameterTypeHints = true, + includeInlayVariableTypeHints = true, + includeInlayVariableTypeHintsWhenTypeMatchesName = false, + includeInlayPropertyDeclarationTypeHints = true, + includeInlayFunctionLikeReturnTypeHints = true, + includeInlayEnumMemberValueHints = true, + quotePreference = "auto", + }, + -- 代码样式 + tsserver_locale = "zh-cn", + complete_function_calls = true, + include_completions_with_insert_text = true, + code_lens = "off", + disable_member_code_lens = true, + jsx_close_tag = { enable = true, filetypes = { "javascriptreact", "typescriptreact" } }, + }, + }, + }, + + -- ESLint LSP(通过 nvim-lspconfig,mason 安装) + { + "neovim/nvim-lspconfig", + optional = true, + opts = { + servers = { + eslint = { + settings = { + workingDirectories = { mode = "auto" }, + format = false, -- 格式化由 prettier 处理 + }, + on_attach = function(_, bufnr) + vim.api.nvim_create_autocmd("BufWritePre", { + buffer = bufnr, + command = "EslintFixAll", + }) + end, + }, + }, + }, + }, + + -- Mason TypeScript 工具 + { + "williamboman/mason.nvim", + optional = true, + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { + "typescript-language-server", "eslint-lsp", "prettierd", + }) + end, + }, + + -- Treesitter TypeScript/JSX + { + "nvim-treesitter/nvim-treesitter", + optional = true, + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + vim.list_extend(opts.ensure_installed, { + "javascript", "typescript", "tsx", "jsdoc", + }) + end, + }, +} diff --git a/nvim/lua/plugins/lint.lua b/nvim/lua/plugins/lint.lua index fee0d86..ea11096 100644 --- a/nvim/lua/plugins/lint.lua +++ b/nvim/lua/plugins/lint.lua @@ -1,78 +1,39 @@ --- lint.lua - 代码检查配置 --- 使用 nvim-lint 替代 null-ls 的诊断功能 --- 与 conform.nvim 配合:conform 负责格式化,lint 负责诊断 +-- lint.lua - 代码静态检查(nvim-lint) return { - { - "mfussenegger/nvim-lint", - event = { "BufReadPre", "BufNewFile" }, - config = function() - local lint = require("lint") + { + "mfussenegger/nvim-lint", + event = { "BufReadPre", "BufNewFile" }, + config = function() + local lint = require("lint") - -- 按文件类型配置 linter - lint.linters_by_ft = { - -- Python: 使用 ruff 替代 flake8/pylint - python = { "ruff" }, + lint.linters_by_ft = { + python = { "ruff" }, + lua = { "selene" }, + go = { "golangcilint" }, + javascript = { "eslint_d" }, + typescript = { "eslint_d" }, + javascriptreact = { "eslint_d" }, + typescriptreact = { "eslint_d" }, + markdown = { "markdownlint" }, + yaml = { "yamllint" }, + dockerfile = { "hadolint" }, + sh = { "shellcheck" }, + bash = { "shellcheck" }, + } - -- Lua - lua = { "luacheck" }, + local lint_augroup = vim.api.nvim_create_augroup("nvim_lint", { clear = true }) - -- Go - go = { "golangcilint" }, + vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost", "InsertLeave" }, { + group = lint_augroup, + callback = function() + lint.try_lint() + end, + }) - -- JavaScript/TypeScript - javascript = { "eslint" }, - typescript = { "eslint" }, - javascriptreact = { "eslint" }, - typescriptreact = { "eslint" }, - - -- 通用 - markdown = { "markdownlint" }, - yaml = { "yamllint" }, - dockerfile = { "hadolint" }, - sh = { "shellcheck" }, - } - - -- 设置自动触发 - local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true }) - - -- 保存后检查 - vim.api.nvim_create_autocmd({ "BufWritePost" }, { - group = lint_augroup, - callback = function() - lint.try_lint() - end, - }) - - -- 进入缓冲区时检查 - vim.api.nvim_create_autocmd({ "BufEnter" }, { - group = lint_augroup, - callback = function() - lint.try_lint() - end, - }) - - -- 插入模式离开后检查(可选,可能较频繁) - vim.api.nvim_create_autocmd({ "InsertLeave" }, { - group = lint_augroup, - callback = function() - lint.try_lint() - end, - }) - - -- 创建用户命令 - vim.api.nvim_create_user_command("Lint", function() - lint.try_lint() - end, { desc = "手动触发代码检查" }) - - vim.api.nvim_create_user_command("LintInfo", function() - local running_linters = lint.get_running() - if #running_linters == 0 then - vim.notify("没有正在运行的 linter", vim.log.levels.INFO) - else - vim.notify("运行中的 linter: " .. table.concat(running_linters, ", "), vim.log.levels.INFO) - end - end, { desc = "显示运行中的 linter" }) - end, - }, + vim.api.nvim_create_user_command("Lint", function() + lint.try_lint() + end, { desc = "手动触发代码检查" }) + end, + }, } diff --git a/nvim/lua/plugins/lsp.lua b/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..5ff7e7e --- /dev/null +++ b/nvim/lua/plugins/lsp.lua @@ -0,0 +1,256 @@ +-- lsp.lua - LSP 核心配置(lazydev + mason + nvim-lspconfig + fidget) + +return { + -- Lua 开发辅助(替代已废弃的 neodev.nvim) + { + "folke/lazydev.nvim", + ft = "lua", + opts = { + library = { + { path = "luvit-meta/library", words = { "vim%.uv" } }, + { path = "nvim-dap-ui" }, + }, + }, + }, + { "Bilal2453/luvit-meta", lazy = true }, + + -- LSP 进度提示 + { + "j-hui/fidget.nvim", + opts = { + notification = { window = { winblend = 0 } }, + }, + }, + + -- Mason 工具管理器 + { + "williamboman/mason.nvim", + build = ":MasonUpdate", + opts = { + ui = { border = "rounded", icons = { package_installed = "✓", package_pending = "➜", package_uninstalled = "✗" } }, + }, + }, + + -- mason-lspconfig 桥接 + { + "williamboman/mason-lspconfig.nvim", + dependencies = { "williamboman/mason.nvim" }, + opts = { + ensure_installed = { + "lua_ls", + "gopls", + "pyright", + "ruff", + "ts_ls", + "eslint", + "jsonls", + "yamlls", + "bashls", + }, + automatic_installation = true, + }, + }, + + -- mason 工具安装器(格式化/lint 工具) + { + "WhoIsSethDaniel/mason-tool-installer.nvim", + dependencies = { "williamboman/mason.nvim" }, + opts = { + ensure_installed = { + -- Go + "gofumpt", "goimports", "golangci-lint", "delve", + -- Rust(通过 rustup 管理,mason 作为备用) + "codelldb", + -- Python + "isort", "debugpy", + -- JS/TS + "prettierd", "eslint_d", + -- 通用 + "stylua", "shfmt", "shellcheck", "selene", + }, + }, + }, + + -- nvim-lspconfig 主配置 + { + "neovim/nvim-lspconfig", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { + "williamboman/mason.nvim", + "williamboman/mason-lspconfig.nvim", + "saghen/blink.cmp", + }, + opts = { + diagnostics = { + underline = true, + update_in_insert = false, + virtual_text = { spacing = 4, source = "if_many", prefix = "●" }, + severity_sort = true, + signs = { + text = { + [vim.diagnostic.severity.ERROR] = " ", + [vim.diagnostic.severity.WARN] = " ", + [vim.diagnostic.severity.HINT] = " ", + [vim.diagnostic.severity.INFO] = " ", + }, + }, + }, + inlay_hints = { enabled = true }, + -- 各语言服务器配置(Rust 由 rustaceanvim 接管,不在此处配置) + servers = { + lua_ls = { + settings = { + Lua = { + completion = { callSnippet = "Replace" }, + workspace = { checkThirdParty = false }, + telemetry = { enable = false }, + diagnostics = { globals = { "vim" } }, + }, + }, + }, + pyright = { + settings = { + python = { + analysis = { + typeCheckingMode = "basic", + autoSearchPaths = true, + useLibraryCodeForTypes = true, + diagnosticMode = "workspace", + }, + }, + }, + }, + ruff = { + -- ruff 处理 import 排序和快速修复,格式化由 conform 接管 + on_attach = function(client) + client.server_capabilities.documentFormattingProvider = false + end, + }, + gopls = { + settings = { + gopls = { + gofumpt = true, + codelenses = { + gc_details = true, generate = true, run_govulncheck = true, + test = true, tidy = true, upgrade_dependency = true, + }, + hints = { + assignVariableTypes = true, compositeLiteralFields = true, + compositeLiteralTypes = true, constantValues = true, + functionTypeParameters = true, parameterNames = true, + rangeVariableTypes = true, + }, + analyses = { + fieldalignment = true, nilness = true, + unusedparams = true, unusedwrite = true, useany = true, + }, + usePlaceholders = true, + completeUnimported = true, + staticcheck = true, + directoryFilters = { "-.git", "-.vscode", "-.idea", "-node_modules" }, + semanticTokens = true, + }, + }, + }, + -- ts_ls 由 typescript-tools.nvim 接管,此处不配置 + eslint = {}, + jsonls = { + -- 延迟加载 schemastore(插件安装后才可用) + on_new_config = function(new_config) + new_config.settings = new_config.settings or {} + new_config.settings.json = new_config.settings.json or {} + new_config.settings.json.schemas = new_config.settings.json.schemas or {} + local ok, schemastore = pcall(require, "schemastore") + if ok then + vim.list_extend(new_config.settings.json.schemas, schemastore.json.schemas()) + end + end, + settings = { + json = { validate = { enable = true } }, + }, + }, + yamlls = {}, + bashls = {}, + }, + }, + config = function(_, opts) + -- 诊断符号 + vim.diagnostic.config(vim.deepcopy(opts.diagnostics)) + + -- LspAttach 公共键绑定 + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(args) + local buf = args.buf + local client = vim.lsp.get_client_by_id(args.data.client_id) + + local map = function(mode, lhs, rhs, desc) + vim.keymap.set(mode, lhs, rhs, { buffer = buf, silent = true, desc = desc }) + end + + -- 导航 + map("n", "gd", function() vim.lsp.buf.definition() end, "转到定义") + map("n", "gD", function() vim.lsp.buf.declaration() end, "转到声明") + map("n", "gr", function() vim.lsp.buf.references() end, "查找引用") + map("n", "gI", function() vim.lsp.buf.implementation() end, "转到实现") + map("n", "gt", function() vim.lsp.buf.type_definition() end, "转到类型定义") + map("n", "K", function() vim.lsp.buf.hover() end, "悬浮文档") + map("n", "gK", function() vim.lsp.buf.signature_help() end, "签名帮助") + map("i", "", function() vim.lsp.buf.signature_help() end, "签名帮助") + + -- 操作 + map({ "n", "v" }, "ca", function() vim.lsp.buf.code_action() end, "代码操作") + map("n", "cr", function() + -- inc-rename 若已加载则使用增量重命名,否则回退到标准 LSP rename + local ok, inc = pcall(require, "inc_rename") + if ok then + return ":" .. inc.rename.cmd .. " " .. vim.fn.expand("") + end + vim.lsp.buf.rename() + end, "重命名") + map("n", "cl", "LspInfo", "LSP 信息") + + -- 诊断 + map("n", "]d", function() vim.diagnostic.goto_next() end, "下一个诊断") + map("n", "[d", function() vim.diagnostic.goto_prev() end, "上一个诊断") + map("n", "cd", function() vim.diagnostic.open_float() end, "行诊断") + + -- Inlay hints 切换 + if client and client.supports_method("textDocument/inlayHint") then + map("n", "uh", function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = buf }), { bufnr = buf }) + end, "切换 Inlay Hints") + end + end, + }) + + -- 构建 capabilities(blink.cmp 提供) + local capabilities = require("blink.cmp").get_lsp_capabilities() + + -- 通过 mason-lspconfig 自动启动服务器 + require("mason-lspconfig").setup_handlers({ + function(server) + local server_opts = vim.tbl_deep_extend("force", { + capabilities = vim.deepcopy(capabilities), + }, opts.servers[server] or {}) + + -- Rust 由 rustaceanvim 接管,跳过 + if server == "rust_analyzer" then return end + -- TypeScript 由 typescript-tools.nvim 接管,跳过 + if server == "ts_ls" or server == "tsserver" then return end + + require("lspconfig")[server].setup(server_opts) + end, + }) + end, + }, + + -- JSON Schema Store(可选,供 jsonls 使用) + { "b0o/SchemaStore.nvim", lazy = true }, + + -- 增量重命名(在命令行实时预览) + { + "smjonas/inc-rename.nvim", + cmd = "IncRename", + opts = {}, + }, +} diff --git a/nvim/lua/plugins/lspconfig.lua b/nvim/lua/plugins/lspconfig.lua deleted file mode 100644 index bbd8f57..0000000 --- a/nvim/lua/plugins/lspconfig.lua +++ /dev/null @@ -1,19 +0,0 @@ --- lspconfig.lua - LSP 配置 -return { - { - "neovim/nvim-lspconfig", - event = { "BufReadPre", "BufNewFile" }, - dependencies = { - "hrsh7th/cmp-nvim-lsp", - "williamboman/mason-lspconfig.nvim", - }, - config = function() - local lspconfig = require("lspconfig") - local capabilities = require("cmp_nvim_lsp").default_capabilities() - -- Go - lspconfig.gopls.setup({ capabilities = capabilities }) - -- Python - lspconfig.pyright.setup({ capabilities = capabilities }) - end, - }, -} diff --git a/nvim/lua/plugins/lua.lua b/nvim/lua/plugins/lua.lua deleted file mode 100644 index 62caefd..0000000 --- a/nvim/lua/plugins/lua.lua +++ /dev/null @@ -1,5 +0,0 @@ --- lua.lua - Lua 开发配置 - -return { - -- Lua 语言支持(已由 neodev 在 coding.lua 中配置) -} diff --git a/nvim/lua/plugins/mason.lua b/nvim/lua/plugins/mason.lua deleted file mode 100644 index 4ba74ce..0000000 --- a/nvim/lua/plugins/mason.lua +++ /dev/null @@ -1,23 +0,0 @@ --- mason.lua - LSP/DAP/格式化工具自动安装 -return { - { - "williamboman/mason.nvim", - build = ":MasonUpdate", - config = true, - }, - { - "williamboman/mason-lspconfig.nvim", - dependencies = { "williamboman/mason.nvim" }, - opts = { - ensure_installed = { "gopls", "pyright" }, - }, - }, - { - "jay-babu/mason-null-ls.nvim", - dependencies = { "williamboman/mason.nvim", "nvimtools/none-ls.nvim" }, - opts = { - ensure_installed = { "gofumpt", "golines", "black", "isort", "flake8" }, - automatic_installation = true, - }, - }, -} diff --git a/nvim/lua/plugins/noice.lua b/nvim/lua/plugins/noice.lua deleted file mode 100644 index 79c3a53..0000000 --- a/nvim/lua/plugins/noice.lua +++ /dev/null @@ -1 +0,0 @@ -return {"folke/noice.nvim", opts={}} \ No newline at end of file diff --git a/nvim/lua/plugins/null-ls.lua b/nvim/lua/plugins/null-ls.lua deleted file mode 100644 index 8d8d39d..0000000 --- a/nvim/lua/plugins/null-ls.lua +++ /dev/null @@ -1,20 +0,0 @@ --- null-ls.lua - 格式化与诊断 -return { - { - "nvimtools/none-ls.nvim", - event = { "BufReadPre", "BufNewFile" }, - opts = function() - local null_ls = require("null-ls") - return { - sources = { - -- Go - null_ls.builtins.formatting.gofumpt, - null_ls.builtins.formatting.golines, - -- Python - null_ls.builtins.formatting.black, - null_ls.builtins.formatting.isort, - }, - } - end, - }, -} diff --git a/nvim/lua/plugins/python.lua b/nvim/lua/plugins/python.lua deleted file mode 100644 index 4104b67..0000000 --- a/nvim/lua/plugins/python.lua +++ /dev/null @@ -1,218 +0,0 @@ --- python.lua - Python 开发专用配置 - -return { - -- Python 专用插件 - { - "linux-cultist/venv-selector.nvim", - cmd = "VenvSelect", - keys = { - { "pv", "VenvSelect", desc = "选择 Python 虚拟环境" }, - { "pc", "VenvSelectCached", desc = "选择缓存的虚拟环境" }, - }, - opts = { - name = { - "venv", - ".venv", - "env", - ".env", - "virtualenv", - }, - auto_refresh = true, - search_from = "root", -- 从项目根目录搜索 - }, - config = function(_, opts) - require("venv-selector").setup(opts) - - -- 自动激活虚拟环境 - vim.api.nvim_create_autocmd("BufEnter", { - pattern = { "*.py" }, - callback = function() - -- 使用缓存的 venv - require("venv-selector").retrieve_from_cache() - end, - }) - end, - }, - - -- Python 单元测试插件 - { - "nvim-neotest/neotest", - optional = true, - dependencies = { - "nvim-neotest/neotest-python", - }, - opts = function(_, opts) - -- 确保 adapters 是列表 - opts.adapters = opts.adapters or {} - -- 添加 neotest-python 适配器 - table.insert(opts.adapters, require("neotest-python")({ - -- 使用项目根目录中的 pytest.ini - runner = "pytest", - -- 额外的 pytest 参数 - args = { - "--color=yes", - "-v", - }, - -- Python 测试发现模式 - python = function() - -- 如果激活了虚拟环境,使用它 - if vim.env.VIRTUAL_ENV then - return vim.env.VIRTUAL_ENV .. "/bin/python" - end - -- 否则使用系统的 Python - return "python" - end, - })) - return opts - end, - keys = { - { "pt", "lua require('neotest').run.run()", desc = "运行最近的测试" }, - { "pT", "lua require('neotest').run.run(vim.fn.expand('%'))", desc = "运行文件中的测试" }, - { "pd", "lua require('neotest').run.run({strategy = 'dap'})", desc = "调试最近的测试" }, - { "ps", "lua require('neotest').run.stop()", desc = "停止测试" }, - { "pa", "lua require('neotest').run.attach()", desc = "附加到测试" }, - { "po", "lua require('neotest').output.open()", desc = "查看测试输出" }, - { "pO", "lua require('neotest').output_panel.toggle()", desc = "切换输出面板" }, - { "pS", "lua require('neotest').summary.toggle()", desc = "切换摘要窗口" }, - }, - }, - - -- Python 导入排序和格式化 - { - "stevearc/conform.nvim", - optional = true, - opts = { - formatters_by_ft = { - python = { "isort", "black" }, - }, - formatters = { - black = { - args = { "--line-length", "88", "--fast", "-" }, - }, - isort = { - args = { "--stdout", "--profile", "black", "--line-length", "88", "-" }, - }, - }, - }, - }, - - -- Python 调试 - { - "mfussenegger/nvim-dap", - optional = true, - dependencies = { - "mfussenegger/nvim-dap-python", - }, - config = function() - local ok, mason_registry = pcall(require, "mason-registry") - local debugpy_path = nil - if ok then - local ok2, debugpy_pkg = pcall(mason_registry.get_package, "debugpy") - if ok2 and debugpy_pkg then - local ok3, path = pcall(debugpy_pkg.get_install_path, debugpy_pkg) - if ok3 then - debugpy_path = path .. "/venv/bin/python" - end - end - end - -- 如果无法通过 mason 获取路径,使用默认路径 - if not debugpy_path then - debugpy_path = vim.fn.exepath("python3") or "python3" - end - require("dap-python").setup(debugpy_path) - - -- 设置 pytest 调试 - require("dap-python").test_runner = "pytest" - - -- 添加自定义配置 - table.insert(require("dap").configurations.python, { - type = "python", - request = "launch", - name = "启动带参数的文件", - program = "${file}", - args = function() - local args_string = vim.fn.input("命令行参数: ") - return vim.split(args_string, " ") - end, - console = "integratedTerminal", - }) - - -- 添加 FastAPI 配置 - table.insert(require("dap").configurations.python, { - type = "python", - request = "launch", - name = "FastAPI", - module = "uvicorn", - args = function() - local args = vim.fn.input("uvicorn 参数 (例如 main:app --reload): ") - return vim.split(args, " ") - end, - console = "integratedTerminal", - }) - end, - keys = { - -- Python 特定调试键 - { "dpr", function() require("dap-python").test_method() end, desc = "调试当前方法" }, - { "dpc", function() require("dap-python").test_class() end, desc = "调试当前类" }, - { "dpf", function() require("dap-python").test_method() end, desc = "调试当前函数" }, - }, - }, - - -- Python 代码格式化和排序 - { - "williamboman/mason.nvim", - optional = true, - opts = function(_, opts) - -- 将额外的 Python 工具添加到确保安装列表中 - if type(opts.ensure_installed) == "table" then - vim.list_extend(opts.ensure_installed, { - "black", - "isort", - "mypy", - "ruff", - "ruff-lsp", - "pyright", - "debugpy", - }) - end - end, - }, - - -- 代码折叠 - { - "kevinhwang91/nvim-ufo", - optional = true, - opts = { - close_fold_kinds_for_ft = { - python = { "imports", "comment" }, - }, - }, - }, - - -- REPL 集成 - { - "michaelb/sniprun", - build = "sh ./install.sh", - cmd = { "SnipRun", "SnipInfo", "SnipReset", "SnipClose" }, - keys = { - { "pe", "SnipRun", desc = "执行选中代码", mode = { "n", "v" } }, - { "pE", "SnipInfo", desc = "Sniprun 信息" }, - }, - opts = { - display = { "NvimNotify" }, - interpreter_options = { - Python3_fifo = { - venv = function() - return vim.env.VIRTUAL_ENV - end, - cwd = function() - return vim.fn.getcwd() - end, - }, - }, - }, - config = function(_, opts) - require("sniprun").setup(opts) - end, - }, -} \ No newline at end of file diff --git a/nvim/lua/plugins/snacks.lua b/nvim/lua/plugins/snacks.lua deleted file mode 100644 index 4ebd0af..0000000 --- a/nvim/lua/plugins/snacks.lua +++ /dev/null @@ -1,62 +0,0 @@ --- snacks.lua - folke's modern utility library --- Provides: notifications, bigfile handling, quickfile, statuscolumn, word highlighting - -return { - { - "folke/snacks.nvim", - priority = 1000, - lazy = false, - opts = { - -- Bigfile optimization - bigfile = { - enabled = true, - notify = true, - line_length = 1000, - }, - - -- Notifications (replaces nvim-notify) - notifier = { - enabled = true, - timeout = 3000, - history = true, - render = "compact", - level = vim.log.levels.INFO, - }, - - -- Quick file navigation - quickfile = { - enabled = true, - exclude = { "gitcommit", "gitrebase" }, - }, - - -- Enhanced statuscolumn - statuscolumn = { - enabled = false, - }, - - -- Word highlighting and jumping - words = { - enabled = true, - debounce = 100, - notify_end = false, - jumplist = true, - mappings = { - ["]w"] = "next", - ["[w"] = "prev", - }, - }, - }, - keys = { - { "un", function() Snacks.notifier.hide() end, desc = "Dismiss All Notifications" }, - { "q", function() Snacks.quickfile() end, desc = "Quick File" }, - { "]w", function() Snacks.words.jump() end, desc = "Next Word Reference" }, - { "[w", function() Snacks.words.jump(-1) end, desc = "Prev Word Reference" }, - }, - init = function() - -- Override vim.notify - vim.notify = function(msg, level, opts) - Snacks.notifier.notify(msg, level, opts) - end - end, - }, -} diff --git a/nvim/lua/plugins/todo-comment.lua b/nvim/lua/plugins/todo-comment.lua deleted file mode 100644 index b65b82e..0000000 --- a/nvim/lua/plugins/todo-comment.lua +++ /dev/null @@ -1 +0,0 @@ -return { "folke/todo-comments.nvim", opts = {} } \ No newline at end of file diff --git a/nvim/lua/plugins/treesitter.lua b/nvim/lua/plugins/treesitter.lua index d11ea6e..49dcf02 100644 --- a/nvim/lua/plugins/treesitter.lua +++ b/nvim/lua/plugins/treesitter.lua @@ -1,13 +1,81 @@ -- treesitter.lua - 语法高亮与代码结构 + return { { "nvim-treesitter/nvim-treesitter", build = ":TSUpdate", - event = { "BufReadPost", "BufNewFile" }, + event = { "BufReadPost", "BufNewFile", "BufWritePre", "VeryLazy" }, + dependencies = { + "nvim-treesitter/nvim-treesitter-textobjects", + }, opts = { - ensure_installed = { "go", "python", "lua", "json", "yaml", "markdown" }, + ensure_installed = { + -- "comment" 已在新版 nvim-treesitter 中弃用,避免 query 校验错误 + "bash", "c", "cmake", "css", "diff", "dockerfile", + "git_config", "git_rebase", "gitcommit", "gitignore", + "go", "gomod", "gosum", "gowork", + "html", "javascript", "jsdoc", "json", "jsonc", + "lua", "luadoc", "luap", "make", "markdown", "markdown_inline", + "python", "regex", "rst", "rust", "sql", "toml", + "tsx", "typescript", "vim", "vimdoc", "xml", "yaml", + }, highlight = { enable = true }, indent = { enable = true }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = "", + node_incremental = "", + scope_incremental = false, + node_decremental = "", + }, + }, + textobjects = { + select = { + enable = true, + lookahead = true, + keymaps = { + ["af"] = "@function.outer", + ["if"] = "@function.inner", + ["ac"] = "@class.outer", + ["ic"] = "@class.inner", + ["aa"] = "@parameter.outer", + ["ia"] = "@parameter.inner", + ["ab"] = "@block.outer", + ["ib"] = "@block.inner", + }, + }, + move = { + enable = true, + set_jumps = true, + goto_next_start = { + ["]f"] = "@function.outer", + ["]c"] = "@class.outer", + }, + goto_next_end = { + ["]F"] = "@function.outer", + ["]C"] = "@class.outer", + }, + goto_previous_start = { + ["[f"] = "@function.outer", + ["[c"] = "@class.outer", + }, + goto_previous_end = { + ["[F"] = "@function.outer", + ["[C"] = "@class.outer", + }, + }, + }, }, + config = function(_, opts) + -- nvim-treesitter v1+ 重构后移除了 configs 子模块,需要兼容两种 API + local ok, configs = pcall(require, "nvim-treesitter.configs") + if ok then + configs.setup(opts) + else + -- 新版 API:直接调用顶层模块 + require("nvim-treesitter").setup(opts) + end + end, }, } diff --git a/nvim/lua/plugins/trouble.lua b/nvim/lua/plugins/trouble.lua deleted file mode 100644 index c22edba..0000000 --- a/nvim/lua/plugins/trouble.lua +++ /dev/null @@ -1 +0,0 @@ -return {"folke/trouble.nvim", opts={}} \ No newline at end of file diff --git a/nvim/lua/plugins/ts-comments.lua b/nvim/lua/plugins/ts-comments.lua deleted file mode 100644 index a251d44..0000000 --- a/nvim/lua/plugins/ts-comments.lua +++ /dev/null @@ -1 +0,0 @@ -return {"folke/ts-comments.nvim", opts={}} \ No newline at end of file diff --git a/nvim/lua/plugins/ui.lua b/nvim/lua/plugins/ui.lua index 1b1cf6d..e060c08 100644 --- a/nvim/lua/plugins/ui.lua +++ b/nvim/lua/plugins/ui.lua @@ -1,6 +1,93 @@ -- ui.lua - UI 增强插件配置 +-- 包含:lualine, bufferline, neo-tree, noice, snacks(dashboard+notifier), indent-blankline return { + -- snacks.nvim - 现代通知 + Dashboard + 其他实用功能 + { + "folke/snacks.nvim", + priority = 1000, + lazy = false, + opts = { + bigfile = { enabled = true }, + dashboard = { + enabled = true, + sections = { + { section = "header" }, + { section = "keys", gap = 1, padding = 1 }, + { section = "startup" }, + }, + preset = { + header = [[ + ███╗ ██╗███████╗ ██████╗ ██╗ ██╗██╗███╗ ███╗ + ████╗ ██║██╔════╝██╔═══██╗██║ ██║██║████╗ ████║ + ██╔██╗ ██║█████╗ ██║ ██║██║ ██║██║██╔████╔██║ + ██║╚██╗██║██╔══╝ ██║ ██║╚██╗ ██╔╝██║██║╚██╔╝██║ + ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║ + ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═══╝ ╚═╝╚═╝ ╚═╝]], + keys = { + { icon = " ", key = "f", desc = "查找文件", action = ":lua Snacks.picker.files()" }, + { icon = " ", key = "g", desc = "全局搜索", action = ":lua Snacks.picker.grep()" }, + { icon = " ", key = "r", desc = "最近文件", action = ":lua Snacks.picker.recent()" }, + { icon = " ", key = "c", desc = "编辑配置", action = ":e $MYVIMRC" }, + { icon = "󰒲 ", key = "l", desc = "Lazy", action = ":Lazy" }, + { icon = " ", key = "q", desc = "退出", action = ":qa" }, + }, + }, + }, + notifier = { + enabled = true, + timeout = 3000, + render = "compact", + style = "compact", + level = vim.log.levels.INFO, + }, + quickfile = { enabled = true }, + statuscolumn = { enabled = false }, + words = { + enabled = true, + debounce = 100, + notify_end = false, + jumplist = true, + }, + indent = { + enabled = true, + animate = { enabled = false }, + }, + picker = { enabled = true }, + input = { enabled = true }, + }, + keys = { + { "un", function() Snacks.notifier.hide() end, desc = "清除通知" }, + { "nh", function() Snacks.notifier.show_history() end, desc = "通知历史" }, + { "nd", function() Snacks.notifier.hide() end, desc = "关闭所有通知" }, + { "]w", function() Snacks.words.jump(1) end, desc = "下一个引用词" }, + { "[w", function() Snacks.words.jump(-1) end, desc = "上一个引用词" }, + { "gg", function() Snacks.lazygit() end, desc = "LazyGit" }, + { "gf", function() Snacks.lazygit.log_file() end, desc = "当前文件 Git 历史" }, + { "gl", function() Snacks.lazygit.log() end, desc = "Git 日志" }, + -- Snacks picker + { "ff", function() Snacks.picker.files() end, desc = "查找文件" }, + { "fr", function() Snacks.picker.recent() end, desc = "最近文件" }, + { "fb", function() Snacks.picker.buffers() end, desc = "查找缓冲区" }, + { "fg", function() Snacks.picker.grep() end, desc = "全局搜索" }, + { "fw", function() Snacks.picker.grep_word() end, desc = "搜索当前单词", mode = { "n", "v" } }, + { "fh", function() Snacks.picker.help() end, desc = "帮助页面" }, + { "fk", function() Snacks.picker.keymaps() end, desc = "快捷键" }, + { "fs", function() Snacks.picker.lsp_symbols() end, desc = "文档符号" }, + { "fS", function() Snacks.picker.lsp_workspace_symbols() end, desc = "工作区符号" }, + { "fd", function() Snacks.picker.diagnostics() end, desc = "诊断" }, + }, + init = function() + vim.notify = function(msg, level, opts) + if Snacks and Snacks.notifier then + Snacks.notifier.notify(msg, level, opts) + else + vim.api.nvim_notify(msg or "", level or 0, opts or {}) + end + end + end, + }, + -- 状态栏 { "nvim-lualine/lualine.nvim", @@ -8,53 +95,34 @@ return { dependencies = { "nvim-tree/nvim-web-devicons" }, opts = { options = { - theme = "auto", -- 自动匹配当前主题 - globalstatus = true, -- 全局状态栏 + theme = "tokyonight", + globalstatus = true, + disabled_filetypes = { statusline = { "dashboard", "snacks_dashboard" } }, component_separators = { left = "", right = "" }, section_separators = { left = "", right = "" }, - disabled_filetypes = { - statusline = { "dashboard", "alpha" }, - winbar = { "dashboard", "alpha" }, - }, }, sections = { lualine_a = { { "mode", icon = "" } }, - lualine_b = { + lualine_b = { { "branch", icon = "" }, - { - "diff", - symbols = { added = " ", modified = " ", removed = " " }, - colored = true - } + { "diff", symbols = { added = " ", modified = " ", removed = " " } }, }, lualine_c = { { "diagnostics", sources = { "nvim_diagnostic" }, - symbols = { - error = " ", - warn = " ", - info = " ", - hint = " ", - }, + symbols = { error = " ", warn = " ", info = " ", hint = " " }, }, { "filetype", icon_only = true, separator = "", padding = { left = 1, right = 0 } }, { "filename", path = 1, symbols = { modified = " ", readonly = " ", unnamed = " " } }, }, lualine_x = { - -- Git 文件状态 { function() - local status = "" - local ft = vim.bo.filetype - - -- 检查 LSP 是否连接 - local clients = vim.lsp.get_active_clients({ bufnr = 0 }) - if #clients > 0 then - status = status .. " LSP" - end - - return status + local clients = vim.lsp.get_clients({ bufnr = 0 }) + if #clients == 0 then return "" end + local names = vim.tbl_map(function(c) return c.name end, clients) + return " " .. table.concat(names, ", ") end, }, { "encoding" }, @@ -62,49 +130,47 @@ return { { "filetype" }, }, lualine_y = { - { "progress", separator = " ", padding = { left = 1, right = 1 } }, - { "location", padding = { left = 1, right = 1 } }, - }, - lualine_z = { - function() - return " " .. os.date("%R") - end, + { "progress", padding = { left = 1, right = 1 } }, + { "location", padding = { left = 0, right = 1 } }, }, + lualine_z = { function() return " " .. os.date("%R") end }, }, - tabline = {}, - extensions = { "neo-tree", "lazy" }, + extensions = { "neo-tree", "lazy", "toggleterm", "mason" }, }, }, - - -- 缩进线 + + -- 缓冲区标签页 { - "lukas-reineke/indent-blankline.nvim", - main = "ibl", - event = "BufReadPost", + "akinsho/bufferline.nvim", + event = "VeryLazy", + keys = { + { "bp", "BufferLineTogglePin", desc = "标记缓冲区" }, + { "bP", "BufferLineGroupClose ungrouped", desc = "关闭未标记缓冲区" }, + { "bo", "BufferLineCloseOthers", desc = "关闭其他缓冲区" }, + { "br", "BufferLineCloseRight", desc = "关闭右侧缓冲区" }, + { "bl", "BufferLineCloseLeft", desc = "关闭左侧缓冲区" }, + { "", "BufferLineCyclePrev", desc = "上一个缓冲区" }, + { "", "BufferLineCycleNext", desc = "下一个缓冲区" }, + }, opts = { - indent = { - char = "│", -- 缩进字符 - tab_char = "│", -- Tab 缩进字符 - }, - scope = { enabled = false }, -- 禁用范围高亮 - exclude = { - filetypes = { - "help", - "alpha", - "dashboard", - "neo-tree", - "Trouble", - "lazy", - "mason", - "notify", - "toggleterm", - "lazyterm", + options = { + close_command = function(n) require("mini.bufremove").delete(n, false) end, + right_mouse_command = function(n) require("mini.bufremove").delete(n, false) end, + diagnostics = "nvim_lsp", + always_show_bufferline = false, + diagnostics_indicator = function(_, _, diag) + local ret = (diag.error and " " .. diag.error .. " " or "") + .. (diag.warning and " " .. diag.warning or "") + return vim.trim(ret) + end, + offsets = { + { filetype = "neo-tree", text = "文件浏览器", highlight = "Directory", text_align = "left" }, }, }, }, }, - - -- 文件树 + + -- 文件树(侧边栏) { "nvim-neo-tree/neo-tree.nvim", branch = "v3.x", @@ -115,20 +181,21 @@ return { "MunifTanjim/nui.nvim", }, keys = { - { "e", "Neotree toggle", desc = "切换文件浏览器" }, + { "e", "Neotree toggle", desc = "文件浏览器" }, { "o", "Neotree focus", desc = "聚焦文件浏览器" }, + { "ge", "Neotree float git_status", desc = "Git 状态" }, }, opts = { sources = { "filesystem", "buffers", "git_status", "document_symbols" }, - open_files_do_not_replace_types = { "terminal", "Trouble", "qf", "edgy" }, + open_files_do_not_replace_types = { "terminal", "Trouble", "trouble", "qf" }, filesystem = { bind_to_cwd = false, follow_current_file = { enabled = true }, use_libuv_file_watcher = true, filtered_items = { - visible = true, -- 显示被过滤的项目 - hide_dotfiles = false, -- 不隐藏点文件 - hide_gitignored = false, -- 不隐藏被 gitignore 的文件 + visible = true, + hide_dotfiles = false, + hide_gitignored = false, }, }, window = { @@ -143,188 +210,90 @@ return { }, default_component_configs = { indent = { - with_expanders = true, -- 启用展开图标 + with_expanders = true, expander_collapsed = "", expander_expanded = "", expander_highlight = "NeoTreeExpander", }, git_status = { symbols = { - -- 状态图标 - added = "✚", -- 或 "✚" - modified = "", -- 或 "" - deleted = "✖", -- 或 "✖" - renamed = "", -- 或 "" - untracked = "", - ignored = "", - unstaged = "", - staged = "", - conflict = "", - }, - }, - }, - commands = { - -- 添加自定义命令,如创建文件时创建路径 - parent_or_close = function(state) - local node = state.tree:get_node() - if (node.type == "directory" or node:has_children()) and node:is_expanded() then - state.commands.toggle_node(state) - else - require("neo-tree.ui.renderer").focus_node(state, node:get_parent_id()) - end - end, - child_or_open = function(state) - local node = state.tree:get_node() - if node.type == "directory" or node:has_children() then - if not node:is_expanded() then - state.commands.toggle_node(state) - else - require("neo-tree.ui.renderer").focus_node(state, node:get_child_ids()[1]) - end - else - state.commands.open(state) - end - end, - }, - }, - }, - - -- 顶部标签页 - { - "akinsho/bufferline.nvim", - event = "VeryLazy", - keys = { - { "bp", "BufferLineTogglePin", desc = "标记/取消标记缓冲区" }, - { "bP", "BufferLineGroupClose ungrouped", desc = "关闭未标记的缓冲区" }, - { "bo", "BufferLineCloseOthers", desc = "关闭其他缓冲区" }, - { "br", "BufferLineCloseRight", desc = "关闭右侧缓冲区" }, - { "bl", "BufferLineCloseLeft", desc = "关闭左侧缓冲区" }, - { "", "BufferLineCyclePrev", desc = "上一个缓冲区" }, - { "", "BufferLineCycleNext", desc = "下一个缓冲区" }, - }, - opts = { - options = { - close_command = function(n) require("mini.bufremove").delete(n, false) end, - right_mouse_command = function(n) require("mini.bufremove").delete(n, false) end, - diagnostics = "nvim_lsp", -- 显示诊断 - always_show_bufferline = false, - diagnostics_indicator = function(_, _, diag) - local icons = { - Error = " ", - Warn = " ", - Hint = " ", - Info = " ", - } - local ret = (diag.error and icons.Error .. diag.error .. " " or "") - .. (diag.warning and icons.Warn .. diag.warning or "") - return vim.trim(ret) - end, - offsets = { - { - filetype = "neo-tree", - text = "文件浏览器", - highlight = "Directory", - text_align = "left", + added = "✚", modified = "", deleted = "✖", + renamed = "", untracked = "", ignored = "", + unstaged = "", staged = "", conflict = "", }, }, }, }, }, - - -- 通知系统 + + -- noice.nvim - 命令行/通知/LSP UI 增强 { - "rcarriga/nvim-notify", - keys = { - { - "un", - function() - require("notify").dismiss({ silent = true, pending = true }) - end, - desc = "清除所有通知", - }, - }, - opts = { - timeout = 3000, - max_height = function() - return math.floor(vim.o.lines * 0.75) - end, - max_width = function() - return math.floor(vim.o.columns * 0.75) - end, - on_open = function(win) - vim.api.nvim_win_set_config(win, { zindex = 100 }) - end, - }, - init = function() - -- 当 "notify" 可用时,将其替换为 vim.notify - vim.notify = function(...) - local loaded, notify = pcall(require, "notify") - if loaded then - vim.notify = notify - return notify(...) - else - return vim.api.nvim_notify(...) - end - end - end, - }, - -- 快捷键提示 - { - "folke/which-key.nvim", + "folke/noice.nvim", event = "VeryLazy", + dependencies = { "MunifTanjim/nui.nvim" }, opts = { - plugins = { - marks = true, -- 显示标记 - registers = true, -- 显示寄存器 - spelling = { - enabled = true, -- 启用拼写建议 - suggestions = 20, + lsp = { + override = { + ["vim.lsp.util.convert_input_to_markdown_lines"] = true, + ["vim.lsp.util.stylize_markdown"] = true, }, - presets = { - operators = true, -- 添加操作符帮助 - motions = true, -- 添加动作帮助 - text_objects = true, -- 添加文本对象帮助 - windows = true, -- 添加窗口帮助 (meta-w) - nav = true, -- 添加导航帮助 - z = true, -- 添加折叠帮助 - g = true, -- 添加 g 命令帮助 + hover = { enabled = true }, + signature = { enabled = false }, -- blink.cmp 处理签名 + progress = { enabled = true, format_done = "" }, + }, + routes = { + { + -- 屏蔽 treesitter query 字段兼容性警告(Neovim 0.12 校验更严格,功能不受影响) + filter = { + event = "msg_show", + any = { + { find = "Invalid field name" }, + { find = "Invalid node type" }, + { find = "Query error" }, + }, + }, + opts = { skip = true }, + }, + { + filter = { + event = "msg_show", + any = { + { find = "%d+L, %d+B" }, + { find = "; after #%d+" }, + { find = "; before #%d+" }, + }, + }, + view = "mini", }, }, - icons = { - breadcrumb = "»", -- 面包屑分隔符 - separator = "➜", -- 键映射前缀和命令之间的分隔符 - group = "+", -- 组图标 - }, - window = { - border = "rounded", -- 边框样式 - position = "bottom", -- 位置 - margin = { 1, 0, 1, 0 }, -- 边距 - padding = { 1, 1, 1, 1 }, -- 内边距 - }, - layout = { - height = { min = 3, max = 25 }, -- 最小和最大高度 - width = { min = 20, max = 50 }, -- 最小和最大宽度 - spacing = 3, -- 间距 - align = "center", -- 对齐方式 - }, - ignore_missing = false, -- 不忽略缺少的键映射 - hidden = { "", "", "", "", "^:", "^ ", "^call ", "^lua " }, -- 隐藏的命令前缀 - show_help = true, -- 显示帮助信息 - triggers = "auto", -- 触发自动显示 - triggers_nowait = { -- 不等待这些前缀的键映射 - -- 字符表示操作符等待模式 - "`", - "'", - "g`", - "g'", - '"', - "", - "z=", + presets = { + bottom_search = true, + command_palette = true, + long_message_to_split = true, + inc_rename = true, }, }, - config = function(_, opts) - local wk = require("which-key") - wk.setup(opts) - end, + keys = { + { "snl", function() require("noice").cmd("last") end, desc = "最后消息" }, + { "snh", function() require("noice").cmd("history") end, desc = "Noice 历史" }, + { "sna", function() require("noice").cmd("all") end, desc = "所有消息" }, + }, }, -} \ No newline at end of file + + -- 缩进线 + { + "lukas-reineke/indent-blankline.nvim", + main = "ibl", + event = "BufReadPost", + opts = { + indent = { char = "│", tab_char = "│" }, + scope = { enabled = false }, + exclude = { + filetypes = { + "help", "snacks_dashboard", "neo-tree", "Trouble", "trouble", + "lazy", "mason", "toggleterm", + }, + }, + }, + }, +} diff --git a/nvim/lua/plugins/utils.lua b/nvim/lua/plugins/utils.lua deleted file mode 100644 index 38665e2..0000000 --- a/nvim/lua/plugins/utils.lua +++ /dev/null @@ -1,287 +0,0 @@ --- utils.lua - 实用工具插件配置 - -return { - -- 启动界面 - { - "goolord/alpha-nvim", - event = "VimEnter", - opts = function() - local dashboard = require("alpha.themes.dashboard") - local logo = [[ - ███╗ ██╗███████╗ ██████╗ ██╗ ██╗██╗███╗ ███╗ - ████╗ ██║██╔════╝██╔═══██╗██║ ██║██║████╗ ████║ - ██╔██╗ ██║█████╗ ██║ ██║██║ ██║██║██╔████╔██║ - ██║╚██╗██║██╔══╝ ██║ ██║╚██╗ ██╔╝██║██║╚██╔╝██║ - ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║ - ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═══╝ ╚═╝╚═╝ ╚═╝ - ]] - - dashboard.section.header.val = vim.split(logo, "\n") - dashboard.section.buttons.val = { - dashboard.button("f", " 查找文件", ":Telescope find_files "), - dashboard.button("e", " 新文件", ":ene startinsert "), - dashboard.button("r", " 最近文件", ":Telescope oldfiles "), - dashboard.button("g", " 查找文本", ":Telescope live_grep "), - dashboard.button("c", " 配置", ":e $MYVIMRC "), - dashboard.button("l", " 懒加载插件", ":Lazy"), - dashboard.button("q", " 退出", ":qa"), - } - - dashboard.section.footer.val = "Neovim 配置 - 专注于 Python 和 Go 开发" - - dashboard.section.header.opts.hl = "Type" - dashboard.section.buttons.opts.hl = "Keyword" - dashboard.section.footer.opts.hl = "Comment" - - dashboard.opts.opts.noautocmd = true - return dashboard - end, - config = function(_, dashboard) - require("alpha").setup(dashboard.opts) - - vim.api.nvim_create_autocmd("User", { - pattern = "LazyVimStarted", - callback = function() - local stats = require("lazy").stats() - local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100) - local version = " v" .. vim.version().major .. "." .. vim.version().minor .. "." .. vim.version().patch - local plugins = " " .. stats.count .. " 个插件加载完成,用时 " .. ms .. "ms" - local footer = version .. "\n" .. plugins - - pcall(function() - local alpha = require("alpha") - local dashboard = alpha.themes.dashboard - dashboard.section.footer.val = footer - alpha.redraw() - end) - end, - }) - end, - }, - - -- 查找器增强 - { - "folke/flash.nvim", - event = "VeryLazy", - opts = { - search = { - multi_window = false, -- 只在当前窗口搜索 - wrap = true, -- 循环搜索 - }, - modes = { - char = { - enabled = true, - keys = { "f", "F", "t", "T", ";", "," }, - }, - }, - }, - keys = { - { - "s", - mode = { "n", "x", "o" }, - function() - require("flash").jump() - end, - desc = "闪烁跳转", - }, - { - "S", - mode = { "n", "x", "o" }, - function() - require("flash").treesitter() - end, - desc = "闪烁 Treesitter", - }, - { - "r", - mode = "o", - function() - require("flash").remote() - end, - desc = "远程闪烁", - }, - { - "R", - mode = { "o", "x" }, - function() - require("flash").treesitter_search() - end, - desc = "Treesitter 搜索", - }, - }, - }, - - -- 项目管理 - { - "ahmedkhalf/project.nvim", - config = function() - require("project_nvim").setup({ - patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json", "pyproject.toml", "go.mod" }, - detection_methods = { "pattern", "lsp" }, - show_hidden = true, - silent_chdir = true, - scope_chdir = "global", - }) - - require("telescope").load_extension("projects") - end, - keys = { - { "fp", "Telescope projects", desc = "项目" }, - }, - }, - - -- 文件浏览器增强 - { - "stevearc/oil.nvim", - opts = { - default_file_explorer = true, - columns = { - "icon", - "permissions", - "size", - "mtime", - }, - buf_options = { - buflisted = false, - bufhidden = "hide", - }, - win_options = { - wrap = false, - signcolumn = "no", - cursorcolumn = false, - foldcolumn = "0", - spell = false, - list = false, - conceallevel = 3, - concealcursor = "n", - }, - delete_to_trash = true, - skip_confirm_for_simple_edits = false, - prompt_save_on_select_new_entry = true, - cleanup_delay_ms = 2000, - keymaps = { - ["g?"] = "actions.show_help", - [""] = "actions.select", - [""] = "actions.select_vsplit", - [""] = "actions.select_split", - [""] = "actions.select_tab", - [""] = "actions.preview", - [""] = "actions.close", - [""] = "actions.refresh", - ["-"] = "actions.parent", - ["_"] = "actions.open_cwd", - ["`"] = "actions.cd", - ["~"] = "actions.tcd", - ["gs"] = "actions.change_sort", - ["gx"] = "actions.open_external", - ["g."] = "actions.toggle_hidden", - ["g\\"] = "actions.toggle_trash", - }, - use_default_keymaps = true, - view_options = { - show_hidden = true, - is_hidden_file = function(name, bufnr) - return vim.startswith(name, ".") - end, - is_always_hidden = function(name, bufnr) - return false - end, - }, - float = { - padding = 2, - max_width = 0, - max_height = 0, - border = "rounded", - win_options = { - winblend = 0, - }, - }, - preview = { - max_width = 0.9, - min_width = { 40, 0.4 }, - width = nil, - max_height = 0.9, - min_height = { 5, 0.1 }, - height = nil, - border = "rounded", - win_options = { - winblend = 0, - }, - }, - progress = { - max_width = 0.9, - min_width = { 40, 0.4 }, - width = nil, - max_height = 0.9, - min_height = { 5, 0.1 }, - height = nil, - border = "rounded", - minimized_border = "none", - win_options = { - winblend = 0, - }, - }, - }, - keys = { - { "-", "Oil", desc = "打开父目录" }, - { "fo", "Oil", desc = "打开文件浏览器" }, - }, - }, - - -- 自动调整窗口大小 - { - "anuvyklack/windows.nvim", - event = "WinNew", - dependencies = { - { "anuvyklack/middleclass" }, - { "anuvyklack/animation.nvim", enabled = true }, - }, - keys = { - { "wm", "WindowsMaximize", desc = "最大化窗口" }, - { "w=", "WindowsEqualize", desc = "均分窗口" }, - }, - config = function() - vim.o.winwidth = 10 - vim.o.winminwidth = 10 - vim.o.equalalways = false - require("windows").setup({ - animation = { enable = true, duration = 150 }, - autowidth = { enable = true }, - }) - end, - }, - - -- 会话管理 - { - "folke/persistence.nvim", - event = "BufReadPre", - opts = { - dir = vim.fn.expand(vim.fn.stdpath("state") .. "/sessions/"), - options = { "buffers", "curdir", "tabpages", "winsize", "help", "globals", "skiprtp" }, - pre_save = nil, - }, - keys = { - { "qs", function() require("persistence").load() end, desc = "恢复上次会话" }, - { "ql", function() require("persistence").load({ last = true }) end, desc = "恢复最后会话" }, - { "qd", function() require("persistence").stop() end, desc = "不保存当前会话" }, - }, - }, - - -- 键位映射管理 - { - "mrjones2014/legendary.nvim", - keys = { - { "k", "Legendary", desc = "键位映射查找器" }, - }, - opts = { - include_builtin = true, - include_legendary_cmds = true, - extensions = { - which_key = { auto_register = true }, - smart_splits = { auto_register = true }, - }, - }, - }, - - -} \ No newline at end of file diff --git a/nvim/lua/plugins/which-key.lua b/nvim/lua/plugins/which-key.lua deleted file mode 100644 index 124b50b..0000000 --- a/nvim/lua/plugins/which-key.lua +++ /dev/null @@ -1,158 +0,0 @@ -return { - "folke/which-key.nvim", - event = "VeryLazy", - opts = { - -- 基础配置 - preset = "helix", -- 使用 helix 预设,更现代的样式 - - -- 延迟配置 - delay = 500, -- 显示 which-key 的延迟时间(毫秒) - - -- 过滤配置 - filter = function(mapping) - -- 只显示有描述的映射 - return mapping.desc and mapping.desc ~= "" - end, - - -- 触发配置 - triggers = { - { "", mode = "nxso" }, - }, - - -- 窗口配置 - win = { - no_overlap = true, - padding = { 1, 2 }, -- 上下, 左右 - title = true, - title_pos = "center", - zindex = 1000, - bo = {}, - wo = { - winblend = 10, - }, - }, - - -- 布局配置 - layout = { - width = { min = 20 }, -- 最小宽度 - spacing = 3, -- 列间距 - align = "left", -- 对齐方式 - }, - - -- 图标配置 - icons = { - breadcrumb = "»", -- 面包屑符号 - separator = "➜", -- 分隔符 - group = "+", -- 分组符号 - ellipsis = "…", - keys = { - Space = "", - Tab = "", - Return = "", - Escape = "", - Backspace = "", - Delete = "", - Insert = "", - Home = "", - End = "", - PageUp = "", - PageDown = "", - ScrollLock = "", - NumLock = "", - CapsLock = "", - Left = "", - Right = "", - Up = "", - Down = "", - F1 = "", - F2 = "", - F3 = "", - F4 = "", - F5 = "", - F6 = "", - F7 = "", - F8 = "", - F9 = "", - F10 = "", - F11 = "", - F12 = "", - Plug = "", - Action = "", - Alt = "%(?(.*)%)?", "%1" }, - { "^[cgls]%[?(.*)%]?$", "%1" }, - { "^ lua%.patterns%.(.+)$", "Pattern: %1" }, - { "^ lua%.snippets%.(.+)$", "Snippet: %1" }, - { "^ which%-key%.(.+)$", "WK: %1" }, - { "^.*%.(.+)$", "%1" }, - }, - }, - - -- 通知配置 - notify = true, - - -- 调试配置 - debug = false, - - -- 自动注册键组 - spec = {}, - }, - config = function(_, opts) - local wk = require("which-key") - wk.setup(opts) - - -- 注册键组 - wk.add({ - -- 文件操作 - { "f", group = "文件/查找", icon = { icon = "📁", color = "blue" } }, - - -- Git 操作 - { "g", group = "Git", icon = { icon = "🌿", color = "green" } }, - - -- LSP/Code 操作 - { "c", group = "代码/LSP", icon = { icon = "💻", color = "cyan" } }, - - -- 诊断 - { "x", group = "诊断", icon = { icon = "🚨", color = "red" } }, - - -- 搜索 - { "s", group = "搜索", icon = { icon = "🔍", color = "yellow" } }, - - -- 终端 - { "t", group = "终端", icon = { icon = "🖥️", color = "purple" } }, - - -- 缓冲区 - { "b", group = "缓冲区", icon = { icon = "📋", color = "blue" } }, - - -- 通知 - { "u", group = "UI/通知", icon = { icon = "🎨", color = "purple" } }, - - -- AI 助手 - { "a", group = "AI 助手", icon = { icon = "🤖", color = "cyan" } }, - - -- Python - { "p", group = "Python", icon = { icon = "🐍", color = "green" } }, - - -- 会话 - { "q", group = "会话/退出", icon = { icon = "🚪", color = "red" } }, - - -- 窗口 - { "w", group = "窗口", icon = { icon = "🪟", color = "blue" } }, - }) - end, -}