您没有做错任何事情。Python omni自动完成
不使用标签文件,这是有意为之的。您不需要为omni自动完成制作标签文件。您仍然可以为通常的标记堆栈跳转制作标签文件,但它被omni自动完成忽略。
我花了很长时间才弄清楚这一点,因为
C语言omni自动完成确实使用标签文件。Python omni自动完成的工作方式不同。
您可以通过尝试在
python
文件类型下和
c
文件类型下进行omni自动完成来快速观察到这种行为。
首先,
:set filetype=python
(这是默认设置),然后
:echo &omnifunc
。Omni complete忽略标记文件,因为
&omnifunc
是
python3complete#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文件,因此
&omnifunc
是
ccomplete#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
我使用一个USER_SITE
文件夹,并找到一种方法将每个Python安装指向它。对于Vim omni-complete使用的Python安装,我通过编辑PYTHONPATH环境变量来实现这一点。
在我的情况下,我的唯一活动的USER_SITE
是用于Python 3.7的,而Vim正在使用Python 3.6,所以我将以下内容添加到我的.bashrc
文件中:
pkg=$HOME/.local/lib/python3.7/site-packages/
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
选项必须包含preview
和menu
或menuone
之一。
completeopt
默认为menu,preview
。要明确设置选项,例如,
使用menuone
代替menu
:
set completeopt=menuone,preview
menuone
使菜单始终显示,即使只有一个匹配项。使用menu
,对于单个匹配项不显示菜单,因此也不会显示preview
窗口。使用menuone
可确保preview
窗口弹出。
关闭preview
可以防止在omni自动完成期间分割窗口:
set completeopt-=preview
需要注意的是,omni complete
的 preview
行为(当您高亮显示菜单项时打开)与标签的 preview
行为(使用 <C-w>}
或 :pta
打开)不同。
tag-preview
在预览窗口中打开代码。
omni-complete-preview
打开文档。
Omni complete
的 preview
根据完成菜单中突出显示的项目而显示不同的内容。如果是变量,则显示其数据类型的 pydoc
;如果是函数,则显示其 docstring
。
minibufexpl.vim
和Taglist.vim
,但是TODO
列表功能将是一个很好的补充。 - a paid nerd+python
和filetype plugin on
,Vim 7.3.45的python自动完成功能可以直接使用。 - Sardathrion - against SE abuse