What are the dark corners of Vim your mom never told you about?
在人们谈论常用技巧时,有很多问题,特别是"vim+ctags技巧和技巧"。
然而,我并没有提到一些刚接触Vim的人会觉得很酷的常用快捷方式。我说的是一个经验丰富的Unix用户(无论他们是开发人员、管理员,还是两者都是),他们认为我们99%的人从未听说过或梦想过什么。这些东西不仅使他们的工作更容易,而且很酷也很刻薄。毕竟,Vim居住在世界上最黑暗的角落里,拥有丰富的操作系统,因此它应该有一些只有少数特权知道的错综复杂的东西,并且希望与我们分享。
可能不是99%的vim用户不知道的,但这是我每天使用的东西,任何Linux+vim poweruser都必须知道。
基本命令,但非常有用。
1 | :w !sudo tee % |
我经常在编辑一个我没有写权限的文件之前忘记使用sudo。当我开始保存那个文件并得到一个权限错误时,我只是发出vim命令来保存这个文件,而不需要将它保存到一个临时文件中,然后再次复制它。
显然,您必须在安装了sudo的系统上,并且拥有sudo权限。
最近我发现了一件我认为很酷的事情:
1 | :earlier 15m |
将文档还原为15分钟前的状态。可以在您想要回滚的时间内使用各种参数,这取决于撤消级别。可以用相反的命令
当您在VIM中时,
但是在冒号后面加一个点,
例如:
1 | :.! ls |
我经常使用这个方法,例如将当前日期添加到我正在键入的文档中:
1 | :.! date |
不完全是模糊的,但是有几个"delete-in"命令非常有用,比如……
diw 删除当前字di( 在当前parens中删除- 删除报价之间的文本。
其他可以在
按可删除所有内容,直至单词结束。在你心中的渴望。
ci(xyz[esc]——这是一个奇怪的。这里,"i"不是指插入模式。相反,它的意思是在括号内。所以这个序列会将您所站在括号内的文本剪切,并将其替换为"xyz"。它也在方括号和数字括号内工作——相应地做ci[或ci即可。当然,您可以执行DI(如果您只想删除所有文本而不键入任何内容)。如果要删除括号,而不仅仅是括号内的文本,也可以使用
ci"-在当前引号中剪切文本
ciw-剪切当前单词。这和前一个一样,只是
C-切断线路的其余部分并切换到插入模式。
zz—保存并关闭当前文件(比ctrl-f4关闭当前选项卡快得多!)
DDP-将当前行下移一行
xp—将当前字符向右移动一个位置
u-大写,所以
~-切换大小写,所以
ctrl+u/ctrl+d向上或向下滚动半屏页面。这似乎比通常的全屏分页更有用,因为这样更容易看到两个屏幕之间的关系。对于那些仍然想一次滚动整个屏幕的人,有ctrl+f表示前进,ctrl+b表示后退。ctrl+y和ctrl+e一次向下或向上滚动一行。
疯狂但非常有用的命令是ZZ——它滚动屏幕使这条线出现在中间。这对于将您正在处理的代码放在您注意力的中心非常好。兄弟命令——zt和zb——使这行成为sreen上的顶部或底部行,这并没有那么有用。
%查找并跳到匹配的括号。
de——从光标到词尾的删除(也可以通过
bde—删除当前单词,从左到右分隔符
df[空格]——删除直到并包括下一个空格
D.--删除到下一个点
dd—删除整行
Ye(或Ye)--将文本从这里拉到单词的结尾
ce-将单词的结尾切掉
再见--复制当前单词(让我想知道"嗨"是什么意思!)
YY—复制当前行
cc——切断当前的线路,你也可以用
VIWY或VIWC。扬起或更改当前单词。多次点击
vi-选择图括号中的所有文本。va-选择所有文本,包括s
vi(p-突出显示()s中的所有内容,并替换为粘贴的文本
b和e逐字移动光标,类似于ctrl+箭头通常的方式。不过,单词的定义有点不同,因为几个连续的斜线被视为一个单词。如果从一个词的中间开始,按B键将始终使您到达当前词的开头,并且每个连续的B将跳到下一个词的开头。同样,也很容易记住,
与
大写D(深呼吸)删除光标右侧的行的其余部分,与正常编辑器中的shift+end/del相同(注意2个按键--shift+d--而不是3)
我很少在大多数VIM教程中找到,但是它非常有用(至少对我来说),是
在变更列表中移动(向前、向后)。
我来演示一下我是如何使用它的。有时我需要复制和粘贴一段代码或字符串,比如说CSS文件中的十六进制颜色代码,所以我搜索、跳转(不关心匹配的地方),复制它,然后跳转回(g;)我编辑代码的地方,最终粘贴它。不需要创建标记。更简单。
就我两分钱。
1 | :%!xxd |
使vim成为十六进制编辑器。
1 | :%!xxd -r |
回复。
警告:如果不使用二进制文件(-b)进行编辑,可能会损坏文件。—乔希·李在评论中。
1 | gv |
重新选择最后一个视觉选择。
有时.vimrc中的设置会被插件或自动命令覆盖。要调试它,一个有用的技巧是将:verbose命令与:set结合使用。例如,要确定Cindent的设置/取消设置位置:
1 | :verbose set cindent? |
这将输出如下内容:
1 2 | cindent Last set from /usr/share/vim/vim71/indent/c.vim |
这也适用于地图和高光。(感谢JoeyWiddle指出这一点。)例如:
1 2 3 4 5 6 7 | :verbose nmap U n U <C-R> Last set from ~/.vimrc :verbose highlight Normal Normal xxx guifg=#dddddd guibg=#111111 font=Inconsolata Medium 14 Last set from ~/src/vim-holodark/colors/holodark.vim |
不确定这是否算是黑暗角落,但我只是刚刚学会了…
1 | :g/match/y A |
将所有包含"匹配"的行拉入(复制)到
创建当前文件的HTML呈现。
要查看您的:命令历史记录吗?
1 | q: |
然后浏览、编辑并最终执行命令。
有没有对两个文件做过类似的更改并在它们之间来回切换?(比如,源文件和头文件?)
1 2 | :set hidden :map <TAB> :e#<CR> |
然后在这些文件之间来回切换。
例如,Vim将打开一个URL
1 | vim http://stackoverflow.com/ |
当你需要调出一个页面的源代码以供参考时很好。
宏可以调用其他宏,也可以调用自身。
如:
1 | qq0dwj@qq@q |
…将从每行删除第一个单词,直到文件结束。
这是一个很简单的例子,但它展示了VIM的一个非常强大的特性。
假设您在中编译了Perl和/或Ruby支持,
您可以使用它来做一些在脚本语言中很容易做的事情,但是使用VIM内置函数并不是很明显。例如,要颠倒一行中单词的顺序:
1 | :perldo $_ = join ' ', reverse split |
在每行末尾插入8个字符(a-z)的随机字符串:
1 | :rubydo $_ += ' ' + (1..8).collect{('A'..'Z').to_a[rand 26]}.join |
一次只能在一行上操作,不能添加换行符。
^和^ i
转到旧/新位置。当您在文件中移动(通过搜索、移动命令等)时,Vim会记住这些"跳跃",这样您就可以重复这些向后跳跃(^o-o表示旧的)和向前跳跃(^i-刚好在键盘上的i旁边)。我发现它在编写代码和执行大量搜索时非常有用。
胃肠道
转到上次停止插入模式的位置。我发现自己经常编辑然后寻找一些东西。要返回编辑位置,请按gi。
GF
将光标放在文件名上(如包含头文件),按gf,文件打开。
GF
类似于gf,但识别格式为"[文件名]:[行号]"。按gf将打开[文件名]并将光标设置为[行号]。
p和^ n
编辑时自动完成文本(^p-上一个匹配项和^n下一个匹配项)
^ xl
当编辑完成到同一行时(对编程有用)。您编写代码,然后回忆起在文件中的某个地方有相同的代码。只需按^x^l,整行就完成了
^ ^ ^ f
完整的文件名。你写了"/etc/pass"嗯。你忘了文件名。只需按^x^f,文件名就完成了。
z或:嘘
临时移动到外壳。如果你需要一个快速的打击:
- 按^Z(将vi置于背景)返回原始shell,按fg返回vim back
- 按:sh转到子shell,按^d/退出返回vi
这是一个用不同编码重新打开当前文件的好技巧:
1 | :e ++enc=cp1250 %:p |
当您必须使用旧编码时很有用。支持的编码列在
1 2 3 4 5 6 | " insert range ip's " " ( O O ) " =======oOO=(_)==OOo====== :for i in range(1,255) | .put='10.0.0.'.i | endfor |
键入==将根据上面的行更正当前行的缩进。
实际上,您可以在任何移动命令后执行一个=符号。= {运动}
例如,可以使用在匹配大括号之间移动的%移动。将光标放在上,代码如下:
1 2 3 4 5 6 | if (thisA == that) { //not indented if (some == other) { x = y; } } |
按.%立即得到:
1 2 3 4 5 6 | if (thisA == that) { //not indented if (some == other) { x = y; } } |
或者,您可以在代码块中执行=a,而不是将自己定位在字符上。
1 | imap jj <esc> |
让我们来看一些非常小的IDE编辑器进行列转换。
1 | :%s/\(.*\)^I\(.*\)/\2^I\1/ |
解释
1 | >>> \(.*\)^I\(.*\) |
记住所有的事情,然后是
1 | >>> \2^I\1 |
用"你记得的第二件事"和"你记得的第一件事"来替换上面的东西——本质上是做一个换位。
不完全是一个黑暗的秘密,但我喜欢把下面的映射放到我的.vimrc文件中,这样我可以随时点击"-"(减号)打开文件资源管理器,显示与我刚编辑的文件相邻的文件。在文件资源管理器中,我可以点击另一个"-"向上移动一个目录,从而无缝浏览复杂的目录结构(就像现在的MVC框架所使用的那样):
1 | map - :Explore<cr> |
这些可能对某些人也有用。我喜欢滚动屏幕,同时向前移动光标:
1 2 | map <c-j> j<c-e> map <c-k> k<c-y> |
标签导航-我喜欢标签,我需要在它们之间轻松移动:
1 2 | map <c-l> :tabnext<enter> map <c-h> :tabprevious<enter> |
仅在Mac OS X上:类似于Safari的选项卡导航:
1 2 | map <S-D-Right> :tabnext<cr> map <S-D-Left> :tabprevious<cr> |
我喜欢用"sudo bash",我的系统管理员讨厌这个。他锁定了"sudo",这样它只能与少数命令(ls、chmod、chown、vi等)一起使用,但我仍然可以使用vim获取根shell:
1 2 3 | bash$ sudo vi +'silent !bash' +q Password: ****** root# |
通常,我喜欢在编辑时更改当前目录-所以我必须少指定路径。
1 | cd %:h |
我经常在项目中使用许多窗口,有时我需要调整它们的大小。我用的是:
1 2 | map + <C-W>+ map - <C-W>- |
这些映射允许增加和减小当前窗口的大小。很简单,但很快。
不是一个模糊的功能,但非常有用和节省时间。
如果要保存打开的缓冲区、选项卡、标记和其他设置的会话,可以发出以下命令:
1 | mksession session.vim |
您可以使用以下方式打开会话:
1 | vim -S session.vim |
将f5映射为快速rot13您的缓冲区:
1 | map <F5> ggg?G`` |
你可以把它当作老板的钥匙。
1 | :r! <command> |
将外部命令的输出粘贴到缓冲区中。
做一些数学运算,直接在文本中得到结果:
1 | :r! echo $((3 + 5 + 8)) |
获取写入makefile时要编译的文件列表:
1 | :r! ls *.c |
不要查阅你在维基百科上读到的事实,直接把它粘贴到你正在写的文档中:
1 | :r! lynx -dump http://en.wikipedia.org/wiki/Whatever |
今天我通过国家自然科学基金会发现了这个:
注释代码块。
按ctrl-v进入分块视觉模式。
标记要注释的块。
点击i(大写i)并在行首输入注释字符串。(/对于C++)
按Esc键,所选的所有行都将//置于行的前面。
我使用vim进行几乎所有的文本编辑,所以我经常使用复制和粘贴。问题是,vim在默认情况下经常会通过粘贴来扭曲导入的文本。阻止这种情况的方法是
1 | :set paste |
在粘贴数据之前。这样就不会把事情搞得一团糟。
请注意,您必须发出
有时打开高对比度配色方案也很有帮助。这可以用
1 | :color blue |
我注意到它不适用于我使用的所有版本的VIM,但是它适用于大多数版本。
这是一些不明显的东西。如果您的$home中有很多自定义插件/扩展,并且您需要从su/sudo/工作。有时,这可能是有用的。
在您的~/.bashrc中:
在你的~/.vimrc中:
它将允许您的本地插件加载-无论您使用什么方式来更改用户。
您可能还希望将*.swp文件从当前路径中取出并放入~/vimtmp(这将进入.vimrc):
另外,我使用一些映射使编辑更容易-使ctrl+s像escape一样工作,ctrl+h/l切换选项卡:
当处于插入模式时,ctrl-n将根据打开缓冲区中的所有单词自动完成您键入的任何单词。如果有多个匹配项,它将为您提供一个可以使用ctrl-n和ctrl-p循环使用的单词列表。
1 | gg=G |
更正整个文件的缩进。我在Eclipse中丢失了我的可靠的
sudo-write的变化:
VIMRC
1 | cmap w!! w !sudo tee % >/dev/null |
重新加载VIM后,可以将"sudo save"作为
1 | :w!! |
能够在基于客户机/服务器的模式上运行VIM。
例如,假设您正在处理一个项目,其中有许多缓冲区、选项卡和其他信息保存在名为session.vim的会话文件中。
您可以通过发出以下命令打开会话并创建服务器:
1 | vim --servername SAMPLESERVER -S session.vim |
注意,如果您想创建一个服务器,并且它不一定是一个会话,那么您可以打开常规文本文件。
现在,假设您在另一个终端中,需要打开另一个文件。如果您通过发布以下内容定期打开:
1 | vim new_file.txt |
您的文件将在单独的VIM缓冲区中打开,这很难与会话中的文件进行交互。要在服务器上的新选项卡中打开new_file.txt,请使用以下命令:
1 | vim --servername SAMPLESERVER --remote-tab-silent new_file.txt |
如果没有运行服务器,则会像打开常规文件一样打开此文件。
因为每次想要运行这些标志时都提供这些标志非常繁琐,所以可以为创建客户机和服务器创建单独的别名。
我在我的bashrc文件中放置了以下内容:
1 2 | alias vims='vim --servername SAMPLESERVER' alias vimc='vim --servername SAMPLESERVER --remote-tab-silent' |
您可以在以下网址找到有关此的更多信息:http://vimdoc.sourceforge.net/htmldoc/remote.html
想要一个IDE吗?
如何:在bash中使用vim时自动完成ctags。对于其他使用vim和ctags的人,我为bash编写了一个小型的自动完成函数。将以下内容添加到~/.bash_完成文件中(如果不存在,则创建它):
感谢Styleshpants对他的许多修复和改进。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | _vim_ctags() { local cur prev COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" case"${prev}" in -t) # Avoid the complaint message when no tags file exists if [ ! -r ./tags ] then return fi # Escape slashes to avoid confusing awk cur=${cur////\\/} COMPREPLY=( $(compgen -W"`awk -vORS="" "/^${cur}/ { print \\$1 }" tags`" ) ) ;; *) _filedir_xspec ;; esac } # Files matching this pattern are excluded excludelist='*.@(o|O|so|SO|so.!(conf)|SO.!(CONF)|a|A|rpm|RPM|deb|DEB|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MP?(E)G|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)' complete -F _vim_ctags -f -X"${excludelist}" vi vim gvim rvim view rview rgvim rgview gview |
重新启动bash会话(或创建新会话)后,可以键入:
代码:
1 | ~$ vim -t MyC<tab key> |
它会像对文件和目录那样自动完成标记:
代码:
1 2 | MyClass MyClassFactory ~$ vim -t MyC |
当我跳进一个快速的错误修复程序时,我发现它真的很有用。
我经常想突出显示一个特定的单词/函数名,但还不想搜索它的下一个实例:
1 | map m* *# |
我什么都用VIM。当我编辑电子邮件时,我使用:
广泛地以一段一段的方式轻松、正确地重新格式化,即使使用引号前导字符也是如此。为了实现此功能,我还添加了:
调用外部编辑器的命令。一个值得注意的添加是向fo(formatOptions)参数添加"a"。这将在键入和导航内容时自动重新格式化段落,但可能会干扰或导致邮件中包含的格式错误或奇怪的问题。
%当你想在一个项目的两个不同的副本之间区分文件,而不磨损小指(从项目1的根目录)时,这也是很好的方法:
1 | :vert diffs /project2/root/% |
:setlocal autoread
自动重新加载当前缓冲区..在查看日志文件时特别有用,它几乎可以从VIM中为UNIX中的"tail"程序提供功能。
检查VIM中的编译错误。根据语言设置makeprg变量,比如Perl
:setlocal makeprg = perl\ -c \ %
对于PHP
set makeprg=php\ -l\ %
set errorformat=%m\ in\ %f\ on\ line\ %l
发出":make"运行相关的makeprg并在QuickFix窗口中显示编译错误/警告,可以轻松导航到相应的行号。
由于延迟和缺少颜色(我喜欢颜色方案:)我不喜欢在远程机器上用油灰编程。所以我开发了这个技巧来解决这个问题。我在窗户上用。
你需要
- 1X GVIM
- 远程和本地计算机上的1X rsync
- 远程计算机的1X ssh私钥身份验证,因此不需要键入密码
- 1X选美
- 1X腻子
设置远程机器
配置rsync以使您的工作目录可访问。我使用ssh隧道,并且只允许来自隧道的连接:
1 2 3 4 5 6 7 | address = 127.0.0.1 hosts allow = 127.0.0.1 port = 40000 use chroot = false [bledge_ce] path = /home/xplasil/divine/bledge_ce read only = false |
然后启动rsyncd:rsync--daemon--config=rsyncd.conf
设置本地计算机
从cygwin安装rsync。启动页导航并加载远程计算机的私钥。如果您正在使用ssh调音,请启动putty来创建通道。在工作目录中创建一个批处理文件push.bat,它将使用rsync将更改的文件上载到远程计算机:
1 | rsync --blocking-io *.cc *.h SConstruct rsync://localhost:40001/bledge_ce |
sconstruct是scons的生成文件。根据需要修改文件列表。如果不使用ssh调优,则将localhost替换为远程计算机的名称。
配置VIM现在很容易。我们将使用QuickFix功能(:make和错误列表),但编译将在远程计算机上运行。所以我们需要设置makeprg:
1 | set makeprg=push\ &&\ plink\ -batch\ xplasil@anna.fi.muni.cz\ "cd\ /home/xplasil/divine/bledge_ce\ &&\ scons\ -j\ 2" |
这将首先启动push.bat任务来上载文件,然后使用ssh(putty套件中的plink)在远程计算机上执行命令。命令首先将目录更改为working dir,然后启动build(我使用scons)。
构建结果将很容易显示在您的本地GVIM错误列表中。
从十六进制值输入字符(插入模式):
1 | <C-Q>x[type the hexadecimal byte] |
把它放到.vimrc中,让它有一个命令来漂亮地打印XML:
1 2 3 4 5 6 7 8 | function FormatXml() %s:\(\S\)\(<[^/]\)\|\(>\)\(</\):\1\3 \2\4:g set filetype=xml normal gg=G endfunction command FormatXml :call FormatXml() |
1 2 3 4 5 6 7 8 9 | ========================================================== In normal mode ========================================================== gf ................ open file under cursor in same window --> see :h path Ctrl-w f .......... open file under cursor in new window Ctrl-w q .......... close current window Ctrl-w 6 .......... open alternate file --> see :h # gi ................ init insert mode in last insertion position '0 ................ place the cursor where it was when the file was last edited |
我肯定有人已经把这个贴出来了,但是这里有。
请使用任何构建系统;make,mvn,ant,随便什么。在项目目录的根目录中,创建您一直使用的命令的文件,如下所示:
MVN安装
MVN清洁安装
…诸如此类
要进行构建,请将光标放在行上并键入!!sh,即筛选该行;将其写入shell并替换为结果。
生成日志将替换行,随时可以滚动、搜索或执行任何操作。
查看完日志后,键入u以撤消,然后返回命令文件。
或是我
一些有用的:
1 2 3 | :set nu # displays lines :44 # go to line 44 '. # go to last modification line |
我最喜欢的:ctrl+n单词完成!
在处理构建过程缓慢的项目时,我总是在后台构建,并将输出通过管道传输到名为errors.err的文件(类似于
(属于Rampion's
在复制和粘贴到stackoverflow之前:
1 2 3 | :retab 1 :% s/^I/ /g :% s/^/ / |
现在复制并粘贴代码。
根据评论要求:
RATAB 1。这会将选项卡大小设置为1。但它也会通过代码添加额外的制表符和空格,这样格式就不会移动任何实际的文本(即文本在Ratab之后看起来是一样的)。
%注意,^i是点击标签的结果。这将搜索所有选项卡并用一个空格替换它们。因为我们刚刚做了一个重新标记,这不应该导致格式改变,但因为把标签放进一个网站被点击和错过,删除它们是很好的。
%S/^/:将行首替换为四个空格。因为您不能用它在行首插入的四个空格来替换行首(这是SO格式需要的,以便使代码突出)。
让vim更像一个IDE编辑器:
- 为左边距中的行号设置nu。
- set cul-突出显示包含光标的行。
在插入模式下,ctrl+xbakbd、ctrl+p将完成(如果您喜欢的话,还有可能完成的菜单)您正在键入的当前长标识符。
1 2 3 4 5 6 | if (SomeCall(LONG_ID_ <-- type c-x c-p here [LONG_ID_I_CANT_POSSIBLY_REMEMBER] LONG_ID_BUT_I_NEW_IT_WASNT_THIS_ONE LONG_ID_GOSH_FORGOT_THIS LONG_ID_ETC ∶ |
重新使用
与其他命令混合的动作,这里更多。
1 2 3 | tx fx Fx |
在Vim中使用您最喜欢的工具。
1 | :r !python anything you want or awk or Y something |
在视觉模式下重复,与上面的提示结合使用时很强大。
1 | ; |
1 2 3 | In Insert mode <C-A> - Increments the number under cursor <C-X> - Decrements the number under cursor |
如果我们想在vim中生成序列号,这将非常有用假设我们要插入第1-10行,数字从1到10[如第1行的"1",第2行的"2…"。
在第一行插入"0",并复制该行和过去9次以便所有行都显示"0"。
运行以下ex命令
1 | :g/^/exe"norm" . line(".") ."\<C-A>" |
我喜欢:指挥。
创建一个函数,使用它的shebang(假设设置了一个)来执行当前缓冲区,并使用crtl-x调用它。
1 2 3 4 5 6 7 8 9 10 11 12 | map <C-X> :call CallInterpreter()<CR> au BufEnter * \ if match (getline(1) , '^\#!') == 0 | \ execute("let b:interpreter = getline(1)[2:]") | \ endif fun! CallInterpreter() if exists("b:interpreter") exec("!".b:interpreter." %") endif endfun |
尝试使用
1 | :set equalprg=perltidy |
要将文本从VIM复制到剪贴板以供其他应用程序使用,请在视觉模式下选择要复制的文本,然后按"+Y"。这样,您可以轻松地将文本粘贴到其他应用程序。
如果您已经垂直拆分了窗口,并且希望从右窗口复制某些内容,那么这尤其有用。使用set mouse=r,对这种情况没有帮助,因为它也会选择左侧窗口中的所有内容。
请注意,必须使用xterm支持编译VIM。
使用鼠标右键在gvim中切换插入模式,设置如下在~/GVIMRC中:
1 2 3 4 5 6 7 | " "------------------------------------------------------------------ " toggle insert mode <--> 'normal mode with the <RightMouse>-key "------------------------------------------------------------------ nnoremap <RightMouse> <Insert> inoremap <RightMouse> <ESC> " |
下面这两个都不是很死板,但我发现它非常有用。
微不足道的捆绑,但我不能没有。它可以在插入模式下(使用ctrl键)启用hjkl样式的移动。在正常模式下:ctrl-k/j向上/向下滚动半个屏幕,ctrl-l/h转到下一个/上一个缓冲区。μ和_映射尤其适用于Azerty键盘,并转到下一个/上一个make error。
1 2 3 4 5 6 7 8 9 10 11 | imap <c-j> <Down> imap <c-k> <Up> imap <c-h> <Left> imap <c-l> <Right> nmap <c-j> <c-d> nmap <c-k> <c-u> nmap <c-h> <c-left> nmap <c-l> <c-right> nmap ù :cp<RETURN> nmap μ :cn<RETURN> |
我写的一个小函数用来突出显示函数、全局、宏、结构和typedef。(对于非常大的文件可能比较慢)。每种类型都有不同的突出显示(请参见":帮助组名称"了解当前颜色主题的设置)用法:使用ww保存文件(默认值为"ww")。你需要CTAG。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | nmap <Leader>ww :call SaveCtagsHighlight()<CR> "Based on: http://stackoverflow.com/questions/736701/class-function-names-highlighting-in-vim function SaveCtagsHighlight() write let extension = expand("%:e") if extension!="c" && extension!="cpp" && extension!="h" && extension!="hpp" return endif silent !ctags --fields=+KS * redraw! let list = taglist('.*') for item in list let kind = item.kind if kind == 'member' let kw = 'Identifier' elseif kind == 'function' let kw = 'Function' elseif kind == 'macro' let kw = 'Macro' elseif kind == 'struct' let kw = 'Structure' elseif kind == 'typedef' let kw = 'Typedef' else continue endif let name = item.name if name != 'operator=' && name != 'operator =' exec 'syntax keyword '.kw.' '.name endif endfor echo expand("%")." written, tags updated" endfunction |
我有编写大量代码和函数的习惯,我不喜欢为它们编写原型。所以我做了一些函数来生成C样式源文件中的原型列表。它有两种风格:一种删除形式参数的名称,另一种保留形式参数的名称。每次需要更新原型时,我都会刷新整个列表。它避免了不同步的原型和函数定义。也需要CTAG。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | "Usage: in normal mode, where you want the prototypes to be pasted: ":call GenerateProptotypes() function GeneratePrototypes() execute"silent !ctags --fields=+KS".expand("%") redraw! let list = taglist('.*') let line = line(".") for item in list if item.kind =="function" && item.name !="main" let name = item.name let retType = item.cmd let retType = substitute( retType, '^/\^\s*','','' ) let retType = substitute( retType, '\s*'.name.'.*', '', '' ) if has_key( item, 'signature' ) let sig = item.signature let sig = substitute( sig, '\s*\w\+\s*,', ',', 'g') let sig = substitute( sig, '\s*\w\+\(\s)\)', '\1', '' ) else let sig = '()' endif let proto = retType ."\t" . name . sig . ';' call append( line, proto ) let line = line + 1 endif endfor endfunction function GeneratePrototypesFullSignature() "execute"silent !ctags --fields=+KS".expand("%") let dir = expand("%:p:h"); execute"silent !ctags --fields=+KSi --extra=+q".dir."/*" redraw! let list = taglist('.*') let line = line(".") for item in list if item.kind =="function" && item.name !="main" let name = item.name let retType = item.cmd let retType = substitute( retType, '^/\^\s*','','' ) let retType = substitute( retType, '\s*'.name.'.*', '', '' ) if has_key( item, 'signature' ) let sig = item.signature else let sig = '(void)' endif let proto = retType ."\t" . name . sig . ';' call append( line, proto ) let line = line + 1 endif endfor endfunction |
映射宏
我经常发现,像定义宏一样,动态定义一些键映射非常有用。这里的转折点是,映射是递归的,执行到失败为止。
例子:
1 2 3 4 5 6 7 8 | enum ProcStats { ps_pid, ps_comm, ps_state, ps_ppid, ps_pgrp, :map X /ps_<CR>3xixy<Esc>X |
给予:
1 2 3 4 5 6 7 | enum ProcStats { xypid, xycomm, xystate, xyppid, xypgrp, |
只是一个愚蠢的例子:)。
我完全意识到了所有的缺点——只是碰巧我发现它在某些场合非常有用。此外,在工作中观看也很有趣;)。
全部替换
1 | :%s/oldtext/newtext/igc |
给a替换全部:)
这些年来我收集了这些。
1 2 3 4 5 6 7 8 9 10 11 12 | " Pasting in normal mode should append to the right of cursor nmap <C-V> a<C-V><ESC> " Saving imap <C-S> <C-o>:up<CR> nmap <C-S> :up<CR> " Insert mode control delete imap <C-Backspace> <C-W> imap <C-Delete> <C-O>dw nmap <Leader>o o<ESC>k nmap <Leader>O O<ESC>j " tired of my typo nmap :W :w |
我想在
您可以避免在.vimrc文件中编写一个很长的augroup列表,而不是为每种类型编写单独的文件。
但是,显然,.vim/ftplugin目录与.vim/after/ftplugin目录做的是相同的事情,但是我更愿意将.vim目录留给vim插件。
使移动以环绕模式在当前屏幕行上操作的映射。我在一篇VIM提示的评论中发现了这一点,它被证明非常方便。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function! ScreenMovement(movement) if &wrap return"g" . a:movement else return a:movement endif endfunction onoremap <silent> <expr> j ScreenMovement("j") onoremap <silent> <expr> k ScreenMovement("k") onoremap <silent> <expr> 0 ScreenMovement("0") onoremap <silent> <expr> ^ ScreenMovement("^") onoremap <silent> <expr> $ ScreenMovement("$") nnoremap <silent> <expr> j ScreenMovement("j") nnoremap <silent> <expr> k ScreenMovement("k") nnoremap <silent> <expr> 0 ScreenMovement("0") nnoremap <silent> <expr> ^ ScreenMovement("^") nnoremap <silent> <expr> $ ScreenMovement("$") |
我最喜欢在窗口之间来回切换的方法:
1 2 3 4 5 6 7 8 9 10 | function! SwitchPrevWin() let l:winnr_index = winnr() if l:winnr_index > 1 let l:winnr_index -= 1 else "set winnr_index to max window open let l:winnr_index = winnr('$') endif exe l:winnr_index ."wincmd w" endfunction |
1 2 | nmap <M-z> :call SwitchPrevWin() imap <M-z> <ESC>:call SwitchPrevWin() |
1 2 | nmap <C-z> :wincmd w imap <C-z> <ESC>:wincmd w |
我的是使用宏而不是搜索-将宏与可视模式结合有时效率更高。
我的一些必备品是:
cscope+ctags+vim,可以在网上找到。
一些用于快速启动新代码文件的缩写,例如:
1 2 3 4 5 6 7 8 | ab cpph #include <iostream><CR>#include <string><CR>#include <cstdlib><CR>#include <cassert><CR>#include <vector><CR>#include < stdexcept><CR>using namespace std;<CR>int main(int argc, char *argv[]) { ab perlh #!/usr/bin/perl<CR>use strict;<CR>use warnings;<CR> ab chdr #include <stdio.h><CR>#include <sys/types.h><CR>#include <unistd.h><CR>#include <stdlib.h><CR>#include <sys/stat.h><CR> #include <sys/wait.h><CR>#include <string.h><CR>int main(int argc, char *argv[]) { ab xhtmlhdr <?xml version="1.0" encoding="UTF-8"?><CR><!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.o rg/TR/xhtml1/DTD/xhtml1-strict.dtd"><CR><html xmlns="http://www.w3.org/1999/xhtml"><CR> <head><CR> <CR><link h ref="style.css" rel="STYLESHEET" type="text/css"><CR></head> |
例如,cpph将插入main.cc文件的基本框架
还有我对功能键的映射:
1 2 3 4 5 6 7 8 9 10 11 12 | map <F1> <Esc>:w<CR>:perl $e = `./error.pl`; my ($f,$l,@w) = split(":",$e); my $w=join(":",@w); $curwin->Cursor($l,0); VIM::Msg($w);<CR> map <F2> :wincmd w<CR> map <F3> :wincmd s<CR> map <F4> :wincmd v<CR> map <F5> :wincmd o<CR> map <F6> :sball<CR> map <F7> :wq<CR> map <F8> :wincmd q<CR> map <F9> :wincmd -<CR> map <F10> :wincmd +<CR> map <F11> :wincmd <<CR> map <F12> :wincmd ><CR> |
在这种情况下,我的f1被映射为将光标放在下一个需要为源代码迁移更正的错误上。
1 | map _ ebi"^[ea"^[ |
这张地图会使一个字符串
按此线程
为了给一组行加前缀,我使用两种不同的方法之一:
一种方法是块选择(由某物提到)。通常,您可以选择一个矩形区域,并使用ctrl-v,然后移动光标。突出显示一个矩形后,按SHIFT-I将在矩形的左侧插入字符,或按SHIFT-A将在矩形的右侧附加字符。因此,可以使用此技术生成一个矩形,其中包含要作为前缀的行的最左边的列,单击shift-i,键入前缀,然后单击escape。
另一种方法是使用替换(如BrianAgnew所提到的)。Brian的替换将影响整个文件(命令中的%表示"所有行")。要只影响几行,最简单的方法是在第一行/最后一行上单击shift-v(启用可视行模式),然后移动到最后一行/第一行。然后键入:
:s/^/您的前缀/
^是一个regex(在本例中是行首)。通过在可视行模式下键入,您将看到在s前面自动插入"<",">"。这意味着替换的范围将是可视选择。
额外提示:如果前缀包含斜杠,可以用反斜杠转义它们,也可以在命令中使用不同的标点符号作为分隔符。例如,为了添加C++行注释,我通常写:
s:^:/ /
对于添加后缀,替换方法通常更容易,除非所有行的长度完全相同。只需将$用于模式而不是^并且您的字符串将被追加而不是预挂起。
如果要同时添加前缀和后缀,可以执行以下操作:
:s/*/前缀和后缀/
*与整行匹配。替换中的&;会将匹配的文本(整行)放回原处,但现在将添加前缀和后缀。
顺便说一句:在注释代码时,您可能希望稍后取消对它的注释。您可以使用可视块(ctrl-v)选择斜线,然后单击d删除斜线,或者使用替换(可能是使用可视线选择,使用shift-v创建)删除前导斜线,如下所示:
S://: