mirror of
https://github.com/d0zingcat/dotfiles.git
synced 2026-05-13 15:09:34 +00:00
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:
366
NVIM_GUIDE.md
Normal file
366
NVIM_GUIDE.md
Normal 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` | 选中 hunk(Visual/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 保存(跳过格式化)
|
||||
```
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
@@ -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 = "搜索单词" })
|
||||
map("n", "g/", "/\\<\\><Left><Left>", { desc = "搜索单词" })
|
||||
|
||||
@@ -21,8 +21,8 @@ vim.opt.rtp:prepend(lazypath)
|
||||
require("lazy").setup({
|
||||
-- 插件列表
|
||||
spec = {
|
||||
-- 导入插件模块
|
||||
{ import = "plugins" },
|
||||
{ import = "plugins.lang" },
|
||||
},
|
||||
|
||||
-- 默认配置
|
||||
|
||||
@@ -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
|
||||
|
||||
99
nvim/lua/plugins/blink.lua
Normal file
99
nvim/lua/plugins/blink.lua
Normal 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",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -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 = "下一个问题",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,101 +1,63 @@
|
||||
-- colorscheme.lua - 主题配置
|
||||
|
||||
return {
|
||||
-- 主题:Tokyo Night
|
||||
{
|
||||
"folke/tokyonight.nvim",
|
||||
lazy = false, -- 不延迟加载主题
|
||||
priority = 1000, -- 确保先加载主题
|
||||
config = function()
|
||||
require("tokyonight").setup({
|
||||
style = "night", -- 可选值:"storm", "moon", "night", "day"
|
||||
transparent = false, -- 启用背景透明
|
||||
terminal_colors = true, -- 设置终端颜色
|
||||
styles = {
|
||||
comments = { italic = true },
|
||||
keywords = { italic = true },
|
||||
functions = {},
|
||||
variables = {},
|
||||
sidebars = "dark",
|
||||
floats = "dark",
|
||||
},
|
||||
sidebars = { "qf", "help", "terminal", "packer", "NvimTree", "Trouble" },
|
||||
dim_inactive = false, -- 非活动窗口变暗
|
||||
lualine_bold = true, -- 在状态栏中使用粗体
|
||||
|
||||
on_highlights = function(hl, c)
|
||||
-- 自定义高亮组
|
||||
hl.CursorLineNr = { fg = c.orange, bold = true }
|
||||
hl.LineNr = { fg = c.orange, bold = false }
|
||||
hl.LineNrAbove = { fg = c.fg_gutter }
|
||||
hl.LineNrBelow = { fg = c.fg_gutter }
|
||||
|
||||
-- 浮动窗口
|
||||
hl.NormalFloat = { bg = c.bg_dark }
|
||||
hl.FloatBorder = { bg = c.bg_dark, fg = c.blue }
|
||||
end,
|
||||
})
|
||||
|
||||
-- 加载主题
|
||||
lazy = false,
|
||||
priority = 1000,
|
||||
opts = {
|
||||
style = "night",
|
||||
transparent = false,
|
||||
terminal_colors = true,
|
||||
styles = {
|
||||
comments = { italic = true },
|
||||
keywords = { italic = true },
|
||||
functions = {},
|
||||
variables = {},
|
||||
sidebars = "dark",
|
||||
floats = "dark",
|
||||
},
|
||||
sidebars = { "qf", "help", "terminal", "Trouble", "neo-tree" },
|
||||
dim_inactive = false,
|
||||
lualine_bold = true,
|
||||
on_highlights = function(hl, c)
|
||||
hl.CursorLineNr = { fg = c.orange, bold = true }
|
||||
hl.LineNr = { fg = c.orange, bold = false }
|
||||
hl.LineNrAbove = { fg = c.fg_gutter }
|
||||
hl.LineNrBelow = { fg = c.fg_gutter }
|
||||
hl.NormalFloat = { bg = c.bg_dark }
|
||||
hl.FloatBorder = { bg = c.bg_dark, fg = c.blue }
|
||||
end,
|
||||
},
|
||||
config = function(_, opts)
|
||||
require("tokyonight").setup(opts)
|
||||
vim.cmd.colorscheme("tokyonight")
|
||||
end
|
||||
end,
|
||||
},
|
||||
|
||||
-- 替代主题:Catppuccin
|
||||
|
||||
{
|
||||
"catppuccin/nvim",
|
||||
name = "catppuccin",
|
||||
lazy = true, -- 懒加载此主题
|
||||
lazy = true,
|
||||
opts = {
|
||||
flavour = "mocha", -- 风格: latte, frappe, macchiato, mocha
|
||||
flavour = "mocha",
|
||||
term_colors = true,
|
||||
transparent_background = false,
|
||||
styles = {
|
||||
comments = { "italic" },
|
||||
conditionals = { "italic" },
|
||||
loops = {},
|
||||
functions = {},
|
||||
keywords = {},
|
||||
strings = {},
|
||||
variables = {},
|
||||
numbers = {},
|
||||
booleans = {},
|
||||
properties = {},
|
||||
types = {},
|
||||
operators = {},
|
||||
},
|
||||
integrations = {
|
||||
cmp = true,
|
||||
gitsigns = true,
|
||||
nvimtree = true,
|
||||
treesitter = true,
|
||||
mason = true,
|
||||
telescope = {
|
||||
enabled = true,
|
||||
style = "nvchad",
|
||||
},
|
||||
native_lsp = {
|
||||
enabled = true,
|
||||
virtual_text = {
|
||||
errors = { "italic" },
|
||||
hints = { "italic" },
|
||||
warnings = { "italic" },
|
||||
information = { "italic" },
|
||||
},
|
||||
underlines = {
|
||||
errors = { "underline" },
|
||||
hints = { "underline" },
|
||||
warnings = { "underline" },
|
||||
information = { "underline" },
|
||||
},
|
||||
},
|
||||
telescope = { enabled = true },
|
||||
native_lsp = { enabled = true },
|
||||
blink_cmp = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- 图标支持
|
||||
|
||||
{
|
||||
"nvim-tree/nvim-web-devicons",
|
||||
lazy = true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,82 @@
|
||||
-- dap.lua - 调试支持
|
||||
-- dap.lua - 调试适配器协议(通用配置)
|
||||
|
||||
return {
|
||||
{
|
||||
"mfussenegger/nvim-dap",
|
||||
event = "VeryLazy",
|
||||
},
|
||||
{
|
||||
"leoluz/nvim-dap-go",
|
||||
ft = "go",
|
||||
dependencies = { "mfussenegger/nvim-dap" },
|
||||
dependencies = {
|
||||
{
|
||||
"rcarriga/nvim-dap-ui",
|
||||
dependencies = { "nvim-neotest/nvim-nio" },
|
||||
opts = {
|
||||
icons = { expanded = "▾", collapsed = "▸", current_frame = "▸" },
|
||||
layouts = {
|
||||
{
|
||||
elements = {
|
||||
{ id = "scopes", size = 0.25 },
|
||||
{ id = "breakpoints", size = 0.25 },
|
||||
{ id = "stacks", size = 0.25 },
|
||||
{ id = "watches", size = 0.25 },
|
||||
},
|
||||
size = 40,
|
||||
position = "left",
|
||||
},
|
||||
{
|
||||
elements = {
|
||||
{ id = "repl", size = 0.5 },
|
||||
{ id = "console", size = 0.5 },
|
||||
},
|
||||
size = 15,
|
||||
position = "bottom",
|
||||
},
|
||||
},
|
||||
floating = { border = "rounded" },
|
||||
},
|
||||
config = function(_, opts)
|
||||
local dap = require("dap")
|
||||
local dapui = require("dapui")
|
||||
dapui.setup(opts)
|
||||
dap.listeners.after.event_initialized["dapui_config"] = dapui.open
|
||||
dap.listeners.before.event_terminated["dapui_config"] = dapui.close
|
||||
dap.listeners.before.event_exited["dapui_config"] = dapui.close
|
||||
end,
|
||||
},
|
||||
{
|
||||
"theHamsta/nvim-dap-virtual-text",
|
||||
opts = { commented = true },
|
||||
},
|
||||
},
|
||||
keys = {
|
||||
{ "<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-go").setup()
|
||||
end,
|
||||
},
|
||||
{
|
||||
"mfussenegger/nvim-dap-python",
|
||||
ft = "python",
|
||||
dependencies = { "mfussenegger/nvim-dap" },
|
||||
config = function()
|
||||
require("dap-python").setup("python")
|
||||
vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" })
|
||||
local signs = {
|
||||
Stopped = { " ", "DiagnosticWarn", "DapStoppedLine" },
|
||||
Breakpoint = " ",
|
||||
BreakpointCondition = " ",
|
||||
BreakpointRejected = { " ", "DiagnosticError" },
|
||||
LogPoint = ".>",
|
||||
}
|
||||
for name, sign in pairs(signs) do
|
||||
sign = type(sign) == "table" and sign or { sign }
|
||||
vim.fn.sign_define("Dap" .. name, {
|
||||
text = sign[1],
|
||||
texthl = sign[2] or "DiagnosticInfo",
|
||||
linehl = sign[3],
|
||||
numhl = sign[3],
|
||||
})
|
||||
end
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
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 配置" },
|
||||
"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({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>", "选择变更")
|
||||
end,
|
||||
},
|
||||
},
|
||||
|
||||
-- 高级语法高亮
|
||||
-- 快速跳转
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
build = ":TSUpdate",
|
||||
event = { "BufReadPost", "BufNewFile" },
|
||||
dependencies = {
|
||||
"nvim-treesitter/nvim-treesitter-textobjects",
|
||||
},
|
||||
"folke/flash.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = {
|
||||
-- 自动安装的语法
|
||||
ensure_installed = {
|
||||
"bash",
|
||||
"c",
|
||||
"cmake",
|
||||
"comment",
|
||||
"cpp",
|
||||
"css",
|
||||
"dockerfile",
|
||||
"gitignore",
|
||||
"go",
|
||||
"gomod",
|
||||
"gowork",
|
||||
"html",
|
||||
"http",
|
||||
"java",
|
||||
"javascript",
|
||||
"json",
|
||||
"kotlin",
|
||||
"lua",
|
||||
"make",
|
||||
"markdown",
|
||||
"markdown_inline",
|
||||
"python",
|
||||
"regex",
|
||||
"ruby",
|
||||
"rust",
|
||||
"sql",
|
||||
"toml",
|
||||
"tsx",
|
||||
"typescript",
|
||||
"vim",
|
||||
"vimdoc",
|
||||
"xml",
|
||||
"yaml",
|
||||
},
|
||||
|
||||
-- 启用特性
|
||||
highlight = { enable = true },
|
||||
indent = { enable = true },
|
||||
incremental_selection = {
|
||||
enable = true,
|
||||
keymaps = {
|
||||
init_selection = "<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",
|
||||
},
|
||||
},
|
||||
search = { multi_window = false, wrap = true },
|
||||
modes = { char = { enabled = true, keys = { "f", "F", "t", "T", ";", "," } } },
|
||||
},
|
||||
keys = {
|
||||
{ "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash 跳转" },
|
||||
{ "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
|
||||
{ "r", mode = "o", function() require("flash").remote() end, desc = "Flash 远程" },
|
||||
{ "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Flash Treesitter 搜索" },
|
||||
},
|
||||
},
|
||||
|
||||
-- TODO 注释高亮
|
||||
{
|
||||
"folke/todo-comments.nvim",
|
||||
dependencies = { "nvim-lua/plenary.nvim" },
|
||||
event = "BufReadPost",
|
||||
opts = { signs = true },
|
||||
keys = {
|
||||
{ "]t", function() require("todo-comments").jump_next() end, desc = "下一个 TODO" },
|
||||
{ "[t", function() require("todo-comments").jump_prev() end, desc = "上一个 TODO" },
|
||||
{ "<leader>ft", "<cmd>TodoTelescope<cr>", desc = "TODO 列表" },
|
||||
},
|
||||
},
|
||||
|
||||
-- which-key 按键提示
|
||||
{
|
||||
"folke/which-key.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = {
|
||||
plugins = {
|
||||
marks = true, registers = true,
|
||||
spelling = { enabled = true, suggestions = 20 },
|
||||
presets = { operators = true, motions = true, text_objects = true, windows = true, nav = true, z = true, g = true },
|
||||
},
|
||||
icons = { breadcrumb = "»", separator = "➜", group = "+" },
|
||||
win = { border = "rounded" },
|
||||
show_help = true,
|
||||
},
|
||||
config = function(_, opts)
|
||||
require("nvim-treesitter.configs").setup(opts)
|
||||
local wk = require("which-key")
|
||||
wk.setup(opts)
|
||||
wk.add({
|
||||
{ "<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", -- 块注释切换
|
||||
},
|
||||
opleader = {
|
||||
line = "gc", -- 行注释操作
|
||||
block = "gb", -- 块注释操作
|
||||
},
|
||||
extra = {
|
||||
above = "gcO", -- 在当前行上方添加注释
|
||||
below = "gco", -- 在当前行下方添加注释
|
||||
eol = "gcA", -- 在当前行尾添加注释
|
||||
},
|
||||
mappings = {
|
||||
basic = true, -- 基本映射
|
||||
extra = true, -- 额外映射
|
||||
modes = {
|
||||
lsp = {
|
||||
win = { position = "right" },
|
||||
},
|
||||
},
|
||||
},
|
||||
keys = {
|
||||
{ "gcc", mode = "n", desc = "行注释" },
|
||||
{ "gbc", mode = "n", desc = "块注释" },
|
||||
{ "gc", mode = { "n", "o" }, desc = "行注释操作" },
|
||||
{ "gb", mode = { "n", "o" }, desc = "块注释操作" },
|
||||
{ "<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" }
|
||||
end,
|
||||
delay = 200,
|
||||
large_file_cutoff = 2000,
|
||||
large_file_overrides = { providers = { "lsp" } },
|
||||
},
|
||||
config = function(_, opts)
|
||||
require("illuminate").configure(opts)
|
||||
local function map(key, dir, buffer)
|
||||
vim.keymap.set("n", key, function()
|
||||
require("illuminate")["goto_" .. dir .. "_reference"](false)
|
||||
end, { desc = dir .. " 引用", buffer = buffer })
|
||||
end
|
||||
map("]]", "next")
|
||||
map("[[", "prev")
|
||||
vim.api.nvim_create_autocmd("LspAttach", {
|
||||
callback = function(args)
|
||||
map("]]", "next", args.buf)
|
||||
map("[[", "prev", args.buf)
|
||||
end,
|
||||
})
|
||||
end,
|
||||
keys = { { "]]", desc = "下一个引用" }, { "[[", desc = "上一个引用" } },
|
||||
},
|
||||
|
||||
-- 代码折叠(基于 LSP/treesitter)
|
||||
{
|
||||
"kevinhwang91/nvim-ufo",
|
||||
dependencies = { "kevinhwang91/promise-async" },
|
||||
event = "BufReadPost",
|
||||
opts = {
|
||||
provider_selector = function() return { "treesitter", "indent" } end,
|
||||
open_fold_hl_timeout = 150,
|
||||
close_fold_kinds_for_ft = {},
|
||||
preview = {
|
||||
win_config = {
|
||||
border = { "", "─", "", "", "", "─", "", "" },
|
||||
winhighlight = "Normal:Folded",
|
||||
winblend = 0,
|
||||
},
|
||||
mappings = {
|
||||
scrollU = "<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" },
|
||||
padding = true,
|
||||
sticky = true,
|
||||
toggler = { line = "gcc", block = "gbc" },
|
||||
opleader = { line = "gc", block = "gb" },
|
||||
extra = { above = "gcO", below = "gco", eol = "gcA" },
|
||||
pre_hook = function()
|
||||
return require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook()()
|
||||
end,
|
||||
},
|
||||
},
|
||||
|
||||
-- 增强文本对象(mini.ai)
|
||||
-- af/if=函数, ac/ic=类, aa/ia=参数, ab/ib=块, aq/iq=引号, at/it=标签
|
||||
{
|
||||
"echasnovski/mini.ai",
|
||||
event = "VeryLazy",
|
||||
opts = {
|
||||
n_lines = 500,
|
||||
custom_textobjects = {
|
||||
-- 整个文件
|
||||
e = function()
|
||||
local from = { line = 1, col = 1 }
|
||||
local to = { line = vim.fn.line("$"), col = math.max(vim.fn.getline("$"):len(), 1) }
|
||||
return { from = from, to = to }
|
||||
end,
|
||||
},
|
||||
},
|
||||
config = function(_, opts)
|
||||
require("illuminate").configure(opts)
|
||||
|
||||
local function map(key, dir, buffer)
|
||||
vim.keymap.set("n", key, function()
|
||||
require("illuminate")["goto_" .. dir .. "_reference"](false)
|
||||
end, { desc = dir:sub(1, 1):upper() .. dir:sub(2) .. " 引用", buffer = buffer })
|
||||
end
|
||||
|
||||
-- 下一个/上一个引用导航
|
||||
map("]]", "next")
|
||||
map("[[", "prev")
|
||||
|
||||
-- 同时也是 LSP 附加时设置键绑定
|
||||
vim.api.nvim_create_autocmd("LspAttach", {
|
||||
callback = function(args)
|
||||
local buffer = args.buf
|
||||
map("]]", "next", buffer)
|
||||
map("[[", "prev", buffer)
|
||||
},
|
||||
|
||||
-- 括号/引号包围操作(mini.surround)
|
||||
-- saiw" = 用 " 包围单词, sd" = 删除 ", sr"' = 替换 " 为 '
|
||||
{
|
||||
"echasnovski/mini.surround",
|
||||
event = "VeryLazy",
|
||||
opts = {
|
||||
mappings = {
|
||||
add = "gsa", -- 添加包围
|
||||
delete = "gsd", -- 删除包围
|
||||
find = "gsf", -- 向前查找包围
|
||||
find_left = "gsF", -- 向后查找包围
|
||||
highlight = "gsh", -- 高亮包围
|
||||
replace = "gsr", -- 替换包围
|
||||
update_n_lines = "gsn", -- 更新搜索范围
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- 项目范围搜索替换(grug-far)
|
||||
{
|
||||
"MagicDuck/grug-far.nvim",
|
||||
cmd = "GrugFar",
|
||||
keys = {
|
||||
{
|
||||
"<leader>sr",
|
||||
function()
|
||||
local ext = vim.bo.filetype ~= "" and ("." .. vim.bo.filetype) or ""
|
||||
require("grug-far").open({ prefills = { filesFilter = "*" .. ext } })
|
||||
end,
|
||||
})
|
||||
end,
|
||||
keys = {
|
||||
{ "]]", desc = "下一个引用" },
|
||||
{ "[[", desc = "上一个引用" },
|
||||
mode = { "n", "v" },
|
||||
desc = "搜索替换(项目范围)",
|
||||
},
|
||||
},
|
||||
opts = { headerMaxWidth = 80 },
|
||||
},
|
||||
|
||||
-- 缓冲区删除
|
||||
{
|
||||
"echasnovski/mini.bufremove",
|
||||
keys = {
|
||||
{ "<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",
|
||||
},
|
||||
}
|
||||
end,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
return {"folke/flash.nvim", opts={}}
|
||||
78
nvim/lua/plugins/formatting.lua
Normal file
78
nvim/lua/plugins/formatting.lua
Normal 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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
121
nvim/lua/plugins/lang/go.lua
Normal file
121
nvim/lua/plugins/lang/go.lua
Normal 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,
|
||||
},
|
||||
}
|
||||
95
nvim/lua/plugins/lang/python.lua
Normal file
95
nvim/lua/plugins/lang/python.lua
Normal 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,
|
||||
},
|
||||
}
|
||||
111
nvim/lua/plugins/lang/rust.lua
Normal file
111
nvim/lua/plugins/lang/rust.lua
Normal 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,
|
||||
},
|
||||
}
|
||||
99
nvim/lua/plugins/lang/typescript.lua
Normal file
99
nvim/lua/plugins/lang/typescript.lua
Normal 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-lspconfig,mason 安装)
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
optional = true,
|
||||
opts = {
|
||||
servers = {
|
||||
eslint = {
|
||||
settings = {
|
||||
workingDirectories = { mode = "auto" },
|
||||
format = false, -- 格式化由 prettier 处理
|
||||
},
|
||||
on_attach = function(_, bufnr)
|
||||
vim.api.nvim_create_autocmd("BufWritePre", {
|
||||
buffer = bufnr,
|
||||
command = "EslintFixAll",
|
||||
})
|
||||
end,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- Mason TypeScript 工具
|
||||
{
|
||||
"williamboman/mason.nvim",
|
||||
optional = true,
|
||||
opts = function(_, opts)
|
||||
opts.ensure_installed = opts.ensure_installed or {}
|
||||
vim.list_extend(opts.ensure_installed, {
|
||||
"typescript-language-server", "eslint-lsp", "prettierd",
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
||||
-- Treesitter TypeScript/JSX
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
optional = true,
|
||||
opts = function(_, opts)
|
||||
opts.ensure_installed = opts.ensure_installed or {}
|
||||
vim.list_extend(opts.ensure_installed, {
|
||||
"javascript", "typescript", "tsx", "jsdoc",
|
||||
})
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -1,78 +1,39 @@
|
||||
-- lint.lua - 代码检查配置
|
||||
-- 使用 nvim-lint 替代 null-ls 的诊断功能
|
||||
-- 与 conform.nvim 配合:conform 负责格式化,lint 负责诊断
|
||||
-- lint.lua - 代码静态检查(nvim-lint)
|
||||
|
||||
return {
|
||||
{
|
||||
"mfussenegger/nvim-lint",
|
||||
event = { "BufReadPre", "BufNewFile" },
|
||||
config = function()
|
||||
local lint = require("lint")
|
||||
{
|
||||
"mfussenegger/nvim-lint",
|
||||
event = { "BufReadPre", "BufNewFile" },
|
||||
config = function()
|
||||
local lint = require("lint")
|
||||
|
||||
-- 按文件类型配置 linter
|
||||
lint.linters_by_ft = {
|
||||
-- Python: 使用 ruff 替代 flake8/pylint
|
||||
python = { "ruff" },
|
||||
lint.linters_by_ft = {
|
||||
python = { "ruff" },
|
||||
lua = { "selene" },
|
||||
go = { "golangcilint" },
|
||||
javascript = { "eslint_d" },
|
||||
typescript = { "eslint_d" },
|
||||
javascriptreact = { "eslint_d" },
|
||||
typescriptreact = { "eslint_d" },
|
||||
markdown = { "markdownlint" },
|
||||
yaml = { "yamllint" },
|
||||
dockerfile = { "hadolint" },
|
||||
sh = { "shellcheck" },
|
||||
bash = { "shellcheck" },
|
||||
}
|
||||
|
||||
-- Lua
|
||||
lua = { "luacheck" },
|
||||
local lint_augroup = vim.api.nvim_create_augroup("nvim_lint", { clear = true })
|
||||
|
||||
-- Go
|
||||
go = { "golangcilint" },
|
||||
vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost", "InsertLeave" }, {
|
||||
group = lint_augroup,
|
||||
callback = function()
|
||||
lint.try_lint()
|
||||
end,
|
||||
})
|
||||
|
||||
-- JavaScript/TypeScript
|
||||
javascript = { "eslint" },
|
||||
typescript = { "eslint" },
|
||||
javascriptreact = { "eslint" },
|
||||
typescriptreact = { "eslint" },
|
||||
|
||||
-- 通用
|
||||
markdown = { "markdownlint" },
|
||||
yaml = { "yamllint" },
|
||||
dockerfile = { "hadolint" },
|
||||
sh = { "shellcheck" },
|
||||
}
|
||||
|
||||
-- 设置自动触发
|
||||
local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true })
|
||||
|
||||
-- 保存后检查
|
||||
vim.api.nvim_create_autocmd({ "BufWritePost" }, {
|
||||
group = lint_augroup,
|
||||
callback = function()
|
||||
lint.try_lint()
|
||||
end,
|
||||
})
|
||||
|
||||
-- 进入缓冲区时检查
|
||||
vim.api.nvim_create_autocmd({ "BufEnter" }, {
|
||||
group = lint_augroup,
|
||||
callback = function()
|
||||
lint.try_lint()
|
||||
end,
|
||||
})
|
||||
|
||||
-- 插入模式离开后检查(可选,可能较频繁)
|
||||
vim.api.nvim_create_autocmd({ "InsertLeave" }, {
|
||||
group = lint_augroup,
|
||||
callback = function()
|
||||
lint.try_lint()
|
||||
end,
|
||||
})
|
||||
|
||||
-- 创建用户命令
|
||||
vim.api.nvim_create_user_command("Lint", function()
|
||||
lint.try_lint()
|
||||
end, { desc = "手动触发代码检查" })
|
||||
|
||||
vim.api.nvim_create_user_command("LintInfo", function()
|
||||
local running_linters = lint.get_running()
|
||||
if #running_linters == 0 then
|
||||
vim.notify("没有正在运行的 linter", vim.log.levels.INFO)
|
||||
else
|
||||
vim.notify("运行中的 linter: " .. table.concat(running_linters, ", "), vim.log.levels.INFO)
|
||||
end
|
||||
end, { desc = "显示运行中的 linter" })
|
||||
end,
|
||||
},
|
||||
vim.api.nvim_create_user_command("Lint", function()
|
||||
lint.try_lint()
|
||||
end, { desc = "手动触发代码检查" })
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
256
nvim/lua/plugins/lsp.lua
Normal file
256
nvim/lua/plugins/lsp.lua
Normal 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,
|
||||
})
|
||||
|
||||
-- 构建 capabilities(blink.cmp 提供)
|
||||
local capabilities = require("blink.cmp").get_lsp_capabilities()
|
||||
|
||||
-- 通过 mason-lspconfig 自动启动服务器
|
||||
require("mason-lspconfig").setup_handlers({
|
||||
function(server)
|
||||
local server_opts = vim.tbl_deep_extend("force", {
|
||||
capabilities = vim.deepcopy(capabilities),
|
||||
}, opts.servers[server] or {})
|
||||
|
||||
-- Rust 由 rustaceanvim 接管,跳过
|
||||
if server == "rust_analyzer" then return end
|
||||
-- TypeScript 由 typescript-tools.nvim 接管,跳过
|
||||
if server == "ts_ls" or server == "tsserver" then return end
|
||||
|
||||
require("lspconfig")[server].setup(server_opts)
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
||||
-- JSON Schema Store(可选,供 jsonls 使用)
|
||||
{ "b0o/SchemaStore.nvim", lazy = true },
|
||||
|
||||
-- 增量重命名(在命令行实时预览)
|
||||
{
|
||||
"smjonas/inc-rename.nvim",
|
||||
cmd = "IncRename",
|
||||
opts = {},
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
-- lua.lua - Lua 开发配置
|
||||
|
||||
return {
|
||||
-- Lua 语言支持(已由 neodev 在 coding.lua 中配置)
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
return {"folke/noice.nvim", opts={}}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
return { "folke/todo-comments.nvim", opts = {} }
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
return {"folke/trouble.nvim", opts={}}
|
||||
@@ -1 +0,0 @@
|
||||
return {"folke/ts-comments.nvim", opts={}}
|
||||
@@ -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 = {
|
||||
lualine_b = {
|
||||
{ "branch", icon = "" },
|
||||
{
|
||||
"diff",
|
||||
symbols = { added = " ", modified = " ", removed = " " },
|
||||
colored = true
|
||||
}
|
||||
{ "diff", symbols = { added = " ", modified = " ", removed = " " } },
|
||||
},
|
||||
lualine_c = {
|
||||
{
|
||||
"diagnostics",
|
||||
sources = { "nvim_diagnostic" },
|
||||
symbols = {
|
||||
error = " ",
|
||||
warn = " ",
|
||||
info = " ",
|
||||
hint = " ",
|
||||
},
|
||||
symbols = { error = " ", warn = " ", info = " ", hint = " " },
|
||||
},
|
||||
{ "filetype", icon_only = true, separator = "", padding = { left = 1, right = 0 } },
|
||||
{ "filename", path = 1, symbols = { modified = " ", readonly = " ", unnamed = " " } },
|
||||
},
|
||||
lualine_x = {
|
||||
-- Git 文件状态
|
||||
{
|
||||
function()
|
||||
local status = ""
|
||||
local ft = vim.bo.filetype
|
||||
|
||||
-- 检查 LSP 是否连接
|
||||
local clients = vim.lsp.get_active_clients({ bufnr = 0 })
|
||||
if #clients > 0 then
|
||||
status = status .. " LSP"
|
||||
end
|
||||
|
||||
return status
|
||||
local clients = vim.lsp.get_clients({ bufnr = 0 })
|
||||
if #clients == 0 then return "" end
|
||||
local names = vim.tbl_map(function(c) return c.name end, clients)
|
||||
return " " .. table.concat(names, ", ")
|
||||
end,
|
||||
},
|
||||
{ "encoding" },
|
||||
@@ -62,49 +130,47 @@ return {
|
||||
{ "filetype" },
|
||||
},
|
||||
lualine_y = {
|
||||
{ "progress", separator = " ", padding = { left = 1, right = 1 } },
|
||||
{ "location", padding = { left = 1, right = 1 } },
|
||||
},
|
||||
lualine_z = {
|
||||
function()
|
||||
return " " .. os.date("%R")
|
||||
end,
|
||||
{ "progress", padding = { left = 1, right = 1 } },
|
||||
{ "location", padding = { left = 0, right = 1 } },
|
||||
},
|
||||
lualine_z = { function() return " " .. os.date("%R") end },
|
||||
},
|
||||
tabline = {},
|
||||
extensions = { "neo-tree", "lazy" },
|
||||
extensions = { "neo-tree", "lazy", "toggleterm", "mason" },
|
||||
},
|
||||
},
|
||||
|
||||
-- 缩进线
|
||||
|
||||
-- 缓冲区标签页
|
||||
{
|
||||
"lukas-reineke/indent-blankline.nvim",
|
||||
main = "ibl",
|
||||
event = "BufReadPost",
|
||||
"akinsho/bufferline.nvim",
|
||||
event = "VeryLazy",
|
||||
keys = {
|
||||
{ "<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 = {
|
||||
indent = {
|
||||
char = "│", -- 缩进字符
|
||||
tab_char = "│", -- Tab 缩进字符
|
||||
},
|
||||
scope = { enabled = false }, -- 禁用范围高亮
|
||||
exclude = {
|
||||
filetypes = {
|
||||
"help",
|
||||
"alpha",
|
||||
"dashboard",
|
||||
"neo-tree",
|
||||
"Trouble",
|
||||
"lazy",
|
||||
"mason",
|
||||
"notify",
|
||||
"toggleterm",
|
||||
"lazyterm",
|
||||
options = {
|
||||
close_command = function(n) require("mini.bufremove").delete(n, false) end,
|
||||
right_mouse_command = function(n) require("mini.bufremove").delete(n, false) end,
|
||||
diagnostics = "nvim_lsp",
|
||||
always_show_bufferline = false,
|
||||
diagnostics_indicator = function(_, _, diag)
|
||||
local ret = (diag.error and " " .. diag.error .. " " or "")
|
||||
.. (diag.warning and " " .. diag.warning or "")
|
||||
return vim.trim(ret)
|
||||
end,
|
||||
offsets = {
|
||||
{ filetype = "neo-tree", text = "文件浏览器", highlight = "Directory", text_align = "left" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- 文件树
|
||||
|
||||
-- 文件树(侧边栏)
|
||||
{
|
||||
"nvim-neo-tree/neo-tree.nvim",
|
||||
branch = "v3.x",
|
||||
@@ -115,20 +181,21 @@ return {
|
||||
"MunifTanjim/nui.nvim",
|
||||
},
|
||||
keys = {
|
||||
{ "<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,
|
||||
},
|
||||
presets = {
|
||||
operators = true, -- 添加操作符帮助
|
||||
motions = true, -- 添加动作帮助
|
||||
text_objects = true, -- 添加文本对象帮助
|
||||
windows = true, -- 添加窗口帮助 (meta-w)
|
||||
nav = true, -- 添加导航帮助
|
||||
z = true, -- 添加折叠帮助
|
||||
g = true, -- 添加 g 命令帮助
|
||||
hover = { enabled = true },
|
||||
signature = { enabled = false }, -- blink.cmp 处理签名
|
||||
progress = { enabled = true, format_done = "" },
|
||||
},
|
||||
routes = {
|
||||
{
|
||||
-- 屏蔽 treesitter query 字段兼容性警告(Neovim 0.12 校验更严格,功能不受影响)
|
||||
filter = {
|
||||
event = "msg_show",
|
||||
any = {
|
||||
{ find = "Invalid field name" },
|
||||
{ find = "Invalid node type" },
|
||||
{ find = "Query error" },
|
||||
},
|
||||
},
|
||||
opts = { skip = true },
|
||||
},
|
||||
{
|
||||
filter = {
|
||||
event = "msg_show",
|
||||
any = {
|
||||
{ find = "%d+L, %d+B" },
|
||||
{ find = "; after #%d+" },
|
||||
{ find = "; before #%d+" },
|
||||
},
|
||||
},
|
||||
view = "mini",
|
||||
},
|
||||
},
|
||||
icons = {
|
||||
breadcrumb = "»", -- 面包屑分隔符
|
||||
separator = "➜", -- 键映射前缀和命令之间的分隔符
|
||||
group = "+", -- 组图标
|
||||
},
|
||||
window = {
|
||||
border = "rounded", -- 边框样式
|
||||
position = "bottom", -- 位置
|
||||
margin = { 1, 0, 1, 0 }, -- 边距
|
||||
padding = { 1, 1, 1, 1 }, -- 内边距
|
||||
},
|
||||
layout = {
|
||||
height = { min = 3, max = 25 }, -- 最小和最大高度
|
||||
width = { min = 20, max = 50 }, -- 最小和最大宽度
|
||||
spacing = 3, -- 间距
|
||||
align = "center", -- 对齐方式
|
||||
},
|
||||
ignore_missing = false, -- 不忽略缺少的键映射
|
||||
hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "^:", "^ ", "^call ", "^lua " }, -- 隐藏的命令前缀
|
||||
show_help = true, -- 显示帮助信息
|
||||
triggers = "auto", -- 触发自动显示
|
||||
triggers_nowait = { -- 不等待这些前缀的键映射
|
||||
-- 字符表示操作符等待模式
|
||||
"`",
|
||||
"'",
|
||||
"g`",
|
||||
"g'",
|
||||
'"',
|
||||
"<c-r>",
|
||||
"z=",
|
||||
presets = {
|
||||
bottom_search = true,
|
||||
command_palette = true,
|
||||
long_message_to_split = true,
|
||||
inc_rename = true,
|
||||
},
|
||||
},
|
||||
config = function(_, opts)
|
||||
local wk = require("which-key")
|
||||
wk.setup(opts)
|
||||
end,
|
||||
keys = {
|
||||
{ "<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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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 },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
Reference in New Issue
Block a user