×

vi 命令手册

vi/vim 命令大全

vim 命令手册

Vim 关于Vim 安装Vim 用法Vim 配置vim 配置.vimrc方案vim 配置.vimrc方案1vim 配置.vimrc方案2Vim 文件合并Vim 技巧和建议Vim 插件Vim 参阅

Vimscript 编程参考

Vimscript 前言Vimscript 鸣谢Vimscript 预备知识Vimscript 打印信息Vimscript 设置选项Vimscript 基本映射Vimscript 模式映射Vimscript 精确映射Vimscript LeadersVimscript 编辑你的Vimrc文件Vimscript AbbreviationsVimscript 更多的MappingsVimscript 锻炼你的手指本地缓冲区的设置和映射Vimscript 自动命令Vimscript 本地缓冲区缩写Vimscript 自动命令组Operator-Pending 映射Operator-Pending 更多映射Vimscript 状态条Vimscript 负责任的编码Vimscript 变量Vimscript 变量作用域Vimscript 条件语句Vimscript 比较Vimscript 函数Vimscript 函数参数Vimscript 数字Vimscript 字符串Vimscript 字符串函数Vimscript Execute命令Vimscript Normal命令Vimscript 执行normal!Vimscript 基本的正则表达式Grep 运算符Operator 第1部分Grep 运算符Operator 第2部分Grep 运算符Operator 第3部分Vimscript 列表Vimscript 循环Vimscript 字典Vimscript 切换Vimscript 函数式编程Vimscript 路径Vimscript 创建一个完整的插件Vimscript 基本插件配置方式用Pathogen配置插件Vimscript 检测文件类型Vimscript 基本语法高亮Vimscript 高级语法高亮Vimscript 基本折叠Vimscript 高级折叠Vimscript 段移动原理Vimscript Potion段移动Vimscript 外部命令Vimscript 自动加载Vimscript 文档Vimscript 发布Vimscript 还剩下什么?

Vimscript 实例研究:Grep 运算符(Operator),第一部分


在本章和下一章中,我们将使用Vimscript来实现一个相当复杂的程序。我们将探讨一些闻所未闻的东西, 也将在实战中把之前学过的东西联系起来。

在本实例研究中,遇到不熟悉的内容,你得用:help弄懂它。如果你只是走马观花,就将所获无多。

Grep

如果你未曾用过:grep,现在你应该花费一分钟读读:help :grep:help :make。 如果之前没用过quickfix window,阅读:help quickfix-window

简明扼要地说::grep ...将用你给的参数来运行一个外部的grep程序,解析结果,填充quickfix列表, 这样你就能在Vim里面跳转到对应结果。

我们将会添加一个"grep运算符"到任意Vim的内置(或自定义!)的动作中,来选择想要搜索的文本, 让:grep更容易使用。

用法

在写下每一个有意义的Vimscript程序的第一步,你需要思索一个问题:“它会被用户怎么使用呢?”。 尝试构思出一种优雅,简易,符合直觉的调用方法。

这次我会替你把这活干了:

  • 我们将创造一个"grep运算符"并绑定到g
  • 它将表现得同其他任意Vim运算符一样,还可以加入到组合键(比如wi{)中。
  • 它将立刻开始搜索并打开quickfix窗口展示结果。
  • 它将_不会_跳到第一个结果,因为当第一个结果不是你想要的时候,这样做会困扰你。

一些你将怎么使用它的用例:

  • giw: Grep光标下的词(word)。
  • giW: Grep光标下的词的大写形式(WORD)。
  • gi': Grep当前所在的单引号括住的词。
  • viweg: 可视状态下选中一个词并拓展选择范围到下一词,然后Grep。

有很多,_很多_其他的方法可以用它。看上去它好像需要写很多,很多代码, 但事实上我们只需要实现"运算符"功能然后Vim就会完成剩下的工作。

一个原型

在埋头写下巨量(trickey bits)的Vimscript之前,有一个也许会帮上忙的方法是简化你的目标并实现, 来推测你最终解决方案可能的"外形"。

让我们简化我们的目标为"创造一个映射来搜索光标下的词"。这有用而且应该更简单,所以我们能更快得到可运行的成果。 目前我们将映射它到g

我们从一个映射骨架开始并逐渐填补它。执行这个命令:

:nnoremap g :grep -R something .

如果你阅读过:help grep,你就能轻易理解这个命令。我们之前也看过许多映射,这里没有什么是新的。

显然我们还没做什么,所以让我们一步步打磨这个映射直到它符合我们的要求。

搜索部分

首先我们需要搜索光标下的词,而不是something。执行下面的命令:

:nnoremap g :grep -R  .

现在试一下。是一个Vim的command-line模式的特殊变量, Vim会在执行命令之前把它替换为"光标下面的那个词"。

你可以使用来得到大写形式(WORD)。执行这个命令:

:nnoremap g :grep -R  .

现在试试把光标放在诸如foo-bar的词上面。Vim将grepfoo-bar而不是其中的一部分。

我们的搜索部分还有一个问题:如果这里面有什么特殊的shell字符,Vim会毫不犹豫地传递给外部的grep命令。 这样会导致程序崩溃(或更糟:铸成某些大错)。

让我们看看如何使它挂掉。输入foo;ls并把光标放上去执行映射。grep命令失败了, 而Vim将执行ls命令!这肯定糟透了,如果词里包括比ls更危险的命令呢?

为了解决这个问题,我们将调用参数用引号括起来。执行这个命令:

:nnoremap g :grep -R '' .

大多数shell把单引号括起来的内容当作(大体上)字面量,所以我们的映射现在更加健壮了。

转义Shell命令参数

搜索部分还有一个问题。在that's上尝试这个映射。它不会工作,因为词里的单引号与grep命令的单引号发生了冲突!

为了解决问题,我们可以使用Vim的shellescape函数。 阅读:help escape():help shellescape()来看它是怎样工作的(真的很简单)。

因为shellescape()要求Vim字符串,我们需要用execute动态创建命令。 首先执行下面命令来转换:grep映射到:execute "..."形式:

:nnoremap g :execute "grep -R '' ."

试一下并确信它可以工作。如果不行,找出拼写错误并改正。 然后执行下面的使用了shellescape的命令。

:nnoremap g :execute "grep -R " . shellescape("") . " ."

在一般的词比如foo上执行这个命令试试。它可以工作。再到一个带单引号的词,比如that's,上试试看。 它还是不行!为什么会这样?

问题在于Vim在拓展命令行中的特殊变量,比如,的之前,就已经执行了shellescape()。 所以Vim shell-escaped了字面量字符串""(什么都不做,除了给它添上一对单引号)并连接到我们的grep命令上。

通过执行下面的命令,你可以亲眼目睹这一切。

:echom shellescape("")

Vim将输出''。注意引号也是输出字符串的一部分。Vim把它作为shell命令参数保护了起来。

为解决这个问题,我们将使用expand()函数来强制拓展为对应字符串, 抢在它被传递给shellescape之前

让我们单独看看这一部分是怎么工作的。把你的光标移到带单引号的词(比如that's)上去, 并执行下面命令:

:echom expand("")

Vim输出that's,因为expand("")以Vim字符串的形式返回当前光标下的词。 是时候加入shellescape的部分了:

:echom shellescape(expand(""))

这次Vim输出'that'''s'。 如果觉得这看上去真可笑,你大概没有感受过看透了各种shell转义的疯狂形式后的淡定吧。 目前,不用为此而纠结。就相信Vim接受了expand的输出并正确地转义了它。

目前我们已经得到了光标下的词的彻底转义版本。是时候连接它到我们的映射了! 执行下面的命令:

:nnoremap g :exe "grep -R " . shellescape(expand("")) . " ."

试一下。这个映射不再有问题,即使我们用它搜索带古怪符号的词。

"从简单的Vimscript开始并一点点转变它直到达成你的目标"这样的工作方式将会被你一再取用。

整理整理

在完成映射之前,还要处理一些小问题。首先,我们说过我们不想自动跳到第一个结果, 所以要用grep!替换掉grep。执行下面的命令:

:nnoremap g :execute "grep! -R " . shellescape(expand("")) . " ."

再一次试试,发现什么都没发生。Vim用结果填充了quickfix窗口,我们却无法打开。 执行下面的命令:

:nnoremap g :execute "grep! -R " . shellescape(expand("")) . " .":copen

现在试试这个映射,你将看到Vim自动打开了包含搜索结果的quickfix窗口。 我们所做的仅仅是在映射的结尾续上:copen

最后一点,在搜索的时候,我们要移除Vim所有的grep输出。执行下面的命令:

:nnoremap g :silent execute "grep! -R " . shellescape(expand("")) . " .":copen

我们完成了,试一试并犒劳一下自己吧!silent命令仅仅是在运行一个命令的同时隐藏它的正常输出。

练习

把我们刚刚做出来的映射加入到你的~/.vimrc文件。

如果你未曾读过:help :grep,去读它。

阅读:help cword

阅读:help cnexthelp cprevious。修改你的grep映射,试一下它们。

设置:cnext:cprevious的映射,让在匹配内容间的移动更加方便。

阅读:help expand

阅读:help copen

在我们创建的映射中加入height参数到:copen命令中,看看quickfix窗口能不能以指定的高度打开。

阅读:help silent


分类导航

关注微信下载离线手册

bootwiki移动版 bootwiki
(群号:472910771)