Vim高级用户指南

2021-02-27 23:00:09

欢迎来到本系列的第三部分,该系列旨在帮助您释放使用全能Vim在地球上从未见过的力量。如果您不了解本文的内容,建议您先阅读本系列的上一篇文章:

但是,亲爱的读者们,在进入本文多汁的内容之前,我为您提供了一些建议:

启动Vim,并在阅读时使用命令和按键进行操作。这是让您记住让您感到震惊的一切的最佳方式。这样一来,您就可以在以后的余生中被震撼。

不要使用备忘单;阅读时写自己的。它将使您轻松返回到找到最适合自己需要的命令。

让我们从以g开头的混合按键开始。 Vim中有许多这样的“ g”命令,我们在先前的文章中已经看到了其中的一些。你能记得他们吗?

gx-打开位于光标下方文件路径的文件。它也适用于URL。它将打开您喜欢的浏览器并加载网站。

gv-启动VISUAL模式并使用在上一个VISUAL模式下所做的选择。

gn-选择上一次搜索的匹配项:您可以继续按n(或gn)以选择当前匹配项和下一个匹配项之间的区域。

gI-无论首字符是什么,都在行首插入文本。

要试用gf和gx,您可以在Vim中编写例如https://www.google.com/,将光标放在其上,然后击键。不要忘记网址中的斜杠。

您很快就会发现gx带来的不便:在文件路径上使用gx时,Vim会挂起,直到关闭文件。这就是为什么我创建了以下可以添加到.vimrc中的映射的原因:

它将击键gX映射为将xdg-open与光标所在的文件路径一起使用。它将在后台使用您最喜欢的应用程序打开文件。程序xdg-open仅在基于Linux的系统上有效;对于MacOS,请尝试打开。

现在我们已经完成了开胃菜,让我们发现Vim盛宴的第一道真正菜式:范围。您可以将它们应用于许多命令,从而使其功能异常强大。

在Vim的帮助下,每个接受范围的命令都将在其前面带有字符串[range]。可以使用多个行说明符,以逗号分隔。

*-使用您在上一个VISUAL模式下所做的最后一个选择。

:2,$ d-删除第二行到文件末尾的每一行。

:。,$ d-从当前行到文件末尾删除每一行。

如果需要,还可以对范围进行一些算术运算。例如,假设您的光标位于第60行:。,。+ 10范围将等于60,70。

在VISUAL模式下进行某些选择后,如果切换到COMMAND-LINE模式,则会看到以下两个符号:'<和'>之间用逗号隔开。这也是一个范围!

符号'<代表您选择的第一行,并且'>最后一行。这些都是标记;再次,我们将在下面看到更多有关标记的信息。

实际上,范围'<'>和*是同义词,但第一个将为您带来更大的灵活性。例如,您可以从所选的第一行开始执行命令,直到文件末尾的范围为'<,$。

现在,让我们讨论一下快速修复列表Vim中可用的非常有用的数据结构。 不要混淆快速修复列表和快速修复窗口:这是两个不同的实体。 第一个是数据结构,第二个可以显示此数据结构。 您可以将快速修复列表视为一个或多个文件中的一组位置。 让我们举个例子:如果运行命令:vimgrep hello *,会发生什么? 它将在工作目录的每个文件中搜索模式“ hello”。 它将使用与模式“ hello”匹配的每个位置填充一个快速修复列表。 如果您想了解更多关于vimgrep和其他可以使用的工具,我写了一篇关于它的文章。 其他命令(例如:make或:grep)也会自动填充快速修复列表。

让我们围绕标记扩大神秘色彩:快速修复列表中的这些位置实际上是隐藏标记!

快速修复列表通常用于显示代码库中的特定错误,通常从编译器或linter中吐出(例如,通过命令:make),但不仅如此,正如我们刚刚看到的那样。我称快速修复列表中的条目为“ positions”(一般情况),但有时Vim的帮助会将其称为“错误”。不要混淆:这是相同的想法。

在其他情况下,快速修复列表条目需要具有文件名才能使您跳到其位置。否则,该条目将不指向任何内容。很难搬到任何地方。

:cl或:clist-显示当前快速修复列表的所有有效条目。您可以添加范围作为参数(仅数字)。

:cdo< cmd> -执行命令< cmd>在当前快速修复列表的每个有效条目上。

:cexpr< expr>或:cex< expr> -使用评估Vimscript表达式< expr>的结果创建一个快速修复列表。

:caddexpr< expr>或:cadde< expr> -附加评估Vimscript表达式< expr>的结果。到当前的快速修复列表。

如果您不知道如何使用最后两个命令,则可以执行以下操作:

:cex system("< cmd>")-使用任何shell命令< cmd>填充您的快速修复列表。您可以尝试使用ls为例。

如何在新缓冲区中显示当前的快速修复列表?您可以使用以下命令执行此操作:

:copen或:cope-打开一个窗口(带有特殊缓冲区)以显示当前的快速修复列表。

您只能打开一个quickfix窗口。要移至快速修复程序窗口中快速修复程序列表的所选条目的位置,请按ENTER或.cc。

位置列表与快速修复列表类似,不同的是第一个在窗口本地,而第二个在Vim实例全局。换句话说,您可以同时拥有多个位置列表(每个打开的窗口一个),但是您只能访问一个快速修复列表。

用于位置列表的命令与用于快速修复列表的命令相似。通常,您只需将命令的第一个c(qui cfix)替换为l(位置)。

:lli或:llist-显示当前位置列表的所有有效条目。 您可以添加范围作为参数(仅数字)。 要填充位置列表,您还可以使用例如:lvimgrep或:lmake命令。 Vim用户通常会使用快速修复列表来查找与他们的代码库中的错误相关的任何内容,并使用位置列表来查找结果。 但这取决于您的一天。 有了Vim,您就是命运的主人。 收银机是我们Vim盛宴中的又一道大菜。 您可以将寄存器视为可以读取或写入一些文本的地方。 我喜欢将它们视为Vim的剪贴板。 这是显示和指定寄存器的命令和正常模式下的按键: 您怎么知道什么时候寄存器< reg> 是通过按键"读写的? 这取决于您随后使用的按键。 例如: 要写入寄存器a:取消,更改或删除某些内容(例如,通过在NORMAL模式下使用dd)将其写入a。

要读取该寄存器,请执行以下操作:在NORMAL(正常)模式下使用击键操作(例如p或P)将当前寄存器中的寄存器内容吐出。 我们在这里以注册一个寄存器为例,但是它适用于任何可写寄存器。 未命名寄存器(")-包含最后删除,更改或删除的内容,即使指定了一个寄存器也是如此。 带编号的寄存器(从0到9)从1到9是一个堆栈,其中包含您已删除或更改的内容。 每次删除或更改某些内容时,它将被添加到寄存器1中。 寄存器1的先前内容将分配给寄存器2,先前内容2至3… 当某些东西添加到寄存器1中时,寄存器9的内容丢失。 如果您之前用击键"指定了一个,则不会写入这些寄存器。

如果您未使用击键"指定它们,则Vim将永远不会写入已命名的寄存器(范围从a到z)。

您可以使用每个寄存器的大写名称来附加它(而不是覆盖它)。

表达式寄存器(=)-存储表达式的结果。有关此寄存器的更多信息,请参见下文。

如您所见,即使您未使用击键"指定任何寄存器,您删除,更改或拉动的内容也会自动覆盖其中的一个(或多个)内容。因此,如果您不希望写入寄存器的内容被Vim静默覆盖,请始终写入命名寄存器。

默认情况下,使用put命令而不指定任何寄存器将吐出未命名寄存器的内容。但是您的vimrc中可能包含以下行:

在这种情况下,您更改,删除或删除的内容将直接进入未命名的寄存器和+寄存器。使用put命令也将直接输出+寄存器。许多人发现(包括我在内)可以更轻松地访问OS剪贴板,而无需指定用于读取或写入的+寄存器。

我们在上一篇文章中看到,您可以使用q记录击键。既然您知道如何使用寄存器,就可以操作以下按键:

如果在录制过程中出错,则可以吐出整个寄存器,对其进行修改,然后将其保存回去。 您可以使用寄存器的大写变体追加到记录中。 例如:按下qa并记录您想要的任何击键。 再次按q停止录制。 执行击键操作,以确保您位于录音的最后位置。 点击qA将其添加到您的注册表中。 完成后,再按一次q。 神奇的击键" 对于NORMAL模式非常有用,但是在INSERT模式下如何分散寄存器的内容呢? 为此,您可以使用CTRL + R< reg> 将寄存器< reg>的内容放入 在您当前的缓冲区中。 例如,如果您在INSERT模式下按CTRL + R%,则会将寄存器%的内容放入当前缓冲区中。 如果您不知道表情寄存器,那么我将改变您的生活。 我希望你准备好了。

切换到INSERT模式,然后按CTRL + r =。 您将转到Vim的命令行。 在这里,您可以键入所需的任何Vimscript表达式,例如我们在上面看到的system(" ls")。 按ENTER运行表达式,您将看到直接在缓冲区中插入的shell命令ls的输出! 您也可以这样调用shell脚本,其输出将在您的缓冲区中吐出。 它比使用纯Vimscript慢,但是对于小型脚本,实际上并不重要。 那有多疯狂? 关于寄存器的最后一个小技巧:如果要清空一个寄存器,可以执行以下操作: 开始记录也会删除该寄存器中的所有内容。 因此,您只需要通过再次按q来停止记录即可获得空寄存器。 让我们继续提升,成为Vim神(或女神)。 替代命令位于菜单上的下一步。

如果您已经熟悉CLI sed,则此命令将提醒您一些美好的往事。

替换是一种使用范围和计数将某些内容替换为其他内容的方法。计数将决定您从范围的最后一行替换所影响的行数。

与许多其他命令一样,如果您未指定,则默认范围是当前行。

还有一个元素,在这里用斜杠/表示:分隔符。它不必是斜杠,可以是任何字符,除了:

替换不是强制性的:如果您省略它,那么replace命令将删除匹配的模式。

您也可以运行:s,而没有任何范围,模式,替换,标志或计数。在这种情况下,它将重复您所做的最后一次替换而没有标记;您可以添加新标记(&除外)和计数(如果需要)。

:s#pattern#replacement#-等效于上面的替换。如果您的模式或替换中有一些URL,则非常方便。

:%s / pattern / replacement /-替换当前缓冲区的每一行上第一次出现的pattern。

:1,10s / pattern / replacement /-替换当前缓冲区前十行中每个第一次出现的pattern。

:s / pattern / replacement / 10-用当前行和下10行的每个第一次出现的模式替换。

:1,10s / pattern / replacement / 5-用范围的最后一行的前十行和后五行中的每个第一次出现的模式替换。

:s g 10-重复最后一个不带其标志的替换,并添加一个新标志g。它会影响最后一个替代命令的最后一行之后的10行。

在这种情况下,模式是正则表达式。但这不是您熟悉的高级编程语言中很好的旧正则表达式引擎。 Vim有其自己的正则表达式引擎(实际上,它有两个!),这可能会造成很大的混乱。

Vim中的正则表达式或多或少是魔术。你以为我在开玩笑吗?我不是。我觉得有必要记住以下几点:

要访问所有正则表达式元字符,可以在\ v前面加上模式前缀(非常神奇)。 要访问几乎所有的正则表达式元字符((,和),|除外),请使用命令:sm而不是:s(替代魔术)。 要访问任何元字符($除外),请使用:sno而不是:s(替代nomagic)。 要访问所有元字符,可以在\ V前面加上模式前缀(非常不可思议)。 例如,如果要删除缓冲区中的所有左括号,可以运行以下三个等效命令之一: 如果您知道自己的正则表达式元字符,您可能会想知道元字符〜。 这是Vim世界中最新的替代字符串。 实际上,您可以在Vim的正则表达式中使用更多的元字符(称为原子)和字符类。 :〜-用相同的替换重复最后的替换命令,但是使用最后使用的搜索模式。

g& -重复最后一个替换项及其范围和标志,并用最后一个搜索模式替换其模式。

你还不够吗?您想要更多的动力吗?看哪圣洁的全球命令!它与替代命令相似,但它将执行命令而不是替换模式。

举例来说,假设您有删除所有当前缓冲区中“无用”模式的冲动。为此,您可以运行:

你知道命令:norm吗?您可以给它一些正常模式的击键,它将为您应用,就像您在正常模式下击键一样。例如,以下将删除光标下的单词:

当我第一次听说这件事时,我看到了宇宙,大爆炸,创造与破坏的循环。我了解生与死。我很幸运,在每个免费的城市都高喊着Vim的力量。

最后提示::norm使用您定义的键映射。如果只想使用Vim的默认映射,则可以使用norm!反而。

如果您编写插件,请始终使用norm!。您不知道您的用户使用了哪些映射。

现在该回答一个困扰您的问题了:什么是商标?

您可以将标记视为缓冲区中的特定位置。要设置一个,可以在正常模式下使用m,后跟以下范围内的字符:

如果通过Vim中的viminfo选项设置了“ viminfo”文件,或者通过Neovim中的shada选项设置了“ shada”文件,则这些标记将保留。这意味着即使您关闭了文件,您也可以回到他们那里。

如果您想知道Vim的选项是什么以及如何显示它们的值,我在本系列的第一篇文章中对此进行了介绍。

也有0-9范围内的只读标记。仅当使用viminfo文件(对于Vim)或shada文件(对于Neovim)时,它们才可用。每次您退出文件时,它们都会存储光标的位置:标记0位于最后一个位置,标记1位于最后一个位置之前,依此类推。

'< mark> -移至标记< mark>所在行的第一个非空白字符。设置好了。

g' < mark> g`< mark> -移至标记< mark>而不更改跳转列表(我在本系列的上一篇文章中已经介绍了跳转列表)。

您可能会想到,还有一些有用的命令来显示或操作标记: 这将用从标记a的确切位置到标记b的确切位置的替换来替换图案的第一个匹配项。 m < 或m> -设置标记'< 和'> 我们在上面看到了。 对于按键gv可能很方便。 `[-移至先前更改,删除或删除的内容的第一个字符。 `]-移至先前更改,删除或删除的内容的最后一个字符。 ``-从跳转列表移至最新跳转之前的位置(或使用m&#39或m`设置的位置)。 `" -移至上次关闭当前文件的位置。

`^-移至上次使用INSERT模式的位置(此标记由引擎盖下的gi键使用)。 对于上述每个使用`的按键操作,您都可以使用' 而是与上面看到的差异有所不同。 这些注册,替换和标记恶作剧之后,这是一个较轻的主题:加(或减)数字。 g CTRL + a-与CTRL + a相同,除非您选择了几行。 在这种情况下,每行的第一个数字将按顺序递增。 g CTRL + x-与CTRL + x相同,除非您选择了几行。 在这种情况下,每行的第一个数字将依次递减。 为了更好地说明最后两次击键,假设您心爱的Vim中包含以下惊人的内容: 1.取一些红色的花朵。1。 加一些鸡蛋1。 忘记它,然后回到您的计算机。

如果您在VISUAL模式下选择了最后两行并按g CTRL + a,您将获得:

1.取一些红色的花2。加一些鸡蛋3。忘记它,然后回到您的计算机。

您还可以在命令前添加一个计数,以添加精确的数量。例如,12 CTRL + a将12加到当前行的第一个数字上。

重要说明:这些击键也可以处理无符号的二进制,八进制和十六进制数字以及字母字符。它们的行为取决于选项nrformats的值。为使这些击键行为如本文所述,nrformats的值中不应包含字母,否则将增加(或减少)该行的第一个字母字符。

就个人而言,我认为最好排除字母字符,但是无论如何,我建议您阅读Vim的帮助以了解更多信息。一如既往。

那一点甜点呢?不错的命令可以直接在Vim中对文本进行排序?以下是命令:

:sort或:sor-根据范围对行进行排序。如果没有给出范围,则对所有行进行排序。 :种类!或:sor! -颠倒顺序。

例如,如果您有一个CSV(以逗号作为分隔符),并且您希望根据第二列对每一行进行排序,则可以运行以下命令: 取一些红色的花朵(1)。忘掉它,然后回到计算机(3)。再添加一些鸡蛋(2)。 取一些红色的花朵(1),再添加一些鸡蛋(2),忘掉它,然后回到计算机(3)。 与往常一样,这里涉及许多微妙之处。 如果您想更深入地了解,应该知道该怎么做:释放Vim的帮助并享受其无限的深度! 但这是最重要的:您不必在意第二点。 始终将自己与过去的自我进行比较,而不是与他人进行比较。 继续走自己的路,就会得到启发。 ......