If_pyth

Nvim :help 页面,生成 使用 tree-sitter-vimdoc 解析器。


NVim 的 Python 接口 python Python
参见 provider-python 获取更多信息。
:python :py E263 E264 E887 :[range]py[thon] {stmt} 执行 Python 语句 {stmt}。一个简单的检查 :python 命令是否工作的测试。
:python print("Hello")
:[range]py[thon] << [trim] [{endmarker}] {script} {endmarker} 执行 Python 脚本 {script}。在 Vim 脚本中包含 python 代码很有用。需要 Python,参见 script-here
如果 [endmarker] 从 "<<" 之后省略,则在 {script} 之后必须使用一个点 '.',就像 :append:insert 命令一样。有关更多信息,请参阅 :let-heredoc
示例
function! IcecreamInitialize()
python << EOF
class StrawberryIcecream:
        def __call__(self):
                print('EAT ME')
EOF
endfunction
要查看你的 Python 版本
:python print(sys.version)
不需要 "import sys",它默认情况下是完成的。
python-environment
在 Vim 中设置的环境变量并不总是可以在 Python 中使用。这取决于 Vim 和 Python 的构建方式。另请参见 https://docs.pythonlang.cn/3/library/os.html#os.environ
注意: Python 对缩进非常敏感。确保 "class" 行和 "EOF" 没有任何缩进。
:pydo
:[range]pydo {body} 对 [range] 中的每一行执行 Python 函数 "def _vim_pydo(line, linenr): {body}",将函数参数分别设置为每一行的文本,不带尾部的 <EOL>,以及当前行号。函数应返回一个字符串或 None。如果返回一个字符串,它将成为当前轮次的行的文本。[range] 的默认值为整个文件:"1,$"。
示例
:pydo return "%s\t%d" % (line[::-1], len(line))
:pydo if line: return "%4d: %s" % (linenr, line)
你可以使用 :pydo:py 结合使用,以使用 python 过滤一个范围。例如
:py3 << EOF
needle = vim.eval('@a')
replacement = vim.eval('@b')
def py_vim_string_replace(str):
        return str.replace(needle, replacement)
EOF
:'<,'>py3do return py_vim_string_replace(line)
:pyfile :pyf :[range]pyf[ile] {file} 执行 {file} 中的 Python 脚本。整个参数用作单个文件名。
这两个命令本质上执行相同的操作 - 它们执行一段 Python 代码,将 "当前范围" python-range 设置为给定的行范围。
对于 :python,要执行的代码在命令行中。对于 :pyfile,要执行的代码是给定文件的内容。
Python 命令不能在 沙盒 中使用。
要传递参数,你需要显式地设置 sys.argv[]。示例
:python sys.argv = ["foo", "bar"]
:pyfile myscript.py
以下是一些示例 python-examples
:python from vim import *
:python current.line = str.upper(current.line)
:python print("Hello")
:python str = current.buffer[42]
请注意,更改(例如 "import" 语句)从一个命令持续到下一个命令,就像 Python REPL 一样。
script-here
当在行内使用脚本语言时,你可能希望在不支持该语言时跳过它。
if has('python')
  python << EOF
    print("python works")
EOF
endif
请注意,"EOF" 必须在行的开头,前面没有空格。

vim 模块 python-vim

Python 代码通过 "vim" 模块获得对 vim 的所有访问权限(有一个例外 - 请参见下面的 python-output)。vim 模块实现了两种方法、三个常量和一个错误对象。你需要在使用它之前导入 vim 模块
:python import vim
概述
:py print("Hello")                # displays a message
:py vim.command(cmd)                # execute an Ex command
:py w = vim.windows[n]                # gets window "n"
:py cw = vim.current.window        # gets the current window
:py b = vim.buffers[n]                # gets buffer "n"
:py cb = vim.current.buffer        # gets the current buffer
:py w.height = lines                # sets the window height
:py w.cursor = (row, col)        # sets the window cursor position
:py pos = w.cursor                # gets a tuple (row, col)
:py name = b.name                # gets the buffer file name
:py line = b[n]                        # gets a line from the buffer
:py lines = b[n:m]                # gets a list of lines
:py num = len(b)                # gets the number of lines
:py b[n] = str                        # sets a line in the buffer
:py b[n:m] = [str1, str2, str3]        # sets a number of lines at once
:py del b[n]                        # deletes a line
:py del b[n:m]                        # deletes a number of lines
"vim" 模块的方法
vim.command(str) python-command
执行 vim(ex 模式)命令 str。返回 None。示例
:py vim.command("set tw=72")
:py vim.command("%s/aaa/bbb/g")
以下定义执行 Normal 模式命令
def normal(str):
        vim.command("normal "+str)
# Note the use of single quotes to delimit a string containing
# double quotes
normal('"a2dd"aP')
vim.eval(str) python-eval
使用 vim 内部表达式评估器(参见 expression)评估表达式 str。以以下形式返回表达式结果
如果 Vim 表达式评估为字符串或数字,则为字符串
如果 Vim 表达式评估为 Vim 列表,则为列表
如果 Vim 表达式评估为 Vim 字典,则为字典字典和列表被递归地展开。示例
:py text_width = vim.eval("&tw")
:py str = vim.eval("12+12")                # NB result is a string! Use
                                    # int() to convert to a
                                    # number.
vim.strwidth(str) python-strwidth
strwidth() 相似:返回 str 占用的显示单元数,tab 计为一个单元。
vim.foreach_rtp(callable) python-foreach_rtp
'runtimepath' 中的每个路径调用给定的可调用对象,直到可调用对象返回除 None 之外的任何东西,或者抛出异常,或者不再有路径。如果在可调用对象返回非 None 时停止,则 vim.foreach_rtp 函数返回可调用对象返回的值。
vim.chdir(*args, **kwargs) python-chdir
vim.fchdir(*args, **kwargs) python-fchdir
运行 os.chdir 或 os.fchdir,然后运行所有相应的 vim 内容。注意:你不应该直接使用这些函数,而应该使用 os.chdir 和 os.fchdir。如果 os.fchdir 不存在,则 vim.fchdir 的行为未定义。
"vim" 模块的错误对象
vim.error python-error
遇到 Vim 错误时,Python 会抛出一个类型为 vim.error 的异常。示例
try:
        vim.command("put a")
except vim.error:
        # nothing in register a
"vim" 模块的常量
请注意,这些实际上并不是常量 - 你可以重新分配它们。但这样做很愚蠢,因为这样你将失去对变量所引用的 vim 对象的访问权限。
vim.buffers python-buffers
一个映射对象,提供对 vim 缓冲区列表的访问。该对象支持以下操作
:py b = vim.buffers[i]        # Indexing (read-only)
:py b in vim.buffers        # Membership test
:py n = len(vim.buffers)        # Number of elements
:py for b in vim.buffers:        # Iterating over buffer list
vim.windows python-windows
一个序列对象,提供对 vim 窗口列表的访问。该对象支持以下操作
:py w = vim.windows[i]        # Indexing (read-only)
:py w in vim.windows        # Membership test
:py n = len(vim.windows)        # Number of elements
:py for w in vim.windows:        # Sequential access
注意:vim.windows 对象始终访问当前标签页。python-tabpage.windows 对象绑定到父 python-tabpage 对象,并始终使用来自该标签页的窗口(或者在标签页被删除时抛出 vim.error)。你可以在不保留对 vim 模块对象或 python-tabpage 的引用的情况下保留对两者的引用,它们在这种情况下不会失去其属性。
vim.tabpages python-tabpages
一个序列对象,提供对 vim 标签页列表的访问。该对象支持以下操作
:py t = vim.tabpages[i]        # Indexing (read-only)
:py t in vim.tabpages        # Membership test
:py n = len(vim.tabpages)        # Number of elements
:py for t in vim.tabpages:        # Sequential access
vim.current python-current
一个对象,通过特定的属性提供对 vim 中可用的各种 "当前" 对象的访问:vim.current.line 当前行(RW)String vim.current.buffer 当前缓冲区(RW)Buffer vim.current.window 当前窗口(RW)Window vim.current.tabpage 当前标签页(RW)TabPage vim.current.range 当前行范围(RO)Range
最后一种情况需要解释一下。当 :python 或 :pyfile 命令指定一个范围时,这行范围将成为 "当前范围"。范围有点像缓冲区,但所有访问都限制在一个行的子集。有关更多详细信息,请参见 python-range
注意:当分配给 vim.current.{buffer,window,tabpage} 时,它期望分别有有效的 python-bufferpython-windowpython-tabpage 对象。分配会触发正常的(带有 autocommands)切换到给定的缓冲区、窗口或标签页。这是在 python 中切换 UI 对象的唯一方式:你不能分配给 python-tabpage.window 属性。要切换而不触发自动命令,请使用
py << EOF
saved_eventignore = vim.options['eventignore']
vim.options['eventignore'] = 'all'
try:
    vim.current.buffer = vim.buffers[2] # Switch to buffer 2
finally:
    vim.options['eventignore'] = saved_eventignore
EOF
vim.vars python-vars
vim.vvars python-vvars
字典类对象,分别保存带有全局 (g:) 和 vim (v:) 变量的字典。
vim.options python-options
部分支持映射协议(支持设置和获取项目)的对象,提供对全局选项的读写访问。注意::set 不同,它只提供对全局选项的访问。你不能使用此对象获取或设置局部选项的值,或以任何方式访问局部选项。如果不存在具有该名称的全局选项(即,对于 global-local 选项和仅全局选项不会引发 KeyError,但对于窗口和缓冲区局部选项会引发 KeyError),则会引发 KeyError。使用 python-buffer 对象访问缓冲区局部选项,使用 python-window 对象访问窗口局部选项。
此对象的类型可以通过 vim 模块的 "Options" 属性获得。
来自 Python 的输出 python-output
Vim 在 Vim 消息区域显示所有 Python 代码输出。正常输出显示为信息消息,错误输出显示为错误消息。
在实现方面,这意味着所有输出到 sys.stdout(包括来自 print 语句的输出)显示为信息消息,所有输出到 sys.stderr(包括错误跟踪)显示为错误消息。
python-input
不支持输入(通过 sys.stdin,包括 input() 和 raw_input()),并且可能导致程序崩溃。这可能应该被修复。
在 python 中,vim.VIM_SPECIAL_PATH 特殊目录用作 'runtimepath' 中找到的路径列表的替换:使用此目录作为 sys.path 和 vim.path_hooks 作为 sys.path_hooks,python 将尝试从 {rtp}/python3 和 {rtp}/pythonx 中加载模块,对于 'runtimepath' 中找到的每个 {rtp}
实现类似于以下内容,但用 C 编写
from imp import find_module, load_module
import vim
import sys
class VimModuleLoader(object):
    def __init__(self, module):
        self.module = module
    def load_module(self, fullname, path=None):
        return self.module
def _find_module(fullname, oldtail, path):
    idx = oldtail.find('.')
    if idx > 0:
        name = oldtail[:idx]
        tail = oldtail[idx+1:]
        fmr = find_module(name, path)
        module = load_module(fullname[:-len(oldtail)] + name, *fmr)
        return _find_module(fullname, tail, module.__path__)
    else:
        fmr = find_module(fullname, path)
        return load_module(fullname, *fmr)
# It uses vim module itself in place of VimPathFinder class: it does not
# matter for python which object has find_module function attached to as
# an attribute.
class VimPathFinder(object):
    @classmethod
    def find_module(cls, fullname, path=None):
        try:
            return VimModuleLoader(_find_module(fullname, fullname, path or vim._get_paths()))
        except ImportError:
            return None
    @classmethod
    def load_module(cls, fullname, path=None):
        return _find_module(fullname, fullname, path or vim._get_paths())
def hook(path):
    if path == vim.VIM_SPECIAL_PATH:
        return VimPathFinder
    else:
        raise ImportError
sys.path_hooks.append(hook)
vim.VIM_SPECIAL_PATH python-VIM_SPECIAL_PATH
与 vim 路径钩子一起使用的字符串常量。如果由 vim 安装的路径钩子被请求处理任何不等于 vim.VIM_SPECIAL_PATH 常量的内容,它会引发 ImportError。在其他唯一的情况下,它使用特殊的加载器。
注意:你不能直接使用此常量的值,始终使用 vim.VIM_SPECIAL_PATH 对象。
vim.find_module(...) python-find_module
vim.path_hook(path) python-path_hook
用于实现上述路径加载的方法或对象。你不应该直接使用这些方法或对象,除非你需要对 sys.meta_path 做些什么,则可以使用 vim.path_hook。不能保证在未来的 vim 版本中这些对象都会存在。
vim._get_paths python-_get_paths
返回路径列表的方法,路径钩子将搜索这些路径。你不应该依赖此方法在未来版本中存在,但可以将其用于调试。
它返回 'runtimepath' 中每个 {rtp}{rtp}/python3 和 {rtp}/pythonx 目录列表。

缓冲区对象 python-buffer

缓冲区对象代表 Vim 缓冲区。你可以通过多种方式获取它们
通过 vim.current.buffer (python-current)
通过索引 vim.buffers (python-buffers)
通过窗口的 "buffer" 属性 (python-window)
缓冲区对象有两个只读属性 - name - 缓冲区的完整文件名,以及 number - 缓冲区编号。它们还有三个方法(append、mark 和 range;见下文)。
你也可以将缓冲区对象视为序列对象。在这种情况下,它们的行为就像字符串列表(是的,它们是可变的),每个元素都是缓冲区中的一行。所有常见的序列操作,包括索引、索引赋值、切片和切片赋值,都按预期工作。请注意,对缓冲区进行索引(切片)的结果是一个字符串(字符串列表)。这有一个不同寻常的结果 - b[:] 与 b 不同。特别是,"b[:] = None" 会删除整个缓冲区,而 "b = None" 只是更新变量 b,对缓冲区没有影响。
缓冲区索引从零开始,这在 Python 中很常见。这与 Vim 行号不同,Vim 行号从 1 开始。这在处理使用 Vim 行号的标记(见下文)时尤其重要。
缓冲区对象属性如下: b.vars 字典状对象,用于访问 缓冲区变量。 b.options 映射对象(支持获取、设置和删除项目),提供对缓冲区局部选项和 全局-局部 选项的缓冲区局部值的访问。如果选项是窗口局部选项,请使用 python-window.options,此对象将引发 KeyError。如果选项是 全局-局部 且本地值缺失,则获取它将返回 None。 b.name 字符串,RW。包含缓冲区名称(完整路径)。 注意: 当为 b.name 赋值时,BufFilePreBufFilePost 自动命令会被启动。 b.number 缓冲区编号。可以用作 python-buffers 键。只读。 b.valid True 或 False。当对应的缓冲区被清除时,缓冲区对象会失效。
缓冲区对象方法如下: b.append(str) 将一行添加到缓冲区 b.append(str, nr) 同上,在 "nr" 行下方 b.append(list) 将一行列表添加到缓冲区 请注意,向 append 方法提供字符串列表的选项与 Python 内置列表对象的等效方法不同。 b.append(list, nr) 同上,在 "nr" 行下方 b.mark(name) 返回一个元组 (row,col),表示命名标记的位置(也可以获取 []"<>" 标记) b.range(s,e) 返回一个范围对象(见 python-range),它表示给定缓冲区中从行号 s 到 e 之间的部分 包含
请注意,在添加一行时,它不能包含换行符 '\n'。允许尾随的 '\n' 并且会被忽略,这样你就可以执行
:py b.append(f.readlines())
缓冲区对象类型可以使用 vim 模块的 "Buffer" 属性获得。
示例(假设 b 是当前缓冲区)
:py print(b.name)                # write the buffer file name
:py b[0] = "hello!!!"                # replace the top line
:py b[:] = None                        # delete the whole buffer
:py del b[:]                        # delete the whole buffer
:py b[0:0] = [ "a line" ]        # add a line at the top
:py del b[2]                        # delete a line (the third)
:py b.append("bottom")                # add a line at the bottom
:py n = len(b)                        # number of lines
:py (row,col) = b.mark('a')        # named mark
:py r = b.range(1,5)                # a sub-range of the buffer
:py b.vars["foo"] = "bar"        # assign b:foo variable
:py b.options["ff"] = "dos"        # set fileformat
:py del b.options["ar"]                # same as :set autoread<

范围对象 python-range

范围对象代表 Vim 缓冲区的一部分。你可以通过多种方式获取它们
通过 vim.current.range (python-current)
通过缓冲区的 range() 方法 (python-buffer)
范围对象在操作上与缓冲区对象几乎相同。但是,所有操作都限制在范围内的行(当然,这个行范围可能会因为切片赋值、行删除或 range.append() 方法而改变)。
范围对象属性如下: r.start 缓冲区中第一行的索引 r.end 缓冲区中最后行的索引
范围对象方法如下: r.append(str) 将一行添加到范围 r.append(str, nr) 同上,在 "nr" 行之后 r.append(list) 将一行列表添加到范围 请注意,向 append 方法提供字符串列表的选项与 Python 内置列表对象的等效方法不同。 r.append(list, nr) 同上,在 "nr" 行之后
范围对象类型可以使用 vim 模块的 "Range" 属性获得。
示例(假设 r 是当前范围): # 将范围内的所有行发送到默认打印机 vim.command("%d,%dhardcopy!" % (r.start+1,r.end+1))

窗口对象 python-window

窗口对象代表 Vim 窗口。你可以通过多种方式获取它们
通过 vim.current.window (python-current)
通过索引 vim.windows (python-windows)
通过索引标签页的 "windows" 属性 (python-tabpage)
通过标签页的 "window" 属性 (python-tabpage)
你只能通过窗口对象的属性来操作它们。它们没有方法,也没有序列或其他接口。
窗口属性如下: buffer (只读) 此窗口中显示的缓冲区 cursor (读写) 窗口中当前光标位置 这是一个元组,(row,col)。 height (读写) 窗口高度,以行为单位 width (读写) 窗口宽度,以列为单位 vars (只读) 窗口 w: 变量。属性不可赋值,但你可以通过这种方式更改窗口变量 options (只读) 窗口局部选项。属性不可赋值,但你可以通过这种方式更改窗口选项。仅提供对窗口局部选项的访问,对于缓冲区局部选项,请使用 python-buffer,对于全局选项,请使用 python-options。如果选项是 全局-局部 且本地值缺失,则获取它将返回 None。 number (只读) 窗口编号。第一个窗口的编号为 1。如果无法确定(例如,当窗口对象属于其他标签页时),则为零。 row, col (只读) 显示单元格中的屏幕窗口位置。第一个位置为零。 tabpage (只读) 窗口标签页。 valid (读写) True 或 False。当对应的窗口被关闭时,窗口对象会失效。
只有当屏幕水平分割时,height 属性才是可写的。只有当屏幕垂直分割时,width 属性才是可写的。
窗口对象类型可以使用 vim 模块的 "Window" 属性获得。

标签页对象 python-tabpage

标签页对象代表 Vim 标签页。你可以通过多种方式获取它们
通过 vim.current.tabpage (python-current)
通过索引 vim.tabpages (python-tabpages)
你可以使用此对象来访问标签页窗口。它们没有方法,也没有序列或其他接口。
标签页属性如下: number 与 tabpagenr() 返回的标签页编号相同。 windows 与 python-windows 相同,但用于当前标签页。 vars 标签页 t: 变量。 window 当前标签页窗口。 valid True 或 False。当对应的标签页被关闭时,标签页对象会失效。
TabPage 对象类型可以使用 vim 模块的 "TabPage" 属性获得。

pyeval() 和 py3eval() Vim 函数 python-pyeval

为了方便双向接口,你可以使用 pyeval()py3eval() 函数来计算 Python 表达式并将它们的值传递给 Vim 脚本。 pyxeval() 也可用。

Python 3 python3

由于 Python 3 是 Nvim 中唯一受支持的版本,因此在当前版本中,“python” 与 “python3” 是同义词。但是,旨在支持 Nvim 的旧版本以及 Vim 的代码,如果需要 Python 3,应该优先明确使用 “python3” 变体。
:py3 :python3 :[range]py3 {stmt} :[range]py3 << [trim] [{endmarker}] {script} {endmarker}
:[range]python3 {stmt} :[range]python3 << [trim] [{endmarker}] {script} {endmarker} :py3:python3 命令的工作原理与 :python 相似。一个简单的检查 :py3 命令是否正常工作的例子
:py3 print("Hello")
要查看你的 Python 版本
:py3 import sys
:py3 print(sys.version)
:py3file
:[range]py3f[ile] {file} :py3file 命令的工作原理与 :pyfile 相似。 :py3do
:[range]py3do {body} :py3do 命令的工作原理与 :pydo 相似。
E880
在 python 中引发 SystemExit 异常不是退出 vim 的推荐方式,请使用
:py vim.command("qall!")
has-python
你可以使用以下方法测试 Python 是否可用
if has('pythonx')
  echo 'there is Python'
endif
if has('python3')
  echo 'there is Python 3.x'
endif
Python 2 已不再受支持。因此,出于向后兼容性的原因,has('python') 始终返回零。

Python X python_x pythonx

"pythonx" 和 "pyx" 前缀是为与 Python 2.6+ 和 Python 3 一起工作的 python 代码引入的。由于 Nvim 仅支持 Python 3,因此所有这些命令现在都与它们的 “python3” 等效命令相同。
:pyx :pythonx :pyx:pythonx 的工作方式与 :python3 相同。要检查 :pyx 是否正常工作
:pyx print("Hello")
要查看正在使用哪个版本的 Python
:pyx import sys
:pyx print(sys.version)
:pyxfile python_x-special-comments :pyxfile 的工作方式与 :py3file 相同。
:pyxdo
:pyxdo 的工作方式与 :py3do 相同。
has-pythonx
要检查 pyx* 函数和命令是否可用
if has('pythonx')
  echo 'pyx* commands are available. (Python ' .. &pyx .. ')'
endif
命令索引
快速参考