[VSCodeVim] 官方文件没有详述的实用技巧:以virtualedit所解决的情境为例


(图源:Tim Pope's twitter)

[系列文目录]

这篇文章会介绍一个VSCodeVim官方文件(v1.23.0以前)并没有详述到的实用技巧。

技巧会「实用」,不是因为它很炫、很艰深或者是很罕见,而是他会帮助我们解决特定场景下的问题。以这篇文章所介绍的技巧为例,它会让我们的操作与命令组合更顺手。

事实上,官方文件没有详述的命令或设定很多,但未必每个都实用,或是每个都能帮助我们建立起操作的思维与观念。所以在挑选它们介绍的时候作者还是有一定原则的。

首先,还是让我们先介绍一下相关原生Vim命令的基本操作,再来看一下情境。

ㄧ、Visual Block Mode基本操作介绍


想像一下,目前我们有一段这样长短不均的文字,我们要同时对第二栏中每一行的user文字都改成command

| Name                   | Type    |  Command(s)                   |
| -----------------------| ------- | ----------------------------- |
| Open Project           | user |  `vsce-script.openProject`       |
| Create Script Project  | user |  `vsce-script.createProject`     |

如果是在Vim里,这时我们可以使用「Ctrl+v」命令,进入Visual Block模式,此时再按j往下可以连续选取到第二行,这时我们按e可以同时选取到这两个字,之後我们按c可以修改它,输入command字样後,按两次Esc,就可以完成动作。

edit-markdown-table

上面这是在Vim里对Visual Block模式的基本操作,让我们来看在该模式时会遇到的一些问题。

二、在Visual Block模式里编辑长短不均的多行文字与现有的Issue


上面这是比较理想的状况,现在我们可能遇到编辑长短不均的多行文字的情境,如下所示:

AAAAAAAAAAA
BBBBB
CCCCCCCCCCCC
DDDD
EEEEEEEE

在这种情境下我们可能因此无法完成某些操作。

此时,我们编辑块状的文字时可能会遇到游标移动不到行尾的状况。

遇到这种情境时,其中一种可行的解决办法是在Vim里启用virtualedit=block的选项,在命令列模式里输入下面这行:

启用後,同样的操作就可以选取至行尾。

可惜,在VSCodeVim里并没有直接实现该选项,这是一个Github上Open的Issue,会选择不实现这个选项跟VS Code的环境有关。

但VSCodeVim没有实现该选项,并不意味着我们因此完全无法编辑多行长短不均的文字。让我们先试着用底下技巧来解决需求。

三、使用 《Practical Vim》Tips 26: Append After a Ragged Visual Block


在此之前,《Practical Vim》在技巧26中提出了一个组合命令的技巧,可以在Vim里面解决在结尾追加文字的需求。

AAAAAAAAAAA
BBBBB
CCCCCCCCCCCC
DDDD
EEEEEEEE

首先,让我们先进入Visual Block,并使用j往下选取到最後一行。

之後,使用$命令,这会让游标移动到结尾。因为是在Visual Block模式里,每一列都会选取到文字最後面。

最後,我们要进行编辑,此时可以使用A(append),让游标进入插入模式。

(注:若是在普通模式使用A,则会直接让游标移到尾端,并进入插入模式。)

此时,我们再输入要追加的文字,此处我们输入追加的文字「123」,再按「Esc」离开,就可以完成文字的追加。

完整的操作如下所示:

四、Visual Block模式与Tips 26的限制


好,刚才的操作是笔者在MacOS里的Vim完成的,同样的技巧也可以在VSCodeVim中使用,让我们在VS Code里面操作看看。

在VS Code里,使用同样技巧追加文字时,多行文字会立刻出现,不会像Vim里按Esc後才全部显示。在这方面的UX好些。

假如,我们想在移动多行後的中间插入文字,一样可以如法炮制,使用A命令。

不过,在VSCodeVim里我们也同样跟Vim一样有着先天上的限制。是什麽样的限制呢?

1. 在Visual Block模式中无法直接使用i(insert),a(append)命令

在Vim的Visual模式中,我们的i, a命令是保留给Text Object的。假如我们要选中一个文字(word),我们可以使用viw来选取它。作为Text Object来使用时,i的语意是inner,a是arround。

这个设计有其理由,但也因此,在Visual Block中我们无法游标移动到哪里,就使用ia,得改用IA命令,这样有点违反直觉。

大部分人,若没有看过相关文章,根本不会知道在Visual Block模式插入文字的命令是这样用的,通常就是直接点击ia命令後效果不如预期就放弃了。

另外,使用A命令时要多按一个shift键,不如直接按i来得轻松愉快。

2. 选取范围呈现块状,无法很好的与组合命令结合

  • 当我们选取多行後,连续按两次e,此时我们可能会预期游标移动到vscodelib的尾端。可惜并不会这样,游标选去的可视范围是块状的。

  • 另外一个例子是我们在markdown表格使用结合f(find)命令时会遇到的状况,在下面的例子中,因为第一栏有一个列长度不一样,我们在使用f|命令时,就无法在第三列精准的选中|字元,同时对其进行操作。

3. 受限於组合命令上的限制,无法进行最有效率的操作

由於组合命令上的限制,我们在「tip26」里进入Visual Block後得先使用$,再使用A$是少数可以在Visual Block模式中正常使用的命令。

若普通模式操作单行文字,只要使用A(append),就可以移动到行尾,并进入到插入模式。上面的方式让我们在相关操作时多打了shift4两个键。

五、官方文件没有详述的实用技巧: 使用<D-alt+down/up>、<C-alt+up/down>命令


在上面,我们的操作受到了些限制。在VSCodeVim里面,我们其实可以使用

  1. <D-alt+down><D-alt+up>: 「cmd+ option+ down」、「cmd+ option+ up
  2. <C-alt+down><C-alt+up>: 「ctrl+ alt+ down」、「ctrl+ alt+ up

这两组快捷键,往下、上新增一个新的游标。

MacOS的使用者用第一组快捷键,Windows使用者使用第二组快捷键。

好的,现在让我们来看一下,怎麽使用这个命令:

  • 往下/上追加一个游标

(此处仅示范往下追加游标的动作,要往上追加的话将快捷键中的方向键改成上即可)

  • 结合次数

在对多行进行操作时,只要是VSCodeVim相关的命令,在普通模式下可以结合次数使用这个命令,帮助我们快速追加多行游标。

下面我们要追加8个游标,所以依序输入8cdm+option+down,就往下新增八个游标,减少许多重复输入命令的时间。

好的,介绍以上操作後,进入重头戏。

透过这几个命令,我们创造了Multiple Cursors。在笔者也有学习并受益过的《Boost Your Coding Fu With Visual Studio Code and Vim》一书中,有一节「ADD MULTIPLE CURSORS ON CONSECUTIVE LINES」是在处理相同的情境,但里面介绍的方法其实也还是基於我们这篇文章第三节所介绍的「《Practical Vim》tips26」的,仍然会遇到上面我们所提到的3个状况。

现在就让我们来看一下这个命令能不能解决上面3种我们在Visual Block模式组合命令时遇到的状况。

  1. 在Multi Cursor模式中直接使用i(insert),a(append)命令

此处在移动游标的过程中使用ia都是可以的,上面我们示范在多游标模式中使用i命令的操作。

  1. 在Multi-Cursor模式中选取长短不规则的范围,与组合命令结合
  • 当我们选取多行後,连续按两次e,此时游标如预期移动到vscodelib的尾端。

  • 在Markdown表格中使用f(find)命令选取不规则长度多行内的指定字元

可以看到,两种命令组合都顺利运作,符合我们的预期。

  1. 在Multi-Cursor模式中使用最有效率的组合命令进行操作

刚才有提到最自然的移动方式其实是直接使用A命令将游标移到尾端并进入插入模式,让我们动手尝试一下:

完成後,我们可以看到,多个游标顺利的移到尾端并进入插入模式,每次修改所需的$命令至此完全被省略了。

透过这组命令,我们可以的操作毫不拖泥带水。前面在组合命令时困扰不复存在,组合各个命令非常的轻松。

在背後,VSCodeVim提供的这两组命令本身是基於VS Code内建的「Add Curosr Above」与「Add Cursor Below」两个命令实现的。

也因此,透过这个例子直接地显示出:

「在VS Code里,结合Vim的思维,搭配适当的VS Code命令,我们可以找出相较Vim预设命令与技巧更有效率的组合。」

这并不是说,VS Code的命令就一定比较好。这需要在各个情境下、经过实际验证後,我们才会知道哪些合适的命令可以被很好的组合在一起。

上面就是一个很好的例子。

本篇小结


官方文件和官方的Roadmap目前还都没有提到这个命令,也许它只被一部分的使用者所使用吧!

至於专案贡献者们与维护者是怎麽知道有这个技巧的?是因为10000颗星星以上专案的开发者们也跟他很熟,所以有人跟他说有这个技巧可以用。然後他好棒棒,每个人都要替他拍手手吗?

笔者当然不走上面这个路线,还是套句老话:

「只要你懂XX,XX就会帮你」。

缘份到了,就知道了(认真讲一下,这是自身经验呦)。

这两组命令的设计其实是基於VS Code内建的多游标快捷键,只是VSCodeVim将这两个预设的快捷键重新绑定,并将其转为的其中一个命令或者说动作(Action)。也因此,它可以搭配数字执行,避免重复。

也就是说,如果读者本身就熟悉VS Code的内建快捷键,是很容易触类旁通,进而发现有这个命令的,只是说不见得会想到可以在与Visual Block模式相关的再把他跟命令组合,因为少了使用情境。

如果是从Vim过来使用VSCodeVim的使用者,可能不见得马上知道有这个快捷键。但如果他们不心生排斥, 等到熟悉VS Code後,他们更有潜力挖掘出更有效率的组合方法。因为客观来看,Vim的学习曲线比VS Code更高。

这个技巧并没有在《Visual Studio Code实用指南》中介绍。虽然它可以解决此一情境的问题,并且算是同类方法里的Best Practice,但对使用者而言,还是有可能自行发现这个命令的,只是对一些细节不见得那麽清楚。笔者认为最重要还是选用方法的观念与经验。而不是只学一些tips。所以在能表现连贯的思想并渐进的交代相关内容的前提下,这个tips的内容被介绍的优先度就不是最高的。

学习Vim跟VS Code的相关资源实在太多,这会造成一个问题,学习者很容易就迷失在细节里。没办法有顺序的建立起操作的习惯与思维。我认为好的书是会选择性的减少某些题材的论述的,尽管这可能让他的某些内容看起来变得简单。

关於这类技巧,之所以会用「官方文件没有详述」到这类语句是因为,客观来讲,这技巧应该是被当年贡献这些程序码的人所熟知的。它并不新,但是对不知道的使用者来讲,是有一段资讯落差。

有些难的东西付出多一点学习成本可以学到,但对於没有相关资讯的素材我们是无法直接透过文件学习并了解它的。

至於为什麽开发者们的文件不写详细一点呢?就笔者实际的例子,写文件本身非常费时也耗脑力,常常一个自己熟知的观念或操作,为了转成文字介绍给别人或初学者就要花老半天时间。开源的专案大多都是下班後进行开发的,要再写文件时间更是缺少。

除此之外,使用者的积极程度也会很大的影响专案的开发者或维护者的心情。当多数人都是在「take」而非「give」时,愿意分享的心情就会跟着低落。除非再有新的贡献者,在他们的热情尚未全部燃尽前提交出新的文件的Pull Request。不然这些隐藏的开发功能是不会自动出现在文件上的。

「尽管他们什麽都知道,但他们有什麽理由要为此而加班?」

好吧,没有掌握所有这些技巧的我们,不必心急。虽然了解这类技巧会有一定帮助,但也不用因为不知道所有技巧而着急。能够有正确的观念与学习方向,逐步解决手头上的问题就已经是很好的步调了。


<<:  Golang - 使用docker部署专案

>>:  资安学习路上-怎麽开始的

Day09 - 【概念篇】再谈身份验证与授权

本系列文之後也会置於个人网站 现在,让我们再一次把视线放到「身份验证」和「存取控制」这些名词身上。...

第5天~

2021/1/25再更新: 因为每个电脑配置都不同,所以要移动时就是要用java和xml档COPY ...

选择性抓取资料

我这次想做个在爬取资料中进行筛选的工作,这样的话以後就可以只得到我想要的关键资料了。那我就沿用上篇抓...

Day 3. 配置写VR的Unity设定

第三天的时间,我发现Hub在新增Project时,有VR范本可以使用,第一次新增使用时,需要先安装V...