跳转到内容

学习 vi 编辑器/Vim/增强 Vim

来自 Wikibooks,开放世界中的开放书籍

学习 vi 编辑器: 熟悉基本任务使工作更轻松高级任务细节vi 克隆 (Vim基本导航模式技巧对程序员有用的东西增强 VimVim 在 Windows 上VimL 脚本语言, Vile, BB vi)vi 参考

增强 Vim

[编辑 | 编辑源代码]

.vimrc 文件

[编辑 | 编辑源代码]

您可以在您的主目录中创建一个名为 .vimrc 的配置文件,并保存任何特定设置。vimrc 的存在会产生一个副作用,即使 Vim 启用 Vim 对 vi 的所有不兼容更改,使其更易于使用。文件的名字取决于使用的操作系统和用户界面

.vimrc UNIX 和 VMS 上的文本用户界面
_vimrc MS-Windows 和 VMS 上的文本用户界面
.gvimrc UNIX 和 VMS 上的图形用户界面
_gvimrc MS-Windows 和 VMS 上的图形用户界面

带有下划线的替代方案是为了与旧版文件系统兼容。如果您在多个操作系统上使用 Vim 并使用现代 MS-Windows 文件系统,则不必维护两个配置文件。将 _vimrc 设置为以下内容完全没问题:

source ~/.vimrc

并在以下内容中执行所有配置 .vimrc.

这是一个示例 .vimrc 文件

"Everything after a double quote is a comment.

"Wrap text after 72 characters
set textwidth=72

"Set tabs to 4 spaces
set tabstop=4
set shiftwidth=4
set stselect=4
set expandtab

"Tell Vim I use a dark background. Syntax highlighting (color coded text) will adjust to more appropriate colors.
set background=dark

"Misc overwrites of default color highlighting.
hi Comment ctermfg=DarkGreen
hi String ctermfg=DarkMagenta
hi pythonPreCondit ctermfg=Green

"Make sure that bottom status bar is running.
set ruler
set laststatus=2

"Make a mapping for "Q" which will reformat the current paragraph, comment,
"or code block according to the formatoptions setting:
map Q gqap

语法高亮

[编辑 | 编辑源代码]

语法高亮允许您使用颜色、粗体和其他字体修改来高亮程序代码和其他文件,以提高可读性。

您可能想要编写简单的语法高亮语句,以便在您的文件中轻松检测模式。也就是说,如果您认为需要为 HTML 进行语法高亮,请不用担心:大多数用户不需要为常见的 文件类型定义语法高亮文件 - 大多数常见开发人员感兴趣的文件类型已经由 Vim 提供了默认的语法高亮定义。即使它没有随 vim 附带,您通常也可以在 vim.org 上找到有人分享他们的作品。但是,如果您需要编写一些简单的东西,那么本节适合您。(如果您需要一个语法高亮定义,它能够正确显示 Perl 代码,即使在 HTML 的 “pre” 标签内,在 Perl print 语句内,在 shell 脚本中的 shell heredoc 内,您可能不太走运,本节可能无法满足您的需求 - 但是您不妨搜索 vim.org,以防有人已经为您完成了)。

语法高亮是 Vim 最强大的功能之一。但是,如果您的知识储备不够(或者您没有耐心,或者您正在处理复杂的程序语言语法),它也可能是最难设置的功能之一。所以让我们看一下一些简单的突出显示定义

第一课:高亮制表符

[编辑 | 编辑源代码]
... 或者如何高亮特殊字符

假设您需要知道您的文件中哪些是制表符,哪些是空格。使用以下高亮,您可以使制表符可见

:syntax match Special "\t"

语法匹配会匹配正则表达式,并将给定的颜色应用于它。在本例中,它是颜色 “Special”。您必须确保颜色 “Special” 具有非标准背景 - 否则您将看不到差异

:highlight Special guifg=SlateBlue guibg=GhostWhite

您也可以在您的 .vimrc 中创建一个映射 - 这样您就可以始终激活制表符高亮

:nnoremap <F12><Tab>      :syntax match Special "\t"<CR>
:inoremap <F12><Tab> <C-O>:syntax match Special "\t"<CR>

另一种方法是使用 listchars。这些可能是制表符、尾随空格和行尾。请注意使用 “>-” 而不是默认的 “^I”。这可以防止显示/隐藏 listchars 时布局发生变化

:set lcs=tab:>-,trail:%,eol:$ <CR>
:map <F12> :set list!<CR>

第二课:高亮空格错误

[编辑 | 编辑源代码]
... 或者如何高亮行尾的空格
... 或者如何查找空格和/或制表符
:syntax match Error "\s\+$"

第三课:高亮制表符错误

[编辑 | 编辑源代码]
... 或者如何不高亮用作分隔符的字符

知道制表符在哪里很好。但是制表符前的空格怎么办?它们只是浪费了文件中的空间。以下高亮将向您显示它们

:syntax match Error " \+\t"me=e-1

正则表达式 “ \+\t” 搜索一个或多个空格,后跟一个制表符。这本身可以解决问题,但也会将制表符高亮为错误。如果我们只高亮空格,而制表符保持原样,那就更好了。实际上,这是可能的,并且通过 “me=e-1” 完成。基本上,它表示:将高亮结束在找到的最后一个字符的前一个字符之前。

第四课:高亮行长度

[编辑 | 编辑源代码]
... 或者如何在特定列高亮
... 或者如何在其他模式内高亮
... 或者如何允许其他模式在内部

以下匹配将在行长为 78 个字符时高亮第 78 列。当您有一行超过您想要的长度时,这可以用作警告。当然,这种高亮不应该干扰您可能使用的任何其他高亮

:syntax match Error "\(^.\{79\}\)\@<=." contains=ALL containedin=ALL

以下是它的工作原理的描述

  1. 正则表达式 “\(^.\{79}\)” 从行首 “^” 开始搜索正好 79 个字符,并对结果进行分组 “\( \)”。
  2. “\@<=” 现在将从 1 开始对组进行“零匹配”。“零匹配”表示必须存在文本,但在找到后会被忽略。
  3. 使用 “.”,将匹配一个字符。该字符将使用 Error 颜色高亮。
  4. 使用 “contains=ALL”,我们允许其他高亮模式从我们的模式内部开始。
  5. “containedin=ALL”,我们允许我们的高亮模式从另一个模式内部开始。

Vim 帮助系统建议使用另一种方法。这对命令将高亮虚拟列 79 及以后的所有字符

:highlight rightMargin ctermfg=lightblue
:match rightMargin /.\%>79v/

这将只高亮第 79 列

:highlight col79 ctermbg=red
:highlight col79 guibg=red
:match col79 /\%<80v.\%>79v/

请注意,使用两个项目也可以匹配占用多个虚拟列的字符,例如 TAB。在最后一个示例中,添加了单独的 ctermbg 和 guibg 定义,以便 col79 在 Vim 和 gVim 中都能起作用。

万能补全

[编辑 | 编辑源代码]

从版本 7 开始,Vim 支持全方位补全。这种补全方式应该跨越多个文件,并支持编程语言的所有特性。但是,要使其正常工作,您需要在您的 "autoload/" 目录中有一个合适的 "*complete.vim" 脚本。这个脚本必须定义一个名为 ...#Complete 的函数,该函数负责执行当前编程语言的所有补全工作。

但是编写一个有用的补全函数可能是一项困难的任务。所有提供的补全函数都跨越了数百行代码。

这里是一个用于 Ada 编程语言 的简单实现,详细描述了您可以创建自己的实现。此实现需要一个 "tags" 文件,对于 Ada,您可以使用 gnat xref -v 命令创建。

完整版本可以从 vim.org 网站 下载。

分步教程

[edit | edit source]

使用 <C-X> <C-O> 将补全设置为自动加载函数。如果此脚本是直接加载的,而不是使用自动加载功能,则此检查将生效。

if exists ('+omnifunc') && &omnifunc == ""
    setlocal omnifunc=adacomplete#Complete
endif

全方位补全和自动加载在低于 7.00 的任何 Vim 版本中都不起作用。

if version < 700
    finish
endif

所有 complete#Complete 函数都必须涵盖两个选项:a:findstart == 1a:findstart != 1

    function adacomplete#Complete (findstart, base)
Findstart 等于 1
[edit | edit source]

a:findstart == 1 时,我们必须找出光标左侧有多少个字符可能是补全的一部分。

	if a:findstart == 1

对于我们的简单示例,找到单词的开头非常简单。我们向左查找,直到找到一个不是单词一部分的字符。对于大多数语言,搜索 “\i” 应该可以解决问题。但是,对于 Ada,我们还想扩展 属性 - 因此我们将 “'” 添加到单词字符列表中。

	    let line = getline ('.')
	    let start = col ('.') - 1
	    while start > 0 && line[start - 1] =~ '\i\|'''
		let start -= 1
	    endwhile
	    return start
Findstart 不等于 1
[edit | edit source]

a:findstart != 1 时,我们需要为 a:base 找到可能的补全。有两个选项可以返回找到的补全。

  1. 使用 return 将所有补全作为 List 返回。
  2. 为每个找到的补全调用 complete_add

您也可以组合使用两者 - 它们随后会被合并 - 所以注意不要创建重复项。补全可以是 StringDirectory

在本示例中,我们使用 complete_add

	else

搜索模式应该在匹配的文本开头查找 a:base。

	    let l:Pattern    = '^' . a:base . '.*$'

在第一步中,我们添加所有已知的 Ada 关键字编译指示属性类型。它们已经被 Ada 文件类型插件 准备成 List 中的 Directorys。我们所要做的就是遍历该列表,并将所有 "word" 字段匹配模式的 Directory 条目添加进去。

	    if exists ('g:Ada_Keywords')
		for Tag_Item in g:Ada_Keywords
		    if l:Tag_Item['word'] =~? l:Pattern

添加值 - 包括简单的错误处理。

			if complete_add (l:Tag_Item) == 0
			    return []
			endif
			{{vi/Ex|if} complete_check ()
			    return []
			endif
		    endif
		endfor
	    endif
搜索匹配项
[edit | edit source]

这里完成了实际的工作:我们在标签文件中搜索匹配项。当然,您首先需要一个标签文件。有很多工具可以创建兼容 Vim 的标签文件。只需四处寻找一个即可。

	    let l:Tag_List = taglist (l:Pattern)

我们再次需要遍历所有找到的 List 元素。

	    for Tag_Item in l:Tag_List
		if l:Tag_Item['kind'] == ''
		    let l:Tag_Item['kind'] = 's'
		endif

由于标签和补全的 Directory 结构不同,因此需要转换数据。

标签中可用的信息取决于标签文件创建工具。但最少的是

“name”
标签的名称。
“filename”
定义标签的文件的名称。
“cmd”
用于在文件中定位标签的示例命令。
“kind”
标签的类型。此条目的值取决于 ctags 工具生成的语言特定的种类值。

补全的内容是固定的,包含以下内容

“word”
实际的补全
“kind”
补全的类型,一个字符,例如 “v” 表示变量。
“menu”
在补全菜单中显示的简短额外信息。
“word”
在额外窗口中显示的较长额外信息。
“icase”
忽略大小写

所以对于没有额外信息的简单标签,转换可能看起来像这样

	        let l:Match_Item = {
		    \ 'word':  l:Tag_Item['name'],
		    \ 'menu':  l:Tag_Item['filename'],
		    \ 'info':  "Symbol from file " . l:Tag_Item['filename'] . " line " . l:Tag_Item['cmd'],
		    \ 'kind':  l:Tag_Item['kind'],
		    \ 'icase': 1}
		if complete_add (l:Match_Item) == 0
		    return []
		endif
		if complete_check ()
		    return []
		endif
	    endfor
请注意
当前的 Ada 插件已经扩展到也支持 ctags,它比 gnat xref -v 提供更多信息。但是,我们没有更新教程,因为我们希望保持示例简单易懂。

我们已经通过 complete_add 添加了所有匹配项,因此我们只返回一个空列表。

	    return []
	endif
    endfunction adacomplete#Complete
    finish
endif

最后一点建议:如果您的标签工具没有对条目进行排序,那么您应该单独对它们进行排序。在排序后的标签文件中进行搜索速度要快得多。


学习 vi 编辑器: 熟悉基本任务使工作更轻松高级任务细节vi 克隆 (Vim基本导航模式技巧对程序员有用的东西增强 VimVim 在 Windows 上VimL 脚本语言, Vile, BB vi)vi 参考

华夏公益教科书