vim 从嫌弃到依赖(22)——自动补全
这篇文章我们将讨论 vim 自带的自动补全功能。当然,针对自动补全功能有许多好用的插件,但是了解vim自带的功能有助于我们更好的用来插件的补全功能。因为我见过有的配置文件将插件的功能配置的比原有的更难用,而且只用基本的功能不一定有原版的好用。所以这里也介绍一下原始版本用法,算是帮助各位在以后的配置中提供一个标杆。
make 命令
在了解自动补全之前,让我们先简单聊聊 :make 这个命令,它与上一篇文章中介绍的 :grep 命令类似,也是对 shell 命令的一个封装。它默认封装的是 make 命令。
我们对 c/c++ 语言执行 :make 也就是在调用 shell 中的 make 命令。它会将编译产生的错误信息存储在 quickfix 列表中。我们上一节中介绍了如何操作 quickfix 列表。也介绍了如何对 :grep 命令进行改造。同样的 :make 也支持使用相同的方法进行改造。
:make 命令中,使用 makeprg 来执行外部命令,使用 errorformat 来格式化输出到 quickfix 中。它们默认的值如下:
makeprg="make"
errorformag="errorformat=%*[^"]"%f"%*\D%l: %m,"%f"%*\D%l: %m,%-G%f:%l: (Each undeclared identifier is reported only once,%-G%f:%l:
for each function it appears in.),%-GIn file included from %f:%l:%c:,%-GIn file included from %f:%l:%c\,,%-GIn file incl
uded from %f:%l:%c,%-GIn file included from %f:%l,%-G%*[ ]from %f:%l:%c,%-G%*[ ]from %f:%l:,%-G%*[ ]from %f:%l\,,%-G%*[
]from %f:%l,%f:%l:%c:%m,%f(%l):%m,%f:%l:%m,"%f"\, line %l%*\D%c%*[^ ] %m,%D%*\a[%*\d]: Entering directory %*[`']%f',%X%*
\a[%*\d]: Leaving directory %*[`']%f',%D%*\a: Entering directory %*[`']%f',%X%*\a: Leaving directory %*[`']%f',%DMaking
%*\a in %f,%f|%l| %m"
可以调整它们的值来适配不同的外部命令。这里就不再详细展开了,相信阅读过上一篇文章的小伙伴对这个应该不陌生。本来 :make 命令是vim中十分有用的一个命令,应该单独写一篇文章的。但是它于 :grep 重复度太高了,所以我决定在介绍其他内容的时候一笔带过。想了解详细信息的可以参考vim的用户手册。
自动补全
自动补全可以在插入模式下触发,当我们触发补全功能的时候,vim会根据当前编辑会话中所有缓冲区的内容建立一张补全列表,然后根据当前光标左侧的字符进行检测,看在表中能否找到单词的一部分,能找到则会用这个未完成的单词对补全列表进行过滤,所以不是以它为开头的单词都被过滤掉,剩余的组成一个弹出式菜单供用户选择。效果如下:

上述例子中,因为以 re 开头的原本只有 require 一项,为了展示补全效果这里我们新增一个以 re 开头的 return
我们使用 <Ctrl +p> 和 <Ctrl + n> 来切换补全菜单中的上一条和下一条。除了这个,我们还有其他的用于操作补全菜单的快捷键。
<Ctrl - n>: 使用来自补全列表中的下一项内容(next)<Ctrl - p>: 使用来自补全列表中的上一项内容(prev)<Down>: 与<Ctrl -n>相同<Up>: 与<Ctrl - p>相同<Ctrl -y>: 确认使用当前选中的匹配项<Ctrl - e>: 还原最初的输入项<Ctrl -h>: 从当前匹配项中删除一个字符<Ctrl - l>: 从当前匹配项中增加一个字符
一般在输入字符的时候,如果有匹配项可以匹配vim会自动弹出,或者也可以手动使用 <Ctrl - n> 弹出匹配项菜单。在确定要使用的匹配后可以使用 <Ctrl-y> 来确认
有时候虽然弹出了匹配项菜单,但是匹配项太多了,而你需要的单词又在列表的太后面,这个时候可以使用 <Ctrl - e> 来退出菜单,手动输入几个字符使匹配项更加精确。或者也可以输入 <Ctrl -p> 到达最开始的项,即我们目前的输入,然后再次输入字符来精简菜单项,接着使用 <Ctrl - n> 弹出菜单。使用这种方式来一步一步的逼近我们想要的结果

自定义补全项来源
默认情况下,vim 补全项主要来源于以下几个地方:
- 缓冲区列表:vim补全项最基本的来源就是当前的缓冲区列表。它可以通过
<Ctrl - x><Ctrl - n>来触发该项。 - 包含文件,所有的编程语言都有包含文件的概念,例如
c/c++中的#include,python中的import。使用<Ctrl-x><Ctrl-i>可以触发这个选项,让vim从被包含文件中提取补全项。vim本身使用c语言编写的,它能够识别c/c++语言中的关键字,我们可以指定include项来使 vim认识其他不同的关键字。一般常用的编程语言 vim 都能够识别,因此不需要修改include项。 - 标签文件,我们使用
ctags或者类似的插件的时候会生成一个标签文件,该文件会将扫描到代码中的关键字、函数、变量等的索引放入到一个文件中以供后续进行跳转。同时他们也会产生一系列的补全项到补全列表中。可以使用<Ctrl+x><Ctrl+]>来触发
一般直接使用 <Ctrl + n> 触发的是当前缓冲区列表中的补全项,使用 <Ctrl+x> 作为前缀,可以触发其他类型的补全项。这么做有一个好处是尽量精简补全列表,减少了我们手动遍历的过程。但是有时候我们并不知道我想要的内容该从哪里来,有没有什么办法能做到,用 <Ctrl + n> 这个按钮就可以调用其他所有来源的补全项呢?
要做到这点,可以使用 complete 这个配置项。该项包含一组由逗号分隔的单个字符表示的参数,当参数出现时表示需要扫描该参数代表的位置。使用 set complete? 可以看到,缺省项为 complete=.,w,b,u,t 。我们可以使用 set complete-=i 或者 set complete+=k 来删除或者添加某个扫描位置。常见的位置参数如下所示:
.: 表示当前以打开的缓冲区w: 当前打开的窗口b: 当前缓冲区列表u: 当前处于缓冲区列表中,但是未打开的缓冲区t: 当前标签文件U: 当前打开的,不属于缓冲区列表中的缓冲区k: 从字典文件中加载的补全项i: 从当前文件和包含文件中读取d: 从当前文件和包含文件中读取使用 define定义的宏
完整的内容可以使用 :h 'complete' 来查看。
使用字典文件
在上面的论述中,我们可以知道 vim 是可以自定义补全的字典文件,然后从字典中产生匹配的。我们可以使用 <Ctrl-x><Ctrl-k> 来加载字典中的匹配项。
我们可以使用 set spell来启动拼写检查,拼写检查也会产生新的字典文件。如果不想使用该项,也可以使用 set dictionary来指定含有一个或者多个单词的字典文件。
在这个例子中我们在 nvim-config 目录中新建一个 spell.txt 文件,我们在里面写入如下内容
require
return
request
然后使用 set dictionary=./spell.txt ,接着删除 init.lua 中的 return ,输入 re 然后使用 <Ctrl+x><Ctrl+k> 这个时候我们发现它已经加载了

补全整行
除了补全单词,vim还可以补全整行的内容,使用 <Ctrl+x><Ctrl+l> 可以触发补全整行的操作。
补全行的补全项来源与补全单词相同,需要注意的是补全行的操作会自动忽略行首的缩进。

补全行的操作与之前介绍的 yy 或者 :t 产生的效果相同,我们应该要根据实际情况分别使用。
补全文件名
在 shell中输入命令可以使用 <Tab> 键来自动补全文件路径,vim中使用 <Ctrl+x><Ctrl+f> 来对文件路径和文件名进行补全。
需要注意的是当我们使用相对路径来补全文件名时,使用的是工作目录,也就是你从哪个目录中进入的vim。我们可以在 vim中使用:cd来切换工作目录。例如我在 nvim-config这个工程的根目录执行 nvim init.lua,我们在这个文件中希望快速补全 basic/settings.lua这项,我们发现它在补全的时候报错

这个时候我们可以使用 :cd lua 来切换工作目录到 nvim-config/lua 。这个时候再执行补全命令就可以了。

根据具体编程语言生成补全
上述补全在编辑普通文本的时候显的有点用处,但是作为程序员平时在写代码如果只能使用上述方式进行补全肯定会抓狂的。好在vim 提供了像其他IDE那样的基于编程语言的补全方式。使用该补全方式的快捷键为 <Ctrl+x><Ctrl+o> 要启用该方式,需要启动文件类型识别。
nvim 中已经启用了这一特性,因此不必特意进行设置,但是这里我还是给出它的配置。
vim.o.filetype="plugin"
或者vim中可以使用如下代码
set filetype=plugin
set nocompatiable # 设置与vi 不兼容
例如我们可以尝试着在 css 文件中使用补全

vim 本身也确实支持很多语言的自动补全,但是为了获得完整的体验还是推荐使用各种专门的补全插件获得更好的体验
最后的总结
在这边文章中,介绍了vim中补全项主要的几个来源分别是:当前缓冲区和缓冲区列表、包含文件、外部程序生成的标签等等。同时也介绍了如何使用快捷键来进行不同项的补全,现在对这些快捷键总结如下:
<Ctrl + n>: 普通关键字补全,主要来源自缓冲区列表和当前缓冲区<Ctrl+x><Ctrl+n>: 与 <Ctrl+n>作用相同<Ctrl+x><Ctrl+i>: 从包含文件中获取补全项<Ctrl+x><Ctrl+]>: 从外部标签中获取补全项<Ctrl+x><Ctrl+k>: 从字典文件中获取补全项<Ctrl+x><Ctrl+l>: 补全整行<Ctrl+x><Ctrl+f>: 补全文件名<Ctrl+x><Ctrl+o>: 根据编程语言来进行补全
vim 从嫌弃到依赖(22)——自动补全的更多相关文章
- 解决IDEA中,maven依赖不自动补全的问题
转载: 作者:七个榴莲链接:https://www.jianshu.com/p/46a423bdde31来源:简书 遇到的问题:Maven依赖不自动补全 在idea上使用maven插件时,发现在pom ...
- vim 实现括号以及引号的自动补全
编辑文件/etc/vim/vimrc sudo vim /etc/vim/vimrc 在最后添加 inoremap ( ()<ESC>i inoremap [ []<ESC>i ...
- Vim 的补全模式加速器,轻松玩转全部 15 种自动补全模式
1. 关于 Vim 补全模式 ---- Vim 一共提供了 15 种自动补全的模式(:help ins-completion).其中有两种的补全列表内容与另外两种相同,只是排序不同,这 15 种 ...
- [转载]启用 VIM 中的 Python 自动补全及提示功能
转载: http://zhongwei-leg.iteye.com/blog/941474 周围的同事不喜欢使用 VIM 写 Python 代码的原因之一就是,VIM 不能像 Visual Studi ...
- vim自动补全插件YouCompleteMe
前言 Valloric/YouCompleteMe可以说是vim安装最复杂的插件之一,但是一旦装好,却又是非常好用的.YouCompleteMe简称ycm 在安装折腾的过程中,我再一次的体会到,除了官 ...
- Vim自动补全神器:YouCompleteMe
第一次听说这个插件还是在偶然的情况下看到别人的博客,听说了这个插件的大名.本来打算在实训期间来完成安装的,无奈网实在不给力,也就拖到了回家的时候.在开始准备工作的时候就了解到这个插件不是很容易安装,安 ...
- Linux VIM python 自动补全插件:pydiction
Pydiction 可以是我们使用Tab键自动补全Python代码在Vim,是一款非常不错的插件. Pydiction不需要安装,所有没有任何依赖包问题,Pydiction主要包含三个文件. pyth ...
- Vim自动补全神器:YouCompleteMe(转)
转自:http://blog.jobbole.com/58978/ 可能会有一段时间写linxu,免不了用vim,留着,找时间实操之 原文出处: marchtea 的博客 第一次听说这个插件还是在偶然 ...
- Linux --- vim 安装、支持python3的配置、插件自动补全YCM的安装配置及全过程错误总结
1.git(用来下载vim和相关插件) sudo apt-get install git 2,cmake(用来编译clang-llvm) sudo apt-get install build-esse ...
- (转)Vim自动补全神器:YouCompleteMe
原文出处:http://blog.jobbole.com/58978/ 第一次听说这个插件还是在偶然的情况下看到别人的博客,听说了这个插件的大名.本来打算在实训期间来完成安装的,无奈网实在不给力,也就 ...
随机推荐
- cxf 动态调用 WebService No compiler detected, make sure you are running on top of a JDK instead of a JRE
WebService cxf No compiler detected, make sure you are running on top of a JDK instead of a JRE [202 ...
- AIGC
博客目录 本地部署modelscope-agent python 使用 Google Gemini API MetaGPT MetaGPT day01: MetaGPT作者代码走读.软件公司初始示例
- 当谈论 React hook,我们究竟说的是什么?
这个标题很大,但是落点很小,只是我,一个开发者在学习和使用 hooks 中的一点感受和总结. React hook 的由来 React hook 的由来,其实也可以看作是前端技术不断演进的结果. 在 ...
- 销售订单BAPI增强
一.需求背景 在销售订单批导时,需要调用BAPI:BAPI_SALESORDER_CREATEFROMDAT2维护成本中心字段, 二.增强实现 BAPI中没有该字段,需要通过增强的方式导入.通过BAP ...
- 5G“乍到”,图扑带你了解室内定位可视化的实现与新突破
前言 现代工业化的推进在极大加速现代化进程的同时也带来的相应的安全隐患,在传统的可视化监控领域,一般都是基于 Web SCADA 的前端技术来实现 2D 可视化监控,本系统采用 Hightopo 的 ...
- 七、mycat-ER分片
系列导航 一.Mycat实战---为什么要用mycat 二.Mycat安装 三.mycat实验数据 四.mycat垂直分库 五.mycat水平分库 六.mycat全局自增 七.mycat-ER分片 一 ...
- 这才是你应该了解的Redis数据结构!
深入了解Redis数据结构 Redis,作为一种高性能的内存数据库,支持多种数据结构,从简单的字符串到复杂的哈希表.在这篇博文中,我们将深入探讨Redis的一些主要数据结构,并通过详细的例子展示它们的 ...
- JPA + MySQL 开发总结
本文为博主原创,转载请注明出处: org.springframework.data.jpa 是 Spring Data JPA 框架中的一个包,用于简化与 JPA(Java Persistence A ...
- Oracle建立索引前后性能比较
1.SQL语句 create table C##HR.t_noindex as select * from all_objects; create table C##HR.t_indexed as s ...
- 【C/C++】宏参数多对一和宏部分替换
宏参数多对一:使用分号分隔多参数 宏部分替换:替换需要转换的再与后续宏接续 #include <stdio.h> #define _MESS_FAILED() printf("% ...