YongSir

专业程序员伪装者

vim拾遗之- better motion

趁着同事那儿借来《Vim使用技巧》的机会,重新梳理一下Vim的常见使用技巧,记录于此
虽说Vim平时用的很多,自认为还是比较熟练的,但直到看到这本书,才知道原来自己用了假的Vim,很多技巧性的组合可以让人耳目一新,效率提高不止一倍,尤其记住书中所言:

在Vim中所有的操作通常都会有更加便捷版本,比如在移动光标时,一旦连续按了2次以上的h,那就意味着浪费时间,停下来想想能不能更简单

当然按作者的苛刻标准绝大多数所谓vimer都是妄称,但这并不妨碍我们对工具的精益求精,配置方面,按照我自己的习惯,有2点建议供参考:
1 在vim中通常首先废弃方向键 + delete键,尤其是初学者
2 中文输入发的问题,基本上这是个无解的问题,能做到最好的就是当从中文inert下Esc时,自动切换到英文输入法,不过也仅仅是这样了

废话不多说了,下边开始记录:

更好的motion

  • 只用h/l键来解决差一错误(off-by-one error),即当目标差一两个字符时才去用
  • 启用行号,区分实际行和显示行,毕竟通常大家都是启用wrap 的,所以在行号的辅助下区分二者很重要
  • 同行多行显示下,移动用gj/g^/g$/g0/gk而不是j/^/$/0/k来操作显示行
  • 使用w,b,e,ge基于单词移动更好,借用这张图:
    基于单词移动
    并且将常见操作组合记忆,如cw就和change word很贴合,ea就是添加单词尾部等
  • 最好的移动永远是查找

    • ; + ,配合f{char}能决绝99%的问题,特别提醒 别把方向字符查找弃之不用 ,当然如果是中文就歇菜了
    • t{char}d/c合用更配噢 ,eg:

      1
      2
      3
      function foo(x: Int, y: int)
      // f,dt)操作之后,变为
      function foo(x: Int)
    • v + t/f{char} + d/c/y 比鼠标托选精准高效一万倍

      1
      2
      3
      console.log('This phrase takes time but eventually gets to the point')
      // 想删除'takes time but eventully',可以ftvfyd即可
      console.log('This phrase gets to the point')
  • 结构化文本结构化处理:
    vim既然是码农的神器,那么对于结构化文本处理能力自然是没得说,只是使用并不不及,是时候应该主注重这方面的锻炼了– 文本对象字符由2个字符组成,第一个永远是i 或者 a,通常以i开头的文本对象会选择分割符内部文本,而已a开头的文本对象会将分割符包含在内,为了记忆不妨把i读成insidea就是around/all, eg:
    结构化文本结构化处理
    熟练掌握vim结构化处理是一个vimer的基本内功,特别是在前端或者简单的脚本语言编程中,使用的尤其多,总结一下常见分割符文本对象的操作:

    1
    2
    3
    4
    5
    6
    a) 或者 ab  // 对应()
    i) 或者 ib // 对应()内部
    a} 或者 aB // 对应{}
    a> // 对应<>
    at // 对应 一对xml标签
    it // 对应 xml标签内部

    第一个例子中特意给出v可视化模式下是为了方便观察,而在操作符待决模式下才能真正展现其强大的能力,配合c / d / y + i / a + {char}才能让你键码齐飞,高效异常,eg:

    1
    2
    3
    4
    5
    <a href="#">ABOUT</a>
    <!-- 光标启示在#,ci"之后,输入http://github.com -->
    <a href="http://github.com">ABOUT</a>
    <!-- 紧接着输入cit 加上 github,就完成了编辑-->
    <a href="http://github.com">github</a>

    不少人都是单独的把ci"解读为修改双引号内部内容,把cit解读为修改标签内部内容,同样dit删除标签内部内容,其实都是文本化操作的产物,完全没有必要去死记硬背

  • 非块级问对对象的操作:按单词w-word,按句子s-sentence,按段落p-paragraph
    其实这一点在前边的按单词操作中已经有所涉及,但结合机构化的操作能有很多意想不到的高效体验,常见的如:

    1
    2
    3
    4
    5
    Improve your writing bu deleting excellent adjectives.
    // fx 光标到excellent, 然后 daw
    Improve your writing bu deleting adjectives.
    // 如果上述是 diw, 就会出现2个空格
    Improve your writing bu deleting adjectives.

    可见awiw得区别很细微,如果不好记忆,不妨想我一样只去记忆i表示inside1之意,其他的它是不管的,接着上面的例子,如果只是想把单词改变, eg:

    1
    2
    3
    Improve your writing bu deleting excellent adjectives.
    // fx ,然后 ciw 加上修改的单词 most
    Improve your writing bu deleting most adjectives.

    所以总结起来就是:
    d + aw / as / ap比较好,而ciw / is 更配

  • 善用自动标记完成移动
    vim的基本操作中其实没有必要涉及到使用m{char},系统为我们提供了很多自动的标记,它指示了一些简单的行为,如上次修改位置,上次插入位置,以及括号之间的移动,like this:

    1
    2
    3
    4
    5
    ``   // 上次跳转动作之前的位置--相当于<C-o>
    `. // 上次更改位置
    `^ // 上次插入位置
    `[/] // 上次c或y的启示/结束
    % // 括号之间的跳转

    特别提醒,括号跳转时,往往要配合标记跳转一起来使用,如下面的ruby代码要将}变为],这里就有一个小陷阱,因为%只会在同级括号键自动跳转,如果直接使用r]就不再能跳转到末尾的],所以正确的做法是:

    1
    2
    3
    4
    5
    cities = %w { london,berlin,nweYourk}
    # dt{ 然后不忙r[ 而是% 跳转到末尾的'}'
    # 然后现更改最后的} 为 ]
    # 在``会光标的上一位置,再r[
    cities = %w [ london, berlin, nweYourk]

    好吧,的确有点儿繁琐,肯定有更好的办法,不过配合光标标记还是完成了

上边的操作都很基本,可以说每个人都会,但vim不是知识而是一种技能,常常练习才能真正的实现手眼并举,编码齐飞