Vim最有效的捷径是什么?

我听说过许多关于Vim的优点和缺点。 看起来你应该(作为一个开发人员)比Vim更快地使用其他编辑器。 我正在使用Vim来做一些基本的工作,而Vim的工作效率最好是10倍。

当谈论速度时,你应该关心的两件事情(你可能不太在乎它们,但你应该):

  1. 使用左手和右手是使用键盘的最快方法。
  2. 不要触摸鼠标是第二种方式尽可能快。 它需要很长的时间来移动你的手,拿起鼠标,移动它,并把它带回到键盘(你经常必须看着键盘,以确保你正确地把你的手回到正确的地方)

下面是两个例子,说明为什么我在Vim方面效率低下很多。

复制/剪切并粘贴。 我一直这样做。 在所有当代编辑器中,用左手按下Shift ,然后用右手移动光标以select文本。 然后Ctrl + C复制,移动光标和Ctrl + V粘贴。

对于Vim来说这太可怕了:

  • yy复制一行(你几乎不需要整行!)
  • [number xx]yyxx行复制到缓冲区中。 但是你永远不知道你是否已经select了你想要的东西。 我经常不得不[number xx]dd然后u撤消!

另一个例子? search和replace。

  • 在PSPad中 : Ctrl + f然后input你想要search的内容,然后按Enter键
  • 在Vim: / ,然后键入要search的内容,然后如果在每个特殊字符前面有一些特殊字符,请按Enter键

而Vim的一切都是这样的:看来我不知道如何正确处理它。

注意: 我已经阅读了Vim 作弊 表 🙂

我的问题是:

你使用Vim的方式是什么让你比当代编辑更有成效?

你对Vim的问题是,你没有理解vi

你提到切割与yy和抱怨,你几乎从来不想削减整个线条。 事实上,程序员,编辑源代码,往往希望在整个行,各行的范围和代码块。 然而, yy只是将文本放入匿名复制缓冲区(或称为“注册”)的许多方法之一。

vi的“禅”是你在说一种语言。 最初的y是一个动词。 yy语句是y_的同义词。 因为这是一个常见的操作,所以y被加倍以便于打字。

这也可以表示为dd P (删除当前行并将副本粘贴回原处;在副本中留下副本作为副作用)。 yd “动词”以任何动作作为他们的“主语”。 因此, yW是“从这里(光标) yW当前/下一个(大)字的y'a ”, y'a是“从这里y'a包含名为' a '的标记的行。

如果你只理解基本的上,下,左,右光标移动,那么vi将不会比“记事本”的副本更有效率。 (好吧,你仍然有语法突出显示和处理大于45KB左右的文件的能力,但在这里与我一起工作)。

vi有26个“标记”和26个“寄存器”。 使用m命令将标记设置为任何光标位置。 每个标记由一个小写字母指定。 因此, ma将“ a ”标记设置为当前位置,并且mz设置“ z ”标记。 您可以使用' (单引号)”命令移动到包含标记的行。 因此'a移动到包含' a '标记的行的开头。 您可以使用` (反引号)命令移动到任何标记的精确位置。 因此`z将直接移动到' z '标记的确切位置。

因为这些是“运动”,所以它们也可以作为其他“陈述”的主题。

所以,削减任意文本select的一种方法是放弃一个标记(我通常使用' a '作为我的“第一个”标记,' z '作为我的下一个标记,' b '作为另一个,' e '作为还有一个(我不记得在15年的使用vi中交互式地使用了四个以上的标记;一个创build自己的约定关于macros如何使用标记和寄存器来不打扰一个交互的上下文)。到我们想要的文本的另一端;我们可以从任何一端开始,没关系,那么我们可以简单地使用d`a来剪切或者复制,因此整个过程有5个按键开销(6如果我们开始“插入”模式,并且需要退出命令模式)。一旦我们已经剪切或复制,然后粘贴复制是一个单一的击键: p

我说这是剪切或复制文本的一种方法。 但是,这只是其中之一。 通常我们可以更简洁地描述文本的范围,而不用移动光标并放下标记。 例如,如果我在一段文字中,我可以分别使用{}移动到段落的开头或结尾。 所以,要移动一段文字,我使用{ d} (3个按键)将其剪下。 (如果我碰巧已经在段落的第一行或最后一行,我可以简单地使用d}d{分别。

“段落”的概念默认为通常直觉上合理的东西。 因此它通常适用于代码和散文。

通常我们知道一些模式(正则expression式),标志着我们感兴趣的文本的一端或另一端。 向前或向后search是vi中的移动。 因此,他们也可以在我们的“陈述”中用作“主体”。 因此,我可以使用d/foo从当前行切换到包含string“foo”和y?bar的下一行,从当前行复制到包含“bar”的最近(前一行)行。 如果我不想整行,我仍然可以使用search动作(作为他们自己的语句),放下我的标记并使用前面所述的`x命令。

除了“动词”和“主语”之外, 还有“宾语”(从语法的angular度来看)。 到目前为止,我只描述了使用匿名注册。 不过,我可以使用26个“命名”寄存器中的任何一个, 通过在“object”引用前添加" (双引号修饰符)。因此,如果我使用"add当前行剪切到” a “我使用"by/foo然后从这里到下一行包含”foo“的文本拷贝到” b “寄存器中。要从一个寄存器中粘贴,我只需要用相同的修饰符序列作为前缀: "ap将“ a ”寄存器内容的副本粘贴到光标后面的文本中, "bP将副本从” b “粘贴到当前行之前。

这个“前缀”的概念也增加了语法“形容词”和“副词”的类似物到我们的文本操作语言中。大多数命令(动词)和动作(动词或对象,取决于上下文)也可以带数字前缀。 3J意思是“join下三行”,而d5}意思是“从第五段开始,从当前行删除”。

这是所有中间级别vi 。 没有一个是Vim特有的,如果你已经准备好学习它们,那么在vi中有更高级的技巧。 如果你只是掌握这些中间概念,那么你很可能会发现,你很less需要编写任何macros,因为文本操作语言足够简洁和富有performance力,可以使用编辑器的“本地”语言轻松完成大多数事情。


一些更高级的技巧:

有许多命令,最值得注意的是:% s/foo/bar/g全局replace技术。 (这不是先进的,但其他:命令可以)。 整个:组命令历史上由vi的先前化身ed (行编辑器)和后来的ex (扩展行编辑器)实用程序inheritance。 事实上, vi是如此命名的,因为它是ex的可视化界面。

:命令通常对文本行进行操作。 edex是在terminal屏幕不常见的时代写的,许多terminal是“电传”(TTY)设备。 所以通常从文本的打印副本开始工作,通过一个非常简洁的界面使用命令(常见的连接速度是110波特,或者大约每秒11个字符 – 这比快速打字员慢;延迟常见多用户交互式会话;另外还有一些保存纸张的动机)。

所以,most : syntax的语法包括地址或地址范围(行号),后跟一个命令。 自然,可以使用文本行号:: :127,215 s/foo/bar在127到215之间的每一行上将“foo”的第一次出现更改为“bar”。还可以使用一些缩写,例如.$分别为当前和最后一行。 也可以使用相对前缀+-来分别指在修改行之后或之前的偏移量。 因此: :.,$j表示“从当前行到最后一行,将它们全部合并成一行”。 :%:1,$ (所有行)的同义词。

:... g:... v命令有一些解释,因为它们非常强大。 :... g是一个前缀,用于将全局的后续命令应用到与模式匹配的所有行(正则expression式),而:... v将这样的命令应用于与给定模式不匹配的所有行(“v “from”conVerse“)。 和其他ex命令一样,这些命令可以通过寻址/范围引用作为前缀。 因此:.,+21g/foo/d意思是“从当前行到下一行21行删除包含string”foo“的所有行。while :.,$v/bar/d表示”从这里到结尾文件,删除任何不包含string“bar”的行。

有趣的是,普通的Unix命令grep实际上是由这个ex命令启发的(并且是按照logging的方式命名的)。 ex命令:g/re/p (grep)是他们logging如何“全局地”“打印”包含“正则expression式”(re)的行的方式。 当使用edex时, :p命令是任何人学习的第一个,而且常常是编辑任何文件时使用的第一个命令。 这是你如何打印当前的内容(通常只用一个页面,一次完整的使用:.,+25p或一些这样的)。

需要注意的是:% g/.../d或(它的reVerse / conVerse对应:: :% v/.../d是最常见的使用模式,但还有其他一些ex命令值得记住:

我们可以用m来移动行, j来连接行。 例如,如果你有一个列表,并且你想分开所有匹配的东西(或者反过来不匹配某个模式)而不删除它们,那么你可以使用像:% g/foo/m$ …和所有的“富“行将被移动到文件的末尾。 (请注意关于使用文件末尾作为暂存空间的其他技巧)。 这将保留所有“富”行的相对顺序,同时从列表的其余部分提取它们。 (这将相当于: 1G!GGmap!Ggrep foo<ENTER>1G:1,'ag/foo'/d (将文件复制到自己的尾部,通过grep过滤尾部,并删除所有东西从头)。

为了连接线,通常我可以find所有需要连接到它们的前一行的模式(例如,在某些项目符号列表中以“^”开头的所有行,而不是“^ *”)。 对于这种情况下,我会使用:: :% g/^ /-1j (对于每个匹配的行,向上一行并join)。 (顺便说一句:子弹列表试图search子弹线,并join到下一个不起作用,有几个原因…它可以join一个子弹线到另一个,它不会join任何子弹线的全部它的延续;它只会在比赛中成对)。

几乎不用说,你可以用gv (global / converse-global)命令来使用我们的老朋友s (替代)。 通常你不需要这样做。 但是,考虑一些您只想在匹配其他模式的行上执行replace的情况。 通常情况下,您可以使用带有捕获的复杂模式,并使用反向引用来保留您不想更改的部分行。 但是,将匹配与replace:: :% g/foo/s/bar/zzz/g分开比较容易,对于包含“foo”的每一行,将所有“bar”replace为“zzz”。 (例如:% s/\(.*foo.*\)bar\(.*\)/\1zzz\2/g只适用于那些以“foo”为前缀的“bar”实例同样的路线;已经够难看了,而且必须进一步纠正,以便抓住所有“酒吧”在“富”之前的情况)

重点是ex命令集中不仅仅有psd行。

地址也可以引用标记。 因此,如果位于“ a ”和“ b ”标记之间的行之间,则可以使用:: :'a,'bg/foo/j将包含stringfoo的行连接到其后续行。 (是的,所有前面的ex命令示例都可以用这些地址expression式的前缀来限制在文件行的子集中)。

这非常晦涩(我在过去的15年里只用了几次)。 不过,我会毫不犹豫地承认,如果我花时间思考正确的咒语的话,我经常以迭代方式和交互方式做事情,这可能会更有效率地完成。

另一个非常有用的viex命令是:r读入另一个文件的内容。 因此:: :r foo在当前行插入名为“foo”的文件的内容。

更强大的是:r! 命令。 这读取命令的结果。 这与挂起vi会话,运行命令,将其输出redirect到临时文件,恢复vi会话以及从temp中读取内容是一样的。 文件。

更强大的! (砰)和:... !ex bang)命令。 这些也执行外部命令并将结果读入当前文本。 但是,他们也通过命令过滤我们的文本的select! 我们可以使用1G!GsortGvi的 “goto”命令;它默认去到文件的最后一行,但是可以用一个行号作为前缀,比如1,第一行)。 这相当于variables:1,$!sort 。 作家经常使用! 与Unix fmt折叠实用程序重新格式化或“文字换行”select的文本。 一个非常常见的macros是{!}fmt (重新设置当前段落的格式)。 程序员有时使用它来通过缩进或其他代码重新格式化工具运行他们的代码,或者只是其中的一部分。

使用:r!! 命令意味着任何外部实用程序或filter都可以视为我们编辑器的扩展。 我偶尔使用这些脚本来从数据库中提取数据,或者使用从网站上获取数据的wgetlynx命令,或者从远程系统中提取数据的ssh命令。

另一个有用的ex命令是:so (short for :source )。 这将读取文件的内容作为一系列命令。 当你启动vi时 ,通常隐式地在~/.exinitrc文件上执行一个:source (而Vim通常在~/.vimrc上执行这个操作就足够了)。 使用这个function,您可以通过简单地获取一组新的macros,缩写和编辑器设置来更改您的编辑器configuration文件。 如果你是鬼鬼祟祟的,你甚至可以使用这个技巧来存储ex编辑命令序列,以便按需使用文件。

例如,我有一个通过wc运行文件的七行文件(36个字符),并在包含该字数统计数据的文件顶部插入一个C样式的注释。 我可以通过使用如下命令将“macros”应用于文件: vim +'so mymacro.ex' ./mytarget

viVim+命令行选项通常用于在给定的行号处开始编辑会话,但是一个鲜为人知的事实是,可以通过任何有效的ex命令/expression式(例如“源”命令,正如我在这里完成的;对于一个简单的例子,我有脚本调用: vi +'/foo/d|wq!' ~/.ssh/known_hosts从我的SSH已知主机文件中删除条目非交互式重新映像一组服务器)。

通常使用Perl,AWK, sed编写这样的“macros”就更容易了(事实上,就像grep一个受ED命令启发的实用程序)。

@命令可能是最隐蔽的vi命令。 在偶尔教授高级系统pipe理课程十年的时间里,我遇到过很less有人曾经使用它。 @执行一个寄存器的内容,就像它是一个viex命令一样。
例如:我经常使用:: :r!locate ...在我的系统上查找某个文件,并将其名称读入我的文档中。 从那里我删除任何多余的命中,只留下我感兴趣的文件的完整path。而不是费力地通过path的每个组件(或更糟糕的是,如果我碰巧没有Tab完成卡在一台机器上在vi的副本中支持)我只是使用:

  1. 0i:r (将当前行转换为有效的r命令),
  2. "cdd (把行删除到”c“寄存器)和
  3. @c执行该命令。

这仅仅是10次击键(expression式"cdd @c对我来说实际上是一个手指macros,所以我可以像任何常见的六个字母一样快地input”)。


一个清醒的想法

我只是抓住了vi的力量,而这里所描述的任何东西都不是vim命名的“改进”的一部分! 我在这里描述的所有内容都应该在20或30年前的任何一个vi的旧版本上工作。

有些人比以往任何时候都更多地使用了vi的力量。

你正在谈论文本select和复制,我认为你应该看看Vim可视化模式 。

在可视化模式下,您可以使用Vim命令select文本,然后您可以根据您的select进行任何操作。

考虑以下常见的情况:

您需要select下一个匹配的括号。

你可以这样做:

  • 如果光标位于开始/结束括号上,则为v%
  • 如果光标位于括号内,则为vib

你想要在引号之间select文本:

  • 六“双引号
  • 六'单引号

你想select一个花括号块(在C风格的语言中很常见):

  • viB
  • vi{

你想select整个文件:

  • ggVG

可视化的块select是另一个非常有用的function,它允许你select一个矩形区域的文本,你只需要按下CtrlV来启动它,然后select你想要的文本块,并执行任何types的操作,如yank,删除,粘贴,编辑等。很好编辑列的文本。

一些生产力提示:

聪明的动作

  • *#在向前/向后的光标下search单词。
  • w到下一个单词
  • W到下一个空格分隔的单词
  • b / e到当前单词的开始/结尾。 (只适用于空间分隔的B / E
  • gg / G跳转到文件的开头/结尾。
  • 跳转到匹配的{..}或(..)等。
  • { / }跳转到下一段。
  • '. 跳回到最后编辑的行。
  • g; 跳回到上次编辑的位置。

快速编辑命令

  • I在开始插入。
  • 追加结束。
  • o / O在当前/之前打开一个新行。
  • v / V / Ctrl+V可视模式(select文本!)
  • Shift+Rreplace文字
  • C改变线的其余部分。

结合命令

大多数命令都接受数量和方向,例如:

  • cW =改变直到结束
  • 3cW =更改3个单词
  • BcW =全字开始,更改全字
  • ciW =改变内部词。
  • ci" =改变”..“之间的内部
  • ci( =改变文字(..)
  • ci< =在<..>之间改变文本(需要在vimrc中set matchpairs+=<:>
  • 4dd =删除4行
  • 3x =删除3个字符。
  • 3s =replace3个字符。

有用的程序员命令

  • rreplace一个字符(例如rddreplace当前字符)。
  • ~改变的情况。
  • Jjoin两行
  • Ctrl + A / Ctrl + X增加/减less一个数字。
  • . 重复上一个命令(一个简单的macros)
  • ==修复行缩进
  • >缩进块(在可视模式下)
  • < unindent块(在可视模式下)

macros录制

  • q[ key ]开始录制。
  • 然后按q停止录制。
  • macros可以用@[ key ]来播放。

通过使用非常特定的命令和动作,VIM可以重播下一行的确切动作。 (例如,A表示追加到结尾, b / e分别将光标移动到单词的开头或结尾)

良好的设置的例子

 # reset to vim-defaults if &compatible # only if not set before: set nocompatible # use vim-defaults instead of vi-defaults (easier, more user friendly) endif # display settings set background=dark # enable for dark terminals set nowrap # dont wrap lines set scrolloff=2 # 2 lines above/below cursor when scrolling set number # show line numbers set showmatch # show matching bracket (briefly jump) set showmode # show mode in status bar (insert/replace/...) set showcmd # show typed command in status bar set ruler # show cursor position in status bar set title # show file in titlebar set wildmenu # completion with menu set wildignore=*.o,*.obj,*.bak,*.exe,*.py[co],*.swp,*~,*.pyc,.svn set laststatus=2 # use 2 lines for the status bar set matchtime=2 # show matching bracket for 0.2 seconds set matchpairs+=<:> # specially for html # editor settings set esckeys # map missed escape sequences (enables keypad keys) set ignorecase # case insensitive searching set smartcase # but become case sensitive if you type uppercase characters set smartindent # smart auto indenting set smarttab # smart tab handling for indenting set magic # change the way backslashes are used in search patterns set bs=indent,eol,start # Allow backspacing over everything in insert mode set tabstop=4 # number of spaces a tab counts for set shiftwidth=4 # spaces for autoindents #set expandtab # turn a tabs into spaces set fileformat=unix # file mode is unix #set fileformats=unix,dos # only detect unix file format, displays that ^M with dos files # system settings set lazyredraw # no redraws in macros set confirm # get a dialog when :q, :w, or :wq fails set nobackup # no backup~ files. set viminfo='20,\"500 # remember copy registers after quitting in the .viminfo file -- 20 jump links, regs up to 500 lines' set hidden # remember undo after quitting set history=50 # keep 50 lines of command history set mouse=v # use mouse in visual mode (not normal,insert,command,help mode # color settings (if terminal/gui supports it) if &t_Co > 2 || has("gui_running") syntax on # enable colors set hlsearch # highlight search (very useful!) set incsearch # search incremently (search while typing) endif # paste mode toggle (needed when using autoindent/smartindent) map <F10> :set paste<CR> map <F11> :set nopaste<CR> imap <F10> <CO>:set paste<CR> imap <F11> <nop> set pastetoggle=<F11> # Use of the filetype plugins, auto completion and indentation support filetype plugin indent on # file type specific settings if has("autocmd") # For debugging #set verbose=9 # if bash is sh. let bash_is_sh=1 # change to directory of current file automatically autocmd BufEnter * lcd %:p:h # Put these in an autocmd group, so that we can delete them easily. augroup mysettings au FileType xslt,xml,css,html,xhtml,javascript,sh,config,c,cpp,docbook set smartindent shiftwidth=2 softtabstop=2 expandtab au FileType tex set wrap shiftwidth=2 softtabstop=2 expandtab # Confirm to PEP8 au FileType python set tabstop=4 softtabstop=4 expandtab shiftwidth=4 cinwords=if,elif,else,for,while,try,except,finally,def,class augroup END augroup perl # reset (disable previous 'augroup perl' settings) au! au BufReadPre,BufNewFile \ *.pl,*.pm \ set formatoptions=croq smartindent shiftwidth=2 softtabstop=2 cindent cinkeys='0{,0},!^F,o,O,e' " tags=./tags,tags,~/devel/tags,~/devel/C # formatoption: # t - wrap text using textwidth # c - wrap comments using textwidth (and auto insert comment leader) # r - auto insert comment leader when pressing <return> in insert mode # o - auto insert comment leader when pressing 'o' or 'O'. # q - allow formatting of comments with "gq" # a - auto formatting for paragraphs # n - auto wrap numbered lists # augroup END # Always jump to the last known cursor position. # Don't do it when the position is invalid or when inside # an event handler (happens when dropping a file on gvim). autocmd BufReadPost * \ if line("'\"") > 0 && line("'\"") <= line("$") | \ exe "normal g`\"" | \ endif endif # has("autocmd") 

这些设置可以存储在/etc/vimrc.local中的~/.vimrc或系统范围内,然后使用以下命令从/etc/vimrc文件读取:

 source /etc/vimrc.local 

(你必须用#replace#注释字符才能在VIM中工作,我想在这里给出适当的语法高亮)。

我在这里列出的命令是非常基本的,至今我使用的主要命令。 他们已经使我更有成效,而不必知道所有的花哨的东西。

Control + R机制非常有用:-)在插入模式命令模式下 (即在input命令时在:行上),继续使用编号或指定的寄存器:

  • az指定的寄存器
  • 未命名的registry,包含最后一次删除或抽出的文本
  • 当前的文件名
  • 备用文件名称
  • *剪贴板内容(X11:初选)
  • +剪贴板内容
  • /最后的search模式
  • 最后的命令行
  • 最后插入的文字
  • -最后一个小(不到一行)删除
  • = 5 * 5将25插入文本(迷你计算器)

请参阅:help i_CTRL-R:help c_CTRL-R了解更多细节,并在附近探听更多的CTRL-R的善良。

Vim插件

这里有很多很好的答案,还有一个关于vi的禅意的惊人的答案。 我没有看到的一件事是vim通过插件是非常可扩展的。 有脚本和插件,使它做原始作者从来没有考虑过的各种疯狂的东西。 下面是几个非常方便的vim插件的例子:

rails.vim

Rails.vim是一个由tpope编写的插件。 这是一个令人难以置信的工具,用于开发钢轨的人。 它使用神奇的上下文敏感的东西,使您可以轻松地从控制器中的方法跳转到关联的视图,转到模型,然后转到该模型的unit testing。 作为铁轨开发者,它已经节省了几十个甚至几百个小时。

gist.vim

这个插件允许你在可视模式下select一个文本区域,然后键入一个快速命令将其发布到gist.github.com 。 这允许轻松地访问pastebin,如果您通过IRC或IM与其他人进行协作,这是非常方便的。

space.vim

这个插件为空格提供了特殊的function。 它把空格变成与时期类似的东西,而不是重复动作重复动作。 这可以非常方便地通过您在飞行中定义的方式快速移动文件。

surround.vim

这个插件使您能够使用以某种方式分隔的文本。 它给你的对象表示东西里面的东西,引号内的东西等。它可以派上用场来处理分隔文本。

supertab.vim

这个脚本为vim带来了奇特的选项卡完成function。 自动完成的东西已经存在于vim的核心,但是这带来了一个快速的选项卡,而不是多个不同的多键快捷键。 非常方便,使用非常有趣。 虽然这不是VS的智能感知,但它是一个很棒的步骤,并带来了大量的function,你希望从一个标签补全工具。

syntastic.vim

该工具将外部语法检查命令带入vim。 我个人并没有使用它,但是我听到了很多关于它的概念,而且这个概念很难被打败。 检查语法而不必手动执行它是一个很好的时间保护程序,可以帮助您在引入它们时捕获语法错误,而不是在最终停止testing时。

fugitive.vim

直接从vim内部访问git。 再次,我没有使用这个插件,但我可以看到实用程序。 不幸的是,我在一个svn被认为是“新”的文化中,所以我不可能在相当长一段时间内看到git在工作。

nerdtree.vim

vim的树形浏览器。 我最近开始使用它,它非常方便。 It lets you put a treeview in a vertical split and open files easily. This is great for a project with a lot of source files you frequently jump between.

FuzzyFinderTextmate.vim

This is an unmaintained plugin, but still incredibly useful. It provides the ability to open files using a "fuzzy" descriptive syntax. It means that in a sparse tree of files you need only type enough characters to disambiguate the files you're interested in from the rest of the cruft.

结论

There are a lot of incredible tools available for vim. I'm sure I've only scratched the surface here, and it's well worth searching for tools applicable to your domain. The combination of traditional vi's powerful toolset, vim's improvements on it, and plugins which extend vim even further, it's one of the most powerful ways to edit text ever conceived. Vim is easily as powerful as emacs, eclipse, visual studio, and textmate.

谢谢

Thanks to duwanis for his vim configs from which I have learned much and borrowed most of the plugins listed here.

. Repeat last text-changing command

I save a lot of time with this one.

Visual mode was mentioned previously, but block visual mode has saved me a lot of time when editing fixed size columns in text file. (accessed with Ctrl-V).

GI

Go to last edited location (very useful if you performed some searching and than want go back to edit)

^P and ^N

Complete previous (^P) or next (^N) text.

^O and ^I

Go to previous ( ^O"O" for old) location or to the next ( ^I"I" just near to "O" ). When you perform searches, edit files etc., you can navigate through these "jumps" forward and back.

I recently (got) discovered this site: http://vimcasts.org/

It's pretty new and really really good. The guy who is running the site switched from textmate to vim and hosts very good and concise casts on specific vim topics. 一探究竟!

CTRL + A increments the number you are standing on.

All in Normal mode:

f<char> to move to the next instance of a particular character on the current line, and ; to repeat.

F<char> to move to the previous instance of a particular character on the current line and ; to repeat.

If used intelligently, the above two can make you killer-quick moving around in a line.

* on a word to search for the next instance.

# on a word to search for the previous instance.

会议

一个。 save session

:mks sessionname

湾 force save session

:mks! sessionname

C。 load session

gvim or vim -S sessionname


Adding and Subtracting

一个。 Adding and Subtracting

CTRL-A ;Add [count] to the number or alphabetic character at or after the cursor. {not in Vi

CTRL-X ;Subtract [count] from the number or alphabetic character at or after the cursor. {not in Vi}

湾 Window key unmapping

In window, Ctrl-A already mapped for whole file selection you need to unmap in rc file. mark mswin.vim CTRL-A mapping part as comment or add your rc file with unmap

C。 With Macro

The CTRL-A command is very useful in a macro. Example: Use the following steps to make a numbered list.

  1. Create the first list entry, make sure it starts with a number.
  2. qa – start recording into buffer 'a'
  3. Y – yank the entry
  4. p – put a copy of the entry below the first one
  5. CTRL-A – increment the number
  6. q – stop recording
  7. @a – repeat the yank, put and increment times

Last week at work our project inherited a lot of Python code from another project. Unfortunately the code did not fit into our existing architecture – it was all done with global variables and functions, which would not work in a multi-threaded environment.

We had ~80 files that needed to be reworked to be object oriented – all the functions moved into classes, parameters changed, import statements added, etc. We had a list of about 20 types of fix that needed to be done to each file. I would estimate that doing it by hand one person could do maybe 2-4 per day.

So I did the first one by hand and then wrote a vim script to automate the changes. Most of it was a list of vim commands eg

 " delete an un-needed function " g/someFunction(/ d " add wibble parameter to function foo " %s/foo(/foo( wibble,/ " convert all function calls bar(thing) into method calls thing.bar() " g/bar(/ normal nmaf(ldi(`aPa. 

The last one deserves a bit of explanation:

 g/bar(/ executes the following command on every line that contains "bar(" normal execute the following text as if it was typed in in normal mode n goes to the next match of "bar(" (since the :g command leaves the cursor position at the start of the line) ma saves the cursor position in mark a f( moves forward to the next opening bracket l moves right one character, so the cursor is now inside the brackets di( delete all the text inside the brackets `a go back to the position saved as mark a (ie the first character of "bar") P paste the deleted text before the current cursor position a. go into insert mode and add a "." 

For a couple of more complex transformations such as generating all the import statements I embedded some python into the vim script.

After a few hours of working on it I had a script that will do at least 95% of the conversion. I just open a file in vim then run :source fixit.vim and the file is transformed in a blink of the eye.

We still have the work of changing the remaining 5% that was not worth automating and of testing the results, but by spending a day writing this script I estimate we have saved weeks of work.

Of course it would have been possible to automate this with a scripting language like Python or Ruby, but it would have taken far longer to write and would be less flexible – the last example would have been difficult since regex alone would not be able to handle nested brackets, eg to convert bar(foo(xxx)) to foo(xxx).bar() . Vim was perfect for the task.

Use the builtin file explorer! The command is :Explore and it allows you to navigate through your source code very very fast. I have these mapping in my .vimrc :

 map <silent> <F8> :Explore<CR> map <silent> <S-F8> :sp +Explore<CR> 

The explorer allows you to make file modifications, too. I'll post some of my favorite keys, pressing <F1> will give you the full list:

  • : The most useful: Change to upper directory ( cd .. )
  • mf : Mark a file
  • D : Delete marked files or the file the cursor is on, if nothing ismarked.
  • R : Rename the file the cursor is on.
  • d : Create a new directory in the current directory
  • % : Create a new file in the current directory

I am a member of the American Cryptogram Association. The bimonthly magazine includes over 100 cryptograms of various sorts. Roughly 15 of these are "cryptarithms" – various types of arithmetic problems with letters substituted for the digits. Two or three of these are sudokus, except with letters instead of numbers. When the grid is completed, the nine distinct letters will spell out a word or words, on some line, diagonal, spiral, etc., somewhere in the grid.

Rather than working with pencil, or typing the problems in by hand, I download the problems from the members area of their website.

When working with these sudokus, I use vi, simply because I'm using facilities that vi has that few other editors have. Mostly in converting the lettered grid into a numbered grid, because I find it easier to solve, and then the completed numbered grid back into the lettered grid to find the solution word or words.

The problem is formatted as nine groups of nine letters, with - s representing the blanks, written in two lines. The first step is to format these into nine lines of nine characters each. There's nothing special about this, just inserting eight linebreaks in the appropriate places.

The result will look like this:

 TO-----C -E-----S- --AT--NL ---NASO-- ---ET--- --SPCL--- ET--OS-- -A-----P- S-----CT 

So, first step in converting this into numbers is to make a list of the distinct letters. First, I make a copy of the block. I position the cursor at the top of the block, then type :y}}p . : puts me in command mode, y yanks the next movement command. Since } is a move to the end of the next paragraph, y} yanks the paragraph. } then moves the cursor to the end of the paragraph, and p pastes what we had yanked just after the cursor. So y}}p creates a copy of the next paragraph, and ends up with the cursor between the two copies.

Next, I to turn one of those copies into a list of distinct letters. That command is a bit more complex:

 :!}tr -cd AZ | sed 's/\(.\)/\1\n/g' | sort -u | tr -d '\n' 

: again puts me in command mode. ! indicates that the content of the next yank should be piped through a command line. } yanks the next paragraph, and the command line then uses the tr command to strip out everything except for upper-case letters, the sed command to print each letter on a single line, and the sort command to sort those lines, removing duplicates, and then tr strips out the newlines, leaving the nine distinct letters in a single line, replacing the nine lines that had made up the paragraph originally. In this case, the letters are: ACELNOPST .

Next step is to make another copy of the grid. And then to use the letters I've just identified to replace each of those letters with a digit from 1 to 9. That's simple: :!}tr ACELNOPST 0-9 . 结果是:

 8-5-----1 -2-----7- --08--4-3 ---4075-- ---2-8--- --7613--- 2-8--57-- -0-----6- 7-----1-8 

This can then be solved in the usual way, or entered into any sudoku solver you might prefer. The completed solution can then be converted back into letters with :!}tr 1-9 ACELNOPST .

There is power in vi that is matched by very few others. The biggest problem is that only a very few of the vi tutorial books, websites, help-files, etc., do more than barely touch the surface of what is possible.

Bulk text manipulations!

Either through macros:

  • Start with recording: qq
  • Do stuff
  • Stop recording: q
  • Repeat: @q (the first time), @@ after that.
  • Repeat 20 times: 20@@

Or through regular expressions:

  • Replace stuff: :%s/[fo]+/bar/g

(But be warned: if you do the latter, you'll have 2 problems :).)

I recently discovered q: . It opens the "command window" and shows your most recent ex-mode (command-mode) commands. You can move as usual within the window, and pressing <CR> executes the command. You can edit, etc. too. Priceless when you're messing around with some complex command or regex and you don't want to retype the whole thing, or if the complex thing you want to do was 3 commands back. It's almost like bash's set -o vi , but for vim itself (heh!).

See :help q: for more interesting bits for going back and forth.

I just discovered Vim's omnicompletion the other day, and while I'll admit I'm a bit hazy on what does which, I've had surprisingly good results just mashing either Ctrl + x Ctrl + u or Ctrl + n / Ctrl + p in insert mode. It's not quite IntelliSense , but I'm still learning it.

试试看! :help ins-completion

These are not shortcuts, but they are related:

  1. Make capslock an additional ESC (or Ctrl)
  2. map leader to "," (comma), with this command: let mapleader=","

They boost my productivity.

Another useful vi "shortcut" I frequently use is 'xp'. This will swap the character under the cursor with the next character.

<Ctrl> + W, V to split the screen vertically
<Ctrl> + W, W to shift between the windows

!python % [args] to run the script I am editing in this window

ZF in visual mode to fold arbitrary lines

Visual Mode

As several other people have said, visual mode is the answer to your copy/cut & paste problem. Vim gives you 'v', 'V', and Cv. Lower case 'v' in vim is essentially the same as the shift key in notepad. The nice thing is that you don't have to hold it down. You can use any movement technique to navigate efficiently to the starting (or ending) point of your selection. Then hit 'v', and use efficient movement techniques again to navigate to the other end of your selection. Then 'd' or 'y' allows you to cut or copy that selection.

The advantage vim's visual mode has over Jim Dennis's description of cut/copy/paste in vi is that you don't have to get the location exactly right. Sometimes it's more efficient to use a quick movement to get to the general vicinity of where you want to go and then refine that with other movements than to think up a more complex single movement command that gets you exactly where you want to go.

The downside to using visual mode extensively in this manner is that it can become a crutch that you use all the time which prevents you from learning new vi(m) commands that might allow you to do things more efficiently. However, if you are very proactive about learning new aspects of vi(m), then this probably won't affect you much.

I'll also re-emphasize that the visual line and visual block modes give you variations on this same theme that can be very powerful…especially the visual block mode.

On Efficient Use of the Keyboard

I also disagree with your assertion that alternating hands is the fastest way to use the keyboard. It has an element of truth in it. Speaking very generally, repeated use of the same thing is slow. This most significant example of this principle is that consecutive keystrokes typed with the same finger are very slow. Your assertion probably stems from the natural tendency to use the s/finger/hand/ transformation on this pattern. To some extent it's correct, but at the extremely high end of the efficiency spectrum it's incorrect.

Just ask any pianist. Ask them whether it's faster to play a succession of a few notes alternating hands or using consecutive fingers of a single hand in sequence. The fastest way to type 4 keystrokes is not to alternate hands, but to type them with 4 fingers of the same hand in either ascending or descending order (call this a "run"). This should be self-evident once you've considered this possibility.

The more difficult problem is optimizing for this. It's pretty easy to optimize for absolute distance on the keyboard. Vim does that. It's much harder to optimize at the "run" level, but vi(m) with it's modal editing gives you a better chance at being able to do it than any non-modal approach (ahem, emacs) ever could.

On Emacs

Lest the emacs zealots completely disregard my whole post on account of that last parenthetical comment, I feel I must describe the root of the difference between the emacs and vim religions. I've never spoken up in the editor wars and I probably won't do it again, but I've never heard anyone describe the differences this way, so here it goes. The difference is the following tradeoff:

Vim gives you unmatched raw text editing efficiency Emacs gives you unmatched ability to customize and program the editor

The blind vim zealots will claim that vim has a scripting language. But it's an obscure, ad-hoc language that was designed to serve the editor. Emacs has Lisp! 说够了。 If you don't appreciate the significance of those last two sentences or have a desire to learn enough about functional programming and Lisp to develop that appreciation, then you should use vim.

The emacs zealots will claim that emacs has viper mode, and so it is a superset of vim. But viper mode isn't standard. My understanding is that viper mode is not used by the majority of emacs users. Since it's not the default, most emacs users probably don't develop a true appreciation for the benefits of the modal paradigm.

In my opinion these differences are orthogonal. I believe the benefits of vim and emacs as I have stated them are both valid. This means that the ultimate editor doesn't exist yet. It's probably true that emacs would be the easiest platform on which to base the ultimate editor. But modal editing is not entrenched in the emacs mindset. The emacs community could move that way in the future, but that doesn't seem very likely.

So if you want raw editing efficiency, use vim. If you want the ultimate environment for scripting and programming your editor use emacs. If you want some of both with an emphasis on programmability, use emacs with viper mode (or program your own mode). If you want the best of both worlds, you're out of luck for now.

Spend 30 mins doing the vim tutorial (run vimtutor instead of vim in terminal). You will learn the basic movements, and some keystrokes, this will make you at least as productive with vim as with the text editor you used before. After that, well, read Jim Dennis' answer again 🙂

What is the way you use Vim that makes you more productive than with a contemporary editor?

Being able to execute complex, repetitive edits with very few keystrokes (often using macros ). Take a look at VimGolf to witness the power of Vim!

After over ten years of almost daily usage, it's hard to imagine using any other editor.

Use \c anywhere in a search to ignore case (overriding your ignorecase or smartcase settings). Eg /\cfoo or /foo\c will match foo , Foo , fOO , FOO , etc.

Use \C anywhere in a search to force case matching. Eg /\Cfoo or /foo\C will only match foo.

I was surprised to find no one mention the t movement. I frequently use it with parameter lists in the form of dt, or yt,

Odd nobody's mentioned ctags. Download "exuberant ctags" and put it ahead of the crappy preinstalled version you already have in your search path. Cd to the root of whatever you're working on; for example the Android kernel distribution. Type "ctags -R ." to build an index of source files anywhere beneath that dir in a file named "tags". This contains all tags, nomatter the language nor where in the dir, in one file, so cross-language work is easy.

Then open vim in that folder and read :help ctags for some commands. A few I use often:

  • Put cursor on a method call and type CTRL-] to go to the method definition.

  • Type :ta name to go to the definition of name.

Automatic indentation:

gg (go to start of document)
= (indent time!)
shift-g (go to end of document)

You'll need 'filetype plugin indent on' in your .vimrc file, and probably appropriate 'shiftwidth' and 'expandtab' settings.

You asked about productive shortcuts, but I think your real question is: Is vim worth it? The answer to this stackoverflow question is -> "Yes"

You must have noticed two things. Vim is powerful, and vim is hard to learn. Much of it's power lies in it's expandability and endless combination of commands. Don't feel overwhelmed. 慢点。 One command, one plugin at a time. Don't overdo it.

All that investment you put into vim will pay back a thousand fold. You're going to be inside a text editor for many, many hours before you die. Vim will be your companion.

Multiple buffers, and in particular fast jumping between them to compare two files with :bp and :bn (properly remapped to a single Shift + p or Shift + n )

vimdiff mode (splits in two vertical buffers, with colors to show the differences)

Area-copy with Ctrl + v

And finally, tab completion of identifiers (search for "mosh_tab_or_complete"). That's a life changer.

Agreed with the top poster – the :r! command is very useful.

Most often I use it to "paste" things:

 :r!cat **Ctrl-V to paste from the OS clipboard** ^D 

This way I don't have to fiddle with :set paste .