Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1438292
  • 博文数量: 704
  • 博客积分: 10140
  • 博客等级: 上将
  • 技术积分: 6230
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-15 20:41
文章分类

全部博文(704)

文章存档

2013年(1)

2012年(16)

2011年(536)

2010年(151)

分类: C/C++

2011-05-26 10:53:44

回到Vim

翻译自:http://stevelosh.com/blog/2010/09/coming-home-to-vim/

我是一名程序员。我每天工作6-12小时处理文本文件,所以我对文字编辑器比较关注。如果换一个不同的编辑器可以提高我的效率,哪怕只有10%,那也将为我节省大量的时间,可以让我去做其他很酷的事情。

我不赞同“你90%的时间在思考,只有10%的时间在编写代码,所以你的编辑器其实并不重要”的说法。即使前提正确,但结论也是错误的。

如果我思考10分钟,然后开始打字,我想要在最短的时间打完让我能赶回去思考。我打字所花的任何时间都是对我思考的打断,所以我希望(时间)尽量短,以便让我可以保持思路。

我最近开始使用Vim作为我的主要编辑器。适应过程中,我发现了很多博客都有关于Vim的非常有用的信息,所以我也希望这篇文章能帮助人们。

一些有关我的背景

从2002年到2005年,我只使用VIM作为我的编辑器。我从来没有认真地学习他,而只是把它用作看上去更高级的nano 。

到了2006年,我决定该是改变的时候了。我想要一个“适合”OS X的编辑器。我尝试了SubEthaEdit一段时间并发现它还不错。它的协同编辑(Collaborative editing)功能比任何我见过的版本都有好,尽管我并没有太多地使用它。

尽管SubEthaEdit很不错,我总觉得还有一个更适合我的编辑器。然后我发现TextMate 。

当时我认为TextMate是令人惊奇的(它确实是)。它看起来就像一个普通的Mac应用程序。而且超级简单易学(所有的OS X的移动命令都可以使用)。插件也是应有尽有。

我还是偶尔使用Vim的(比如当我有一份工作必须在只装有Windows的机器上完成的时候),但大部分我都是一个TextMate的粉丝。

使用了四年的TextMate后,我决定进行下一次转变。现在TextMate的开发工作停滞不前,而且似乎永远(额,是TextMate 2)正在开发中。我开始对Vim有想法(同时阅读了很多别人的关于如何转回到VIM的博客),并决定再试试看。

几个月前,我买了Learning the vi and Vim Editors(学习Vi和Vim编辑器) ,并与Vim相处得相当愉快。至今我都没有回头。

为什么我曾切换到TextMate

正如我前面提到的,我切换到TextMate有几个首要原因。

第一:它是一个专业的OS X应用程序 。你可以拖动文件到它的图标来打开它们,而且它支持所有默认 OS X文字移动命令,就像它真正属于OS X一样。我当时并不知道有没有MacVim,如果有的话,我确实也没有发现。

这一点很重要。如果一个编辑器支持这个操作系统的所有常用操作的话,从头学习它所花的经历将会大大减少。

它也有充满活力的社区,很多人为它撰写插件,所以它几乎支持我使用的任何东西。

为什么我回到Vim

我转回Vim有许多原因。

首先:我想要使用一些TextMate最近可能都不太会实现的功能。其中最重要的是窗口分割(Split windows)。实在无法想象如果不能使用它将会是什么情况。

另一个原因是版本控制。前段时间我开始将我的dotfiles存在Mercurial仓库(Repository)中,这使得在新机器上设定运行环境变得相当容易。Vim把它所有的配置存在两个相当简单的地方:一个简明的~/.vimrc文件和全是纯文本文件的~/.vim目录。

Vim的纯文本配置文件和插件是非常容易进行版本控制的。它们很容易进行diff比较,TextMate的多个Bundles目录和丑陋的XML文件则不同。

Vim的社区存在的远比TextMate久远,所以它有更多的插件,捆绑(bundles)和语法文件。

人们欣赏Vim的另一个原因是,它到处都可以运行。确实,当我通过SSH登录到另一台机器的时候如果可以使用我最喜欢的编辑器的话那是相当的正点, 不过不能用也没什么大不了的。我几乎总是在我自己的机器上编辑文件,然后通过某种自动化的脚本部署它们,在服务器上直接编辑对我来说很罕见。

核心差异

对我来说,Vim和TextMate有很大的不同。TextMate主要依靠键盘快捷键(Shift,Ctrl,Cmd和Alt)做更多的编辑。Vim使用的“编辑模式(modal editing”的概念来完成相同的任务。

TextMate的设计哲学和任何普通的OS X应用程序是大致的相同的, 操作系统的内建功能降低了编辑器的使用复杂度,那么为什么我更喜欢Vim的理念?

首先,我得先声明我的观点:学习曲线对我来说不算什么,特别是像编辑器这种对我来说相当重要咯工具。是的,少学一点确实很惬意,不过我还是愿意多花点精力如果它确实能节约我很多时间。

我对TextMate的哲学的意见可以归纳为一个词:“阴影(shadowing)”。

如果我想在Bundle中定义一个新的命令,我从来无法确定我是否“覆盖(overwriting)”了其他命令,我的手指知道,但是那样的命令并没有在我的大脑中注册。

到我想使用默认的命令的时候,这可能是在我定义了我自己定制的命令的几天或者几周之后,我不得不仔细回忆我当初是怎么弄的,这确实相当令人沮丧。

Vim的“插入(insert)”模式意味着,当我编辑文本我使用的是我相当喜欢的正常的OS X文字移动命令。当我想要做一些特别的,我会进入正常(normal mode)模式,不必担心阴影命令(Vim的leader key也有助于这一点)。

Vim的“感觉”

Vim的正常模式(normal mode)有一种独特的“感觉”( 尽管E的出现可能会改变这个事实)。我听过很多种说法但没有一种能够完全地表达这样的感觉,倒是所有这些说法一起组成了对Vim最好的描述。

文本编辑的“语言”

人们可以把有关Vim的正常模式(normal-mode)的命令看作是一门语言。它有“动词”和“名词”。例如:“chang”命令(‘c’)是一个动词,而“word”(‘w’)是个名词。你可以把它们结合成句子来谈论你想对怎样编辑你的文字。

关于这个奇妙之处是当你学会一个动词(如“delete”(‘d’))你可以立即应用到所有你知道的名词,反之亦然。

Vim还有”形容词“,如”inside“和”around”(‘i’和’a'),从而让你可以使用形如“change inside perethesis”(ci(或cib)这样的句子。一旦你了解了这些形容词,你可以立即应用到所有的已经知道了的动词和名词上。

文本的物理

第二种方式来描述Vim的感觉是“物理”。这是一个很不具体的说明,但我认为它还是有用的。

如果我朝空中扔保龄球和火鸡三明治,它们的运动状况差不多。也许当他们落在某人身上的状况会有不同但是单单扔他们的这个状态基本是差不多的。

Vim的operators/actions/verbs行为方式相同。 ‘daw‘的作用跟‘da{‘比起来区别很大,但它们都可以从这一基本原则去理解: da将“delete around’‘“。

“程序化”你的编辑

我听到的最后一种人们对Vim编辑的评论是:“它感觉就像你对你的文字进行’编程’。”

这个比喻往往是来自程序员(显然),我认为它涵盖不止一个层面。

第一:Vim的基本编辑命令,可以比喻为函数调用。 daw可以被想象成一个函数调用一delete(type='word', around=True) 。我不这样认为(我更喜欢前面提到的语言和物理类比),但其他人喜欢这样。

虽然我不把基本的Vim命令看作为编程,但我看到了它在其他方面的应用。例如:在我的~/.vimrc文件中我定义了一个leader键:

nnoremap 1 yypVr=

我把这个定义1看作为一个函数,它执行以下操作:

*拷贝/复制当前行。 *粘贴在下面(然后向下移动到粘贴的版本)。 *选择被复制行。 *用= 替换每个字符。

另一个更明显的类似“编程”的方面则是在Vim中创建宏。宏就像是你创建用来帮助你编辑文件的小函数。你可以定义,执行它们,甚至通过粘贴,修改和拷贝(yanking)来编辑它们。

开始

当我切换回Vim的时候,我做了几件事帮助我过渡。

第一:我买了学习vi和Vim编辑器(Learning the vi and Vim Editors)并且从头到尾地阅读它。它介绍了相当多Vim背后的历史,这本书也教你Vim的编辑命令的基本知识。

我也看遍了the Vim subreddit找一些有关(从TextMate到Vim)切换的博客。很多人都写过,了解他们的经验是非常有帮助的,

最后,最重要的部分:我的转换过程轻松愉快。Vim的运行无处不在,所以实在没有理由不这样做。每一个像样的操作系统都有一个Vim版本,使插入模式(inser-mode)在他们的操作系统中工作的很好(如gvim的或MacVim),所以现在的门槛是相当低的。

你可以开始使用Vim并且在大部分时间里呆在插入模式(insert-mode)。然后你就可以以自己的步伐开始学习它真正的特性。尝试同时使用两种不同的编辑器不但减慢了你的学习过程,而且在两个中都使你的生产力降低。

让Vim更好用

Vim的一个缺点是,它需要相当多的配置才能使其表现得很好。默认配置是为了向后兼容vi(年龄超过大多数大学生),所以不是非常有用。

下面我将会使Vim变得更加好用。

边注:即使你不使用Vim,你也需要重新映射你的CapsLock键到一些有用的东西上。只要做到这一点,你以后会感谢我的。

.vimrc中重要的行

我不会解释我的~/.vimrc文件中的每一行 ,这里是一些绝对不能错过的。

首先,这几行你绝对必须有:

filetype off call pathogen#runtime_append_all_bundles() filetype plugin indent on set nocompatible set modelines=0

filetype和call是为了载入Pathogen,具体内容下面的插件章节会提到。参考Pathogen’s doc ,以了解为什么第一个filetype会在那里。

set nocompatible去除所有为了跟vi兼容的累赘。现在是2010年–我们再也不需要为了跟Vi兼容而牺牲一些功能。

modelines位是为了防止一些有关modelines的[安全漏洞][]。我从不使用modelines,所以我这样设置不会丢失任何功能。

接下来,我调整我的tab设置:

set tabstop=4 set shiftwidth=4 set softtabstop=4 set expandtab

我喜欢把所有tab扩展为四个空格。参考这个Vimcast了解更多有关这些选项的信息。

接下来的几个选项是为了让事情变得更好:

set encoding=utf-8 set scrolloff=3 set autoindent set showmode set showcmd set hidden set wildmenu set wildmode=list:longest set visualbell set cursorline set ttyfast set ruler set backspace=indent,eol,start set laststatus=2 set relativenumber set undofile

其中每一行基本上是使Vim表现得更理智。两个“有趣”的是最后两个,都是有关Vim 7.3的新特性

relativenumber改变Vim的行号列以显示相对行号,而不是显示绝对行号。

我几乎从来不关心我正在编辑文件中的哪一行(如果需要,我可以从状态行看到),所以我不想要正常行号。我关心我离一个特定的行究竟有多远,因为当我使用诸如dd这样的命令时它可以让我知道确切的数字。

undofile告诉Vim每当你编辑一个文件的时候要创建.un~文件。这些文件包含undo信息,以便撤消以前的操作,即使你关闭并重新打开文件。

接下来,我改变键:

let mapleader = ","

对我来说,,比\更容易输入 。我经常使用leader键所以这值得改变。

接下来我要做的就是驯服 搜索/移动:

nnoremap / /\v vnoremap / /\v set ignorecase set smartcase set gdefault set incsearch set showmatch set hlsearch nnoremap :noh nnoremap % vnoremap %

前两行通过自动插入一个\v在任何你想要搜索的字符串之前,修复Vim的可怕的正杂表达式处理方式。这将关闭Vim疯狂的默认正则表达式字符,使搜索功能使用正常的正则表达式。我已经知道Perl/Python兼容的正则表达式格式,为什么我要学习另一种?

ignorecase 和 smartcase 共同使Vim智能化地处理区分大小写的搜索。如果你搜索一个全小写的字符串这将是不区分大小写的搜索,但是如果一个或多个字符大写,搜索将区分大小写。大多数时候,这样是你想要的。

gdefault 试替换操作扩展到一整行。例如,你只需要输入: :%s/foo/bar/g 而不是: :%s/foo/bar/ 。这几乎总是你想要的(你最后一次只想替换在一行中的第一个匹配项是什么时候?)如果你需要默认的搜索你只需要在最后加上 g 。

incsearch , showmatch和hlsearch` 一起高亮显示搜索结果(跟你输入的一样)。这真的很方便,只要存在下一行。

映射可以很容易地用 , 清除搜索结果。一旦我找到了我要找的,这去除了分散注意力的高亮。

最后两行使tab键匹配括号对。我所有的时间都是用 ,它比 % 方便得多 。

下一段使Vim正确地处理长行(long lines):

set wrap set textwidth=79 set formatoptions=qrn1 set colorcolumn=85

这些行管理我的换行设置,同时在第85个字符的位置显示了一个高亮列(这样当我写了一行过长的代码时我会很直观地看到)。

参考: :help fo-table 和 soft wrapping 和 hard wrapping 的Vimcasts以获取更多信息。

接下来是其他东西TextMate粉丝可能会喜欢的:

set list set listchars=tab:▸\ ,eol:¬

这使Vim显示和TextMate相同的不可见字符。您可能需要调整自己的颜色方案,以便他们不会太引人注意。这个 Vimcast包含更多的信息。

新的Vim用户都需要下面的行教他们做正确的事情:

nnoremap nnoremap nnoremap nnoremap inoremap inoremap inoremap inoremap nnoremap j gj nnoremap k gk

这将在normal-mode禁用方向键来帮助你学习使用 hjkl 。相信我,你肯定想要学习使用 hjkl 。多玩点Nethack也有帮助。

它同样也在inserting-mode下禁止方向键,当你完成插入文字后,迫使你进入normal-mode,这是做事“正确的方式”。

这也使得J和K按你期望的方式工作。

其次,摆脱那个愚蠢该死的帮助键,当你想要按ESC的时候它总是不经意地被碰到。

inoremap nnoremap vnoremap

我也喜欢用 ; 代替 : 做同样的事情 — 每当我想要保存的时候它都让我少按一个键:

nnoremap ; :

我不重新映射 : 回 ; 因为它似乎会让一些插件无法运行。

最后,我真的很喜欢TextMate的“当失去焦点时保存”功能。我不记得有什么时候当我转到别的标签(tab)时,我会不不希望保存文件(特别有了版本控制和Vim的persistent undo之后):

au FocusLost * :wa

这些都是我的~/.vimrc文件中最重要的部分。接下来我将谈谈自定义命令(customization)美妙的命名空间(namespace),那就是Vim的键。

使用’Leader’键

Vim中整个键盘都可以被映射成用户自定义操作。这就是“leader”键,默认情况下它映射到 \ 。正如我在上一节提到我喜欢用 , 来代替。

每个人都有自己经常使用的特定的一些命令,并希望为这些东西创造快捷方式。“leader”键就像是一种命名空间”namespace“,它使自定义命令与系统内建命令区别来开。

下面是一些我使用”leader“键的例子。你肯定有不同的想法,不过下面的应该会给你一些启示。

我使用 ,W 以 ”去除当前文件中所有行尾的空格“ :

nnoremap W :%s/\s\+$//:let @/=''

我经常使用ACK(如下所述),所以我为它映射了一个”leader“键:

nnoremap a :Ack

我的工作经常使用 HTML,所以我把,ft映射到一个“折叠标签(fold tag)”的功能:

nnoremap ft Vatzf

我还与尼克警长(Nick Sergeant)一起工作,他喜欢把他的CSS属性(properties)排序,所以这里有一个,S映射对它们进行排序:

nnoremap S ?{jV/^\s*\}?$k:sort:noh

下一个映射模仿TextMates的 Ctrl+Q 功能,对段落重新”hardwrap“

nnoremap q gqip

我有一个 ,v 映射用来重新选择刚刚粘贴的文本,这样我就可以对它执行一些命令(比如缩进):

nnoremap v V`]

这最后一个映射让我在一个垂直分割的窗口中快速打开我的~/.vimrc文件这样一来我便可以方便地加入一些新的东西。

nnoremap ev :e $MYVIMRC 更快的ESC

Vim中你不断重复的便是从insert-mode切换到normal-mode。默认的方式是按ESC键盘,但是这个键有点远不是很容易按到。

另一种方法是使用 Ctrl+C 或 Ctrl+[ ,但我也不太喜欢。

我个人使用 jj 返回到正常模式。唯一的一次我连续按了2个 j 就是在写这篇文章的时候,所以这样完全不会跟一般的编辑相冲突。

inoremap jj 使用分割窗口

我切换到Vim的主要原因之一是它能够分割编辑窗口以同时显示多个文件。当我看完网上那些要求TextMate也实现这个功能的呼吁之后,我知道自己并不孤独。

Vim默认的分割窗口的命令有点笨重。我加了点功能到~/.vimrc使它变得更加顺畅。

这第一个映射使用,w打开一个新的垂直分割窗口并切换过去。什么时候你分割新的窗口却不想立即切换过去?

nnoremap w vl

您可能会注意到,这个映射只能用于垂直分割。我几乎从来不使用水平分割。我的屏幕都是宽屏,所以我的屏幕上能同时显示几个垂直分割的窗口。水平分割常常不能提供足够的空间。如果我真的想要一个水平分割,我可以使用s。

下面一组映射把 映射到那些你用来在分割窗口中移动的命令。如果您重新映射您的CapsLock键到 Ctrl ,导航便会变得非常简单。

nnoremap h nnoremap j nnoremap k nnoremap l 美学

我知道有些人说:“外观并不重要,唯一重要的是功能”。这是完全错误的。

如果我每天长时间看着某样东西,它必须得好看才行。有三个步骤可以让Vim变得好看(对我来说, 在 OS X 中-步骤可能会有所不同)。

第一:获得MacVim 。它使Vim看起来(和表现起来)想一个原生Mac应用程序。Linux和Windows用户可能会希望使用gvim。

下一步:选择一个好看的字体。我喜欢12pt的Menlo ,你可能有不同的偏好。

最后:找到一个很好的配色方案。我一直在使用稍加修改的的Molokai (从TextMate的Monokai主题移植而来)因为刚转回到Vim,但最近我也开始使用MustangClouds Midnight 。花点时间找找你看起来更舒服的东西。

我目前的配置:

我用的插件

Vim已经存在了很长一段时间,很多人都写了它的扩展。下面是我在日常编辑中离不开的一些插件。

Pathogen

Tim Pope创造了美好的Pathogen插件,使得管理其它Vim插件非常方便。你可以把插件保存在一个单独的~/.vim/bundles/文件夹 而不是让他们散乱地堆积在~/.vim/下。

安装它并保持你的理智。

PeepOpen

TextMate的一个“杀手锏“就是其 Cmd+T 键。它可以让你通过输入文件名的片段而迅速地打开文件。

有很多Vim插件试图模仿这个功能。我最喜欢的是PeepOpen 。是的,它只能用于 OS X而且要花点钱,但它确实值得。它看起来不错,用起来也凑合。

PeepOpen有一些漂亮的小功能,如在文件列表中显示Git的元数据(moetadata)。我已经提供了一个补丁为Mercurial实现同样的功能,但是没有得到回应。

如果你不使用 OS X(或想要一个免费的PeepOpen的替代)我听说的插件是相当不错的。

NERDTree

你几乎会从所有“切换到Vim”博客文章中看到的插件便是NERDTree 。这个插件用来浏览项目中的文件,它太棒了。

NERDCommenter

你想按几个键就注释或者取消注释代码段吗? 你需要NERDCommenter。令人惊讶的是Vim竟然没有内置像样的注释功能,不过NERDCommenter解决了这个问题。

我基本只用这个插件中的一个功能:”打开注释“ c 。仅仅为了这个功能你也应该安装它。

Ack

如果你是一个程序员,却不知道Ack ,你应该马上使用它。它比grep好得多。

Ack plugin把Ack跟Vim的QuickFix窗口整合起来,让你可以轻松地搜索和跳转到结果。

正如我刚才在”leader“映射章节提到的,,a 映射用来调出Ack并准备搜索。

Snipmate

另一个TextMate的惊人特征就是它的snippets。SnipMate是一个Vim插件,模拟TextMate的snippets。

它把snippets存在易于版本控制的纯文本文件中,这比TextMate中的snippets要好哦。

Sparkup

SparkupZen Coding在Vim上一个相当好的移植。如果你写很多的HTML,它将会为你节省大量的时间。

简言之它可以让你只输入如:

:::text div.content>h1.post-title+p{Sample Content}

然后按Cmd+E ,它便会扩展成:

:::html

Sample Content

随着时间的增长,这愈发节约时间。

Yankring

Vim的复制和粘贴功能(使用寄存器)非常,非常强大,但它却不是很“对用户友好”。该YankRing插件增加更多的功能,而且还加入了一些特性使得复制和粘贴更加方便。

例如,在你粘贴一些文字之后,你可以通过按Ctrl-P把它们替换成你之前复制过的文字 。你可以通过不断地按Ctrl-P来调出更早复制过的文字。

YankRing也使你复制的内容在Vim窗口中共享,当你要把文字从一个窗口粘贴到另一个的时候这便非常好用了。

你还可以通过:YRShow显示一个包含你之前复制过文字的列表 。把这个命令映射到一个专门的键是非常有帮助的:

nnoremap :YRShow inoremap :YRShow

YankRing提供了非常多的有用的功能,但我没有时间和动机,真正挖掘并了解如何使用它。

Surround (and Repeat)

我一直使用的另一个Time Pope写的插件就是Surround插件。它在Vim的物理学(physics)中增加了另外一层:“环绕项(surrounding items)”。

例如,你可以用cs'"来把环绕(surrounding)的单引号改成双引号。或者,如果你在编辑Markdown文件,你可以使用ysiW*来使一个词斜体化(italicize ) 。

你知道可以的所有的名词和动词都可以使用,这适合Vim的理念,使得它非常强大。

Repeat插件是必要的,它通过 .使得这些环绕操作变得可重复 。

Slime

Emacs的用户经常吹嘘SLIME是Emacs其中之一的”杀手锏“。当写LISP代码时它确实相当不错。

Vim没有SLIME之类的东西。它并没有像Emacs跟LISP那样与任何编程语言集成。但是,你可以在Vim中获得SLIME的一些功能 。

Jonathan Palardy写了一个小插件叫做Slime.vim ,让Vim简单地与一个屏幕会话(screen session)通信,比如LISP,Python或者Ruby的REPL环境。

总的想法是,你先在一个屏幕会话中打开LISP,然后在Vim中使用Ctrl+C Ctrl+C把Vim窗口中的代码提交到屏幕会话中去。

这样很有效而且当你想对一个文件的内容做一些试验性的工作时非常方便。

我个人使用了一个稍加修改的版本 ,它去除了一些我不需要的灵活性来使它用起来更迅速。也许有一天我会给它多加点功能并放到Bitbuket和GitHub上专门的仓库中。

Scratch

Scratch插件添加了一个功能,用来快速打开一个永远不会被保存的”scratch“ buffer。

我把它映射到并和slime一起使用,这样便可以把一些我并不打算保存的代码直接丢到REPL里去运行。

bow Parentheses

Rainbow Parentheses是一个根据圆括号,方括号,大括号和角括号嵌套的层次来着色的插件。

最简单地描述它是什么就是看看下面这个截图:

我使用一个稍加修改的版本 。我把它映射到R并且默认关闭。当我面对一段有很多嵌套层次的代码的时候我只需按下R,有了这些颜色的帮助,很容易搞清楚层次 。

总体思想

在使用了几年的TextMate之后转回到Vim并不容易,但我觉得努力是值得的。我有了像分割窗口这类功能,而且有很多的插件提供了TextMate里面每一个我用的功能。

如果TextMate 2上市的话,它那些有趣的功能可能会吸引我回去。

总的来说,与Vim相处我感到非常高兴。但有很多是可以改进的,特别是那些默认设置(谁还会在2010年考虑跟vi的兼容性?),一点点学习曲线对这样一个好的编辑器来说是值得的。

在我眼里Vim有两个超过了几乎所有其他编辑器巨大的优势。首先是它的巨大的插件和语法定义的生态系统(ecosystem),这一点只有Emacs可以相媲美(也可能是 TextMate尽管我持怀疑态度)。第二是它的“模式编辑(modal editing)”的理念,这是非常强大的,尚未出现在任何其他主流编辑器上(除了最新版本的E)。

如果你有问题或意见,你应该在Twitter上找我,以便让我知道 。

阅读(1101) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~