refactor(nvim): 完整重写配置,支持 Go/Rust/Python/TypeScript 开发

- 架构重构:新增 plugins/lang/ 子目录,按语言拆分配置
- 补全引擎:nvim-cmp → blink.cmp + LuaSnip
- 文件浏览:新增 neo-tree(<Space>e)
- 语言支持:
  - Go: ray-x/go.nvim + dap-go + neotest-go
  - Rust: rustaceanvim + crates.nvim
  - Python: venv-selector + dap-python + neotest-python
  - TypeScript: typescript-tools.nvim(替换 ts_ls)
- LSP: lazydev + mason + mason-lspconfig + fidget + inc-rename
- 格式化: conform.nvim(lsp_format fallback,保存时自动格式化)
- Lint: nvim-lint(selene 替换 luacheck,Mason 可直接安装)
- UI: snacks.nvim(dashboard+notifier+picker)+ noice + lualine + bufferline
- 编辑增强: mini.ai + mini.surround + grug-far + flash + ufo + trouble v3
- 删除废弃文件: cmp/coding/null-ls/mason/lspconfig/go/python 等旧文件
- 修复: Neovim 0.12 treesitter query 校验报错(noice routes 过滤)
- 新增: NVIM_GUIDE.md 快捷键使用手册

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-07 16:55:07 +08:00
parent 2aa176dff5
commit 6fd5d96043
36 changed files with 2087 additions and 2814 deletions

366
NVIM_GUIDE.md Normal file
View File

@@ -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
| 快捷键 | 功能 |
|--------|------|
| `<Space>e` | **打开/关闭文件树** |
| `<Space>o` | 聚焦到文件树 |
| `<Space>ge` | 浮动显示 Git 状态树 |
**文件树内操作:**
| 按键 | 功能 |
|------|------|
| `Enter` / `l` | 打开文件/展开目录 |
| `h` | 折叠目录 |
| `a` | 新建文件(末尾加 `/` 则创建目录) |
| `d` | 删除 |
| `r` | 重命名 |
| `y` | 复制 |
| `x` | 剪切 |
| `p` | 粘贴 |
| `q` | 关闭文件树 |
---
## 🔍 查找 / 搜索
| 快捷键 | 功能 |
|--------|------|
| `<Space>ff` | **查找文件** |
| `<Space>fr` | 最近打开的文件 |
| `<Space>fb` | 已打开的缓冲区 |
| `<Space>fg` | **全局内容搜索grep** |
| `<Space>fw` | 搜索光标下的单词 |
| `<Space>fh` | 搜索帮助文档 |
| `<Space>fk` | 查看所有快捷键 |
| `<Space>fs` | 当前文件符号 |
| `<Space>fS` | 工作区符号 |
| `<Space>fd` | 诊断错误 |
| `<Space>ft` | TODO 注释 |
| `<Space>sr` | **项目范围搜索替换**grug-far |
---
## 💡 LSP 代码智能
| 快捷键 | 功能 |
|--------|------|
| `gd` | **跳转到定义** |
| `gD` | 跳转到声明 |
| `gr` | 查看所有引用 |
| `gI` | 跳转到实现 |
| `gy` | 跳转到类型定义 |
| `K` | **悬浮显示文档** |
| `gK` | 函数签名帮助 |
| `<C-k>` | 签名帮助(插入模式) |
| `<Space>ca` | **代码操作**(自动修复、重构) |
| `<Space>cr` | **重命名符号**(实时预览) |
| `<Space>cd` | 显示当前行诊断详情 |
| `<Space>cl` | LSP 状态信息 |
| `<Space>cf` | **格式化**(文件或选中范围) |
| `<Space>uf` | 切换当前缓冲区自动格式化 |
| `<Space>uF` | 切换全局自动格式化 |
| `<Space>uh` | 切换 Inlay Hints |
| `]d` / `[d` | 跳到下/上一个诊断 |
---
## 🔴 诊断列表Trouble
| 快捷键 | 功能 |
|--------|------|
| `<Space>xx` | 工作区所有诊断 |
| `<Space>xX` | 当前文件诊断 |
| `<Space>xs` | 符号列表 |
| `<Space>xL` | 位置列表 |
| `<Space>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
| 快捷键 | 功能 |
|--------|------|
| `<C-n>` | 选中光标下的词(重复按继续选下一个) |
| `<C-Down/Up>` | 向下/上添加光标 |
| `q` | 跳过当前,选下一个 |
| `<Esc>` | 退出多光标 |
---
## 🐛 调试DAP
| 快捷键 | 功能 |
|--------|------|
| `<Space>dc` | **开始/继续调试** |
| `<Space>db` | 切换断点 |
| `<Space>dB` | 条件断点 |
| `<Space>di` | 单步进入 |
| `<Space>do` | 单步跳出 |
| `<Space>dO` | 单步跳过 |
| `<Space>dC` | 运行到光标处 |
| `<Space>dt` | 终止调试 |
| `<Space>du` | 调试 UI 面板 |
| `<Space>dw` | 悬浮查看变量值 |
| `<Space>dr` | 打开 REPL |
| `<Space>dl` | 重新运行上次调试 |
---
## 🐹 Go 开发
| 快捷键 | 功能 |
|--------|------|
| `<Space>gr` | 运行 |
| `<Space>gb` | 构建 |
| `<Space>gv` | go vet |
| `<Space>gi` | 实现接口 |
| `<Space>gge` | 生成 if err 错误处理 |
| `<Space>ggf` | 填充结构体字段 |
| `<Space>ggs` | 填充 switch case |
| `<Space>gts` | 切换测试/实现文件 |
| `<Space>gtt` | 运行测试 |
| `<Space>gtf` | 测试当前函数 |
| `<Space>gtc` | 查看测试覆盖率 |
| `<Space>gta` | 添加 struct tag |
| `<Space>dtg` | 调试当前 Go 测试 |
---
## 🦀 Rust 开发
| 快捷键 | 功能 |
|--------|------|
| `<Space>rr` | 运行目标列表 |
| `<Space>rt` | 测试目标列表 |
| `<Space>rd` | 调试目标列表 |
| `<Space>re` | 解释错误 |
| `<Space>rm` | 展开宏 |
| `<Space>rc` | 打开 Cargo.toml |
| `<Space>rp` | 跳转到父模块 |
| `<Space>rx` | 打开外部文档 |
| `<Space>rcu` | 升级所有 crate 依赖 |
| `<Space>rco` | 查看 crate 信息 |
---
## 🐍 Python 开发
| 快捷键 | 功能 |
|--------|------|
| `<Space>pt` | 运行测试 |
| `<Space>pT` | 运行当前文件全部测试 |
| `<Space>pd` | DAP 调试测试 |
| `<Space>ps` | 停止测试 |
| `<Space>po` | 查看测试输出 |
| `<Space>pO` | 测试输出面板 |
| `<Space>pS` | 测试摘要面板 |
| `<Space>dpm` | 调试当前方法 |
| `<Space>dpc` | 调试当前类 |
---
## 📘 TypeScript/JavaScript 开发
| 快捷键 | 功能 |
|--------|------|
| `<Space>to` | 整理 import |
| `<Space>ta` | 添加缺失 import |
| `<Space>tu` | 删除未使用 import |
| `<Space>tf` | 修复所有问题 |
| `<Space>tr` | 重命名文件(自动更新引用) |
| `<Space>tR` | 查看文件引用 |
---
## 🌿 Git 操作
| 快捷键 | 功能 |
|--------|------|
| `<Space>gg` | **打开 LazyGit** |
| `<Space>gl` | Git 日志 |
| `<Space>gf` | 当前文件 Git 历史 |
| `<Space>gs` | 暂存当前 hunk |
| `<Space>gr` | 重置当前 hunk |
| `<Space>gS` | 暂存整个文件 |
| `<Space>gR` | 重置整个文件 |
| `<Space>gu` | 取消暂存 hunk |
| `<Space>gp` | 预览变更 hunk |
| `<Space>gb` | 查看当前行 blame |
| `<Space>gB` | 开关行 blame 显示 |
| `<Space>gd` | 文件 diff |
| `]h` / `[h` | 跳到下/上一个 hunk |
| `ih` | 选中 hunkVisual/Operator 模式) |
---
## 🖥️ 终端
| 快捷键 | 功能 |
|--------|------|
| `<C-\>` | 切换终端(浮动) |
| `<Space>tf` | 浮动终端 |
| `<Space>th` | 水平终端 |
| `<Space>tv` | 垂直终端 |
| `Esc``jk` | 退出终端模式 |
---
## ⚡ 快速跳转Flash
| 快捷键 | 功能 |
|--------|------|
| `s` | 字符跳转(高亮标记) |
| `S` | Treesitter 节点跳转 |
| `f/F/t/T` | 行内增强跳转 |
| `r` (operator) | Flash 远程操作 |
---
## 📑 缓冲区管理
| 快捷键 | 功能 |
|--------|------|
| `<S-h>` | 上一个缓冲区 |
| `<S-l>` | 下一个缓冲区 |
| `<Space>bd` | 关闭当前缓冲区 |
| `<Space>bD` | 强制关闭 |
| `<Space>bo` | 关闭其他缓冲区 |
| `<Space>bp` | 标记/取消固定缓冲区 |
| `<Space>br` / `<Space>bl` | 关闭右/左侧缓冲区 |
---
## 🪟 窗口管理
| 快捷键 | 功能 |
|--------|------|
| `<C-h/j/k/l>` | 切换窗口 |
| `<Space>sv` | 垂直分割 |
| `<Space>sh` | 水平分割 |
| `<Space>se` | 均分窗口 |
| `<Space>sx` | 关闭当前窗口 |
| `<C-Up/Down/Left/Right>` | 调整窗口大小 |
---
## 🔢 代码折叠UFO
| 快捷键 | 功能 |
|--------|------|
| `zR` | 展开所有折叠 |
| `zM` | 折叠所有 |
| `zr` | 展开一级 |
| `zm` | 折叠一级 |
| `zp` | 预览折叠内容 |
---
## 🗂️ 会话管理
| 快捷键 | 功能 |
|--------|------|
| `<Space>qs` | 恢复上次会话 |
| `<Space>ql` | 恢复最后会话 |
| `<Space>qd` | 退出不保存会话 |
---
## 🔔 通知
| 快捷键 | 功能 |
|--------|------|
| `<Space>nh` | 通知历史 |
| `<Space>nd` | 关闭所有通知 |
| `<Space>snl` | 最后一条消息 |
| `<Space>snh` | Noice 历史 |
---
## ⚙️ 通用编辑技巧
| 快捷键 | 功能 |
|--------|------|
| `<Space>w` | 保存文件 |
| `<Space>q` | 退出 |
| `<Space>Q` | 退出全部 |
| `<Space>h` | 清除搜索高亮 |
| `<Space>r` | 替换光标下单词(全文) |
| `jk` | Insert 模式退出 |
| `<C-d/u>` | 翻页并保持光标居中 |
| `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 保存(跳过格式化)
```

View File

@@ -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" }
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }
}

View File

@@ -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,
})

View File

@@ -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", "<ESC>", opts)
-- 保存和退出
@@ -29,89 +14,60 @@ map("n", "<leader>Q", "<cmd>qa<cr>", { desc = "退出全部" })
-- 清除搜索高亮
map("n", "<leader>h", "<cmd>nohlsearch<cr>", { desc = "清除搜索高亮" })
-- 更好的缩进
-- 缩进保持选中
map("v", "<", "<gv", opts)
map("v", ">", ">gv", opts)
-- 上下移动选中文本
map("v", "J", ":m '>+1<CR>gv=gv", { desc = "向下移动选中文本" })
map("v", "K", ":m '<-2<CR>gv=gv", { desc = "向上移动选中文本" })
-- 上下移动选中文本
map("v", "J", ":m '>+1<CR>gv=gv", { desc = "向下移动选中" })
map("v", "K", ":m '<-2<CR>gv=gv", { desc = "向上移动选中" })
-- 保持复制内容在粘贴后
-- 粘贴不覆盖寄存器
map("x", "p", [["_dP]], { desc = "粘贴不覆盖寄存器" })
-- 删除到黑洞寄存器
map({ "n", "v" }, "<leader>d", [["_d]], { desc = "删除到黑洞寄存器" })
-- 快速移动
map("n", "J", "mzJ`z", { desc = "连接行保持光标位置" })
map("n", "<C-d>", "<C-d>zz", { desc = "向下移动保持光标居中" })
map("n", "<C-u>", "<C-u>zz", { desc = "向上移动保持光标居中" })
map("n", "n", "nzzzv", { desc = "下一个搜索结果居中" })
map("n", "N", "Nzzzv", { desc = "上一个搜索结果居中" })
-- 快速移动(保持居中)
map("n", "J", "mzJ`z", { desc = "连接行" })
map("n", "<C-d>", "<C-d>zz", { desc = "向下翻页居中" })
map("n", "<C-u>", "<C-u>zz", { desc = "向上翻页居中" })
map("n", "n", "nzzzv", { desc = "下一个结果居中" })
map("n", "N", "Nzzzv", { desc = "上一个结果居中" })
-------------------------
-- 窗口和缓冲区管理 --
-------------------------
-- 窗口间导航
map("n", "<C-h>", "<C-w>h", { desc = "移动到左窗口" })
map("n", "<C-j>", "<C-w>j", { desc = "移动到下窗口" })
map("n", "<C-k>", "<C-w>k", { desc = "移动到上窗口" })
map("n", "<C-l>", "<C-w>l", { desc = "移动到右窗口" })
-- 缓冲区导航
map("n", "<S-h>", "<cmd>bprevious<cr>", { desc = "上一个缓冲区" })
map("n", "<S-l>", "<cmd>bnext<cr>", { desc = "下一个缓冲区" })
map("n", "<leader>bd", "<cmd>bdelete<cr>", { desc = "关闭当前缓冲区" })
map("n", "<leader>ba", "<cmd>bufdo bd<cr>", { desc = "关闭所有缓冲区" })
-- 窗口导航
map("n", "<C-h>", "<C-w>h", { desc = "左窗口" })
map("n", "<C-j>", "<C-w>j", { desc = "下窗口" })
map("n", "<C-k>", "<C-w>k", { desc = "上窗口" })
map("n", "<C-l>", "<C-w>l", { desc = "右窗口" })
-- 窗口分割
map("n", "<leader>sv", "<cmd>vsplit<cr>", { desc = "垂直分割" })
map("n", "<leader>sh", "<cmd>split<cr>", { desc = "水平分割" })
map("n", "<leader>se", "<C-w>=", { desc = "使所有窗口等宽" })
map("n", "<leader>sx", "<cmd>close<cr>", { desc = "关闭当前窗口" })
map("n", "<leader>se", "<C-w>=", { desc = "均分窗口" })
map("n", "<leader>sx", "<cmd>close<cr>", { desc = "关闭窗口" })
-- 调整窗口大小
map("n", "<C-Up>", "<cmd>resize +2<cr>", { desc = "增加窗口高度" })
map("n", "<C-Down>", "<cmd>resize -2<cr>", { desc = "小窗口高度" })
map("n", "<C-Left>", "<cmd>vertical resize -2<cr>", { desc = "小窗口宽度" })
map("n", "<C-Right>", "<cmd>vertical resize +2<cr>", { desc = "增加窗口宽度" })
map("n", "<C-Up>", "<cmd>resize +2<cr>", { desc = "增加高度" })
map("n", "<C-Down>", "<cmd>resize -2<cr>", { desc = "高度" })
map("n", "<C-Left>", "<cmd>vertical resize -2<cr>", { desc = "宽度" })
map("n", "<C-Right>", "<cmd>vertical resize +2<cr>", { desc = "增加宽度" })
-------------------------
-- 终端模式映射 --
-------------------------
-- 退出终端模式
-- 终端模式
map("t", "<Esc>", "<C-\\><C-n>", { desc = "退出终端模式" })
map("t", "jk", "<C-\\><C-n>", { desc = "退出终端模式" })
map("t", "<C-h>", "<C-\\><C-n><C-w>h", opts)
map("t", "<C-j>", "<C-\\><C-n><C-w>j", opts)
map("t", "<C-k>", "<C-\\><C-n><C-w>k", opts)
map("t", "<C-l>", "<C-\\><C-n><C-w>l", opts)
-- 终端窗口导航
map("t", "<C-h>", "<C-\\><C-n><C-w>h", { desc = "终端模式下向左移动" })
map("t", "<C-j>", "<C-\\><C-n><C-w>j", { desc = "终端模式下向下移动" })
map("t", "<C-k>", "<C-\\><C-n><C-w>k", { desc = "终端模式下向上移动" })
map("t", "<C-l>", "<C-\\><C-n><C-w>l", { desc = "终端模式下向右移动" })
-------------------------
-- 实用功能 --
-------------------------
-- 全文快速替换当前单词
-- 实用工具
map("n", "<leader>r", [[:%s/\<<C-r><C-w>\>/<C-r><C-w>/gI<Left><Left><Left>]], { desc = "替换当前单词" })
map("n", "<leader>x", "<cmd>!chmod +x %<CR>", { desc = "使文件可执行", silent = true })
-- 使当前文件可执行
map("n", "<leader>x", "<cmd>!chmod +x %<CR>", { desc = "使当前文件可执行", silent = true })
-- 打开一个新的终端
map("n", "<leader>t", "<cmd>terminal<cr>", { desc = "打开终端" })
-- 快速编辑配置文件
map("n", "<leader>ev", "<cmd>e $MYVIMRC<cr>", { desc = "编辑init.lua" })
map("n", "<leader>sv", "<cmd>source $MYVIMRC<cr>", { desc = "重新加载配置" })
-- 更简单的命令行历史导航
map("c", "<C-j>", "<Down>", { desc = "下一个命令历史" })
map("c", "<C-k>", "<Up>", { desc = "上一个命令历史" })
-- 命令行历史
map("c", "<C-j>", "<Down>", { desc = "下一条命令" })
map("c", "<C-k>", "<Up>", { desc = "上一条命令" })
-- 更好的搜索
map("n", "g/", "/\\<\\><Left><Left>", { desc = "搜索单词" })

View File

@@ -21,8 +21,8 @@ vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
-- 插件列表
spec = {
-- 导入插件模块
{ import = "plugins" },
{ import = "plugins.lang" },
},
-- 默认配置

View File

@@ -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

View File

@@ -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",
["<C-Space>"] = { "show", "show_documentation", "hide_documentation" },
["<C-e>"] = { "hide" },
["<CR>"] = { "accept", "fallback" },
["<Tab>"] = { "snippet_forward", "fallback" },
["<S-Tab>"] = { "snippet_backward", "fallback" },
["<C-n>"] = { "select_next", "fallback" },
["<C-p>"] = { "select_prev", "fallback" },
["<C-b>"] = { "scroll_documentation_up", "fallback" },
["<C-f>"] = { "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",
},
},
}

View File

@@ -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({
["<C-Space>"] = cmp.mapping.complete(),
["<CR>"] = cmp.mapping.confirm({ select = true }),
}),
sources = cmp.config.sources({
{ name = "nvim_lsp" },
{ name = "luasnip" },
{ name = "buffer" },
{ name = "path" },
}),
}
end,
},
}

View File

@@ -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", "<cmd>Telescope lsp_definitions<cr>", { desc = "转到定义" })
map("n", "gr", "<cmd>Telescope lsp_references<cr>", { desc = "查找引用" })
map("n", "gD", vim.lsp.buf.declaration, { desc = "转到声明" })
map("n", "gI", "<cmd>Telescope lsp_implementations<cr>", { desc = "转到实现" })
map("n", "gt", "<cmd>Telescope lsp_type_definitions<cr>", { desc = "转到类型定义" })
map("n", "K", vim.lsp.buf.hover, { desc = "显示悬停信息" })
map("n", "gK", vim.lsp.buf.signature_help, { desc = "显示签名帮助" })
-- 代码操作键绑定
map("n", "<leader>ca", vim.lsp.buf.code_action, { desc = "代码操作" })
map("n", "<leader>cr", vim.lsp.buf.rename, { desc = "重命名" })
-- 诊断键绑定
map("n", "]d", vim.diagnostic.goto_next, { desc = "下一个诊断" })
map("n", "[d", vim.diagnostic.goto_prev, { desc = "上一个诊断" })
map("n", "<leader>cd", vim.diagnostic.open_float, { desc = "行诊断" })
map("n", "<leader>cl", "<cmd>LspInfo<cr>", { desc = "LSP 信息" })
-- 格式化文档(如果服务器支持)
if client and client.supports_method("textDocument/formatting") then
map("n", "<leader>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({
["<C-n>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
["<C-p>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
["<C-b>"] = cmp.mapping.scroll_docs(-4),
["<C-f>"] = cmp.mapping.scroll_docs(4),
["<C-Space>"] = cmp.mapping.complete(),
["<C-e>"] = cmp.mapping.abort(),
["<CR>"] = cmp.mapping.confirm({ select = true }),
["<S-CR>"] = cmp.mapping.confirm({
behavior = cmp.ConfirmBehavior.Replace,
select = true,
}),
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { "i", "s" }),
["<S-Tab>"] = 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 = {
{
"<leader>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 = {
{ "<leader>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 = {
{ "<leader>dB", function() require("dap").set_breakpoint(vim.fn.input('断点条件: ')) end, desc = "条件断点" },
{ "<leader>db", function() require("dap").toggle_breakpoint() end, desc = "切换断点" },
{ "<leader>dc", function() require("dap").continue() end, desc = "继续执行" },
{ "<leader>da", function() require("dap").continue({ before = get_args }) end, desc = "带参数运行" },
{ "<leader>dC", function() require("dap").run_to_cursor() end, desc = "运行到光标处" },
{ "<leader>dg", function() require("dap").goto_() end, desc = "跳转到行" },
{ "<leader>di", function() require("dap").step_into() end, desc = "单步进入" },
{ "<leader>dj", function() require("dap").down() end, desc = "下栈帧" },
{ "<leader>dk", function() require("dap").up() end, desc = "上栈帧" },
{ "<leader>dl", function() require("dap").run_last() end, desc = "运行最后的配置" },
{ "<leader>do", function() require("dap").step_out() end, desc = "单步跳出" },
{ "<leader>dO", function() require("dap").step_over() end, desc = "单步跳过" },
{ "<leader>dp", function() require("dap").pause() end, desc = "暂停执行" },
{ "<leader>dr", function() require("dap").repl.toggle() end, desc = "切换 REPL" },
{ "<leader>ds", function() require("dap").session() end, desc = "获取会话" },
{ "<leader>dt", function() require("dap").terminate() end, desc = "终止调试" },
{ "<leader>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 = "<esc>",
refresh = "r",
jump = { "<cr>", "<tab>", "<2-leftmouse>" },
open_split = { "<c-s>" },
open_vsplit = { "<c-v>" },
open_tab = { "<c-t>" },
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 = {
{ "<leader>xx", "<cmd>TroubleToggle document_diagnostics<cr>", desc = "文档诊断" },
{ "<leader>xX", "<cmd>TroubleToggle workspace_diagnostics<cr>", desc = "工作区诊断" },
{ "<leader>xL", "<cmd>TroubleToggle loclist<cr>", desc = "位置列表" },
{ "<leader>xQ", "<cmd>TroubleToggle quickfix<cr>", 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 = "下一个问题",
},
},
},
}

View File

@@ -1,16 +1,14 @@
-- 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, -- 设置终端颜色
lazy = false,
priority = 1000,
opts = {
style = "night",
transparent = false,
terminal_colors = true,
styles = {
comments = { italic = true },
keywords = { italic = true },
@@ -19,83 +17,47 @@ return {
sidebars = "dark",
floats = "dark",
},
sidebars = { "qf", "help", "terminal", "packer", "NvimTree", "Trouble" },
dim_inactive = false, -- 非活动窗口变暗
lualine_bold = true, -- 在状态栏中使用粗体
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,
},
}

View File

@@ -1,23 +1,82 @@
-- dap.lua - 调试支持
-- dap.lua - 调试适配器协议(通用配置)
return {
{
"mfussenegger/nvim-dap",
event = "VeryLazy",
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",
},
{
"leoluz/nvim-dap-go",
ft = "go",
dependencies = { "mfussenegger/nvim-dap" },
config = function()
require("dap-go").setup()
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,
},
{
"mfussenegger/nvim-dap-python",
ft = "python",
dependencies = { "mfussenegger/nvim-dap" },
"theHamsta/nvim-dap-virtual-text",
opts = { commented = true },
},
},
keys = {
{ "<leader>dB", function() require("dap").set_breakpoint(vim.fn.input("断点条件: ")) end, desc = "条件断点" },
{ "<leader>db", function() require("dap").toggle_breakpoint() end, desc = "切换断点" },
{ "<leader>dc", function() require("dap").continue() end, desc = "继续/启动" },
{ "<leader>dC", function() require("dap").run_to_cursor() end, desc = "运行到光标" },
{ "<leader>di", function() require("dap").step_into() end, desc = "单步进入" },
{ "<leader>do", function() require("dap").step_out() end, desc = "单步跳出" },
{ "<leader>dO", function() require("dap").step_over() end, desc = "单步跳过" },
{ "<leader>dl", function() require("dap").run_last() end, desc = "重新运行" },
{ "<leader>dt", function() require("dap").terminate() end, desc = "终止调试" },
{ "<leader>dr", function() require("dap").repl.toggle() end, desc = "REPL" },
{ "<leader>du", function() require("dapui").toggle() end, desc = "调试 UI" },
{ "<leader>dw", function() require("dap.ui.widgets").hover() end, desc = "悬浮变量" },
},
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,
},
}

View File

@@ -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 = {
{ "<leader>gg", "<cmd>LazyGit<cr>", desc = "打开 LazyGit" },
{ "<leader>gf", "<cmd>LazyGitCurrentFile<cr>", desc = "当前文件 Git 历史" },
{ "<leader>gc", "<cmd>LazyGitConfig<cr>", desc = "LazyGit 配置" },
},
},
-- 模糊搜索
-- 模糊搜索(保留 telescope 作为备选/LSP 操作入口)
{
"nvim-telescope/telescope.nvim",
cmd = "Telescope",
@@ -35,34 +18,7 @@ return {
},
},
keys = {
-- 文件查找
{ "<leader>ff", "<cmd>Telescope find_files<cr>", desc = "查找文件" },
{ "<leader>fr", "<cmd>Telescope oldfiles<cr>", desc = "最近文件" },
{ "<leader>fb", "<cmd>Telescope buffers<cr>", desc = "查找缓冲区" },
-- 内容搜索
{ "<leader>fg", "<cmd>Telescope live_grep<cr>", desc = "全局搜索" },
{ "<leader>fw", "<cmd>Telescope grep_string<cr>", desc = "搜索当前单词" },
-- 其他功能
{ "<leader>fh", "<cmd>Telescope help_tags<cr>", desc = "帮助标签" },
{ "<leader>fm", "<cmd>Telescope marks<cr>", desc = "跳转到书签" },
{ "<leader>fc", "<cmd>Telescope commands<cr>", desc = "命令" },
{ "<leader>fk", "<cmd>Telescope keymaps<cr>", desc = "快捷键" },
-- 工作区相关
{ "<leader>ws", "<cmd>Telescope lsp_workspace_symbols<cr>", desc = "工作区符号" },
-- LSP 相关
{ "<leader>cs", "<cmd>Telescope lsp_document_symbols<cr>", desc = "文档符号" },
{ "<leader>cr", "<cmd>Telescope lsp_references<cr>", desc = "引用" },
{ "<leader>ci", "<cmd>Telescope lsp_implementations<cr>", desc = "实现" },
{ "<leader>cd", "<cmd>Telescope lsp_definitions<cr>", desc = "定义" },
{ "<leader>ct", "<cmd>Telescope lsp_type_definitions<cr>", desc = "类型定义" },
-- 诊断
{ "<leader>xx", "<cmd>Telescope diagnostics bufnr=0<cr>", desc = "当前文件诊断" },
{ "<leader>xw", "<cmd>Telescope diagnostics<cr>", desc = "工作区诊断" },
{ "<leader>fp", "<cmd>Telescope projects<cr>", desc = "项目" },
},
opts = {
defaults = {
@@ -70,228 +26,230 @@ return {
selection_caret = " ",
mappings = {
i = {
["<C-j>"] = function(...)
return require("telescope.actions").move_selection_next(...)
end,
["<C-k>"] = function(...)
return require("telescope.actions").move_selection_previous(...)
end,
["<C-n>"] = function(...)
return require("telescope.actions").cycle_history_next(...)
end,
["<C-p>"] = function(...)
return require("telescope.actions").cycle_history_prev(...)
end,
["<C-c>"] = function(...)
return require("telescope.actions").close(...)
end,
["<C-u>"] = function(...)
return require("telescope.actions").preview_scrolling_up(...)
end,
["<C-d>"] = function(...)
return require("telescope.actions").preview_scrolling_down(...)
end,
},
n = {
["q"] = function(...)
return require("telescope.actions").close(...)
end,
["<C-j>"] = function(...) return require("telescope.actions").move_selection_next(...) end,
["<C-k>"] = function(...) return require("telescope.actions").move_selection_previous(...) end,
["<C-c>"] = 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",
"lewis6991/gitsigns.nvim",
event = { "BufReadPre", "BufNewFile" },
opts = {
signs = {
add = { text = "" }, change = { text = "" }, delete = { text = "" },
topdelete = { text = "" }, changedelete = { text = "" }, untracked = { text = "" },
},
dependencies = {
"nvim-lua/plenary.nvim",
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" }, "<leader>gs", ":Gitsigns stage_hunk<CR>", "暂存变更")
map({ "n", "v" }, "<leader>gr", ":Gitsigns reset_hunk<CR>", "重置变更")
map("n", "<leader>gS", gs.stage_buffer, "暂存文件")
map("n", "<leader>gu", gs.undo_stage_hunk, "取消暂存变更")
map("n", "<leader>gR", gs.reset_buffer, "重置文件")
map("n", "<leader>gp", gs.preview_hunk, "预览变更")
map("n", "<leader>gb", function() gs.blame_line({ full = true }) end, "查看责任")
map("n", "<leader>gB", gs.toggle_current_line_blame, "开关行责任")
map("n", "<leader>gd", gs.diffthis, "文件差异")
map({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>", "选择变更")
end,
},
},
-- 快速跳转
{
"folke/flash.nvim",
event = "VeryLazy",
opts = {
search = { multi_window = false, wrap = true },
modes = { char = { enabled = true, keys = { "f", "F", "t", "T", ";", "," } } },
},
keys = {
{ "<leader>gg", "<cmd>LazyGit<cr>", desc = "打开 LazyGit" },
{ "<leader>gf", "<cmd>LazyGitCurrentFile<cr>", desc = "当前文件 Git 历史" },
{ "<leader>gc", "<cmd>LazyGitConfig<cr>", desc = "LazyGit 配置" },
{ "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 注释高亮
{
"nvim-treesitter/nvim-treesitter",
build = ":TSUpdate",
event = { "BufReadPost", "BufNewFile" },
dependencies = {
"nvim-treesitter/nvim-treesitter-textobjects",
"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" },
{ "<leader>ft", "<cmd>TodoTelescope<cr>", desc = "TODO 列表" },
},
},
-- which-key 按键提示
{
"folke/which-key.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 = "<C-space>",
node_incremental = "<C-space>",
scope_incremental = false,
node_decremental = "<bs>",
},
},
-- 文本对象
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",
},
},
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({
{ "<leader>b", group = "缓冲区" },
{ "<leader>c", group = "代码" },
{ "<leader>d", group = "调试" },
{ "<leader>f", group = "查找/文件" },
{ "<leader>g", group = "Git" },
{ "<leader>n", group = "通知" },
{ "<leader>q", group = "退出/会话" },
{ "<leader>r", group = "Rust" },
{ "<leader>s", group = "搜索" },
{ "<leader>t", group = "TypeScript/终端" },
{ "<leader>u", group = "UI 切换" },
{ "<leader>x", group = "诊断" },
{ "<leader>p", group = "Python" },
{ "<leader>gt", group = "Go 测试" },
{ "<leader>gg", group = "Go 生成" },
{ "<leader>dt", group = "调试 - 测试" },
{ "<leader>dp", group = "调试 - Python" },
{ "<leader>rc", group = "Rust Crate" },
{ "<leader>sn", group = "Noice" },
})
end,
},
-- 代码注释
-- Trouble v3 - 诊断列表
{
"numToStr/Comment.nvim",
"folke/trouble.nvim",
cmd = "Trouble",
opts = {
padding = true, -- 在注释分隔符后添加空格
sticky = true, -- 注释时光标不移动
toggler = {
line = "gcc", -- 行注释切换
block = "gbc", -- 块注释切换
modes = {
lsp = {
win = { position = "right" },
},
opleader = {
line = "gc", -- 行注释操作
block = "gb", -- 块注释操作
},
extra = {
above = "gcO", -- 在当前行上方添加注释
below = "gco", -- 在当前行下方添加注释
eol = "gcA", -- 在当前行尾添加注释
},
mappings = {
basic = true, -- 基本映射
extra = true, -- 额外映射
},
},
keys = {
{ "gcc", mode = "n", desc = "行注释" },
{ "gbc", mode = "n", desc = "块注释" },
{ "gc", mode = { "n", "o" }, desc = "行注释操作" },
{ "gb", mode = { "n", "o" }, desc = "块注释操作" },
{ "<leader>xx", "<cmd>Trouble diagnostics toggle<cr>", desc = "诊断" },
{ "<leader>xX", "<cmd>Trouble diagnostics toggle filter.buf=0<cr>", desc = "当前文件诊断" },
{ "<leader>xL", "<cmd>Trouble loclist toggle<cr>", desc = "位置列表" },
{ "<leader>xQ", "<cmd>Trouble qflist toggle<cr>", desc = "快速修复" },
{ "<leader>xs", "<cmd>Trouble symbols toggle<cr>", 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 = {
{ "<leader>bd", function() require("mini.bufremove").delete(0, false) end, desc = "关闭缓冲区" },
{ "<leader>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 = "<M-e>" },
},
},
-- 高亮相同单词
{
"RRethy/vim-illuminate",
event = "BufReadPost",
opts = {
provider_selector = function()
return { "treesitter", "indent" }
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 = "<C-u>",
scrollD = "<C-d>",
jumpTop = "[",
jumpBot = "]",
},
win_config = { border = { "", "", "", "", "", "", "", "" }, winhighlight = "Normal:Folded", winblend = 0 },
mappings = { scrollU = "<C-u>", scrollD = "<C-d>", 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 {
{ "<leader>tf", "<cmd>ToggleTerm direction=float<cr>", desc = "浮动终端" },
{ "<leader>th", "<cmd>ToggleTerm direction=horizontal<cr>", desc = "水平终端" },
{ "<leader>tv", "<cmd>ToggleTerm direction=vertical size=40<cr>", desc = "垂直终端" },
{ "<leader>tt", "<cmd>ToggleTerm<cr>", desc = "切换终端" },
{ "<C-\\>", "<cmd>ToggleTerm<cr>", 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 = [[<c-\>]],
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 = {
{
"<tab>",
function()
return require("luasnip").jumpable(1) and "<Plug>luasnip-jump-next" or "<tab>"
end,
expr = true, silent = true, mode = "i",
},
{ "<tab>", function() require("luasnip").jump(1) end, mode = "s" },
{ "<s-tab>", function() require("luasnip").jump(-1) end, mode = { "i", "s" } },
{ "<leader>qs", function() require("persistence").load() end, desc = "恢复上次会话" },
{ "<leader>ql", function() require("persistence").load({ last = true }) end, desc = "恢复最后会话" },
{ "<leader>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 = "<M-e>",
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" }, "<leader>gs", ":Gitsigns stage_hunk<CR>", "暂存变更")
map({ "n", "v" }, "<leader>gr", ":Gitsigns reset_hunk<CR>", "重置变更")
map("n", "<leader>gS", gs.stage_buffer, "暂存文件")
map("n", "<leader>gu", gs.undo_stage_hunk, "取消暂存变更")
map("n", "<leader>gR", gs.reset_buffer, "重置文件")
map("n", "<leader>gp", gs.preview_hunk, "预览变更")
map("n", "<leader>gb", function() gs.blame_line({ full = true }) end, "查看责任")
map("n", "<leader>gB", gs.toggle_current_line_blame, "开关行责任")
map("n", "<leader>gd", gs.diffthis, "文件差异")
map("n", "<leader>gD", function() gs.diffthis("~") end, "与HEAD差异")
map("n", "<leader>gt", gs.toggle_deleted, "开关显示删除")
-- 文本对象
map({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>", "选择变更")
end,
},
},
-- 多光标编辑
-- 多光标(<C-n> 选择当前词,<C-Down/Up> 添加光标)
{
"mg979/vim-visual-multi",
event = "BufReadPost",
init = function()
vim.g.VM_leader = ";"
-- 使用默认 <C-n> 而非覆盖 <C-d><C-d> 已用于滚动)
vim.g.VM_maps = {
["Find Under"] = "<C-d>",
["Find Subword Under"] = "<C-d>",
["Find Under"] = "<C-n>",
["Find Subword Under"] = "<C-n>",
}
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" },
},
},
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)
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,
})
end,
keys = {
{ "]]", desc = "下一个引用" },
{ "[[", desc = "上一个引用" },
},
},
-- 缓冲区删除
-- 增强文本对象mini.ai
-- af/if=函数, ac/ic=类, aa/ia=参数, ab/ib=块, aq/iq=引号, at/it=标签
{
"echasnovski/mini.bufremove",
keys = {
{ "<leader>bd", function() require("mini.bufremove").delete(0, false) end, desc = "删除缓冲区" },
{ "<leader>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",
},
}
"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,
},
},
},
-- 括号/引号包围操作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 = {
{
"<leader>sr",
function()
local ext = vim.bo.filetype ~= "" and ("." .. vim.bo.filetype) or ""
require("grug-far").open({ prefills = { filesFilter = "*" .. ext } })
end,
mode = { "n", "v" },
desc = "搜索替换(项目范围)",
},
},
opts = { headerMaxWidth = 80 },
},
}

View File

@@ -1 +0,0 @@
return {"folke/flash.nvim", opts={}}

View File

@@ -0,0 +1,78 @@
-- formatting.lua - 代码格式化conform.nvim
return {
{
"stevearc/conform.nvim",
event = { "BufReadPre", "BufNewFile" },
cmd = { "ConformInfo" },
keys = {
{
"<leader>cf",
function()
require("conform").format({ async = true, lsp_format = "fallback" })
end,
mode = { "n", "v" },
desc = "格式化代码",
},
{
"<leader>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 = "切换当前缓冲区自动格式化",
},
{
"<leader>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,
},
},
}

View File

@@ -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", "<leader>gfs", "<cmd>GoFillStruct<cr>", "填充结构体")
map("n", "<leader>gfa", "<cmd>GoAddTag<cr>", "添加标签")
map("n", "<leader>gfr", "<cmd>GoRmTag<cr>", "移除标签")
map("n", "<leader>gcl", "<cmd>GoClearTag<cr>", "清除标签")
map("n", "<leader>ge", "<cmd>GoIfErr<cr>", "生成错误处理")
-- 代码生成
map("n", "<leader>ggt", "<cmd>GoTest<cr>", "生成测试")
map("n", "<leader>ggf", "<cmd>GoTestFunc<cr>", "生成函数测试")
map("n", "<leader>ggc", "<cmd>GoCoverage<cr>", "显示测试覆盖率")
map("n", "<leader>ggC", "<cmd>GoCoverageClear<cr>", "清除测试覆盖率")
map("n", "<leader>ggb", "<cmd>GoBuild<cr>", "构建")
map("n", "<leader>ggr", "<cmd>GoRun<cr>", "运行")
-- 代码操作
map("n", "<leader>gil", "<cmd>GoImport<cr>", "导入包")
map("n", "<leader>gia", "<cmd>GoImportAll<cr>", "导入所有")
map("n", "<leader>gif", "<cmd>GoImpl<cr>", "实现接口")
map("n", "<leader>gid", "<cmd>GoDoc<cr>", "查看文档")
-- 代码移动
map("n", "<leader>gca", "<cmd>GoCodeAction<cr>", "代码操作")
map("n", "<leader>gfd", "<cmd>GoFixDocumentation<cr>", "修复文档")
map("n", "<leader>gsf", "<cmd>GoFillSwitch<cr>", "填充 switch")
map("n", "<leader>gsj", "<cmd>GoAddErrCheck<cr>", "添加错误检查")
-- 调试和测试
map("n", "<leader>gtc", "<cmd>GoCmt<cr>", "生成注释")
map("n", "<leader>gts", "<cmd>GoAlt<cr>", "在实现和测试间切换")
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 = {
-- 测试
{ "<leader>gts", "<cmd>GoAlt<cr>", desc = "切换测试/实现文件" },
{ "<leader>gtt", "<cmd>GoTest<cr>", desc = "运行包测试" },
{ "<leader>gtf", "<cmd>GoTestFunc<cr>", desc = "测试函数" },
{ "<leader>gtc", "<cmd>GoCoverage<cr>", desc = "测试覆盖率" },
{ "<leader>gtC", "<cmd>GoCoverageClear<cr>", desc = "清除测试覆盖率" },
-- 格式化
{ "<leader>gff", "<cmd>GoFormat<cr>", desc = "格式化" },
{ "<leader>gfi", "<cmd>GoImport<cr>", desc = "导入" },
{ "<leader>gfI", "<cmd>GoImportAll<cr>", desc = "导入所有" },
-- 模板
{ "<leader>gge", "<cmd>GoIfErr<cr>", desc = "生成错误处理" },
{ "<leader>ggf", "<cmd>GoFillStruct<cr>", desc = "填充结构体" },
{ "<leader>ggs", "<cmd>GoFillSwitch<cr>", desc = "填充 switch" },
-- 标签
{ "<leader>gta", "<cmd>GoAddTag<cr>", desc = "添加标签" },
{ "<leader>gtr", "<cmd>GoRmTag<cr>", desc = "移除标签" },
{ "<leader>gtc", "<cmd>GoClearTag<cr>", desc = "清除标签" },
-- 运行和构建
{ "<leader>gr", "<cmd>GoRun<cr>", desc = "运行" },
{ "<leader>gb", "<cmd>GoBuild<cr>", desc = "构建" },
-- 工具
{ "<leader>gi", "<cmd>GoImpl<cr>", desc = "实现接口" },
{ "<leader>gd", "<cmd>GoDoc<cr>", desc = "查看文档" },
{ "<leader>gl", "<cmd>GoLint<cr>", desc = "运行 golint" },
{ "<leader>gv", "<cmd>GoVet<cr>", 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 = {
{ "<leader>dgr", function() require("dap-go").debug_test() end, desc = "调试当前测试" },
{ "<leader>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,
},
}

View File

@@ -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 = {
{ "<leader>gts", "<cmd>GoAlt<cr>", ft = "go", desc = "切换测试/实现" },
{ "<leader>gtt", "<cmd>GoTest<cr>", ft = "go", desc = "运行测试" },
{ "<leader>gtf", "<cmd>GoTestFunc<cr>", ft = "go", desc = "测试当前函数" },
{ "<leader>gtc", "<cmd>GoCoverage<cr>", ft = "go", desc = "测试覆盖率" },
{ "<leader>gtC", "<cmd>GoCoverageClear<cr>", ft = "go", desc = "清除覆盖率" },
{ "<leader>gge", "<cmd>GoIfErr<cr>", ft = "go", desc = "生成错误处理" },
{ "<leader>ggf", "<cmd>GoFillStruct<cr>", ft = "go", desc = "填充结构体" },
{ "<leader>ggs", "<cmd>GoFillSwitch<cr>", ft = "go", desc = "填充 switch" },
{ "<leader>gta", "<cmd>GoAddTag<cr>", ft = "go", desc = "添加标签" },
{ "<leader>gtr", "<cmd>GoRmTag<cr>", ft = "go", desc = "移除标签" },
{ "<leader>gr", "<cmd>GoRun<cr>", ft = "go", desc = "运行" },
{ "<leader>gb", "<cmd>GoBuild<cr>", ft = "go", desc = "构建" },
{ "<leader>gi", "<cmd>GoImpl<cr>", ft = "go", desc = "实现接口" },
{ "<leader>gdc", "<cmd>GoDoc<cr>", ft = "go", desc = "查看文档" },
{ "<leader>gv", "<cmd>GoVet<cr>", 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 = {
{ "<leader>dtg", function() require("dap-go").debug_test() end, ft = "go", desc = "调试当前测试" },
{ "<leader>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,
},
}

View File

@@ -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 = {
{ "<leader>pv", "<cmd>VenvSelect<cr>", 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 = {
{ "<leader>dpm", function() require("dap-python").test_method() end, ft = "python", desc = "调试当前方法" },
{ "<leader>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 = {
{ "<leader>pt", function() require("neotest").run.run() end, ft = "python", desc = "运行最近测试" },
{ "<leader>pT", function() require("neotest").run.run(vim.fn.expand("%")) end, ft = "python", desc = "运行文件测试" },
{ "<leader>pd", function() require("neotest").run.run({ strategy = "dap" }) end, ft = "python", desc = "调试测试" },
{ "<leader>ps", function() require("neotest").run.stop() end, ft = "python", desc = "停止测试" },
{ "<leader>po", function() require("neotest").output.open() end, ft = "python", desc = "测试输出" },
{ "<leader>pO", function() require("neotest").output_panel.toggle() end, ft = "python", desc = "输出面板" },
{ "<leader>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,
},
}

View File

@@ -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", "<leader>rr", function() vim.cmd.RustLsp("runnables") end, "Rust 运行目标")
map("n", "<leader>rt", function() vim.cmd.RustLsp("testables") end, "Rust 测试目标")
map("n", "<leader>rd", function() vim.cmd.RustLsp("debuggables") end, "Rust 调试目标")
map("n", "<leader>re", function() vim.cmd.RustLsp("explainError") end, "解释错误")
map("n", "<leader>rc", function() vim.cmd.RustLsp("openCargo") end, "打开 Cargo.toml")
map("n", "<leader>rp", function() vim.cmd.RustLsp("parentModule") end, "父模块")
map("n", "<leader>rm", function() vim.cmd.RustLsp("expandMacro") end, "展开宏")
map("n", "<leader>rx", function() vim.cmd.RustLsp("externalDocs") end, "外部文档")
map("n", "K", function() vim.cmd.RustLsp({ "hover", "actions" }) end, "悬浮操作")
map("n", "<leader>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 = {
{ "<leader>rcu", function() require("crates").upgrade_all_crates() end, ft = "toml", desc = "升级所有依赖" },
{ "<leader>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,
},
}

View File

@@ -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", "<leader>to", "<cmd>TSToolsOrganizeImports<cr>", "整理 Import")
map("n", "<leader>ta", "<cmd>TSToolsAddMissingImports<cr>", "添加缺失 Import")
map("n", "<leader>tu", "<cmd>TSToolsRemoveUnusedImports<cr>", "删除未使用 Import")
map("n", "<leader>tf", "<cmd>TSToolsFixAll<cr>", "修复所有")
map("n", "<leader>tr", "<cmd>TSToolsRenameFile<cr>", "重命名文件")
map("n", "<leader>tR", "<cmd>TSToolsFileReferences<cr>", "文件引用")
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-lspconfigmason 安装)
{
"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,
},
}

View File

@@ -1,6 +1,4 @@
-- lint.lua - 代码检查配置
-- 使用 nvim-lint 替代 null-ls 的诊断功能
-- 与 conform.nvim 配合conform 负责格式化lint 负责诊断
-- lint.lua - 代码静态检查nvim-lint
return {
{
@@ -9,70 +7,33 @@ return {
config = function()
local lint = require("lint")
-- 按文件类型配置 linter
lint.linters_by_ft = {
-- Python: 使用 ruff 替代 flake8/pylint
python = { "ruff" },
-- Lua
lua = { "luacheck" },
-- Go
lua = { "selene" },
go = { "golangcilint" },
-- JavaScript/TypeScript
javascript = { "eslint" },
typescript = { "eslint" },
javascriptreact = { "eslint" },
typescriptreact = { "eslint" },
-- 通用
javascript = { "eslint_d" },
typescript = { "eslint_d" },
javascriptreact = { "eslint_d" },
typescriptreact = { "eslint_d" },
markdown = { "markdownlint" },
yaml = { "yamllint" },
dockerfile = { "hadolint" },
sh = { "shellcheck" },
bash = { "shellcheck" },
}
-- 设置自动触发
local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true })
local lint_augroup = vim.api.nvim_create_augroup("nvim_lint", { clear = true })
-- 保存后检查
vim.api.nvim_create_autocmd({ "BufWritePost" }, {
vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost", "InsertLeave" }, {
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,
},
}

256
nvim/lua/plugins/lsp.lua Normal file
View File

@@ -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", "<C-k>", function() vim.lsp.buf.signature_help() end, "签名帮助")
-- 操作
map({ "n", "v" }, "<leader>ca", function() vim.lsp.buf.code_action() end, "代码操作")
map("n", "<leader>cr", function()
-- inc-rename 若已加载则使用增量重命名,否则回退到标准 LSP rename
local ok, inc = pcall(require, "inc_rename")
if ok then
return ":" .. inc.rename.cmd .. " " .. vim.fn.expand("<cword>")
end
vim.lsp.buf.rename()
end, "重命名")
map("n", "<leader>cl", "<cmd>LspInfo<cr>", "LSP 信息")
-- 诊断
map("n", "]d", function() vim.diagnostic.goto_next() end, "下一个诊断")
map("n", "[d", function() vim.diagnostic.goto_prev() end, "上一个诊断")
map("n", "<leader>cd", function() vim.diagnostic.open_float() end, "行诊断")
-- Inlay hints 切换
if client and client.supports_method("textDocument/inlayHint") then
map("n", "<leader>uh", function()
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = buf }), { bufnr = buf })
end, "切换 Inlay Hints")
end
end,
})
-- 构建 capabilitiesblink.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 = {},
},
}

View File

@@ -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,
},
}

View File

@@ -1,5 +0,0 @@
-- lua.lua - Lua 开发配置
return {
-- Lua 语言支持(已由 neodev 在 coding.lua 中配置)
}

View File

@@ -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,
},
},
}

View File

@@ -1 +0,0 @@
return {"folke/noice.nvim", opts={}}

View File

@@ -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,
},
}

View File

@@ -1,218 +0,0 @@
-- python.lua - Python 开发专用配置
return {
-- Python 专用插件
{
"linux-cultist/venv-selector.nvim",
cmd = "VenvSelect",
keys = {
{ "<leader>pv", "<cmd>VenvSelect<cr>", desc = "选择 Python 虚拟环境" },
{ "<leader>pc", "<cmd>VenvSelectCached<cr>", 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 = {
{ "<leader>pt", "<cmd>lua require('neotest').run.run()<cr>", desc = "运行最近的测试" },
{ "<leader>pT", "<cmd>lua require('neotest').run.run(vim.fn.expand('%'))<cr>", desc = "运行文件中的测试" },
{ "<leader>pd", "<cmd>lua require('neotest').run.run({strategy = 'dap'})<cr>", desc = "调试最近的测试" },
{ "<leader>ps", "<cmd>lua require('neotest').run.stop()<cr>", desc = "停止测试" },
{ "<leader>pa", "<cmd>lua require('neotest').run.attach()<cr>", desc = "附加到测试" },
{ "<leader>po", "<cmd>lua require('neotest').output.open()<cr>", desc = "查看测试输出" },
{ "<leader>pO", "<cmd>lua require('neotest').output_panel.toggle()<cr>", desc = "切换输出面板" },
{ "<leader>pS", "<cmd>lua require('neotest').summary.toggle()<cr>", 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 特定调试键
{ "<leader>dpr", function() require("dap-python").test_method() end, desc = "调试当前方法" },
{ "<leader>dpc", function() require("dap-python").test_class() end, desc = "调试当前类" },
{ "<leader>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 = {
{ "<leader>pe", "<cmd>SnipRun<cr>", desc = "执行选中代码", mode = { "n", "v" } },
{ "<leader>pE", "<cmd>SnipInfo<cr>", 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,
},
}

View File

@@ -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 = {
{ "<leader>un", function() Snacks.notifier.hide() end, desc = "Dismiss All Notifications" },
{ "<leader>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,
},
}

View File

@@ -1 +0,0 @@
return { "folke/todo-comments.nvim", opts = {} }

View File

@@ -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 = "<C-space>",
node_incremental = "<C-space>",
scope_incremental = false,
node_decremental = "<bs>",
},
},
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,
},
}

View File

@@ -1 +0,0 @@
return {"folke/trouble.nvim", opts={}}

View File

@@ -1 +0,0 @@
return {"folke/ts-comments.nvim", opts={}}

View File

@@ -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 = {
{ "<leader>un", function() Snacks.notifier.hide() end, desc = "清除通知" },
{ "<leader>nh", function() Snacks.notifier.show_history() end, desc = "通知历史" },
{ "<leader>nd", function() Snacks.notifier.hide() end, desc = "关闭所有通知" },
{ "]w", function() Snacks.words.jump(1) end, desc = "下一个引用词" },
{ "[w", function() Snacks.words.jump(-1) end, desc = "上一个引用词" },
{ "<leader>gg", function() Snacks.lazygit() end, desc = "LazyGit" },
{ "<leader>gf", function() Snacks.lazygit.log_file() end, desc = "当前文件 Git 历史" },
{ "<leader>gl", function() Snacks.lazygit.log() end, desc = "Git 日志" },
-- Snacks picker
{ "<leader>ff", function() Snacks.picker.files() end, desc = "查找文件" },
{ "<leader>fr", function() Snacks.picker.recent() end, desc = "最近文件" },
{ "<leader>fb", function() Snacks.picker.buffers() end, desc = "查找缓冲区" },
{ "<leader>fg", function() Snacks.picker.grep() end, desc = "全局搜索" },
{ "<leader>fw", function() Snacks.picker.grep_word() end, desc = "搜索当前单词", mode = { "n", "v" } },
{ "<leader>fh", function() Snacks.picker.help() end, desc = "帮助页面" },
{ "<leader>fk", function() Snacks.picker.keymaps() end, desc = "快捷键" },
{ "<leader>fs", function() Snacks.picker.lsp_symbols() end, desc = "文档符号" },
{ "<leader>fS", function() Snacks.picker.lsp_workspace_symbols() end, desc = "工作区符号" },
{ "<leader>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 = {
{ "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 } },
{ "progress", padding = { left = 1, right = 1 } },
{ "location", padding = { left = 0, right = 1 } },
},
lualine_z = {
function()
return " " .. os.date("%R")
end,
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",
opts = {
indent = {
char = "", -- 缩进字符
tab_char = "", -- Tab 缩进字符
"akinsho/bufferline.nvim",
event = "VeryLazy",
keys = {
{ "<leader>bp", "<Cmd>BufferLineTogglePin<CR>", desc = "标记缓冲区" },
{ "<leader>bP", "<Cmd>BufferLineGroupClose ungrouped<CR>", desc = "关闭未标记缓冲区" },
{ "<leader>bo", "<Cmd>BufferLineCloseOthers<CR>", desc = "关闭其他缓冲区" },
{ "<leader>br", "<Cmd>BufferLineCloseRight<CR>", desc = "关闭右侧缓冲区" },
{ "<leader>bl", "<Cmd>BufferLineCloseLeft<CR>", desc = "关闭左侧缓冲区" },
{ "<S-h>", "<cmd>BufferLineCyclePrev<cr>", desc = "上一个缓冲区" },
{ "<S-l>", "<cmd>BufferLineCycleNext<cr>", desc = "下一个缓冲区" },
},
scope = { enabled = false }, -- 禁用范围高亮
exclude = {
filetypes = {
"help",
"alpha",
"dashboard",
"neo-tree",
"Trouble",
"lazy",
"mason",
"notify",
"toggleterm",
"lazyterm",
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 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 = {
{ "<leader>e", "<cmd>Neotree toggle<cr>", desc = "切换文件浏览器" },
{ "<leader>e", "<cmd>Neotree toggle<cr>", desc = "文件浏览器" },
{ "<leader>o", "<cmd>Neotree focus<cr>", desc = "聚焦文件浏览器" },
{ "<leader>ge", "<cmd>Neotree float git_status<cr>", 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 = {
{ "<leader>bp", "<Cmd>BufferLineTogglePin<CR>", desc = "标记/取消标记缓冲区" },
{ "<leader>bP", "<Cmd>BufferLineGroupClose ungrouped<CR>", desc = "关闭未标记的缓冲区" },
{ "<leader>bo", "<Cmd>BufferLineCloseOthers<CR>", desc = "关闭其他缓冲区" },
{ "<leader>br", "<Cmd>BufferLineCloseRight<CR>", desc = "关闭右侧缓冲区" },
{ "<leader>bl", "<Cmd>BufferLineCloseLeft<CR>", desc = "关闭左侧缓冲区" },
{ "<S-h>", "<cmd>BufferLineCyclePrev<cr>", desc = "上一个缓冲区" },
{ "<S-l>", "<cmd>BufferLineCycleNext<cr>", 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 = {
{
"<leader>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,
},
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",
},
},
presets = {
operators = true, -- 添加操作符帮助
motions = true, -- 添加动作帮助
text_objects = true, -- 添加文本对象帮助
windows = true, -- 添加窗口帮助 (meta-w)
nav = true, -- 添加导航帮助
z = true, -- 添加折叠帮助
g = true, -- 添加 g 命令帮助
bottom_search = true,
command_palette = true,
long_message_to_split = true,
inc_rename = true,
},
},
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 = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "^:", "^ ", "^call ", "^lua " }, -- 隐藏的命令前缀
show_help = true, -- 显示帮助信息
triggers = "auto", -- 触发自动显示
triggers_nowait = { -- 不等待这些前缀的键映射
-- 字符表示操作符等待模式
"`",
"'",
"g`",
"g'",
'"',
"<c-r>",
"z=",
keys = {
{ "<leader>snl", function() require("noice").cmd("last") end, desc = "最后消息" },
{ "<leader>snh", function() require("noice").cmd("history") end, desc = "Noice 历史" },
{ "<leader>sna", function() require("noice").cmd("all") end, desc = "所有消息" },
},
},
-- 缩进线
{
"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",
},
},
},
config = function(_, opts)
local wk = require("which-key")
wk.setup(opts)
end,
},
}

View File

@@ -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 <CR>"),
dashboard.button("e", " 新文件", ":ene <BAR> startinsert <CR>"),
dashboard.button("r", " 最近文件", ":Telescope oldfiles <CR>"),
dashboard.button("g", " 查找文本", ":Telescope live_grep <CR>"),
dashboard.button("c", " 配置", ":e $MYVIMRC <CR>"),
dashboard.button("l", " 懒加载插件", ":Lazy<CR>"),
dashboard.button("q", " 退出", ":qa<CR>"),
}
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 = {
{ "<leader>fp", "<cmd>Telescope projects<cr>", 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",
["<CR>"] = "actions.select",
["<C-s>"] = "actions.select_vsplit",
["<C-h>"] = "actions.select_split",
["<C-t>"] = "actions.select_tab",
["<C-p>"] = "actions.preview",
["<C-c>"] = "actions.close",
["<C-l>"] = "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 = {
{ "-", "<cmd>Oil<cr>", desc = "打开父目录" },
{ "<leader>fo", "<cmd>Oil<cr>", desc = "打开文件浏览器" },
},
},
-- 自动调整窗口大小
{
"anuvyklack/windows.nvim",
event = "WinNew",
dependencies = {
{ "anuvyklack/middleclass" },
{ "anuvyklack/animation.nvim", enabled = true },
},
keys = {
{ "<leader>wm", "<cmd>WindowsMaximize<cr>", desc = "最大化窗口" },
{ "<leader>w=", "<cmd>WindowsEqualize<cr>", 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 = {
{ "<leader>qs", function() require("persistence").load() end, desc = "恢复上次会话" },
{ "<leader>ql", function() require("persistence").load({ last = true }) end, desc = "恢复最后会话" },
{ "<leader>qd", function() require("persistence").stop() end, desc = "不保存当前会话" },
},
},
-- 键位映射管理
{
"mrjones2014/legendary.nvim",
keys = {
{ "<leader>k", "<cmd>Legendary<cr>", desc = "键位映射查找器" },
},
opts = {
include_builtin = true,
include_legendary_cmds = true,
extensions = {
which_key = { auto_register = true },
smart_splits = { auto_register = true },
},
},
},
}

View File

@@ -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 = {
{ "<auto>", 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 = "<space>",
Tab = "<tab>",
Return = "<cr>",
Escape = "<esc>",
Backspace = "<bs>",
Delete = "<del>",
Insert = "<ins>",
Home = "<home>",
End = "<end>",
PageUp = "<pageup>",
PageDown = "<pagedown>",
ScrollLock = "<scrolllock>",
NumLock = "<numlock>",
CapsLock = "<capslock>",
Left = "<left>",
Right = "<right>",
Up = "<up>",
Down = "<down>",
F1 = "<f1>",
F2 = "<f2>",
F3 = "<f3>",
F4 = "<f4>",
F5 = "<f5>",
F6 = "<f6>",
F7 = "<f7>",
F8 = "<f8>",
F9 = "<f9>",
F10 = "<f10>",
F11 = "<f11>",
F12 = "<f12>",
Plug = "<plug>",
Action = "<action>",
Alt = "<a-",
Control = "<c-",
Meta = "<m-",
Shift = "<s-",
Super = "<d-",
Leader = "<leader>",
LocalLeader = "<localleader>",
},
},
-- 排序配置
sort = { "alphanum" },
-- 替换配置
replace = {
desc = {
{ "<Plug>%(?(.*)%)?", "%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({
-- 文件操作
{ "<leader>f", group = "文件/查找", icon = { icon = "📁", color = "blue" } },
-- Git 操作
{ "<leader>g", group = "Git", icon = { icon = "🌿", color = "green" } },
-- LSP/Code 操作
{ "<leader>c", group = "代码/LSP", icon = { icon = "💻", color = "cyan" } },
-- 诊断
{ "<leader>x", group = "诊断", icon = { icon = "🚨", color = "red" } },
-- 搜索
{ "<leader>s", group = "搜索", icon = { icon = "🔍", color = "yellow" } },
-- 终端
{ "<leader>t", group = "终端", icon = { icon = "🖥️", color = "purple" } },
-- 缓冲区
{ "<leader>b", group = "缓冲区", icon = { icon = "📋", color = "blue" } },
-- 通知
{ "<leader>u", group = "UI/通知", icon = { icon = "🎨", color = "purple" } },
-- AI 助手
{ "<leader>a", group = "AI 助手", icon = { icon = "🤖", color = "cyan" } },
-- Python
{ "<leader>p", group = "Python", icon = { icon = "🐍", color = "green" } },
-- 会话
{ "<leader>q", group = "会话/退出", icon = { icon = "🚪", color = "red" } },
-- 窗口
{ "<leader>w", group = "窗口", icon = { icon = "🪟", color = "blue" } },
})
end,
}