W10: 结构化导航
引入 Treesitter 语法树高亮与 Telescope 异步模糊搜索系统, 重塑全域精确导航体验.
1. Treesitter: 语法树革命
传统的高亮基于脆弱的 Regex. nvim-treesitter 将代码实时解析为抽象语法树 (AST).
1.1 Treesitter 带来的变革
| 特性 | 传统正则 | Treesitter |
|---|---|---|
| 高亮准确性 | 猜测 | 精确语义 |
| 缩进 | 基于字符 | 基于语法结构 |
| 文本对象 | 固定 | 可按函数/类选择 |
| 性能 | 中等 | 增量解析, 极快 |
1.2 安装配置
-- plugins/treesitter.lua
return {
{
"nvim-treesitter/nvim-treesitter",
build = ":TSUpdate",
event = { "BufReadPre", "BufNewFile" },
dependencies = {
"nvim-treesitter/nvim-treesitter-textobjects",
},
config = function()
require("nvim-treesitter.configs").setup({
ensure_installed = {
"lua", "vim", "vimdoc",
"go", "python", "rust", "javascript", "typescript",
"json", "yaml", "toml", "markdown", "markdown_inline",
"bash", "dockerfile", "sql",
},
auto_install = true,
highlight = {
enable = true,
additional_vim_regex_highlighting = false,
},
indent = {
enable = true,
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = "<C-space>",
node_incremental = "<C-space>",
node_decremental = "<BS>",
scope_incremental = false,
},
},
})
end,
},
}1.3 增量选择
基于语法逻辑智能扩展选择范围:
光标在变量上:
按 <C-space> → 选中变量
再按 <C-space> → 选中表达式
再按 <C-space> → 选中语句
再按 <C-space> → 选中函数体
按 <BS> → 缩小选择1.4 Treesitter 文本对象
-- 配置 textobjects
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",
["al"] = "@loop.outer", -- 选中循环
["il"] = "@loop.inner",
["ai"] = "@conditional.outer", -- 选中条件语句
["ii"] = "@conditional.inner",
},
},
move = {
enable = true,
set_jumps = true,
goto_next_start = {
["]f"] = "@function.outer",
["]c"] = "@class.outer",
},
goto_previous_start = {
["[f"] = "@function.outer",
["[c"] = "@class.outer",
},
},
swap = {
enable = true,
swap_next = {
["<leader>a"] = "@parameter.inner",
},
swap_previous = {
["<leader>A"] = "@parameter.inner",
},
},
},使用示例:
daf " 删除整个函数
cif " 修改函数体
vac " 选中整个类
yia " 复制参数
]f " 跳到下一个函数
[c " 跳到上一个类
<leader>a " 交换参数位置2. Telescope: 模糊搜索中心
在现代架构中, 我们不再手动翻找目录, 而是使用 Telescope 进行模糊匹配.
2.1 安装配置
-- plugins/telescope.lua
return {
{
"nvim-telescope/telescope.nvim",
branch = "0.1.x",
dependencies = {
"nvim-lua/plenary.nvim",
{ "nvim-telescope/telescope-fzf-native.nvim", build = "make" },
},
cmd = "Telescope",
keys = {
{ "<leader>ff", "<cmd>Telescope find_files<CR>", desc = "Find files" },
{ "<leader>fg", "<cmd>Telescope live_grep<CR>", desc = "Live grep" },
{ "<leader>fb", "<cmd>Telescope buffers<CR>", desc = "Buffers" },
{ "<leader>fh", "<cmd>Telescope help_tags<CR>", desc = "Help tags" },
{ "<leader>fr", "<cmd>Telescope oldfiles<CR>", desc = "Recent files" },
{ "<leader>fc", "<cmd>Telescope commands<CR>", desc = "Commands" },
{ "<leader>fk", "<cmd>Telescope keymaps<CR>", desc = "Keymaps" },
{ "<leader>fs", "<cmd>Telescope lsp_document_symbols<CR>", desc = "LSP symbols" },
{ "<leader>fd", "<cmd>Telescope diagnostics<CR>", desc = "Diagnostics" },
{ "<leader>fw", "<cmd>Telescope grep_string<CR>", desc = "Grep word" },
{ "<leader>gc", "<cmd>Telescope git_commits<CR>", desc = "Git commits" },
{ "<leader>gb", "<cmd>Telescope git_branches<CR>", desc = "Git branches" },
{ "<leader>gs", "<cmd>Telescope git_status<CR>", desc = "Git status" },
},
config = function()
local telescope = require("telescope")
local actions = require("telescope.actions")
telescope.setup({
defaults = {
mappings = {
i = {
["<C-j>"] = actions.move_selection_next,
["<C-k>"] = actions.move_selection_previous,
["<C-q>"] = actions.send_to_qflist + actions.open_qflist,
["<Esc>"] = actions.close,
},
},
file_ignore_patterns = {
"node_modules", ".git/", "vendor/", "*.lock",
},
layout_config = {
horizontal = { preview_width = 0.5 },
},
},
pickers = {
find_files = {
hidden = true,
},
live_grep = {
additional_args = function()
return { "--hidden" }
end,
},
},
})
telescope.load_extension("fzf")
end,
},
}2.2 核心 Picker
| Picker | 功能 | 快捷键 |
|---|---|---|
find_files | 查找文件 | <leader>ff |
live_grep | 全局搜索 | <leader>fg |
buffers | 缓冲区列表 | <leader>fb |
oldfiles | 最近文件 | <leader>fr |
lsp_document_symbols | 符号导航 | <leader>fs |
diagnostics | 诊断列表 | <leader>fd |
git_commits | Git 提交 | <leader>gc |
git_branches | Git 分支 | <leader>gb |
2.3 Telescope 内快捷键
| 按键 | 功能 |
|---|---|
<C-j> / <C-k> | 上下移动 |
<CR> | 打开文件 |
<C-x> | 水平分割打开 |
<C-v> | 垂直分割打开 |
<C-t> | 新标签页打开 |
<C-q> | 发送到 Quickfix |
<C-u> / <C-d> | 预览滚动 |
2.4 搜索技巧
" 搜索时可以使用空格分隔多个词 (AND 逻辑)
" 例如输入: user service
" 会找到同时包含 user 和 service 的文件
" 使用 ! 排除
" 例如输入: user !test
" 会找到包含 user 但不包含 test 的项
" 使用 ^ 匹配开头
" 例如输入: ^main
" 会找到以 main 开头的项3. Harpoon: 快速标记导航
对于常用文件, Harpoon 比 Telescope 更快.
3.1 配置
return {
"ThePrimeagen/harpoon",
branch = "harpoon2",
dependencies = { "nvim-lua/plenary.nvim" },
keys = {
{ "<leader>ha", function() require("harpoon"):list():append() end, desc = "Harpoon add" },
{ "<leader>hh", function() require("harpoon").ui:toggle_quick_menu(require("harpoon"):list()) end, desc = "Harpoon menu" },
{ "<leader>1", function() require("harpoon"):list():select(1) end, desc = "Harpoon 1" },
{ "<leader>2", function() require("harpoon"):list():select(2) end, desc = "Harpoon 2" },
{ "<leader>3", function() require("harpoon"):list():select(3) end, desc = "Harpoon 3" },
{ "<leader>4", function() require("harpoon"):list():select(4) end, desc = "Harpoon 4" },
},
}3.2 使用方式
<leader>ha " 将当前文件加入列表
<leader>hh " 打开 Harpoon 菜单
<leader>1-4 " 直接跳转到第 1-4 个文件4. 本周实战任务
4.1 Treesitter 练习
- 安装 Treesitter 并运行
:TSUpdate - 观察代码高亮的变化
- 练习
<C-space>增量选择 - 使用
daf,cif,vac等文本对象
4.2 Telescope 练习
- 配置 Telescope 快捷键
- 使用
<leader>ff查找文件 - 使用
<leader>fg全局搜索 - 使用
<leader>fs导航符号
4.3 Harpoon 练习
- 将 4 个常用文件加入 Harpoon
- 使用
<leader>1-4快速切换 - 感受与 Telescope/Buffer 切换的不同
5. 思考题
- Treesitter 相比正则高亮有什么优势?
- 什么场景用 Telescope, 什么场景用 Harpoon?
- 增量选择如何提高效率?
- 如何将搜索结果发送到 Quickfix?
- Treesitter 文本对象和内置文本对象有何区别?
结构化导航是现代开发的基础. Treesitter 提供语义理解, Telescope 提供快速检索, Harpoon 提供热点跳转.