Vim 学习手记(七) --- 程序员专用福利(下)

 2010年01月22日 星期五 21:19 | 3780次浏览 | 4条评论


    Vim有一个叫"quickfix"的命令集. 这些命令可以让程序员在Vim中编辑程序, 如果编译器报告了程序的错误, 你还能在这些错误中自由遍历, 修补后再重新编译, 如此反复, 直到你的程序编译无误为止.

下面的命令运行程序"make"(如果你要跟什么参数的话, 直接放在后面就行了)并捕捉它可能的错误:
:make {arguments}
如果有错误产生, Vim会自动将光标定位于第一个错误的事发地点.

下面的命令会带你到下一个错误的事发地点:
:cnext

屏幕上可用的空间紧张时, Vim会缩减必需显示的错误信息.要查看完整的错误信息描述, 使用下面的命令:
:cc

":clist"命令会列出一个所有错误信息的列表, 输出的信息类似于:

:clist
3 main.c: 6:too many arguments to function 'do_sub'
5 main.c: 10:parse error before '}'

这里只列出了包含文件名和一个行号的简要信息, Vim认为这些对于理解一个错误是最重要的, 其它的行相对就没那么要紧了. 然而事实上有时候被忽略掉的那些行正是你想要的东西. 比如链接器报告说哪个函数没有定义. 这只要在":clist"命令后加一个"!"就可以列出完整的错误信息列表
:clist!

Vim会以特殊颜色显示当前的错误. 要回到前一个错误去, 使用命令:
:cprevious

此外还有一些其它的命令用于遍历整个错误列表:
:cfirst  到第一个错误处
:clast   到最后一个错误处
:cc 3    到第3个错误处

'makeprg'选项定义了":make"命令被执行时要实际调用的外部程序. 通常情况是"make"程序, 不过Visual C++的用户就需要把它定义为"nmake" :
:set makeprg=nmake
这个选项中还可以跟上命令的参数, 注意其中的特殊字符要用反斜杠来特殊处理:
set makeprg=nmake -f project.mak

在这个选项1 中还可以引用一些Vim的关键字. 字符%代表当前的文件名. 所以如果你这样设置该选项:
:set makeprg=make %

当你编辑的文件是main.c时, ":make"命令就会实际执行:
make main.c
这在实际中用处不大, 最好是对上面的设定稍事调整, 使用:r这个修饰标志:
:set makeprg=make %:r.o
现在命令执行起来就是:
make main.o


//上一个错误列表
    假设你正在用命令":make"来构建一个程序, 编译过程中出现了两个错误2 , 一个是位于某个源文件中的一个警告, 另一个是位于另一个是位于另一源文件中的错误.

一般来说你会先去修改产生了"错误"的源文件, 然后重新编译该文件以检查是否真正排除了这个错误, 但是现在你却不能在现在的错误列表中看到刚才的那个警告信息了, 因为这一次的":make"只是针对产生错误的这一个文件, 而不是整个项目 .

还好, Vim在内部维护了一个关于错误列表的列表.每次的":make"命令都会产生一个错误列表, 多次执行":make"就形成一个关于错误列表的列表, 你可以用下面的命令回到前一个错误列表:
 :colder

现在你就可以使用":clist"命令和":cc {nr}"命令来针对前一个错误清单进行操作, 回到刚才引起warning的位置了. 要向前查看下一个错误清单, 使用下面的命令:
:cnewer

Vim可以同时记住10个错误清单列表.


如此诱人的功能不是白给的, 你得告诉Vim你所用的编译器产生的错误信息的格式是什么样子. 这可以通过对'errorformat'选项的设置来完
成.
该选项的语法略有些复杂不过也正因为如此它才可以应用于几乎是任何的编译器.

有可能你在工作中要使用不同的编译器.不过每次都去分别设置'makeprg'和'errorformat可不是一件容易的事. Vim为此提供了一个简易办法, 比如说, 现在你要切换到使用Microsoft Visual C++的编译器就可以使用下面的命令:
:compiler msvc

这个命令会自动查看关于"msvc"这个编译器设置的Vim脚本并应用里面的设置. 你也可以自己量身打造这样一个为某种编译器进行设置的脚本文件.


//输出重定向
":make"命令的幕后工作是把编译过程的输出重定向到一个记录错误信息的文件中. 这个过程需要几个Vim选项的紧密配合, 比如'shell'.  果你的":make"命令不能捕获错误,请检查'makeef'和'shellpipe'这两个选项, 'shellquote'和'shellxquote'的设置也可能与此有关.

如果你不能把":make"命令重定向到文件, 还有别的办法, 你还可以单独编译程序并把编译输出重定向到一个文件中, 然后使用下面的命令读取这个错误信息文件:
:cfile {filename}
这会跟使用":make"命令一样能让你跳转到出错地点去.


//C程序的缩进
   程序缩进得当的话会大大提高可读性. Vim有几种措施来协助进行缩进.

   对C程序来说打开'cindent'选项即可, Vim对C程序有良好的支持, 它会为你的C程序以良好的风格缩进做大量的工作. 对于多级缩进你还可以通过'shiftwidth'选项的值来调整缩进量. 4个空格是一个不错的选择.

也可以用一个":set"命令备齐这两个选项:
:set cindent shiftwidth=4
   在上面的设置下, 你若键入了"if (x)"这样的语句, 那么下一行就会自动向右缩进一级.

使用自动缩进的另一个辅助作用是帮助你发现程序里的错误. 丢了)和;符号也一样会引起异常的缩进. 所以如果你看到缩进量多于预期时, 最好检查一下前面的程序段.

如果你正在接手一些缩进格式相当糟糕的代码, 或者要在已有的代码里增删修补时. 或许你会想重新对这些代码的缩进进行整理. 使用"="操作符命令, 最简单的形式是:
==

这个简单的命令会重新为当前行进行适当的缩进. 与其它的操作符命令一样, 它有三种命令形式. 在Visual模式下"="命令为被选择的行设定缩进. 对于可用的文件对象, "a{" 是有最用的--它选择的对象是当前的{}程序块. 所以下面的命令会为当前的代码块重新设定缩进:
=a{

如果手头的代码实在是糟糕透顶, 你也可以用下面的命令重新为整个文件进行缩进:
gg=G


设置缩进风格
   不同的人喜欢不同风格的缩进, Vim对缩进风格的设置对90%的程序来说正是他们所喜欢的. 不过, 还是应该允许不同的风格存在, 你可以
在'cinoptions'选项里定义自己的缩进风格.

   默认情况下'cinoptions'选项的值是一个空字串, Vim会使用默认的风格. 如果你希望有改变某些情况下的缩进风格.
   可以使用下面的命令:
:set cinoptions+={2

虽然由编辑器为你的程序进行缩进是个不错的主意, 你也不会想每次打开一个C文件时都去手工把'cindent'选项打开, 这样的工作完全可以自
动化:
:filetype indent on

如果你不想用自动缩进的话, 还可以再把它关闭掉:
:filetype indent off

如果你只是不想对某种类型的文件使用自动缩进, 可以创建一个只包含下面一行的文件:
:let b:did_indent = 1
现在给它起个名字保存为:
{directory}/indent/{filetype}.vim
其中的{filetype}就是你想避免它自动缩进的文件类型, 比如"cpp"或"java".

你可以用下面的命令查看Vim检测到的当前文件类型到底是什么:
:set filetype

对现在这个文件来说, 它的类型是:
filetype=help

这里你的{filetype}就是"help". 对于{directory}部分你需要知道你的运行时目录. 检查下面命令的输出:
set runtimepath

使用第一个逗号之前的那一项即可. 如果它的输出看起来是:
runtimepath=~/.vim,/usr/local/share/vim/vim60/runtime,~/.vim/after
你的{directory}就可以指定为"~/.vim".  所以完整的文件名就是:
 ~/.vim/indent/help.vim

//其它的种种缩进
    使用自动缩进最简单的形式是打开'autoindent'选项. 它使用当前行前面一行的缩进.一个更智能一点的方案是使用'smartindent'选项. 这主要用于没有缩进文件的程序语言.

'smartindent'并没有'cindent'对缩进考虑的那么周全, 不过它比'autoindent'还是智能一点. 打开'smartindent'选项的话, 每一个开花括号之后都会增加一级的缩进, 而在对应的闭花括号}之后再撤去这一级的缩进.
此外, 也会在遇到'cinwords'选项中列出的词时增加一级缩进. 以符号#开始的行也会被特殊对待:
不使用任何缩进. 这样所有的预处理器指示器就都从第1列开始 . 下一行又会恢复在此之前的缩进量.


修正缩进
如果你使用'autoindent'或'smartindent'得到了前一行的缩进量,很可能这个缩进量不是你刚好想要的.
一个快速增减当前缩进量的办法是在Insert模式下使用CTRL-D 和CTRL-T

在Normal模式下, 你也可以使用">>"和"<<" 命令来向右/左2 . ">"和"<"其实是操作符命令, 所以仍然可以使用此类命令的3 种形式 . 下面是一个比较有用的组合:
>i{
这为{}内的所有行增加一个缩进单位4 . ">a{"命令则包括了{ 与}所在的行本身.


//制表符和空格
    'tabstop'选项的默认值是8. 虽然你可以改变这个值, 不过很快你就会遇到麻烦. 因为其它的程序都假设一个制表符占据8个字符宽度, 似乎突然之间你的文件看起来就大不一样了. 另外, 大多数打印机也都假设一个固定制表符的宽度是8. 所以最好还是保留'tabstop'的值为8不要动.

如果你是在混合使用空格和制表符, 你就只管编辑吧, Vim会在幕后处理这些工作. 你可以使用'softtabstop'选项来简化工作. 这个选项告诉Vim让一个<Tab>看起来就象是由'softtabstop'所设置的宽度, 但实际上是对制表符和空格的混合.

执行下面的命令后, 每次你按下制表符键, 光标就会向前移动4列:
:set softtabstop=4

使用退格键时是另一种情况. 一个退格键总是删除由'softtabstop'指定的宽度. 同样剩余的空白会尽可能多地使用制表符, 留下的间隙用空格来填充.



只用空格
如果你根本不想在文件中看到制表符, 你可以设置'expandtab'选项:
:set expandtab

打开该选项之后 , 按下制表符就会插入相应宽度的空格来代替. 看起来空白区域的宽度都是一样, 但是文件中实际上不会有制表符.
打开'expandtab'选项并不会影响到此前输入的制表符

如果你想把所有的制表符都转为空格, 可以使用":retab"命令:
:%retab

如果你想把所有的制表符都转为空白,在命令后加一个 ! 
:%retab!

要反过来转换, 即使用制表符换掉空格这样即可:
:set noexpandtab
:%retab!


//对注释的格式化
Vim的另一个引人之处是它能理解注释. 你可以让Vim来格式化你的注释. 假如你有下面的注释:
 /*
  * This is a test
  * of the text formatting.
  */

你可以把光标置到注释的开始, 然后用如下命令来格式它:
 gq]/
 "gq"是格式化命令的操作符. "]/"是移动到注释结尾的移动命令.

执行后结果是:
/*
 * This is a test of the text formatting.
 */
注意Vim已经正确处理了注释中的每一行的开头.
另一个办法是在Visual模式下先选定要格式化的内容然后再按下命令"gq".

要在注释中加入一行, 把光标放在其中一行上, 然后按"o".  Vim会自动为你新加的注释行插入一个星号和一个空格.
现在你直接写注释就行了. 如果你写入的内容超出了'textwidth'的限制, Vim还会自动为你断行, 断行时它同时不会忘了为新行注释插入星号和一个空格

要达到上述功能就必需在'formatoptions'选项里设置正确的标志:
r   在Insert模式下按下回车时插入一个星号
o   在Normal模式下按"o"或"O"时插入一个星号
c   根据'textwidth'的设置自动为注释断行


自定义注释格式
'comments'选项定义一个注释的外观. Vim会区别对待单行注释和那种对头, 体, 尾各有规定的多行注释.

很多的多行注释都以一个特殊字符开头, C++中用//, Makefiles中用#, Vim脚本用双引号". 比如, 要让Vim理解C++的注释:
:set comments=://
其中的冒号是为了分隔标志和后面的注释关键字, Vim就是根据这里的注释关键字来识别一个注释的. 'comments'选项的内容一般形式是:
{flags}:{text}
{flags}部分可以是空的, 就象上面的例子中一样.

多个这样的注释项定义可以串连在一起, 其间用逗号分隔, 这样就可以同时定义多种类型的注释. 比如, 若要想在回覆e-mail信息时, 使它人写的以">"和"!"字符开头的内容成为注释, 可以这样:
:set comments=n:>,n:!

这里有两个注释项定义, 分别定义了以">"开头的注释和以"!" 开头的注释. 两者的定义都使用了标志"n". 该标志是说这些注释可以是嵌套的. 这样以">"开头的后面内容本身也可能是注释


三段式注释
   典型的C风格的多行注释以"/*"开头, 中间的注释行以"*"开头, 注释的最后以"*/"结尾. 这三段对应于'comments'这样的形式:
:set comments=s1:/*,mb:*,ex:*/

注释的开头以"s1:/*"定义. "s"意为start. 冒号是用于分隔标志字符和其后的注释关键字"/*". 注释中还有一个"1". 这是告诉Vim三段式注释的中间行要有一个字符宽度的右偏移.

中间部分的定义是"mb:*", 其中"m"意为middle, "b"标志是说注释关键字"*"之后要有空格. 否则Vim会认为象"*pointer"这样的指针定义也是三段式注释的一部分.

结尾的定义:"ex:*/", "e"意为注释的结尾(end)1 "x"标志在这里有一层特殊含义, 它告诉Vim自动插入一个星号后, 如果接下来输入了一个/字符, 就要移除多余的空格.

评论

我的评论:

发表评论

请 登录 后发表评论。还没有在Zeuux哲思注册吗?现在 注册 !
龙

回复  2010年01月31日 星期日 02:57

照搬 VIM 手册 的内容而已,作为个程序员,大家要养成读文档的好习惯

0条回复

刘志超

回复 刘志超  2010年01月23日 星期六 16:25

受教了。。。

0条回复

Ford Guo

回复 Ford Guo  2010年01月22日 星期五 21:45

骨灰级的vi玩家,佩服!我也就用vi来编辑基本配置文件,很少用来进行make之类

0条回复

徐继哲

回复 徐继哲  2010年01月22日 星期五 21:21

找机会来哲思沙龙和大家分享一下使用VIM的技巧?

0条回复

暂时没有评论

Zeuux © 2024

京ICP备05028076号