2007年11月27日火曜日

VIM(GVIM)常用命令

在 文 本 中 查 找 一 个 单 词
假设你在文本中看到一个单词 "TheLongFunctionName" 而你想找到下一个相同的单词。
你可以输入 "/TheLongFunctionName",但这要输入很多东西。而且如果输错了,Vim 是
不可能找到你要找的单词的。
有一个简单的方法:把光标移到那个单词下面使用 "*" 命令。Vim 会取得光标上的
单词并把它作为被查找的字符串。
"#" 命令在反向完成相同的功能。你可以在命令前加一个计数:"3*" 查找光标下单
词第三次出现的地方。

查 找 整 个 单 词
如果你输入 "/the",你也可能找到 "there"。要找到以 "the" 结尾的单词,可以用:
/the\> "\>" 是一个特殊的记号,表示只匹配单词末尾。类似地,"\<" 只匹配单词的开头。 这样,要匹配一个完整的单词 "the",只需: /\ 这不会匹配 "there" 或者 "soothe"。注意 "*" 和 "#" 命令也使用了 "词首" 和
"词尾" 标记来匹配整个单词 (要部分匹配,使用 "g*" 和 "g#")

你可以用如下命令取得所有的标记的列表:
:marks 你会注意到有一些特殊的标记,包括:
' 跳转前的光标位置
" 最后编辑的光标位置
[ 最后修改的开始位置
] 最后修改的结束位置

快 捷 键
有些 "操作符-动作" 命令由于经常被使用,所以被设置为单字符命令:
x 表示 dl (删除当前光标下的字符)
X 表示 dh (删除光标左边的字符)
D 表示 d$ (删除到行尾)
C 表示 c$ (修改到行尾)
s 表示 cl (修改一个字符)
S 表示 cc (修改一整行)

在 什 么 地 方 加 入 计 数 前 缀
命令 "3dw" 和 "d3w" 都是删除 3 个单词。如果你非要寻根问底,那么:"3dw" 表示删
除一个单词 3 次,而 "d3w" 表示删除三个单词一次。这是一个没有分别的分别。实际上
你可以放两个计数前缀,例如,"3d2w" 删除两个单词三次,共计六个单词。

可视模式
你可以用 "v" 命令启动可视模式
如果你想对整行做操作,可以使用 "V" 命令来启动可视模式。
如果你要处理一个矩形块内的文本,可以使用 CTRL-V 启动可视模式。这在处理表格时非
常有用。

移 动 到 另 一 端
如果你在可视模式下选中了一些文字,然后你又发现你需要改变被选择的文字的另一端,
用 "o" 命令即可 (提示:"o" 表示 other end),光标会移动到被选中文字的另一端,现
在你可以移动光标去改变选中文字的开始点了。再按 "o" 光标还会回到另一端。
当使用列块可视模式的时候,你会有四个角,"o" 只是把你移到对角上。而用 "O" 则能
移到同一行的另一个角上。
备注: "o" 和 "O" 在可视模式下与在普通模式下的作用有很大的不同;在普通模式下,
它们的作用是在光标后或前加入新的一行。

拷贝文本
注意:"yw" 命令包括单词后面的空白字符。如果你不想要这个字符,改用 "ye" 命令。
"yy" 命令拷贝一整行,就像 "dd" 删除一整行一样。出乎意料地是,"D" 删除到行尾而
"Y" 却是拷贝一整行。要注意这个区别!"y$" 拷贝到行尾。

使用剪贴板
如果你用的不是 GUI,或者你根本不喜欢用菜单,你只能用其它办法了。你还是可以用普
通的 "y" (yank) 和 "p" (put) 命令,但在前面必须加上 "* (一个双引号加一个星
号)。例如,要拷贝一行到剪贴板中:
"*yy 要粘贴回来:
"*p 这仅在支持剪贴板的 Vim 版本中才能工作。

文本对象
如果你在一个单词的中间而又想删掉这个单词,在你用 "dw" 前,你必须先移到这个单词
的开始处。这里还有一个更简单的方法:"daw"。
"daw" 的 "d" 是删除操作符。"aw" 是一个文本对象。提示:"aw" 表示 "A Word" (一个
单词),这样,"daw" 就是 "Delete A Word" (删除一个单词)。确切地说,该单词后的空
格字符也被删除掉了。

使用文本对象是 Vim 中执行修改的第三种方法。我们已经有 "操作符-动作" 和可视模
式两种方法了。现在我们又有了 "操作符-文本对象"。
这种方法与 "操作符-动作" 很相似,但它不是操作于从当前位置到移动目标间的内
容,而是对光标所在位置的 "文本对象" 进行操作。文本对象是作为一个整体来处理的。
现在光标在对象中的位置无关紧要。

用 "cis" 可以改变一个句子。看下面的句子:

Hello there. This
is an example. Just
some text.

移动到第二行的开始处。现在使用 "cis":

Hello there. Just
some text.

现在你输入新的句子 "Another line.":

Hello there. Another line. Just
some text.

"cis" 包括 "c" (change,修改) 操作符和 "is" 文本对象。这表示 "Inner Sentence"
(内含句子)。还有一个文本对象是 "as",区别是 "as" 包括句子后面的空白字符而 "is"
不包括。如果你要删除一个句子,而且你还想同时删除句子后面空白字符,就用 "das";
如果你想保留空白字符而替换一个句子,则使用 "cis"。

你还可以在可视模式下使用文本对象。这样会选中一个文本对象,而且继续留在可视模
式,你可以继续多次执行文本对象命令。例如,先用 "v" 启动可视模式,再用 "as" 就
可以选中一个句子。现在重复执行 "as",就会继续选中更多的句子。最后你可以使用一
个操作符去处理这些被选中的句子。

你可以在这里找到一个详细的文本对象的列表:|text-objects|。
动作和操作符

动作命令出现在操作符之后,从而使操作符作用于被该动作所跨越的文本之上。也就 是,在动作之前和之后的光标位置之间的文本。一般的,操作符用来删除或者改变文本。 下面列出所有的操作符: |c| c 修改 (change)
|d| d 删除 (delete)
|y| y 抽出 (yank) 到寄存器 (不改变文本)
|~| ~ 变换大小写 (只有当 'tildeop' 置位时有效)
|g~| g~ 变换大小写
|gu| gu 变为小写
|gU| gU 变为大写
|!| ! 通过外部程序过滤
|=| = 通过 'equalprg' (若为空,C-indenting) 过滤
|gq| gq 文本排版
|g?| g? ROT13 编码
|>| > 右移
|<| < 左移 |zf| zf 定义折叠
|g@| g@ 调用 'operatorfunc' 选项定义的函数
预 定 义 标 记
当你跳转到另一个文件后,有两个预定义的标记非常有用:
`" 这个标记使你跳转到你上次离开这个文件时的位置。
另一个标记记住你最后一次修改文件的位置:
`.
假设你在编辑 "one.txt",在文件中间某个地方你用 "x" 删除一个字符,接着用 "G" 命
令移到文件末尾,然后用 "w" 存盘。然后你又编辑了其它几个文件。你现在用 ":edit
one.txt" 回到 "one.txt"。如果现在你用 `",Vim 会跳转到文件的最后一行;而用 `.
则跳转到你删除字符的地方。即使你在文件中移动过,但在你修改或者离开文件前,这两
个标记都不会改变。

文 件 标 记

在第四章,我们介绍过使用 "mx" 命令在文件中增加标记,那只在一个文件中有效。如果
你编辑另一个文件并在那里加了标记,这些标记都是这个文件专用的。这样,每个文件都
有一个自己的标记集,并只能在该文件中使用。
到此为止,我们都用小写字母的标记。实际上还可以使用大写字母标记,这种标记是
全局的,它们可以在任何文件中使用。例如,你在编辑一个文件 "foo.txt"。在文件的中
间 (50%) 并建立一个 J 标记 (J 表示甲):

50%mJ
现在编辑文件 "bar.txt" 并在文件的最后一行放一个标记 Y (Y 表示乙):

GmY
现在你可以使用 "`J" 命令跳回到 foo.txt 的中间。或者在另一个文件中输入 "`Y" 跳
回到 bar.txt 的末尾。

文件标记会被一直记住直到被重新定义。这样,你可以在一个文件中留下一个标记,然后
任意做一段时间的编辑,最后用这个标记跳回去。
让文件标记符和对应的位置建立一些关系常常是很有用的。例如,用 H 表示头文件
(Head File),M 表示 Makefile 而 C 表示 C 的代码文件。

要知道一个标记在什么地方,在 ":marks" 命令中加上标记名作为参数即可:

:marks M
你还可以带多个参数:

:marks MCP
别忘了你还可以 CTRL-OCTRL-I 在整个跳转序列中前后跳转。
用 vimdiff 显示文件差异

有一种特殊的启动 Vim 的方法可以用来显示两个文件的差异。让我们打开一个 "main.c" 并插入一些字符。在设置了 'backup' 选项的情况下保存这个文件,以便产生 "main.c~" 备份文件。 在命令行中输入如下命令:(不是在 Vim 中) vimdiff main.c~ main.c Vim 会用垂直分割的方式打开两个文件。你只能看到你修改过的地方和上下几行的地方。
折 叠 栏

每个窗口在左边都有一个颜色略有不同的显示栏,图中标识为 "VV"。你会发现每个折叠
在那个位置都有一个加号。把鼠标移到那里并按左键可以打开那个折起,从而让你看到里
面的内容。
对于打开的折叠,折叠栏上会出现一个减号。如果你单击那个减号,折叠会被重新关
闭。
当然,这只能在你有鼠标的情况下使用。如果你没有,可以用 "zo" 打开一个折叠。
关闭使用 "zc"。

用 Vim 做 比 较

启动比较模式的另一种方法从 Vim 内部开始:编辑 "main.c" 文件,然后分割窗口显示
区别:

:edit main.c
:vertical diffsplit main.c
":vertical" 命令使窗口用垂直的方式分割。如果你不写这个命令,结果会变成水平分
割。

如果你有一个当前文件的补丁或者 diff 文件,你可以用第三种方法启动比较模式:先编
辑这个文件,然后告诉 Vim 补丁文件的名称:

:edit main.c
:vertical diffpatch main.c diff
警告:补丁文件中必须仅包括为一个目标文件所做的补丁,否则你可能会得到一大堆错误
信息。还可能有些你没打算打补丁的文件也被打了补丁。
补丁功能只改变内存中的文件备份,不会修改你硬盘上的文件 (除非你决定写入改
动)。

滚 动 绑 定

当文件中有很多改动时,你可以用通常的方式滚动屏幕。Vim 会尽可能保持两个文件对
齐,以便你可以并排看到文件的区别。
如果暂时想关闭这个特性,使用如下命令:

:set noscrollbind

跳 转 到 修 改 的 地 方

如果你通过某种方法取消了折叠功能,可能很难找到有改动的地方。使用如下命令可以跳
转到下一个修改点:

]c
反向跳转为:

[c
加上一个计数前缀可以跳得更远。

消 除 差 异

你可以把文本从一个窗口移到另一个,并以此来消除差异,或者为其中一个文件中增加几
行。Vim 有时可能无法及时更新高亮显示。要修正这种问题,使用如下命令:

:diffupdate
要消除差异,你可以把一个高亮显示的块从一个窗口移动到另一个窗口。以上面的
"main.c" 和 "main.c~" 为例,把光标移到左边的窗口,在另一个窗口中被删除的行的位
置,执行如下命令:

:dp
这将把文字从左边拷到右边,从而消除两边的差异。"dp" 代表 "diff put"。
你也可以反过来做:把光标移到右边的窗口,移到被 "改动" 了的行上,然后执行
如下命令:

:do
这把文本从左边拷到右边,从而消除差异。
由于两个文件已经没有区别了,Vim 会把所有文字全部折叠起来。"do" 代表 "diff
obtain"。本来用 "dg" (diff get) 会更好。可是它已经有另外的意思了 ("dgg" 删除从
光标为止到首行的所有文本)。
标签页
假设你正在编辑文件 "thisfile"。下面的命令可以建立新的标签页:

:tabedit thatfile
这会在一个窗口中编辑文件 "thatfile",这个窗口会占满整个 Vim 窗口。你会注意到在
顶部有一个含有两个文件名的横条:
你可以通过单击顶端的标签切换标签页。如果没有鼠标或者不想用它,可以使用 "gt" 命
令。助记符:Goto Tab。

现在,让我们通过下面的命令建立另一个标签页:

:tab split
这会建立一个新的标签页,包含一个窗口,编辑和刚才所在窗口中的缓冲区相同的缓冲
区:
在任何打开窗口的 Ex 命令前面,你都可以放上 ":tab"。这个窗口在新标签页中打开。
另一个例子:

:tab help gt
它将在新的标签页中显示关于 "gt" 的帮助。

使用标签页可以完成更多的工作:

- 在末尾标签后面的空白处单击鼠标
选择下个标签页,同 "gt"。

- 在右上角的 "X" 处单击鼠标
关闭当前标签页,除非当前标签页中的改变没有保存。

- 在标签行上双击鼠标
建立新标签页。

- "tabonly" 命令
关闭除了当前标签页以外的所有标签页,除非其它标签页中的改变没有保存。

关于标签页更多的信息,参见 |tab-page|。
反转行顺序

|:global| 命令可以和 |:move| 命令联用,将所有行移动到文件首部。结果是文件被按 行反转了次序。命令是: :global/^/m 0 缩写: :g/^/m 0 正则表达式 "^" 匹配行首 (即使该行是一个空行)。|:move| 命令将匹配的行移动到那个 神秘的第 0 行之后。这样匹配的行就成了文件中的第一行。由于 |:global| 命令不会被 改变了的行号搞混,该命令继续匹配文件中剩余的行并将它们一一变为首行。 这对一个行范围同样有效。先移动到第一行上方并做标记 't' (mt)。然后移动到范围的 最后一行并键入: :'t+1,.g/^/m 't

单词统计

有时你要写一些有最高字数限制的文字。Vim 可以帮你计算字数。 如果你需要统计的是整个文件的字数,可以用这个命令:

g CTRL-G

不要在 "g" 后面输入一个空格,这里只是方便阅读。 它的输出是:

Col 1 of 0; Line 141 of 157; Word 748 of 774; Byte 4489 of 4976 (译者注:中文是:
第 1/0 列; 第 141/157 行; 第 748/774 个词; 第 4489/4976 个字节 )

你可以看到你在第几个单词 (748) 上以及文件中的单词总数 (774)。
如果你要知道的是全文的一部分的字数,你可以移到该文本的开头,输入 "g CTRL-G",
然后移到该段文字的末尾,再输入 "g CTRL-G",最后心算出结果来。
这是一种很好的心 算练习,不过不是那么容易。比较方便的办法是使用可视模式,选中你要计算字数的文 本,然后输入 "g CTRL-G",结果将是: Selected 5 of 293 Lines; 70 of 1884 Words; 359 of 10928 Bytes (译者注:中文是: 选择了 5/293 行; 70/1884 个词; 359/10928 个字节 ) 要知道其它计算字数,行数和其它东西总数的方法,可以参见 |count-items|。
查阅 man 信息

编辑一个脚本文件或者 C 程序的时候,有时你会需要从 man 手册中查询某个命令或者函
数的用法 (使用 Unix 的情况下)。让我们先用一个简单的方法:把鼠标移到对应的单词
上然后输入:

K
Vim 会在对应的单词上执行外部命令:man。如果能找到相应的手册,那个手册页就会被
显示出来。它常常用 more 一类的程序显示页面。在手册滚动到文件末并回车,控制就会
回到 Vim 中。

这种方法的缺点是你不能同时查看手册和编辑文档。这里有一种办法可以把手册显示到一
个 Vim 的窗口中。首先,加载 man 文件类型的外挂:

:runtime! ftplugin/man.vim
如果你经常用到这种方法,可以把这个命令加到你的 vimrc 文件中。现在你可以用
":Man" 命令打开一个显示 man 手册的窗口了:

:Man csh
你可以在这个新的窗口中上下滚动,而手册的本文会用语法高亮的形式显示。这样,你可
以找到需要的地方,并用 CTRL-W w 跳转到原来的窗口中继续工作。
要指定手册的章节,可以在手册名称前面指定。例如,要找第三章的 "echo":

:Man 3 echo
要跳转到另一个由 "word(1)" 形式定义的手册,只要在上面敲 CTRL-]。无论怎样,
":Man" 命令总使用同一个窗口。

要显示当前光标下的单词的手册,这样:

\K
(如果你重定义了 ,用那个字符代替上面命令的反斜杠)。
例如,你想知道下面语句中的 "strstr()" 函数的返回值:

if ( strstr(input, "aap") == )

可以把光标移到 "strstr" 并输入 "\K"。手册使用的窗口会显示 strstr() 的信息。

使 用 XXD
一个真正的二进制编辑器用两种方式来显示文本: 二进制和十六进制格式。你可以在 Vim
里通过转换程序 "xxd" 来达到这效果。该程序是随 Vim 一起发布的。
首先以二进制方式编辑这个文件:

vim -b datafile
现在用 xxd 把这个文件转换成十六进制:

:%!xxd
文本看起来像这样:

0000000: 1f8b 0808 39d7 173b 0203 7474 002b 4e49 ....9..;..tt.+NI
0000010: 4b2c 8660 eb9c ecac c462 eb94 345e 2e30 K,.`.....b..4^.0
0000020: 373b 2731 0b22 0ca6 c1a2 d669 1035 39d9 7;'1.".....i.59.

现在你可以随心所欲地阅读和编辑这些文本了。 Vim 把这些信息当作普通文本来对待。
修改了十六进制部分并不导致可显示字符部分的改变,反之亦然。
最后,用下面的命令把它转换回来:

:%!xxd -r
只有十六进制部分的修改才会被采用。右边可显示文本部分的修改忽略不计。

欲知更多详情,参见 xxd 手册。

补 全 特 定 文 本

如果你知道你要找什么,那么你可以用这些命令来补全某种类型的文本:

CTRL-X CTRL-F 文件名
CTRL-X CTRL-L 整行
CTRL-X CTRL-D 宏定义 (包括包含文件里的)
CTRL-X CTRL-I 当前文件以及所包含的文件
CTRL-X CTRL-K 字典文件内的单词
CTRL-X CTRL-T 同义词词典文件内的单词
CTRL-X CTRL-] 标签
CTRL-X CTRL-V Vim 命令行
    CTRL-X CTRL-O 全能补全的热键

每个命令之后,CTRL-N 可以用来搜索下一个匹配,而 CTRL-P 则用于搜索前一个匹配。
重复一次插入
如果你按 CTRL-A,编辑器就把你上次在插入模式下输入的文本再输入一次。
比如,假定你有个文件,开头是这样的:

"file.h"
/* Main program begins */

你在第一行开始处插入 "#include ":

#include "file.h"
/* Main program begins */

你再用命令 "j^" 往下来到下一行的开始处。现在你开始插入一个新的 "#include" 行。
所以你键入:

i CTRL-A
结果就像下面这样:

#include "file.h"
#include /* Main program begins */

"#include " 被插入是因为 CTRL-A 会插入上次插入过的文本。现在你键入 "main.h"
以结束这一行:


#include "file.h"
#include "main.h"
/* Main program begins */

CTRL-@ 命令会完成 CTRL-A 的操作后退出插入模式。这是一个快速重复插入一模一样的
文本的一个方法。
从另一行拷贝
CTRL-Y 命令插入光标上方的字符。当你复制前一行文本的时候,这个命令很有用。例
如,你有这么一行 C 代码:

b_array[i]->s_next = a_array[i]->s_next;

现在你需要把这一行再键入一次,并以 "s_prev" 取代 "s_next"。换行以后,按 14 次
CTRL-Y,直到光标位于 "next" 的 "n" 上:

b_array[i]->s_next = a_array[i]->s_next;
b_array[i]->s_

现在你键入 "prev":

b_array[i]->s_next = a_array[i]->s_next;
b_array[i]->s_prev

继续按 CTRL-Y 直到下一个 "next":

b_array[i]->s_next = a_array[i]->s_next;
b_array[i]->s_prev = a_array[i]->s_

现在键入 "prev;" 以结束这一行。

CTRL-E 命令操作起来跟 CTRL-Y 一样,只不过它插入光标下方的字符。
插入一个寄存器内容
命令 CTRL-R {register} 插入寄存器里的内容。它的用处是让你不必键入长词。例如,
你要输入下面这些:

r = VeryLongFunction(a) + VeryLongFunction(b) + VeryLongFunction(c)

这个函数的定义见于另一个文件。编辑那个文件并把光标移到该函数名上,然后把文件名
摄入寄存器 v:

"vyiw
"v 指定寄存器,"yiw" 意思是拷贝一个词,不含空格 (yank-inner-word)。现在编辑那
个要插入一行代码的文件,先键入开头几个字符:

r =

现在用 CTRL-R v 来插入函数名:

r = VeryLongFunction

你接下来在函数名后面键入其它必要字符,然后再用两次 CTRL-R v。
你也可以用补全功能来完成同样的工作。但当你有好几个词,其开头几个字符都一样
的时候,寄存器就有用多了。

如果寄存器存放着诸如 或其它特殊字符,这些字符就被解释成好像它们本来是从键
盘键入的。如果你不要这样解释 (你确实要在文本中插入 ),那么要命令 CTRL-R
CTRL-R {register}

0 件のコメント: