Vim使用ctags对系统头文件进行自动完成只有在手动触发弹出窗口时才有效。

3
在OS X上,我使用以下命令为系统包含文件生成了一组ctags:
ctags -f c -h ".h" -R --c-kinds=+p --fields=+iaS --extra=+q /usr/include

这是在~/.vim/ctags/目录中运行的,我将所有为系统级头文件生成的ctags放在该目录下(我还有一些用于ROS和CPP的内容,但这与此无关)。
无论如何。我的.vimrc中正确设置了ctags文件,而且vim肯定可以看到ctags,但由于某种原因,自动完成弹出窗口只会显示来自已包含的头文件的结果,如果我写出整个符号然后开始删除,则可以显示结果。例如,如果我在项目中#include <string.h>,然后想调用strlen(),并在活动vim缓冲区中开始键入str,我只会得到当前vim缓冲区中的符号结果。但是,如果我键入strlen然后开始删除一个或两个字符并按<C-n>,则弹出菜单将填充来自任何其他包含的头文件的匹配项。 编辑:事实证明,如果我只是按下“s”,然后再按<C-n>,它也可以工作。所以问题似乎是只有在手动启动弹出菜单时才能工作。这让我认为它是一个插件问题(见下文)。

附加信息:

  • completeopt被设置为completeopt=menuone,menu,preview,longest

  • 我安装了OmniCppComplete,我认为它可能会影响行为。它目前没有仅在C++文件中被有条件地加载。如果您想让我编辑并发布我的.vimrc中的OmniCppComplete设置,请告诉我。

  • 我还安装了AutoComplPop,但我还没有做任何配置,所以它正在使用其默认设置运行。我还没有真正研究这个插件,所以不知道它的一些行为是否会干扰结果。

  • 我安装了AutoTagTagBar,但这些应该只是调整当前目录的本地标签文件。

我是一个新手,对于Vim不太熟悉,我不知道该从哪里开始调试这个问题,无论是与随机插件还是我的.vimrc设置有关。
2个回答

4
Vim有许多特定的完成机制。
  • <C-n><C-p> 使用由complete选项定义的多个来源。默认情况下,它们将使用当前和所有已加载和未加载的缓冲区、标签和包含的文件来提供完成。虽然你通常可以通过这些得到相当有用的建议,但它是一个“通用”解决方案:如果你在相当大的项目上工作,那么它就不太可靠。

  • <C-x><C-]>仅使用标签,因此可能对你更有用。

  • 还有更多,请参见:h ins-completion

  • Omni完成更加智能:它通常运行一个自定义的文件类型特定脚本,尝试提供有意义的完成。它由<C-x><C-o>触发,你可以在:h ft-c-omni中了解它。当处理代码时,Omni完成通常是更好的选择。

因为你有两个重叠的“自动”完成插件,很难说哪个完成机制在起作用。你应该禁用这些插件,并尝试使用可用的不同完成机制。

问题似乎在于AutoComplPop没有为C和C++文件定义内置行为,因此它会退回到使用<C-x><C-u>,不管它做什么。在C文件中使用<C-x><C-o>会返回一个未找到模式的错误,因此现在我只是禁用AutoComplPop并使用<C-n>来获得最小特定结果。我需要进行更多的研究和实验。感谢您指引我正确的方向! - Doug Stephen
<C-x><C-u> 调用了一个自定义函数,但你没有这个函数,因此出现了错误。我也使用 ACP。它也不支持 JavaScript,所以我进行了修改。实际上,即使对于当时的新手来说,这也很容易。请参见此处和同一位置的其他地方。 - romainl
谢谢提供链接。不过我还是在使用<C-x><C-o>时遇到了错误,我猜测这意味着我的vim运行时中不存在一个能够响应C文件中给定模式的函数。我会尝试根据配置调整AutoComplPop,看看能否解决问题。这看起来很简单。我唯一的问题是,你是如何创建acp#meetsForJavaScriptOmni的?其他的我都明白了。 - Doug Stephen
我刚刚复制了另一个看起来有点像 JS 的定义。我想它是 Python 或 Ruby。然后根据我的需求进行了调整。我认为对于 C 做同样的事情不应该太难。 - romainl
1
非常感谢您的所有帮助。我能够实现一个简单的正则表达式,它在“.”和“->”上进行短路,否则在3个字符后调用omnifunc。事实证明,真正的问题是#include文件被注册为关键字,因此ACP在前进时调用了关键字完成,因此结果范围较小,但由于正则表达式作用域的缘故,当我在退格时调用了omnifunc。我通过设置全局变量来将关键字触发器更改为使用omnifunc而不是ACP的函数,当加载C文件时。 - Doug Stephen

0

我还没有掌握这个技巧,但我认为以下观察可能会有所帮助。

Vim的默认自动完成功能可能会很嘈杂,经常会妨碍你使用<C-x><C-o>调用的内容。具体来说,我发现自己使用<C-x><C-o>调用基于标签的补全时,却被Vim默认建议的打开缓冲区的内容所替换。

关闭其中一个插件的建议是有道理的。在我的情况下,关键是如何关闭Vim的默认行为。我看到过几个人(包括我自己),在触发Vim默认行为之前将表达式的长度设置为一个较高的数字。对我来说,这个数字是:

    let g:deoplete#auto_complete_start_length = 99

...这样可以消除默认的完成层,无论您打算通知工作的命令如何,它都会来来去去。

这仍然感觉像一个hack,但它有助于保持我的工作集中在基于标记的完成上。

顺便说一下:我在Mac上使用NVIM。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接