Vim中使用Python的Omnicompletion无法正常工作

53

我已经在 Stack Overflow 和其他地方搜索了一个小时,但很遗憾!请帮忙。Vim 的 omnicompletion 根本不起作用

  1. 我已编译支持 Python 的 Vim 7.2。

  2. filetype plugin on 在我的 .vimrc 文件中。

  3. 当打开一个 .py 文件时,:echo &omnifunc 打印出 pythoncomplete#Complete

  4. 我正在处理一个大项目,并且我有一个由 exuberant-ctags 生成的 tags 文件。它在 Vim 的 ctags 路径中。我可以通过在符号上按下 ^] 来测试它,然后会定位到该符号的定义。

  5. 更新 1: 我的所有项目代码都在 Python-in-Vim 的路径中。我可以成功地执行 :python import myproject

现在,无论我在哪里尝试使用 C-x C-o,我都只得到:

-- Omni completion (^O^N^P) Pattern not found

我做错了什么?

更新2: 当我在模块级别输入C-x C-o C-n时,Vim会显示一个弹出窗口,其中包含我的项目中其他模块的一些模块级常量。但这只是常量(符号大写字母),而且补全仍然无法在其他任何地方使用。

更新3: 我发现在文件顶部按C-x C-o会开始某种omnicompletion,输入pprint. 会带出pprint模块中所有内容的菜单和快速参考。然而,我的模块导入并没有被自动完成。

更新4,一年后: 我放弃了并学习了Emacs。我到了黑暗面,神秘的香料之地,我告诉你们我已经找到了正确的方法。

更新5,两年后: 我回到了Vim。Emacs很美,但即使经过1.5年的Emacs训练,我仍然能够更快地完成工作。不过,我现在已经停止编写Python代码,无法测试这些建议的有效性。


如果你还没有尝试过的话,可以试试这个:http://blog.dispatched.ch/2009/05/24/vim-as-python-ide/ - Johannes Charra
@jellybean -- 好链接,谢谢!我已经使用了 minibufexpl.vimTaglist.vim,但是 TODO 列表功能将是一个很好的补充。 - a paid nerd
4
我从未找到答案 :( - a paid nerd
使用+pythonfiletype plugin on,Vim 7.3.45的python自动完成功能可以直接使用。 - Sardathrion - against SE abuse
10个回答

12

你要完成的符号在哪个模块中?它在Python标准库中吗?还是第三方模块?

确保该模块/包在PYTHONPATH中。

在 Vim 中,执行以下操作:

:python import sys
:python print sys.path

添加模块的目录:

:python sys.path.append("/path/to/directory/")

好的建议,谢谢。这些是我项目代码中的符号。是的,路径在Vim的Python路径中。我已经更新了问题描述。 - a paid nerd
那么,在自己的库中无法实现自动完成吗? - gitaarik
是的,这是可能的,只要确保模块和包在Python的模块搜索路径中。 - codeape
3
如果你在项目中使用 virtualenv,请确保在运行 vim 之前(在同一个终端中),已经切换到你的虚拟环境。当你切换到虚拟环境后,在 vim 命令行中检查 sys.path,以确保需要自动补全的模块都在其中。 - alexche8
我尝试了这个,但是得到了“抱歉,该命令在此版本中不可用”的提示。但是运行vim --version显示我的vim支持+python3和-python(支持python3但不支持python2),只需将上述命令中的python更改为python3即可正常工作。 - mondaugen
我不得不使用 :py3 而不是 :python。然而,它并没有解决我的问题 :-) - Ignatius J. Reilly

10

由于您很谨慎并确保您的代码可通过PYTHONPATH访问,正如codeape的建议,是否有可能您遇到了Vim Python omni-completeimport bug? 我们可以确定,在Vim 7.2.245版本中仍存在该漏洞。

基本上,如果您正在处理的文件中任何一个导入语句失败,无论它是否包含在Try-Except子句中,都会完全破坏omni-completion。 检查此问题应该相当容易,因为大多数导入都发生在文件开头。

如果您决定这个bug是您的麻烦的原因,您的选项包括:

  • 确保您导入的模块在系统路径上而不仅仅是项目文件
  • 注释掉任何失败的import语句
  • 修复该漏洞
  • 使用ropevim作为完成方法
  • 使用其他编辑器;Netbeans IDE支持Python,并且如果您像我一样沉迷于Vim,则jVi插件非常好用(不要让主页的20世纪90年代的外观欺骗您)

1
我也遇到过这个问题,即任何导入问题都会彻底破坏我的omni-complete。我认为,即使是关于模块已经从项目中的不同位置导入的“警告”,当您尝试进行omni-complete时,也会崩溃您的vim会话。 - Bodhi
Bodhi,请看一下ropevim(请参见我上面编辑答案中的链接)。 - gotgenes

9
听起来提问者已经走向黑暗面了,但就我所知,我最近遇到了这个问题,我的情况是我使用的一个模块依赖于Python 2.7,但我的Vim版本是用Python 2.5编译的。
为了诊断问题,我尝试了“:python import mymodule”,但失败了,因为它报错了一个关于导入依赖模块的错误。然后又尝试了“:python import dependentmodule”,但在这个链条的下一步中失败了。如此往复,直到它尝试导入一个自Python 2.7以来的新系统模块时失败。问题找到了。
要解决这个问题,我只需要执行“sudo port install vim +python27”。但这是针对OSX的。你的情况可能有所不同。
(* 我开玩笑的。Emacs用户是我们的朋友。我们都必须拯救那些在记事本中编程的人...)

这是最有前途的解决方案之一。谢谢! - a paid nerd
有趣..我强烈感觉我也遇到了这个问题!我正在使用带有Python支持的MacVim(Macports构建),它链接到(也是Macports)Python 2.5。我正在开发一个使用Python 2.7的项目,我确定我们导入了一些仅适用于2.7的模块。当我的tab键自动完成失败时(Supertab插件),它实际上会导致我的vim会话出现SEGV故障!我希望重新安装带有python2.7的MacVim可以解决这个问题。干杯! - Bodhi
1
感觉回报告是值得的 - 我的Supertab插件和omnicompletion现在工作得*更好了,但有时仍然会导致我的macvim会话崩溃:(似乎是每当完成正在查找的导入序列中出现问题(例如潜在的循环导入)时。总之,情况正在好转,谢谢! - Bodhi

4
您没有做错任何事情。Python omni自动完成不使用标签文件,这是有意为之的。您不需要为omni自动完成制作标签文件。您仍然可以为通常的标记堆栈跳转制作标签文件,但它被omni自动完成忽略。
我花了很长时间才弄清楚这一点,因为C语言omni自动完成确实使用标签文件。Python omni自动完成的工作方式不同。
您可以通过尝试在python文件类型下和c文件类型下进行omni自动完成来快速观察到这种行为。
首先,:set filetype=python(这是默认设置),然后:echo &omnifunc。Omni complete忽略标记文件,因为&omnifuncpython3complete#Complete,它不使用标签文件。
请注意,如果您的Vim不支持Python,则没有设置omnifunc。检查Python支持。
以下是一个示例,显示无Python支持
vim --version | grep python
+cmdline_hist      +langmap           -python            +viminfo
+cmdline_info      +libcall           -python3           +virtualedit

现在,输入命令:set filetype=c:echo &omnifunc。Vim将Python脚本视为C文件,因此&omnifuncccomplete#Complete,该函数使用标签文件。当然,将Python文件视为C文件并不是解决方法!
以下是:
- 两个Python omni自动完成的示例 - 实现了&omnifunc(syntaxcomplete#Complete)的Vimscripts - preview窗口行为在标签文件预览(:pta)和omni自动完成预览之间的区别。
还有标签自动完成:<C-x><C-]>。如果您已经使用了tags文件,想要Vim使用这些标签进行自动完成,那么<C-x><C-]>就是您要寻找的自动完成方式,而不是<C-x><C-o>
但我鼓励您继续阅读。Omni自动完成不仅可以进行标签自动完成:
1. Omni自动完成可以识别模块名称并使用正确的Python语法进行自动完成。例如,如果您import numpy as np,那么np.a<C-x><C-o>会呈现以字母“ a”开头的numpy函数菜单。标签完成仅自动完成标签文件中的匹配项。 2. Omni自动完成会在预览窗口中填充文档。标签完成功能不会打开预览窗口。 3. 对于Python,omni完成不需要更新标签文件!
示例1:使用omni完成来匹配该文件中的模式的示例。
Python omni自动完成要求您正在编辑的Python脚本是有效的Python代码。这里有一个带有本地变量的简单示例:
foo_name_I_expect_omni_completion

这个单行脚本无法运行(我的变量名未定义),所以如果我编辑此脚本并尝试使用omni完成:
foo_name_I_expect_omni_completion
foo_name_<C-x><C-o>

我收到了"未找到模式"的消息。

这真是让人生气,因为它应该匹配的模式就在上一行!

但是,要使omni补全正常工作,我们只需要将其更改为有效的Python代码:

foo_name_I_expect_omni_completion = 2
foo_name_<C-x><C-o>

现在自动完成功能已经可用!

示例2:使用omni complete匹配导入模块中的模式

作为第二个例子,如果要匹配的模式在另一个文件中,并且该文件可以被脚本看见(通过import语句),则omni完成也可以工作。

同样,我将使用foo_name_I_expect_omni_completion=2。我将保存这个单行代码到一个名为mymodule.py的文件中。现在,在一个新文件example.py中,我会导入mymodule

import mymodule

输入import mymodule后,使用i_<C-x><C-o>来操作模块名称:

import mymodule
mym<C-x><C-o>

Omni完成将其转换为:

import mymodule
mymodule.

当我需要使用omni自动补全时,只需在insert模式下键入<C-x><C-o>。此时将弹出一组模式(有关配置菜单行为,请参见:h completeopt),然后我可以像往常一样使用<C-n><C-y>来选择列表中的第一项并退出omni自动补全回到insert模式。

import mymodule
mymodule.foo_name_I_expect_omni_completion

如果omni complete无法使用,请检查导入的模块是否可执行

如果omni completion似乎无法看到导入的模块,那是因为你导入的模块不可执行。

与上面的玩具示例不同,如果导入的模块还导入了其他包并且你安装了多个Python版本且每个版本都安装了不同的包,则很难跟踪。

例如,我安装了3.6和3.7,但我只在3.6上安装了某个特定的包。 而我正在尝试使用omni complete编辑的脚本中导入了相同的包。

不知何故,python3.6是我的默认python3(来自bash),但是python3.7是我的默认Vim版本。 因此,在从bash运行它时,该模块似乎是有效的,因为我的python3.6安装有必要的包。

检查Vim正在使用哪个版本的Python:

:py3 print(sys.version)

还要检查sys.path,如codeape的答案所述:

:py3 print(sys.path)

我有许多 Python 安装,每个 Python 安装都有自己的 USER_SITE 路径。

:py3 import site; print(site.USER_SITE)

我使用一个USER_SITE文件夹,并找到一种方法将每个Python安装指向它。对于Vim omni-complete使用的Python安装,我通过编辑PYTHONPATH环境变量来实现这一点。

在我的情况下,我的唯一活动的USER_SITE是用于Python 3.7的,而Vim正在使用Python 3.6,所以我将以下内容添加到我的.bashrc文件中:

# Python USERSITE folder
pkg=$HOME/.local/lib/python3.7/site-packages/

# Add to PYTHONPATH for Vim omni-complete to see packages I wrote
PYTHONPATH=$PYTHONPATH:$pkg

文档

我通过追踪Vim脚本来解决了这个问题。

引用自Vim帮助文档:

:h compl-omni-filetypes

在 'runtimepath' 中,{filetype} 用于的文件应该是 autoload/{filetype}complete.vim。因此,对于 "java" 来说,它是 autoload/javacomplete.vim。
这些 autoload/{filetype}complete.vim 文件位于您的 Vim 安装中。例如,这里是我的 C 和 Python 文件:
/usr/share/vim/vim81/autoload/ccomplete.vim
/usr/share/vim/vim81/autoload/python3complete.vim

或者调用:echo &omnifunc,并在GitHub上查找Vimscript: https://github.com/vim/vim/blob/master/runtime/autoload/

当我发现tag一词不出现在python3complete.vim文件中时,我开始怀疑自己对问题的基本误解:)

Omni完成具有特殊的预览行为

我一直被预览窗口的行为所困惑。与标签不同, Omni complete 具有不同的预览行为。

首先,要使用omni complete获得预览窗口,Vim completeopt选项必须包含previewmenumenuone之一。

completeopt默认为menu,preview。要明确设置选项,例如, 使用menuone代替menu

set completeopt=menuone,preview

menuone使菜单始终显示,即使只有一个匹配项。使用menu,对于单个匹配项不显示菜单,因此也不会显示preview窗口。使用menuone可确保preview窗口弹出。

关闭preview可以防止在omni自动完成期间分割窗口:

set completeopt-=preview

需要注意的是,omni completepreview 行为(当您高亮显示菜单项时打开)与标签的 preview 行为(使用 <C-w>}:pta 打开)不同。

  • tag-preview 在预览窗口中打开代码。
  • omni-complete-preview 打开文档。

Omni completepreview 根据完成菜单中突出显示的项目而显示不同的内容。如果是变量,则显示其数据类型的 pydoc;如果是函数,则显示其 docstring


2

在更新到Fedora 16后(但仍从源代码编译vim),omni自动完成功能停止工作,并显示与上述相同的消息。我通过重新映射键“修复”了它。

inoremap <C-space> <C-x><C-o>

~/.vimrc中进行修改,现在它又可以正常工作了。

2
我曾经遇到过omni completion无法正常工作的类似问题。后来发现是minibufexpl.vim插件干扰了omni completion。以下是我找到问题的方法:
正常的关键字自动补全可以使用,但是任何语言的omni complete都无法使用,即使omnifunc已正确设置。当我按下C-X C-O时,什么也没有发生。我执行“:py print globals()”,明显看到pythoncomplete没有被加载。我可以执行“:call pythoncomplete#Complete(1,'')”并看到它被加载。对我来说,这排除了Vim本身的问题。似乎有些东西正在干扰按键映射或拦截omni completion请求。因此,我开始逐个禁用我的插件。结果发现罪魁祸首是“minibufexpl”。我从github上下载了Holgado版本。
根据github上的问题追踪器,MBE存在许多未解决的问题,并且自2012年初以来一直没有进展。我现在只需禁用它即可使用自动完成。同时,我将添加以下内容到我的vimrc中,以保持多个修改的缓冲区处于打开状态,并使用简单的按键序列循环浏览它们(MBE可以更智能地选择要循环浏览的缓冲区,但对于简单的问题来说似乎太过于复杂)。
set hidden
noremap <C-TAB> :bnext<CR>
noremap <C-S-TAB> :bprev<CR>

1
你尝试过使用 <C_x><C-]> 吗?

0

我使用了supertab插件(http://www.vim.org/scripts/script.php?script_id=1643)

因为C-x C-o有点难用

在.vimrc文件中:

let g:SuperTabDefaultCompletionType = "<c-x><c-o>"

然后只需使用Tabb进行全自动完成


我通过在我的 .vimrc 文件中添加以下内容解决了一个问题(SuperTab 插件配置): `let g:SuperTabDefaultCompletionType = ""` - nexayq

0
如果您正在使用 Python2,请确保您:
sudo apt-get install vim.nox-py2 

使用vim.nox-py2代替vim。


0

c-x c-n 可以获取对象成员列表。


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