调整 Python 的 `include` 和 `includeexpr` 表达式后无法使 `include-search` 工作
Unable to get `include-search` working after tweaking `include` & `includeexpr` expression for Python
我正在尝试在我的 vim 配置中使用基于 include-search 的设置。这导致 [i
、[i
、[d
、]d
等命令无法按预期工作。此外,当 :checkpath!
为 运行 查看包含的文件时,它也没有按预期工作。
你能帮我告诉我我做错了什么以及我能做些什么来解决这个问题吗?
我的项目根目录如下所示。我故意不列出 venv
目录的条目,只是为了保持条目列表较小。
\> tree -I "build|dist|*egg*|__pycache__" -L 2
.
├── MANIFEST.in
├── README.md
├── acs_datamodels-0.0.1-py3-none-any.whl
├── ai_core-0.0.1-py3-none-any.whl
├── datamodels
│ ├── __init__.py
│ ├── fabric.py
│ ├── literals.py
│ └── precompute.py
├── encrypt.log
├── setup.py
├── tests
│ ├── __init__.py
│ ├── data
│ ├── test_fabric.py
│ └── test_precompute.py
└── venv
├── bin
├── include
├── lib
├── lib64 -> lib
└── pyvenv.cfg
我的:set path?
长得像
path=datamodels,venv/lib/python3.7/site-packages/*/**2
我的:set include?
长得像
^\s*\(from\|import\)\s*\zs\(\S\+\|\S\+\s*import\{1}\s*\S\+\)\ze\($\|\s*as\|,\)
我的:set includeexpr?
长得像
includeexpr=PyInclude(v:fname)
~/.vim/after/ftplugin/python.vim
内容如下
set shiftwidth=4 tabstop=4 softtabstop=4 expandtab autoindent smartindent
setlocal wildignore=*.pyc,bin,*egg*,__pycache__/*,build,dist
setlocal include=^\s*\(from\\|import\)\s*\zs\(\S\+\\|\S\+\s*import\{1}\s*\S\+\)\ze\($\\|\s*as\\|,\)
function! PyInclude(fname)
echom "fname: " a:fname
let parts = split(a:fname, ' import ')
echom "parts: " parts
let l = parts[0] " (1) logging (2) ai_core.commons (3) datamodels.literals
if len(parts) > 1
let r = parts[1] " (1) datamodels (2) datetime
let joined = join([l, r], '.') " datetime.datetime, ai_core.commons.decode_token
let fp = substitute(joined, '\.', '/', 'g') . '.py' " datetime/datetime, ai_core/commons/decode_token
let found = glob(fp, 1)
echom "parts > 1" found
if len(found)
return found
endif
endif
let kp = substitute(l, '\.', '/', 'g') . '.py'
echom "parts < 1" kp
return kp " ai_core/commons.py, datamodels/literals.py
endfunction
setlocal includeexpr=PyInclude(v:fname)
:checkpath!
的输出如下。请注意输出还包含一些我添加的调试信息。如果您看到 from typing import Dict
和 import logging
已从 venv
目录中识别出来,但其他库:from ai_core.commons import decode_token
我从 wheel 文件安装的库无法识别,即使它们'在 venv
目录中。此外,无法识别当前文件相对路径 import datamodels.literals
中的其他模块。
fname: typing import Dict
parts: ['typing', 'Dict']
parts > 1
parts < 1 typing.py
venv/lib/python3.7/site-packages/pip/_internal/utils/typing.py
fname: ai_core.commons import decode_token
parts: ['ai_core.commons', 'decode_token']
parts > 1
parts < 1 ai_core/commons.py
ai_core.commons import decode_token NOT FOUND
fname: logging
parts: ['logging']
parts < 1 logging.py
venv/lib/python3.7/site-packages/pip/_internal/utils/logging.py
fname: datamodels.literals
parts: ['datamodels.literals']
parts < 1 datamodels/literals.py
datamodels.literals NOT FOUND
我从 this video, thanks a ton to Leeren 那里学到了这些,向我介绍了这些以及更多内容。
&path
是要在其中搜索文件的目录白名单。基本上,您可以将 include search 视为将文件名附加到 &path
中列出的每个目录,然后查看该路径是否通向某些东西(它实际上并不像那样工作,但对于问题而言,这是一个足够好的心智模型手)。
例如,如果您的文件名是 quux
而您的 &path
是 foo,bar,baz
,那么 Vim 将搜索以下文件:
foo/quux
bar/quux
baz/quux
这里,文件名是 datamodels/literals.py
而你的 &path
是 datamodels,venv/lib/python3.7/site-packages/*/**2
所以 Vim 将搜索:
datamodels/datamodels/literals.py
venv/lib/python3.7/site-packages/*/**/datamodels/literals.py
venv/...
由于相当明显的原因而失败。
有两种方法可以解决这个问题:
在您的 &path
前面加上 .,,
,它告诉 Vim 在当前文件的目录和工作目录中搜索文件。您的 &path
将如下所示:
.,,datamodels,venv/lib/python3.7/site-packages/*/**2
这应该让 Vim 轻松找到 datamodels/literals.py
:
datamodels/literals.py <-- BINGO!
datamodels/datamodels/literals.py
venv/lib/python3.7/site-packages/*/**/datamodels/literals.py
venv/...
制作你的 &includeexpr
return literals.py
,可以用你当前的 &path
找到,而不是 datamodels/literals.py
:
datamodels/literals.py <-- BINGO!
venv/lib/python3.7/site-packages/*/**/literals.py
venv/...
IMO,你应该两者都做。
:set path=.,,venv/lib/python3/site-packages/**2
施展了魔法。更正为 **2
以表示具有 2 级深度的子目录,而不是我原来的 post 中的 */**2
。
是的,正如 @romail 指出的那样,我确实尝试将 includeexpr
中的每个文件名附加到 path
中的目录列表中。谢谢。
我正在尝试在我的 vim 配置中使用基于 include-search 的设置。这导致 [i
、[i
、[d
、]d
等命令无法按预期工作。此外,当 :checkpath!
为 运行 查看包含的文件时,它也没有按预期工作。
你能帮我告诉我我做错了什么以及我能做些什么来解决这个问题吗?
我的项目根目录如下所示。我故意不列出
venv
目录的条目,只是为了保持条目列表较小。\> tree -I "build|dist|*egg*|__pycache__" -L 2 . ├── MANIFEST.in ├── README.md ├── acs_datamodels-0.0.1-py3-none-any.whl ├── ai_core-0.0.1-py3-none-any.whl ├── datamodels │ ├── __init__.py │ ├── fabric.py │ ├── literals.py │ └── precompute.py ├── encrypt.log ├── setup.py ├── tests │ ├── __init__.py │ ├── data │ ├── test_fabric.py │ └── test_precompute.py └── venv ├── bin ├── include ├── lib ├── lib64 -> lib └── pyvenv.cfg
我的
:set path?
长得像path=datamodels,venv/lib/python3.7/site-packages/*/**2
我的
:set include?
长得像^\s*\(from\|import\)\s*\zs\(\S\+\|\S\+\s*import\{1}\s*\S\+\)\ze\($\|\s*as\|,\)
我的
:set includeexpr?
长得像includeexpr=PyInclude(v:fname)
~/.vim/after/ftplugin/python.vim
内容如下set shiftwidth=4 tabstop=4 softtabstop=4 expandtab autoindent smartindent setlocal wildignore=*.pyc,bin,*egg*,__pycache__/*,build,dist setlocal include=^\s*\(from\\|import\)\s*\zs\(\S\+\\|\S\+\s*import\{1}\s*\S\+\)\ze\($\\|\s*as\\|,\) function! PyInclude(fname) echom "fname: " a:fname let parts = split(a:fname, ' import ') echom "parts: " parts let l = parts[0] " (1) logging (2) ai_core.commons (3) datamodels.literals if len(parts) > 1 let r = parts[1] " (1) datamodels (2) datetime let joined = join([l, r], '.') " datetime.datetime, ai_core.commons.decode_token let fp = substitute(joined, '\.', '/', 'g') . '.py' " datetime/datetime, ai_core/commons/decode_token let found = glob(fp, 1) echom "parts > 1" found if len(found) return found endif endif let kp = substitute(l, '\.', '/', 'g') . '.py' echom "parts < 1" kp return kp " ai_core/commons.py, datamodels/literals.py endfunction setlocal includeexpr=PyInclude(v:fname)
:checkpath!
的输出如下。请注意输出还包含一些我添加的调试信息。如果您看到from typing import Dict
和import logging
已从venv
目录中识别出来,但其他库:from ai_core.commons import decode_token
我从 wheel 文件安装的库无法识别,即使它们'在venv
目录中。此外,无法识别当前文件相对路径import datamodels.literals
中的其他模块。fname: typing import Dict parts: ['typing', 'Dict'] parts > 1 parts < 1 typing.py venv/lib/python3.7/site-packages/pip/_internal/utils/typing.py fname: ai_core.commons import decode_token parts: ['ai_core.commons', 'decode_token'] parts > 1 parts < 1 ai_core/commons.py ai_core.commons import decode_token NOT FOUND fname: logging parts: ['logging'] parts < 1 logging.py venv/lib/python3.7/site-packages/pip/_internal/utils/logging.py fname: datamodels.literals parts: ['datamodels.literals'] parts < 1 datamodels/literals.py datamodels.literals NOT FOUND
我从 this video, thanks a ton to Leeren 那里学到了这些,向我介绍了这些以及更多内容。
&path
是要在其中搜索文件的目录白名单。基本上,您可以将 include search 视为将文件名附加到 &path
中列出的每个目录,然后查看该路径是否通向某些东西(它实际上并不像那样工作,但对于问题而言,这是一个足够好的心智模型手)。
例如,如果您的文件名是 quux
而您的 &path
是 foo,bar,baz
,那么 Vim 将搜索以下文件:
foo/quux
bar/quux
baz/quux
这里,文件名是 datamodels/literals.py
而你的 &path
是 datamodels,venv/lib/python3.7/site-packages/*/**2
所以 Vim 将搜索:
datamodels/datamodels/literals.py
venv/lib/python3.7/site-packages/*/**/datamodels/literals.py
venv/...
由于相当明显的原因而失败。
有两种方法可以解决这个问题:
在您的
&path
前面加上.,,
,它告诉 Vim 在当前文件的目录和工作目录中搜索文件。您的&path
将如下所示:.,,datamodels,venv/lib/python3.7/site-packages/*/**2
这应该让 Vim 轻松找到
datamodels/literals.py
:datamodels/literals.py <-- BINGO! datamodels/datamodels/literals.py venv/lib/python3.7/site-packages/*/**/datamodels/literals.py venv/...
制作你的
&includeexpr
returnliterals.py
,可以用你当前的&path
找到,而不是datamodels/literals.py
:datamodels/literals.py <-- BINGO! venv/lib/python3.7/site-packages/*/**/literals.py venv/...
IMO,你应该两者都做。
:set path=.,,venv/lib/python3/site-packages/**2
施展了魔法。更正为 **2
以表示具有 2 级深度的子目录,而不是我原来的 post 中的 */**2
。
是的,正如 @romail 指出的那样,我确实尝试将 includeexpr
中的每个文件名附加到 path
中的目录列表中。谢谢。