12-搜索… - Some-soda

12-搜索…

第 12 章 搜索…

令人惊讶的是,我们竟然在没有涉及搜索的情况下走到了这一步。Vim 中的查找和替换一直比大多数编辑器(它们只给你一个带有三个字段的小对话框,如果幸运的话,还有一个指定正则表达式的复选框)强大得多,也细致得多。

LazyVim 扩展了 Neovim 强大的搜索功能,使其更易于使用且更美观。你已经了解了用于导航到和选择你能看到的对象的可视化 Seek (s) 和 TreeSitter (S) 模式,以及它们对应的远程操作符待决对象:rR。当你要查找的文本当前可见时,这些都很好用。然而,当你需要搜索一个文件并让它自动滚动到搜索结果时,它们就不够用了。

12.1. 在当前文件中搜索

要在 Vim 中搜索模式,请在普通模式下使用 / 命令。助记符是 / 键也是问号键,而搜索某物是一种提问。

译者注: / 向下搜索,? 向上搜索。

许多不被认为是模态编辑的工具已经采用了 Vi 的 / 作为调用搜索的命令。例如,卓越的 Linear 任务跟踪工具使用 / 开始搜索,无处不在的 GitHub 也是如此。

当你第一次在普通模式下输入 / 时,你可能会丢失光标!它不会弹出新窗口。相反,/ 会接管当前文件的状态栏,并显示一个放大镜图标:

osearch dat dark

图 54. 搜索 “dat”

在这张图片中,我输入了 /dat/ 启动了搜索模式,然后我搜索了 dat。我的光标在搜索框中。

如你所见,LazyVim 已经很贴心地高亮了所有(可见的)“dat”匹配项。“主要"结果将始终是你按下 / 时光标位置之后的第一个匹配结果。

如果你按 Enter 确认搜索,你的光标将跳转到主要结果。像往常一样,按 Escape 取消搜索。

此时,你回到了普通模式,可以正常编辑缓冲区。然而,在此之前,请注意所有高亮的结果仍然是高亮的。你可以使用 n(代表 next,下一个)键轻松跳转到下一个结果。这个命令接受计数,所以你可以使用 3n 跳转到当前光标位置之后的第三个结果。

如果没有更多匹配结果在底部,搜索将环绕到文档顶部。如果你知道需要跳转多远,你也可以对 / 命令使用计数,例如 3/something 向前跳转到第三个 something。不过,弄清楚你需要跳转多远需要一些思维敏捷性,所以通常使用 Seek 模式更快。

如果你用 n 跳得太远,你可以使用 Shift-N 将光标移动到上一个结果。如果你知道你需要向后搜索到上一个结果,你可以用 ?(即 Shift-/)而不是仅仅 / 来启动搜索。

如果你以前用过 Vim,我应该提醒你,nN 的这种行为与默认的 Neovim 行为不同。它们过去是“重复上一次的 /? 命令”,所以如果你用 ? 开始,n 会继续向文档上方移动。LazyVim 的模型更容易记住;n 总是表示“下一个向下”,N 总是表示“上一个向上”。

12.2. 忽略大小写

如果你输入的搜索词全部是小写字母,LazyVim 默认会忽略大小写,但如果你在搜索词中包含一个大写字母,它将启用大小写敏感。所以搜索 in 会匹配 inIn,但搜索 In 只会匹配 In

译者注: 这是通过 smartcase 选项实现的,LazyVim 默认开启。

如果你明确只想搜索小写匹配项,你可以通过在搜索词中的某处插入两个字符 \C(那个 C 是大写的)来修改搜索词。

译者注: \C 强制后续模式进行大小写敏感匹配。

方便的是,它不必在搜索词的开头;如果搜索字符串中的任何位置有 \C,它将使整个搜索大小写敏感。所以,假设你正在寻找小写单词“initiate”。如果你开始输入 in 并意识到它匹配了一堆不必要的 In 因为忽略大小写已启用,你可以在输入 iti 之前附加 \C(所以你最终得到 in\C)切换到大小写敏感模式(所以总的搜索字符串是 in\Citi)。

如果你想暂时禁用忽略大小写,请输入冒号命令 :set noignorecase。这只持续到你退出 Neovim,或者用 :set ignorecase 再次明确启用它为止。

如果你想让这个更改永久生效,打开你的 options.lua 文件并在其中某处添加 vim.opt.ignorecase = false。注意,现在如果你想让任何特定的搜索大小写敏感,你需要在搜索短语中使用小写的 \c 而不是 \C

译者注: \c 强制后续模式进行大小写不敏感匹配。

\C 的技巧起初看起来有点奇怪,但当你想到大多数代码编辑器中使用的替代方法,即你必须将手移到鼠标上,用瞄准一个像是Aa的小复选框并点击它,然后重新聚焦搜索框并继续输入时,你可能会觉得 \C 更快。

12.3. 正则表达式

Vim 搜索默认使用正则表达式。但它们是有点奇怪的正则表达式。

好吧,我承认所有正则表达式都有点奇怪。Vim 的正则表达式只是与大多数现代编程语言中常见的 PCRE 风格的正则表达式相比才显得奇怪。幸运的是,如果你只是搜索文本,你可能不需要 Perl 兼容表达式提供的全部复杂性。

译者注: Vim 的正则表达式语法有其自己的“怪癖”,特别是关于哪些元字符需要反斜杠转义。它有两种主要模式:magic (默认) 和 very magic (\v)。very magic 更接近 PCRE。

我这本书没有空间来指导正则表达式语法,所以我只提一些主要的常用法,剩下的留给你自己查找:

  • . 匹配任何单个字符。如果你需要搜索字面上的句点,请用 \. 转义它。
  • \s 匹配任何空白字符。(译者注:原文漏了 \s,补充上)。\S 匹配任何非空白字符。
  • * 字符匹配前面的表达式零次或多次。值得注意的是,.* 将匹配任意长度的任何字符串。
  • \+ 字符串匹配前面的表达式一次或多次。(这与我见过的大多数正则表达式解析器显著不同,在那些解析器中你不需要在 + 前加 \ 来匹配一次或多次)。它可以与例如 \S 结合来匹配任何不含空格的单词:\S\+
  • \= 可以用来匹配前面的模式零次或一次。对于像 https\=: 这样 “s” 是可选的情况很有用。这个模式在大多数正则表达式引擎中通常是 ?,实际上 \? 也能达到这个效果。然而,当用 ? 调用向后搜索命令时,这会使 Vim 混淆,所以 \= 胜出。(译者注:\? 确实在 Vim 正则中表示 0 或 1 次匹配,但用它搜索时确实需要注意。)
  • \\ 匹配字面上的反斜杠,\/ 匹配字面上的正斜杠。

**译者注:**你会在未来的时间里面多次反复学习正则表达式的。

总的来说,如果你了解 PCRE 风格的正则表达式,你会发现在 Vim 中你需要更多的反斜杠。话虽如此,绝大多数代码编辑器的搜索都包含在上述范围内了。

如果你想为特定搜索“禁用”正则表达式匹配,请在行的开头放置 \V(或者如果你只需要为搜索的剩余部分禁用它,则放在行的中间)。“V”代表“very nomagic”(非常无魔法),如果你想被极度搞糊涂,请输入 :help magic。它实际上是如此令人困惑,以至于你会宁愿学习直接使用正则表达式(是的,我知道这有多么令人困惑,纯粹的Vim黑魔法)。

译者注: 使用 \v (very magic) 开启更接近 PCRE 的模式,通常比默认的 magic\V (very nomagic) 更容易使用。例如,在 \v 模式下,+, ?, |, () 等元字符不需要反斜杠。

如果你迫切需要一个正则表达式来做某件事,你可以让 ChatGPT 帮助你浏览 :help regular expressions 来找到你需要的语法。你最终要么恍然大悟,要么感到沮丧。

12.4. 在项目中搜索

如果你需要跨整个代码库搜索一个词,而不仅仅是在一个文件中,请使用命令 <Space>/ 而不是仅仅 /。它会弹出那个非常熟悉的选择器,这次是 live_grep 模式。

译者注: <Space> / 通常映射到 Telescope 或类似插件的实时 grep (live grep) 功能。

确保你安装了 ripgrep 并可在你的路径中以 rg 的形式使用,因为这是选择器底层使用的工具。

输入你正在寻找的字符串。结果将显示在左侧,文件将在右侧的预览中显示,这样你就可以找到正确的那个了:

live grep dark

图 55. Live Grep 选择器

记住,你可以通过按 Alt-s 给选择器结果添加标签。我发现在 live_grep 窗口中这更有用,因为与大多数选择器不同,live_grep 中的空格会被作为字面上的空格发送给 ripgrep,而不是让我通过搜索行中更早的内容来缩小搜索结果范围。

因为这是一个选择器,你可以在它打开时按 Alt-t 将所有搜索结果放入 Trouble 窗口,这样你就可以在编辑时导航它们(使用 ]q[q)。

令人烦恼的是,这种搜索模式与 Vim 的内置搜索完全不同。它只是将你的模式传递给 ripgrep 并按照 ripgrep 的方式行事。而 ripgrep 不知道 Vim 奇怪的正则表达式引擎之类的东西。它确实支持正则表达式,但它们使用的语法与 Vim 的截然不同,令人抓狂。也就是说,与几乎所有非 Vim 的东西使用的语法相同。在这里令人抓狂的是 Vim,而不是 ripgrep。只是为了让大家都清楚。

译者注: ripgrep 使用 Rust 的正则表达式引擎,语法更接近 PCRE。

12.5. 总结

本章全部是关于搜索:进入搜索模式的 / 快捷键,以及进入项目中查找模式的 <Space>/ 快捷键。后者可能不够强大,所以我们还设置了 telescope-live-grep-args 插件(译者注:原文在此处提到这个插件,但在前面配置部分未提及,可能是在后面章节或作者个人配置中),让我们对项目范围的搜索有更多的控制。

当然,搜索只是故事的一半。在下一章中,我们将介绍替换文本,既作为搜索操作的一部分,也在更广泛的项目层面上进行。