821

人们谈论常见技巧的问题很多,特别是“ Vim+ctags 技巧和窍门”。

但是,我并不是指那些刚接触 Vim 的人会觉得很酷的常用快捷键。我说的是一位经验丰富的 Unix 用户(无论他们是开发人员还是管理员,等等),他们认为他们知道我们 99% 的人从未听说过或梦想过的事情。不仅让他们的工作更轻松,而且很酷和hackish的东西。毕竟,Vim存在于世界上最黑暗角落的操作系统中,因此它应该具有只有少数特权人员知道并想与我们分享的复杂性。

4

70 回答 70

797

可能不是 99% 的 Vim 用户不知道的东西,但它是我每天都在使用的东西,任何 Linux+Vim 高级用户都必须知道。

基本命令,但非常有用。

:w !sudo tee %

在编辑我没有写权限的文件之前,我经常忘记 sudo。当我来保存该文件并收到权限错误时,我只需发出该 vim 命令即可保存该文件,而无需将其保存到临时文件然后再次将其复制回来。

您显然必须在安装了 sudo 并拥有 sudo 权限的系统上。

于 2009-04-07T18:03:41.483 回答
628

我最近发现的一些我认为很酷的东西:

:earlier 15m

将文档恢复到 15 分钟前的状态。可以为要回滚的时间采用各种参数,并且取决于撤消级别。可以用相反的命令反转:later

于 2009-04-07T18:09:16.883 回答
419

:! [command]在 Vim 中执行外部命令。

但是在冒号之后添加一个点 :.! [command],它会将命令的输出转储到您的当前窗口中。那是: . !

例如:

:.! ls

我经常使用它来将当前日期添加到我正在输入的文档中:

:.! date
于 2009-04-26T04:03:04.300 回答
316

并不完全晦涩难懂,但有几个“删除”命令非常有用,例如..

  • diw删除当前单词
  • di(在当前括号内删除
  • di"删除引号之间的文本

其他可以在:help text-objects

于 2009-04-07T20:33:30.437 回答
240

de按 删除直到单词结尾的所有内容。随心所欲。

ci(xyz[Esc] -- 这是一个奇怪的。这里,'i' 并不意味着插入模式。相反,它意味着括号内。所以这个序列剪切你所在的括号内的文本并将其替换为“xyz”。它也适用于方括号和数字括号内——只需执行 ci[ 或ci a{i也想删除括号,而不仅仅是其中的文本。

ci" - 剪切当前引号中的文本

ciw - 剪切当前单词。这与前一个一样工作,只是(被替换为w.

C - 剪切其余的行并切换到插入模式。

ZZ -- 保存并关闭当前文件(比 Ctrl-F4 更快地关闭当前选项卡!)

ddp - 将当前行向下移动一行

xp -- 将当前字符向右移动一位

U - 大写,所以大写viwU单词

~ - 切换大小写,因此viw~将反转整个单词的大小写

Ctrl+u / Ctrl+d向上或向下滚动页面半个屏幕。这似乎比通常的全屏分页更有用,因为它可以更容易地查看两个屏幕的关系。对于那些仍然想一次滚动整个屏幕的人来说,Ctrl+f 用于前进,Ctrl+b 用于后退。Ctrl+Y 和 Ctrl+E 一次向下或向上滚动一行。

疯狂但非常有用的命令是 zz——它滚动屏幕使这条线出现在中间。这非常适合将您正在处理的代码放在您的注意力中心。兄弟命令 - zt 和 zb - 使这条线在屏幕上的顶部或底部,这不太有用。

%查找并跳转到匹配的括号。

de -- 从光标处删除到词尾(也可以dE删除到下一个空格)

bde -- 删除当前单词,从左到右分隔符

df[space] -- 删除直到并包括下一个空格

DT。-- 删除直到下一个点

dd -- 删除整行

ye (or yE) -- 将文本从这里拉到词尾

ce - 切开词尾

再见——复制当前单词(让我想知道“hi”是做什么的!)

yy -- 复制当前行

cc -- 剪切当前行,你也可以这样做S。还有一个较低的上限s,可以切断当前字符并切换到插入模式。

viwy 或 viwc。拉动或更改当前单词。w多次点击以继续选择每个后续单词,用于b向后移动

vi{ - 选择括号中的所有文本。va{ - 选择所有文本,包括 {}s

vi(p - 突出显示 () 中的所有内容并替换为粘贴的文本

b 和 e 逐字移动光标,类似于 Ctrl+Arrows 通常的做法。单词的定义略有不同,因为几个连续的分隔符被视为一个单词。如果你从一个单词的中间开始,按 b 总是会让你到当前单词的开头,并且每个连续的 b 都会跳到下一个单词的开头。类似地,并且易于记忆,e将光标移到当前单词的末尾以及每个后续单词的末尾。

类似于b/ e,大写BE仅使用空格作为分隔符逐字移动光标。

大写 D(深呼吸)删除光标右侧的其余行,与普通编辑器中的 Shift+End/Del 相同(注意 2 次按键 -- Shift+D -- 而不是 3)

于 2009-04-29T13:21:55.380 回答
211

我在大多数 Vim 教程中很少找到,但它非常有用(至少对我而言)是

g; and g,

在更改列表中移动(向前、向后)。

让我展示一下我是如何使用它的。有时我需要复制和粘贴一段代码或字符串,比如 CSS 文件中的十六进制颜色代码,所以我搜索、跳转(不在乎匹配在哪里)、复制它然后跳回 (g;) 到哪里我正在编辑代码以最终粘贴它。无需创建标记。更简单。

只是我的2美分。

于 2009-06-04T11:54:15.460 回答
187
:%!xxd

将 vim 变成一个十六进制编辑器。

:%!xxd -r

恢复。

警告:如果您不使用二进制 (-b) 进行编辑,您可能会损坏文件。- 乔什·李在评论中。

于 2009-04-07T21:19:32.400 回答
136
gv

重新选择最后的视觉选择。

于 2011-01-12T20:03:40.860 回答
123

有时 .vimrc 中的设置会被插件或自动命令覆盖。要调试这个有用的技巧是结合使用:verbose 命令和:set。例如,要找出 cindent 设置/取消设置的位置:

:verbose set cindent?

这将输出如下内容:

cindent
    Last set from /usr/share/vim/vim71/indent/c.vim

这也适用于地图和高光。(感谢 joeytwiddle 指出这一点。)例如:

: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
于 2009-05-04T20:04:33.233 回答
103

:%TOhtml

创建当前文件的 html 呈现。

于 2011-03-27T10:05:01.137 回答
102

不确定这是否算作黑暗角落,但我才刚刚学会......

:g/match/y A

将所有包含“匹配”的行拉入(复制)到"a/@a寄存器中。(大写 asA使 vim追加yankings 而不是替换以前的寄存器内容。)我最近在制作 Internet Explorer 样式表时经常使用它。

于 2009-04-08T15:36:36.977 回答
96

想查看您的 :command 历史记录吗?

q:

然后浏览,编辑,最后执行命令。

曾经对两个文件进行类似的更改并在它们之间来回切换吗?(比如说,源文件和头文件?)

:set hidden
:map <TAB> :e#<CR>

然后在这些文件之间来回切换。

于 2009-04-20T20:36:25.020 回答
88

Vim 会打开一个 URL,例如

vim http://stackoverflow.com/

当您需要提取页面的源代码以供参考时,这很好。

于 2010-09-17T16:50:46.907 回答
71

宏可以调用其他宏,也可以调用自身。

例如:

qq0dwj@qq@q

...将删除每一行的第一个单词,直到文件末尾。

这是一个非常简单的例子,但它展示了 vim 的一个非常强大的特性

于 2009-09-11T12:39:23.203 回答
57

^O 和 ^I

转到较旧/较新的位置。当您在文件中移动(通过搜索、移动命令等)时,vim 会记住这些“跳转”,因此您可以向后重复这些跳转(^O - O 表示旧)和向前(^I - 就在键盘上的 I 旁边)。我发现它在编写代码和执行大量搜索时非常有用。

转到最后停止插入模式的位置。我发现自己经常编辑然后搜索一些东西。要返回编辑位置,请按 gi。

女朋友

将光标放在文件名上(例如包含头文件),按 gf 并打开文件

gF

类似于 gf 但识别格式“[文件名]:[行号]”。按 gF 将打开 [文件名] 并将光标设置为 [行号]。

^P 和 ^N

编辑时自动完成文本(^P - 上一个匹配和 ^N 下一个匹配)

^X^L

编辑完成到同一行(对编程很有用)。您编写代码,然后您回想起文件中某处有相同的代码。只需按 ^X^L 即可完成整行

^X^F

完整的文件名。你写“/etc/pass”嗯。你忘记了文件名。只需按^X^F,文件名就完成了

^Z 或 :sh

临时移动到外壳。如果您需要快速抨击:

  • 按 ^Z(将 vi 置于后台)返回原始 shell,按 fg 返回 vim
  • 按 :sh 转到子 shell 并按 ^D/exit 返回 vi 返回
于 2009-07-13T19:18:26.800 回答
57

假设您已编译 Perl 和/或 Ruby 支持,:rubydo并将:perldo在范围内的每一行(默认为整个缓冲区)上运行 Ruby 或 Perl 单行,并$_绑定到当前行的文本(减去换行符)。操作$_将更改该行的文本。

您可以使用它来完成某些在脚本语言中很容易完成但使用 Vim 内置函数不那么明显的事情。例如要反转一行中单词的顺序:

:perldo $_ = join ' ', reverse split

在每行末尾插入一个 8 个字符 (AZ) 的随机字符串:

:rubydo $_ += ' ' + (1..8).collect{('A'..'Z').to_a[rand 26]}.join

您一次只能处理一行,并且不能添加换行符。

于 2009-04-08T01:15:58.930 回答
51
" insert range ip's
"
"          ( O O )
" =======oOO=(_)==OOo======

:for i in range(1,255) | .put='10.0.0.'.i | endfor
于 2009-08-17T13:57:55.707 回答
51

键入==将根据上面的行更正当前行的缩进。

实际上,您可以在任何移动命令后执行一个 = 符号。= {运动}

例如,您可以使用在匹配的大括号之间移动的 % 移动。将光标定位在以下代码中的 { 上:

if (thisA == that) {
//not indented
if (some == other) {
x = y;
}
}

然后按=%立即得到这个:

if (thisA == that) {
    //not indented
    if (some == other) {
        x = y;
    }
}

或者,您可以在代码块中执行=a{,而不是将自己定位在 { 字符上。

于 2010-04-16T00:44:56.780 回答
47

这是用不同的编码重新打开当前文件的好技巧:

:e ++enc=cp1250 %:p

当您必须使用旧编码时很有用。支持的编码列在encoding-values(参见 参考资料help encoding-values)下的表中。类似的事情也适用于++ff,因此如果您第一次出错,您可以重新打开以 Windows/Unix 行结尾的文件(请参阅 参考资料help ff)。

于 2009-04-07T18:40:23.813 回答
41
imap jj <esc>
于 2009-04-19T18:33:15.337 回答
37

让我们看看一些漂亮的小 IDE 编辑器做列转置。

:%s/\(.*\)^I\(.*\)/\2^I\1/

解释

\(并且\)是如何记住正则表达式中的东西。\1等等\2是如何检索记住的东西。

>>> \(.*\)^I\(.*\)

记住所有内容,然后是^I(选项卡),然后是所有内容。

>>> \2^I\1

用“你记得的第二件事”替换上面的东西,然后是“你记得的第一件事”——本质上是做一个转置。

于 2009-04-07T18:03:21.373 回答
31

不完全是一个秘密,但我喜欢将以下映射放入我的 .vimrc 文件中,因此我可以随时点击“-”(减号)打开文件资源管理器以显示与我刚刚编辑的文件相邻的文件。在文件资源管理器中,我可以点击另一个“-”来向上移动一个目录,提供对复杂目录结构的无缝浏览(就像现在 MVC 框架使用的那些):

map - :Explore<cr>

这些可能对某人也有用。我喜欢同时滚动屏幕和前进光标:

map <c-j> j<c-e>
map <c-k> k<c-y>

标签导航 - 我喜欢标签,我需要在它们之间轻松移动:

map <c-l> :tabnext<enter>
map <c-h> :tabprevious<enter>

仅在 Mac OS X 上:类似 Safari 的标签导航:

map <S-D-Right> :tabnext<cr>
map <S-D-Left> :tabprevious<cr>
于 2009-04-11T07:14:21.593 回答
29

通常,我喜欢在编辑时更改当前目录 - 所以我必须少指定路径。

cd %:h
于 2009-04-07T20:11:12.033 回答
27

我喜欢使用“sudo bash”,我的系统管理员讨厌这个。他锁定了“sudo”,因此它只能与少数命令(ls、chmod、chown、vi 等)一起使用,但无论如何我都能使用 vim 获得 root shell:

bash$ sudo vi +'silent !bash' +q
Password: ******
root#
于 2009-06-12T05:54:59.633 回答
26

当我处理一个项目时,我经常使用很多窗口,有时我需要调整它们的大小。这是我使用的:

map + <C-W>+
map - <C-W>-

这些映射允许增加和减少当前窗口的大小。这很简单,但速度很快。

于 2009-04-07T21:11:26.320 回答
24

不是一个不起眼的功能,但非常有用且节省时间。

如果要保存打开的缓冲区、选项卡、标记和其他设置的会话,可以发出以下命令:

mksession session.vim

您可以使用以下命令打开会话:

vim -S session.vim
于 2011-03-04T02:20:57.050 回答
24
:r! <command>

将外部命令的输出粘贴到缓冲区中。

做一些数学运算,直接在文本中得到结果:

:r! echo $((3 + 5 + 8))

在编写 Makefile 时获取要编译的文件列表:

:r! ls *.c

不要查找您在维基百科上阅读的事实,将其直接粘贴到您正在编写的文档中:

:r! lynx -dump http://en.wikipedia.org/wiki/Whatever
于 2009-05-06T07:38:25.990 回答
21

将 F5 映射到快速 ROT13 您的缓冲区:

map <F5> ggg?G``

您可以将其用作老板键:)。

于 2009-07-08T19:19:08.073 回答
20

我几乎使用 vim 进行任何文本编辑,所以我经常使用复制和粘贴。问题是 vim 默认情况下经常会通过粘贴扭曲导入的文本。阻止这种情况的方法是使用

:set paste

在粘贴您的数据之前。这将防止它搞砸。

请注意,您必须发出:set nopaste才能恢复自动缩进。粘贴预格式化文本的替代方法是剪贴板寄存器(*+),和:r!cat(您必须用 ^D 结束粘贴的片段)。

有时打开高对比度配色方案也很有帮助。这可以通过

:color blue

我注意到它不适用于我使用的所有版本的 vim,但它适用于大多数版本。

于 2009-04-29T18:56:49.773 回答
19

我今天刚刚通过NSFAQ找到了这个:

注释代码块。

按 CTRL-V 进入 Blockwise Visual 模式。

标记您要评论的块。

点击 I(大写 I)并在行首输入您的注释字符串。(// 对于 C++)

点击 ESC 并且所有选择的行都将在行的前面加上 //。

于 2009-05-11T21:59:04.003 回答
12

Ctrl-n 在插入模式下将根据打开缓冲区中的所有单词自动完成您输入的任何单词。如果有多个匹配项,它将为您提供一个可能的单词列表,您可以使用 ctrl-n 和 ctrl-p 循环遍历这些单词。

于 2009-06-05T19:10:57.123 回答
11

这里有一些不明显的东西。如果您的 $HOME 中有很多自定义插件/扩展,并且有时需要从 su / sudo / ... 工作,那么这可能很有用。

在你的 ~/.bashrc 中:

export VIMINIT=":so $HOME/.vimrc"

在你的 ~/.vimrc 中:

if $HOME=='/root'
        if $USER=='root'
                if isdirectory('/home/your_typical_username')
                        let rtuser = 'your_typical_username'
                elseif isdirectory('/home/your_other_username')
                        let rtuser = 'your_other_username'
                endif
        else
                let rtuser = $USER
        endif
        let &runtimepath = substitute(&runtimepath, $HOME, '/home/'.rtuser, 'g')
endif

它将允许您的本地插件加载 - 无论您使用什么方式来更改用户。

您可能还想将 *.swp 文件从当前路径中取出并放入 ~/vimtmp(进入 .vimrc):

if ! isdirectory(expand('~/vimtmp'))
   call mkdir(expand('~/vimtmp'))
endif
if isdirectory(expand('~/vimtmp'))
   set directory=~/vimtmp
else
   set directory=.,/var/tmp,/tmp
endif

此外,我使用一些映射来简化编辑 - 使 ctrl+s 像转义一样工作,并且 ctrl+h/l 切换选项卡:

inoremap <C-s> <ESC>
vnoremap <C-s> <ESC>
noremap <C-l> gt
noremap <C-h> gT

于 2009-04-07T22:29:44.697 回答
11

想要一个 IDE?

:make将在当前目录中运行 makefile,解析编译器输出,然后您可以使用:cn:cp逐步检查编译器错误,打开每个文件并查找有问题的行号。

:syntax on打开 vim 的语法高亮。

于 2009-06-06T14:27:05.820 回答
10
gg=G

更正整个文件的缩进。我错过了我<C-a><C-i>在 Eclipse 中的信任,但发现 vim 可以很好地处理它。

于 2010-02-22T04:28:29.740 回答
10

sudo write 的变体:

进入 .vimrc

cmap w!! w !sudo tee % >/dev/null

重新加载 vim 后,您可以将“sudo save”作为

:w!!
于 2011-05-11T19:54:15.727 回答
10

能够在基于客户端/服务器的模式下运行 Vim。

例如,假设您正在处理一个项目,其中有很多缓冲区、选项卡和其他信息保存在名为 session.vim 的会话文件中。

您可以通过发出以下命令打开会话并创建服务器:

vim --servername SAMPLESERVER -S session.vim

请注意,如果要创建服务器,则可以打开常规文本文件,并且不必一定是会话。

现在,假设您在另一个终端中并且需要打开另一个文件。如果您通过发出以下命令定期打开它:

vim new_file.txt

您的文件将在单独的 Vim 缓冲区中打开,这很难与会话中的文件进行交互。为了在服务器上的新选项卡中打开 new_file.txt,请使用以下命令:

vim --servername SAMPLESERVER --remote-tab-silent new_file.txt

如果没有服务器运行,该文件将像普通文件一样打开。

由于每次要运行它们时都提供这些标志非常繁琐,因此您可以创建一个单独的别名来创建客户端和服务器。

我在我的 bashrc 文件中放置了以下内容:

alias vims='vim --servername SAMPLESERVER'
alias vimc='vim --servername SAMPLESERVER --remote-tab-silent'

您可以在以下位置找到更多信息:http: //vimdoc.sourceforge.net/htmldoc/remote.html

于 2011-03-24T22:44:40.250 回答
9

我经常想突出显示一个特定的单词/函数名称,但还不想搜索它的下一个实例:

map m* *#
于 2009-04-19T18:18:26.903 回答
8

HOWTO:在 Bash 中使用 Vim 时自动完成 Ctags。对于其他使用 Vim 和 Ctags 的人,我为 Bash 编写了一个小型自动完成功能。将以下内容添加到您的 ~/.bash_completion 文件中(如果不存在则创建它):

感谢 stylepants 的许多修复和改进。

_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 会话(或创建一个新会话)后,您可以键入:

代码:

~$ vim -t MyC<tab key>

它会像处理文件和目录一样自动完成标签:

代码:

MyClass MyClassFactory
~$ vim -t MyC

当我开始快速修复错误时,我发现它非常有用。

于 2009-04-07T23:11:04.193 回答
7

当您想在项目的两个不同副本之间区分文件而不磨损小指(从 project1 的根目录)时, % 也很好:

:vert diffs /project2/root/%
于 2009-04-09T12:37:25.807 回答
7

我什么都用 Vim。当我编辑电子邮件时,我使用:

gqap(或gwap

广泛地在逐段的基础上轻松正确地重新格式化,即使使用引号前导字符也是如此。为了实现这个功能,我还添加了:

-c 'set fo=tcrq' -c 'set tw=76'

到命令以在外部调用编辑器。一个值得注意的补充是在 fo (formatoptions) 参数中添加“ a ”。这将在您键入和浏览内容时自动重新格式化段落,但可能会干扰或导致消息中包含的错误或奇怪的格式出现问题。

于 2009-05-08T01:36:24.907 回答
7

:setlocal 自动读取

自动重新加载当前缓冲区..在查看日志文件时特别有用,它几乎可以从 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 窗口中显示编译错误/警告,并且可以轻松导航到相应的行号。

于 2009-07-08T19:07:42.607 回答
6

把它放在你的 .vimrc 中有一个命令来漂亮打印 xml:

function FormatXml()
    %s:\(\S\)\(<[^/]\)\|\(>\)\(</\):\1\3\r\2\4:g
    set filetype=xml
    normal gg=G
endfunction

command FormatXml :call FormatXml()
于 2009-04-19T18:35:13.430 回答
6

从其十六进制值输入一个字符(插入模式):

<C-Q>x[type the hexadecimal byte]
于 2009-04-09T12:53:15.160 回答
6

由于延迟和缺乏颜色(我喜欢配色方案:)我不喜欢在PuTTY中的远程机器上编程。所以我开发了这个技巧来解决这个问题。我在 Windows 上使用它。

你会需要

  • 1x gVim
  • 远程和本地机器上的 1x rsync
  • 1x SSH 私钥对远程机器进行身份验证,因此您无需输入密码
  • 1x选美
  • 1x 腻子

设置远程机器

配置 rsync 以使您的工作目录可访问。我使用 SSH 隧道并且只允许来自隧道的连接:

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。启动 Pageant 并为远程机器加载你的私钥。如果您使用 SSH 调谐,请启动 PuTTY 来创建隧道。在您的工作目录中创建一个批处理文件 push.bat,它将使用 rsync 将更改的文件上传到远程机器:

rsync --blocking-io *.cc *.h SConstruct rsync://localhost:40001/bledge_ce

SConstruct 是 scons 的构建文件。修改文件列表以满足您的需要。如果您不使用 SSH 调谐,请将 localhost 替换为远程机器的名称。

配置 Vim 现在很容易。我们将使用快速修复功能(:make 和错误列表),但编译将在远程机器上运行。所以我们需要设置makeprg:

set makeprg=push\ &&\ plink\ -batch\ xplasil@anna.fi.muni.cz\ \"cd\ /home/xplasil/divine/bledge_ce\ &&\ scons\ -j\ 2\"

这将首先启动 push.bat 任务以上传文件,然后使用 SSH 在远程机器上执行命令(来自 PuTTY 套件的Plink )。该命令首先将目录更改为工作目录,然后开始构建(我使用 scons)。

构建的结果会方便地显示在您本地的 gVim 错误列表中。

于 2009-10-02T07:38:30.830 回答
6
==================================================== ========
在正常模式下
==================================================== ========
gf ................ 在同一窗口中打开光标下的文件 --> 查看 :h 路径
Ctrl-w f .......... 在新窗口中打开光标下的文件
Ctrl-w q .......... 关闭当前窗口
Ctrl-w 6 .......... 打开备用文件 --> 见 :h #
gi ................ 在最后一个插入位置初始化插入模式
'0 ...... 将光标放在文件最后一次编辑时的位置
于 2009-08-20T12:21:53.330 回答
6

我确信有人已经发布了这个,但是这里有。

采用任何你喜欢的构建系统;make, mvn, ant, 随便什么。在项目目录的根目录中,创建一个包含您一直使用的命令的文件,如下所示:

mvn install
mvn clean install
... 等等

要进行构建,请将光标放在该行上并键入 !!sh。即过滤该行;将其写入外壳并替换为结果。

构建日志替换了行,准备滚动、搜索等等。

查看完日志后,键入 u 撤消,然后您将返回命令文件。

于 2009-05-08T01:54:44.897 回答
5

set colorcolumn=+1或者set cc=+1对于 vim 7.3

于 2011-07-12T12:21:24.057 回答
5

几个有用的:

:set nu # displays lines
:44     # go to line 44
'.      # go to last modification line

我最喜欢的:Ctrl+n单词完成!

于 2010-01-19T00:26:07.960 回答
4

在复制并粘贴到 stackoverflow 之前:

:retab 1
:% s/^I/ /g
:% s/^/    /

现在复制并粘贴代码。

根据评论中的要求:

retab 1. 这会将标签大小设置为 1。但它也遍历代码并添加额外的制表符和空格,以便格式不会移动任何实际文本(即文本在 ratab 之后看起来相同)。

% s/^I/ /g:注意 ^I 是点击制表符的结果。这将搜索所有选项卡并将它们替换为单个空格。由于我们只是做了一个 retab,这不应该导致格式改变,但是由于将标签放入网站会被击中并错过它,最好删除它们。

%s/^/ /:用四个空格替换行首。由于您实际上不能用任何内容替换行首,因此它会在行首插入四个空格(SO 格式化需要这样做以使代码脱颖而出)。

于 2009-09-15T20:18:16.863 回答
4

:sp %:h- 目录列表/文件选择器使用当前文件的目录

(属于rampion的cd提示下的评论,但我还没有评论权)

于 2009-08-06T09:33:01.673 回答
4

在处理构建过程缓慢的项目时,我总是在后台构建并将输出通过管道传输到名为 errors.err 的文件(类似于make debug 2>&1 | tee errors.err)。这使我可以在构建过程中继续编辑或查看源代码。准备就绪后(在 GTK 上使用 pynotify 通知我它已完成),我可以使用quickfix在 vi​​m 中查看结果。首先发出 :cf[ile] 读取错误文件并跳转到第一个错误。我个人喜欢使用 cwindow 在单独的窗口中获取构建结果。

于 2009-12-28T09:21:01.443 回答
3

地图宏

我经常发现动态定义一些键映射很有用,就像定义一个宏一样。这里的转折是,映射是递归的,并且一直执行到失败为止。

例子:

enum ProcStats
{
        ps_pid,
        ps_comm,
        ps_state,
        ps_ppid,
        ps_pgrp,
:map X /ps_<CR>3xixy<Esc>X

给出:

enum ProcStats
{
        xypid,
        xycomm,
        xystate,
        xyppid,
        xypgrp,

只是一个愚蠢的例子:)。

我完全意识到所有的缺点——碰巧我发现它在某些场合相当有用。在工作中观看它也会很有趣;)。

于 2011-01-12T15:22:06.153 回答
3

在插入模式下,ctrl+ xctrl+p将完成(如果您喜欢的话,可以使用可能的完成菜单)您正在输入的当前长标识符。

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
             ∶
于 2011-03-17T20:41:47.670 回答
3

我喜欢 :ls 命令。

于 2009-04-24T13:36:44.687 回答
3

为了让 vim 更像一个 IDE 编辑器:

  • 设置 nu - 用于左边距中的行号。
  • set cul - 突出显示包含光标的行。
于 2009-05-11T04:39:04.767 回答
3

以下都不是真正的顽固,但我发现它非常有用。

琐碎的绑定,但我不能没有。它在插入模式下启用 hjkl 样式的移动(使用 ctrl 键)。在正常模式下: ctrl-k/j 向上/向下滚动半个屏幕, ctrl-l/h 进入下一个/上一个缓冲区。µ 和ù 映射特别适用于AZERTY 键盘并转到下一个/上一个错误。

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。(在非常大的文件上可能会很慢)。每种类型都有不同的突出显示(参见 ":help group-name" 以了解当前颜色主题的设置) 用法:用 ww 保存文件(默认为 "\ww")。为此,您需要 ctags。

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 风格的源文件中生成一个原型列表。它有两种风格:一种删除形式参数的名称,另一种保留它。每次需要更新原型时,我都会刷新整个列表。它避免了原型和函数定义不同步。还需要ctags。

"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
于 2009-09-13T18:29:22.463 回答
3

重用

与其他命令混合的动作,更多在这里

tx
fx
Fx

在 Vim 中使用您最喜欢的工具。

:r !python anything you want or awk or Y something

在视觉模式下重复,结合上述提示时功能强大。

;
于 2011-01-12T14:32:03.393 回答
3
In Insert mode 
<C-A>   - Increments the number under cursor 
<C-X>   - Decrements the number under cursor

如果我们想在 vim 中生成连续数字,这将非常有用假设我们
是否要插入数字从 1 到 10 的第 1-10 行 [比如第一行的“1”,第二行的“2”..]
插入第一行的“0”并复制该行并过去9次,以便所有行都显示“0”。

运行以下 Ex 命令

:g/^/exe "norm " . line(".") . "\<C-A>"
于 2011-06-29T16:05:50.133 回答
2

这些年来我收集了这些。

" 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
于 2009-11-24T20:21:01.600 回答
2

全部替换

  :%s/oldtext/newtext/igc

给一个替换所有:)

于 2009-04-27T13:06:44.920 回答
2

使用鼠标右键在 gVim 中切换插入模式,并在 ~/.gvimrc 中进行以下设置:

"
"------------------------------------------------------------------
" toggle insert mode <--> 'normal mode with the <RightMouse>-key
"------------------------------------------------------------------
nnoremap  <RightMouse> <Insert>
inoremap  <RightMouse> <ESC>
"
于 2009-04-22T16:41:05.863 回答
2

尝试使用普通模式命令perltidy进行格式化=

:set equalprg=perltidy
于 2009-08-20T18:55:48.970 回答
2

创建一个函数来使用它的 shebang 执行当前缓冲区(假设设置了一个)并使用 crtl-x 调用它。

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
于 2010-05-10T15:01:43.753 回答
2

要将文本从 Vim 复制到剪贴板以供其他应用程序使用,请在可视模式下选择要复制的文本,然后按“+y”。这样,您可以轻松地将文本粘贴到其他应用程序。

如果您已垂直拆分窗口并且想要从右侧窗口复制某些内容,这将特别有用。使用 set mouse=r 对这种情况没有帮助,因为它也会选择左侧窗口中的所有内容。

请注意,您的 vim 必须使用 xterm 支持进行编译。

于 2011-04-05T18:43:08.820 回答
1

映射以使移动以环绕模式在当前屏幕行上运行。前段时间我在 Vim 技巧的评论中发现了这一点,事实证明它非常方便。

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("$")
于 2009-07-02T16:22:19.777 回答
1

我的一些必备品是:

cscope + ctags + vim,可以在网上找到。

一些用于快速启动新代码文件的缩写,例如:

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>  <title></title><CR><link h
ref="style.css" rel="STYLESHEET" type="text/css"><CR></head>

例如 cpph 将插入 main.cc 文件的基本骨架

还有我的功能键映射:

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 被映射为将光标放在下一个需要纠正以进行源代码迁移的错误上。

map _ ebi"^[ea"^[

这张地图将使 _ 引用一个字符串

于 2009-05-06T16:08:49.820 回答
1

根据这个线程

为了给一组行添加前缀,我使用两种不同的方法之一:

一种方法是块选择(由某物提到)。通常,您可以使用 ctrl-V 后跟光标移动来选择一个矩形区域。突出显示一个矩形后,按 shift-I 将在矩形的左侧插入字符,或者按 shift-A 将它们附加到矩形的右侧。因此,您可以使用此技术制作一个矩形,其中包含要添加前缀的行的最左侧列,按 shift-I,键入前缀,然后按转义键。

另一种方法是使用替换(如 Brian Agnew 所述)。Brian 的替换将影响整个文件(命令中的 % 表示“所有行”)。要仅影响几行,最简单的方法是在第一行/最后一行时按 shift-V(启用可视行模式),然后移动到最后/第一行。然后输入:

:s/^/你的前缀/

^ 是一个正则表达式(在本例中为行首)。通过在可视行模式下键入此内容,您将看到 '<,'> 自动插入到 s 之前。这意味着替换的范围将是视觉选择。

额外提示:如果您的前缀包含斜杠,您可以使用反斜杠对其进行转义,或者您可以使用不同的标点符号作为命令中的分隔符。例如,要添加 C++ 行注释,我通常会这样写:

:s:^:// :

对于添加后缀,替换方法通常更容易,除非所有行的长度完全相同。只需将 $ 用于模式而不是 ^ ,您的字符串将被附加而不是预先附加。

如果要同时添加前缀和后缀,可以执行以下操作:

:s/.*/前缀和后缀/

.* 匹配整行。替换中的 & 将匹配的文本(整行)放回原处,但现在它将添加您的前缀和后缀。

顺便说一句:注释掉代码时,您可能希望稍后取消注释。您可以使用视觉块(ctrl-V)选择斜杠,然后按 d 删除它们,或者您可以使用替换(可能使用视线选择,使用 shift-V)来删除前导斜杠,像这样:

:s://::

于 2009-08-11T13:29:45.547 回答
1

我正在使用宏而不是搜索 - 将宏与可视模式结合起来有时更有效。

于 2009-08-13T10:50:24.440 回答
1

我想在after-directory. 它对ftplugin.

您可以避免在 .vimrc 文件中编写一长串 augroup ,而不是为每种类型编写单独的文件。

但是,很明显,.vim/ftplugin 目录与 .vim/after/ftplugin 做同样的事情,但我更愿意将 .vim 目录留给 vim 插件。

于 2011-07-12T10:49:15.160 回答
1

我最喜欢在窗口之间来回切换的食谱:

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

nmap <M-z> :call SwitchPrevWin()
imap <M-z> <ESC>:call SwitchPrevWin()

nmap <C-z> :wincmd w
imap <C-z> <ESC>:wincmd w
于 2010-09-04T04:13:11.883 回答