if_pyth

if_pyth.txt 适用于 Vim 9.2 版本。 最近更新: 2026年2月 VIM 参考手册 by Paul Moore 译者: lang2、Willis Vim 的 Python 编程接口 python Python 1. 命令 python-commands 2. vim 模块 python-vim 3. 缓冲区对象 python-buffer 4. 范围对象 python-range 5. 窗口对象 python-window 6. 标签页对象 python-tabpage 7. vim.bindeval 对象 python-bindeval-objects 8. pyeval()、py3eval() Vim 函数 python-pyeval 9. 动态调入 python-dynamic 10. Python 3 python3 11. Python X python_x 12. 编译时带 Python 支持 python-building Vim 的 Python 2.x 接口仅当 Vim 编译时加入 +python 特性时才可用。 Vim 的 Python 3 接口仅当 Vim 编译时加入 +python3 特性时才可用。 可以同时使用两种接口,但请先阅读 python-2-and-3备注: Python 2 太过老旧,也不再开发。强烈推荐使用 Python 3。如果 Python 2 支持 无法继续工作,有朝一日它将被彻底移除。

1. 命令 python-commands

:python :py E263 E264 E887 :[range]py[thon] {stmt} 执行 Python 语句 {stmt}。判断 ":python" 命令是否可用的 简单检查: :python print "Hello" :[range]py[thon] << [trim] [{endmarker}] {script} {endmarker} 执行 Python 脚本 {script}备注: 如果编译时未加入 Python 特性,此命令不能工作。要 避免错误,见 script-here 。 如果在 "<<" 之后省略了 [endmarker]{script} 结束后必须加上一个句号 '.',类似 于 :append:insert 命令。详见 :let-heredoc 。 这种形式的 :python 命令主要用于在 Vim 脚本中嵌入 Python 代码。 示例: 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.python.org/3/library/os.html#os.environ 备注: Python 对于缩进非常敏感。上命名中,请确保 "class" 所在行及 "EOF" 不使用 任何缩进。 :pydo :[range]pydo {body}[range] 行范围的每行执行 Python 函数 "def _vim_pydo(line, linenr): {body}",其中,函数参数 line 为每行的文本,不包含行尾的 <EOL>,linenr 为该行行 号。函数应该返回字符串或者 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} 执行 Python 文件 {file} 中的脚本。整个参数被用作单个文 件名。 以上命令本质上在做同样一件事 - 执行一段 Python 代码。并将 "当前范围" python-range 设为给定的行范围。 :python 执行的代码来自命令行。 :pyfile 执行的代码来自给定文件的内容。 不能在 sandbox 里使用 Python 命令。 要传递参数时,需要使用 sys.argv[]。例如: :python sys.argv = ["foo", "bar"] :pyfile myscript.py 下面是一些例子 python-examples :python from vim import * :python from string import upper :python current.line = upper(current.line) :python print "Hello" :python str = current.buffer[42] (注意 这些修改 (如 import 语句) 对后续命令持续有效。这和 Python 解释程序的工作 方式相同。)

2. vim 模块 python-vim

Python 代码中所有对 Vim 的访问 (只有一个例外 - 看下面的 python-output ) 都是 通过 "vim" 模块来进行的。该模块包括两个方法、三个常量、以及一个异常对象。在使 用它们之前,必须先导入 (import) vim 模块: :python import vim 总览 :py print "Hello" # 显示消息 :py vim.command(cmd) # 执行 Ex 命令 :py w = vim.windows[n] # 获取窗口 "n" :py cw = vim.current.window # 获取当前窗口 :py b = vim.buffers[n] # 获取缓冲区 "n" :py cb = vim.current.buffer # 获取当前缓冲区 :py w.height = lines # 设置窗口高度 :py w.cursor = (row, col) # 设置光标位置 :py pos = w.cursor # 获取元组 (行,列) :py name = b.name # 获取缓冲区的文件名 :py line = b[n] # 获取缓冲区内的一行 :py lines = b[n:m] # 获取多行 :py num = len(b) # 获取统计的行数 :py b[n] = str # 在缓冲区里写入一行文本 :py b[n:m] = [str1, str2, str3] # 一次性写入多行文本 :py del b[n] # 删除一行 :py del b[n:m] # 删除多行 "vim" 模块中的方法 vim.command(str) python-command 执行 vim (ex-模式) 命令 str。返回 None。 例如: :py vim.command("set tw=72") :py vim.command("%s/aaa/bbb/g") 可用以下函数定义来执行普通模式命令: def normal(str): vim.command("normal "+str) # 注意使用了单引号来界定含有双引号的字符串 normal('"a2dd"aP') E659 在 Python 2.2 及之前版本上,不能嵌套使用 ":python"。以下命令仅适用于 Python 2.3 或之后版本: :py vim.command("python print 'Python 我又来了'") vim.eval(str) python-eval 使用 vim 内部表达式处理器来计算表达式 str (参阅 expression )。返回表 达式的计算结果: -计算结果是字符串或者数值时,返回字符串 -计算结果是 Vim list 时,返回列表 -计算结果是 Vim tuple 时,返回元组 -计算结果是 Vim dict 时,返回字典 -计算结果是 v:truev:false 时,返回布尔型 -计算结果是 v:nullv:none 时,返回 None 字典、列表和元组被递归扩展。 示例: :" 'textwidth' 选项值 :py text_width = vim.eval("&tw") : :" 'a' 寄存器的内容 :py a_reg = vim.eval("@a") : :" 计算结果以字符串形式返回!要转换成数值,可用 string.atoi()。 :py str = vim.eval("12+12") : :py tuple = vim.eval('(1, 2, 3)') : :py tagList = vim.eval('taglist("eval_expr")') 最后一例将返回 python 类型的字典列表,例如: [{'cmd': '/^eval_expr(arg, nextcmd)$/', 'static': 0, 'name': 'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}] 注意: Vim9 脚本里,def 函数里的局部变量在 python 计算环境里不可见。要 把这些局部变量传递给 python 参与计算,可在调用 py3eval() 及类似函数 时,使用 {locals} 字典。 vim.bindeval(str) python-bindeval python-eval 类同,但会返回 python-bindeval-objects 中描述的特殊 对象。这些 python 对象可用于修改 ( ListTupleDictionary ) 或 调用 ( Funcref ) vim 对象。 vim.strwidth(str) python-strwidth 相当于 strwidth() : 返回 str 占据的显示单元数,制表符算作一个单元。 vim.foreach_rtp(callable) python-foreach_rtp 对于 'runtimepath' 中的每个路径,都会调用指定的 callable,直到某次 callable 返回非 None 值、抛出异常、或者没有更多的路径为止。如果是因为 callable 返回非 None 值而停止,本函数会返回 callable 的返回值。 vim.chdir(*args, **kwargs) python-chdir vim.fchdir(*args, **kwargs) python-fchdir 运行 os.chdir 或 os.fchdir,然后再完成 vim 端相应的操作。 备注: 不应直接调用这些函数,应使用 os.chdir 或 os.fchdir 代替 (译者注: 这里似应理解为不应调用 os.*,而应改用 vim.* 代替)。如果 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] # 索引 (只读) :py b in vim.buffers # 成员测试 :py n = len(vim.buffers) # 成员个数 :py for b in vim.buffers: # 遍历缓冲区列表 vim.windows python-windows 提供 vim 窗口访问的序列对象。该对象支持以下操作: :py w = vim.windows[i] # 索引 (只读) :py w in vim.windows # 成员测试 :py n = len(vim.windows) # 成员个数 :py for w in vim.windows: # 顺序存取 注意: vim.windows 对象总是访问当前标签页。而 python-tabpage .windows 对象和其父 python-tabpage 对象绑定,因此总是会使用该标签页里的窗口 (如果该标签页被删除,会抛出 vim.error)。可以直接保存这两者的引用,而无 需保存 vim 模块对象或 python-tabpage 的引用。这些对象的属性不会因此 丢失。 vim.tabpages python-tabpages 提供 vim 标签页访问的序列对象。该对象支持以下操作: :py t = vim.tabpages[i] # 索引 (只读) :py t in vim.tabpages # 成员测试 :py n = len(vim.tabpages) # 成员个数 :py for t in vim.tabpages: # 顺序存取 vim.current python-current 提供用于访问各种 "当前" 对象的对象。该对象包含若干特定属性: vim.current.line 当前行 (可读写) 字符串 vim.current.buffer 当前缓冲区 (可读写) 缓冲区 vim.current.window 当前窗口 (可读写) 窗口 vim.current.tabpage 当前标签页 (可读写) 标签页 vim.current.range 当前行范围 (只读) 范围 最后一种情况需要额外解释一下。使用 :python 或 :pyfile 命令时如果指定了 范围,该范围将成为 "当前范围"。范围如同缓冲区,只不过操作的对象局限于 部分行。请参阅 python-range注意: 将值赋给 vim.current.{buffer,window,tagpage} 时,分别需要提供合 法的 python-bufferpython-windowpython-tabpage 对象。赋值操 作会触发到指定缓冲区、窗口、标签页的正常切换 (同时会执行相应的 autocommand 自动命令)。在 python 里,这是切换 UI 对象的唯一方法: 不 能直接给 python-tabpage .window 属性赋值来切换窗口。要想进行切换但不 执行自动命令,可用 py << EOF saved_eventignore = vim.options['eventignore'] vim.options['eventignore'] = 'all' try: vim.current.buffer = vim.buffers[2] # 切换到缓冲区 2 finally: vim.options['eventignore'] = saved_eventignore EOF vim.vars python-vars vim.vvars python-vvars 分别对应全局 ( g: ) 和 vim ( v: ) 变量的类字典对象。等价于 vim.bindeval("g:") ,但效率更高。 vim.options python-options 部分支持映射协议 (即读写子项目) 的对象,用于对全局选项进行读写访问。 注意: 和 :set 不同,此对象只能访问全局选项,不能用于读写局部变量值或 以任何其他方式访问局部专用变量。如果没有指定名字的全局变量,会抛出 KeyError (换句话说,对于 global-local 或仅限全局的选项,不会抛出异 常,但如果是局部于窗口或缓冲区的选项,则会)。 python-buffer 对象可用 于访问局部于缓冲区的选项, python-window 选项则可用于访问局部于窗口的 选项。 vim 模块的 "Options" 属性会返回此对象的类型。 Python 的输出 python-output 所有 Python 代码的输出都会显示在 Vim 的信息区。普通输出会以一般信息出 现,而错误会以出错信息出现。 用具体实现的术语来讲,这表示所有 sys.stdout (包括 print 语句的输出) 会 以一般信息形式出现,而所有 sys.stderr (包括 error tracebacks) 都会被显 示为出错信息。 python-input Vim 并不支持通过 Python (例如通过 sys.stdin,包括 input() 和 raw_input()) 进行输入。这些调用可能会导致系统崩溃。这个问题可能以后会 修正。 python2-directory python3-directory pythonx-directory Python 'runtimepath' 处理 python-special-path 在 python 中,vim.VIM_SPECIAL_PATH 特殊目录用于代替 'runtimepath' 里的路径列 表: 因为 sys.path 包含此目录而 sys.path_hooks 也包含 vim.path_hooks,python 会 试图载入 'runtimepath' 里的每个 {rtp}{rtp}/python2 (或 python3) 和 {rtp}/pythonx (同时支持两个 python 版本) 里的模块 (备注: 从 Python 3.12.0a7 开始,imp 模块的 find_module() 已被删除)。 实现大致如下,但以 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.modul嗯e 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) # 它直接使用 vim 模块本身来代替 VimPathFinder 类:对于 Python 来说,哪个对 # 象附加了 find_module 函数作为属性并不重要。 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.VIM_SPECIAL_PATH 对象。 vim.find_module(...) python-find_module vim.path_hook(path) python-path_hook vim.find_spec(...) python-find_spec 用于实现上述路径加载的方法或对象。除非为了直接操作 sys.meta_path 而想 了解 vim.path_hook,否则不应直接使用它们,从 Python 3.7 版本开始,可用 vim.find_spec() 进行模式查找。 未来 vim 版本不保证这里描述的任何对象仍然存在。 vim._get_paths python-_get_paths 用于产生路径钩搜索使用的路径列表的方法。可以用于调试,但不要假定未来 vim 版本中此方法仍然存在。 返回 'runtimepath' 中每个 {rtp} 对应的 {rtp}/python2 (或 {rtp}/python3) 和 {rtp}/pythonx 这些目录组成的列表。

3. 缓冲区对象 python-buffer

缓冲区对象代表 vim 缓冲区。可用以下几种办法获取: - 通过 vim.current.buffer ( python-current ) - 通过 vim.buffers 的索引访问 ( python-buffers ) - 通过一个窗口的 "buffer" 属性 ( python-window ) 缓冲区对象有两个只读属性 - name - 缓冲区文件全名,还有 number - 缓冲区号。该对 象还包括三个方法 (append,mark 及 range;见下)。 缓冲区对象也可被当作序列对象来使用。在此上下文下,可将其视作字符串列表,并可进 行读写 (即,这是可变列表)。每一个列表项对应缓冲区中的一行文本。可以进行所有常 用的序列存取操作,包括索引访问,索引赋值,切片 (slice) 及切片赋值等等。注意 索 引 (切片) 操作的结果是字符串 (或字符串列表)。这产生了一个意想不到的结果 - b[:] 和 b 是不同的。更准确地说,"b[:] = None" 会清空整个缓冲区,而 "b = None" 仅仅 更新变量 b 的值,完全不会影响到缓冲区。 缓冲区索引从 0 开始算起,这与通常的 Python 语法一致。但这和 Vim 的行号从 1 算 起有分歧。这一点在处理标记 (见下) 时要特别留意,因为标记使用 Vim 行号记法。 缓冲区对象的属性有: b.vars 类字典对象,可用于访问 buffer-variable 。 b.options 映射对象 (支持子项目的读写和删除),用于访问局部于缓冲 区的选项和 global-local 选项的缓冲区局部值。如果选项 局部于窗口,请使用 python-window .options,使用本对象 会抛出 KeyError。用于 global-local 选项但没有局部值 时,返回 None。 b.name 字符串,可读写。包含缓冲区名 (完整路径)。 备注: 给 b.name 赋值时会触发 BufFilePreBufFilePost 自动事件。 b.number 缓冲区编号。可用作 python-buffers 的键。只读。 b.valid True 或 False。缓冲区被删除 (wipe) 后,对应的缓冲区对 象会成为无效 (即本属性为 False)。 缓冲区对象的方法有: b.append(str) 在缓冲区末尾位置之后追加一行文本 b.append(str, nr) 同上,但在第 "nr" 行之后 b.append(list) 在缓冲区末尾位置之后追加一系列行文本 备注: append 方法可以带一个字符串列表作为参数,这和 Python 中内建的列表对象的对应方法不同 (内建列表使用 append 来追加单个项目,extend 来追加项目列表)。 b.append(list, nr) 同上,但在第 "nr" 行之后 b.mark(name) 返回命名标记的所在位置,以元组 (行,列) 形式表示 (也可 用于 []"<> 等标记) b.range(s,e) 返回范围对象 (参见 python-range ),用来代表指定缓冲区 中行 s 与 行 e (包含 s 和 e inclusive ) 之间的部分。 注意: 追加一行文本时,文本不应包含换行符 '\n'。拖尾的 '\n' 可以接受但会被忽 略。因此,以下操作合法: :py b.append(f.readlines()) vim 模块的 "Buffer" 属性会返回缓冲区对象的类型。 例如 (假定 b 是当前缓冲区) :py print b.name # 输出缓冲区的名字 :py b[0] = "hello!!!" # 替换顶行文本 :py b[:] = None # 删除整个缓冲区 :py del b[:] # 删除整个缓冲区 :py b[0:0] = [ "a line" ] # 在第一行前添加一行 :py del b[2] # 删除第三行 :py b.append("bottom") # 在缓冲区结尾添加一行 :py n = len(b) # 总行数 :py (row,col) = b.mark('a') # 命名标记 :py r = b.range(1,5) # 缓冲区内的子范围 :py b.vars["foo"] = "bar" # 给 b:foo 变量赋值 :py b.options["ff"] = "dos" # 设置 fileformat :py del b.options["ar"] # 同 :set autoread<

4. 范围对象 python-range

范围对象代表 vim 缓冲区内的一个部分。可用以下几种方法获取: - 通过 vim.current.range ( python-current ) - 通过缓冲区的 rOKange() 方法 ( python-buffer ) 范围对象和缓冲区对象可用的操作几乎完全相同。不过,其操作的目标仅作用于行范围 (当然,这个行范围会随着切片赋值,行删除,或者 range.append() 等等操作而改变)。 范围对象的属性有: r.start 首行在缓冲区内的索引 r.end 尾行在缓冲区内的索引 范围对象的方法有: r.append(str) 在范围末尾位置追加一行文本 r.append(str, nr) 同上,但在第 "nr" 行之后 r.append(list) 在范围末尾位置追加一系列行文本 备注: append 方法可以带一个字符串列表作为参数,这和 Python 中内建的列表对象的对应方法不同 (内建列表使用 append 来追加单个项目,extend 来追加项目列表)。 r.append(list, nr) 同上,但在第 "nr" 行之后 vim 模块的 "Range" 属性会返回范围对象的类型。 例如 (假设 r 是当前范围): # 发送范围内的所有行给缺省打印机 vim.command("%d,%dhardcopy!" % (r.start+1,r.end+1))

5. 窗口对象 python-window

窗口对象代表一个 vim 窗口。可用以下几种方法获取: - 通过 vim.current.window ( python-current ) - 通过对 vim.windows 的索引操作 ( python-windows ) - 通过对标签页的 "windows" 属性的索引操作 ( python-tabpage ) - 通过标签页的 "window" 属性 ( python-tabpage ) 只能通过窗口对象的属性来控制窗口。此类对象不提供方法,也没有序列等其它接口。 窗口的属性包括: buffer (只读) 窗口中显示的缓冲区 cursor (读写) 窗口中的当前光标位置,采用元组 (行,列) 形式 height (读写) 窗口高度,以行数计 width (读写) 窗口宽度,以列数计 vars (只读) 窗口 w: 变量。不能给本属性赋值,但可以用此属 性修改窗口变量 options (只读) 局部于窗口的选项。不能给本属性赋值,但可以用此 属性修改窗口选项。只能用于访问局部于窗口的选 项,对局部于缓冲区的选项要用 python-buffer , 对全局选项用 python-options 。用于 global-local 选项但没有局部值时,返回 None。 number (只读) 窗口编号。首个窗口的编号为 1。无法决定时返回 0 (如当窗口对象属于其他标签页时)。 row、col (只读) 窗口在屏幕上的位置,以显示单元计。首行或首列返 回零。 tabpage (只读) 窗口的标签页。 valid (读写) True 或 False。窗口被关闭后,对应的窗口对象会 成为无效 (即本属性为 False)。 height 属性仅当窗口被水平分割时才可写。 width 属性仅当窗口被垂直分割时才可写。 vim 模块的 "Window" 属性会返回窗口对象的类型。

6. 标签页对象 python-tabpage

标签页对象代表一个 vim 标签页。可用以下几种方法获取: - 通过 vim.current.tabpage ( python-current ) - 通过对 vim.tabpages 的索引操作 ( python-tabpages ) 可以通过该对象来访问标签页里的窗口。此类对象不提供方法,也没有序列等其它接口。 标签页的属性包括: number 标签页编号,和 tabpagenr() 相同。 windows 类似于 python-windows ,但对应当前标签页。 vars 标签页 t: 变量。 valid True 或 False。标签页被关闭后,对应的标签页对象会成为 无效 (即本属性为 False)。 vim 模块的 "TabPage" 属性会返回标签页对象的类型。

7. vim.bindeval 对象 python-bindeval-objects

vim.Dictionary 对象 python-Dictionary 类字典对象,用于访问 vim Dictionary 类型。 属性: 属性 描述 locked 以下值之一 python-.locked 值 描述 zero 变量没有上锁 vim.VAR_LOCKED 变量已上锁,但可以解锁 vim.VAR_FIXED 变量已上锁,且不可以解锁 读写。可以通过给本属性赋值 TrueFalse 来给变量解锁。 不支持递归上锁。 scope 以下值之一 值 描述 zero 字典无作用域 vim.VAR_DEF_SCOPE g:l: 字典 vim.VAR_SCOPE 其他作用域的字典, 见 internal-variables 方法 (备注: 这些方法不支持关键字参数): 方法 描述 keys() 返回字典所有键的列表。 values() 返回字典所有值的列表。 items() 返回字典所有内容的二元组 (键, 值) 组成的列表。 update(iterable)、update(dictionary)、update(**kwargs) 把新的键值加入字典。 get(key[, default=None]) 从字典中读入 key 对应值,如果不存在返回 default。 pop(key[, default]) 从字典中删除给定 key 并返回对应值。如果找不到 key,给出 default 时会返回 default,不然会抛出 KeyErrror。 popitem() 从字典中删除随机键,并返回 (键, 值) 对。 has_key(key) 检查字典中是否包含给定的键 key,类似于 `key in dict`。 __new__(), __new__(iterable), __new__(dictionary), __new__(update) 可用 vim.Dictionary() 建立新 vim 字典。 d=vim.Dictionary(arg) 等价于 d=vim.bindeval('{}');d.update(arg) 。无参数的版本会构建空 字典。 示例: d = vim.Dictionary(food="bar") # 构造函数 d['a'] = 'b' # 子项目赋值 print d['a'] # 读取子项目 d.update({'c': 'd'}) # .update(dictionary) d.update(e='f') # .update(**kwargs) d.update((('g', 'h'), ('i', 'j'))) # .update(iterable) for key in d.keys(): # .keys() for val in d.values(): # .values() for key, val in d.items(): # .items() print isinstance(d, vim.Dictionary) # True for key in d: # 遍历所有键 class Dict(vim.Dictionary): # 子类 注意: 遍历键时不应对字典进行修改。 vim.List 对象 python-List 类序列对象,用于访问 vim List 类型。 支持 .locked 属性,见 python-.locked 。还支持以下方法: 方法 描述 extend(item) 为列表加入项目列表 item。 __new__(), __new__(iterable) 可用 vim.List() 建立新 vim 列表。 l=vim.List(iterable) 等价于 l=vim.bindeval('[]');l.extend(iterable) 。无参数的版 本会构建空列表。 示例: l = vim.List("abc") # 构造函数,返回: ['a', 'b', 'c'] l.extend(['abc', 'def']) # .extend() 方法 print l[1:] # 切片 (slicing) l[:0] = ['ghi', 'jkl'] # 切片赋值 print l[0] # 读取项目 l[0] = 'mno' # 赋值 for i in l: # 遍历 print isinstance(l, vim.List) # True class List(vim.List): # 子类 vim.Tuple 对象 python-Tuple 类序列对象,用于访问 vim Tuple 类型。 支持 .locked 属性,见 python-.locked 。还支持以下方法: 方法 描述 __new__(), __new__(iterable) 可用 vim.Tuple() 建立新 vim 元组。 无参数的版本会构建空列表 (译者注: 原文如此,应为空元 组)。 示例: t = vim.Tuple("abc") # 构造函数,返回: ('a', 'b', 'c') print t[1:] # 切片 print t[0] # 读取项目 for i in t: # 遍历 print isinstance(t, vim.Tuple) # True class Tuple(vim.Tuple): # 子类 vim.Function 对象 python-Function 类函数对象,相当于 vim Funcref 对象。接受特殊关键字参数 self ,见 Dictionary-function 。也可用 vim.Function(name) 构造函数,等价于 vim.bindeval('function(%s)'%json.dumps(name)) 。 属性 (只读): 属性 描述 name 函数名。 args None 或用作参数的 python-List 对象。注意 这是参数列表 的备份,每次请求该属性时都会重新构建。对此列表的修改会被 忽略 (但不适用于参数列表里的容器: 类似于 copy() 而不是 deepcopy() )。 self None 或用作 self 字典的 python-Dictionary 对象。注意 调用函数对象时,显式提供的 self 参数会覆盖此属性。 auto_rebind 布尔值。如果由此 Python 对象创建的偏函数存储在 Vim 脚本字 典中,当将该偏函数赋值给其他字典并调用时,它会自动绑定到 新字典上,则此属性值为 True。这体现了 Vim 内部 dict.func (auto_rebind=True) 和 function(dict.func,dict) (auto_rebind=False) 的差异。见 Partial 。如果 self 属性为 None ,此属性无意义。 构造函数额外接受 argsselfauto_rebind 关键字。给出 args 和/或 self 参数时,会构造偏函数,见 function() 。仅当给定 self 时才会使用 auto_rebind ,否则无论是否给出,总是假定其为 True 。给出 self 时,缺省 auto_rebindFalse 。 示例: f = vim.Function('tr') # 构造函数 print f('abc', 'a', 'b') # 调用 tr('abc', 'a', 'b') vim.command(''' function DictFun() dict return self endfunction ''') f = vim.bindeval('function("DictFun")') print f(self={}) # 相当于 # call('DictFun', [], {}) print isinstance(f, vim.Function) # True p = vim.Function('DictFun', self={}) print f() p = vim.Function('tr', args=['abc', 'a']) print f('b')

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

pyeval()py3eval() 函数提供了反向接口。它们用于计算 Python 表达式,并将 计算结果返回给 Vim 脚本。为此,也可用 pyxeval() 。 可选的 {locals} 字典在计算时可用于注入局部变量。这对 vim9script 尤其有用,因为 那里 def 定义的函数内部的局部变量 对 vim.eval python-eval 不可见。 Python "None" 值返回时会被转换为 v:none。

9. 动态调入 python-dynamic

MS-Windows 和 Unix 上,可动态调入 Python 库。此时, :version 输出会包含 +python/dyn+python3/dyn 。 此时,Vim 仅在必要时才会寻找 Python DLL 文件或共享库。不使用 Python 接口时,就 不需要库文件。因此,即使没有这些文件,仍然可以使用 Vim。 MS-Windows 要使用 Python 接口,必须确保 Python DLL 位于系统搜索路径中。可以在控制台窗口里 输入 "path",查看当前使用的搜索路径。如果搜索路径上找不到 DLL,Vim 会检查注册 表以寻找 Python 安装的位置。也可用 'pythondll''pythonthreedll' 选项指定 Python DLL 的位置。 DLL 的版本必须和 Vim 编译时使用的 Python 版本保持一致。写作本文档时,用于 Python 2 的名字为 "python27.dll",对应 Python 2.7。用于 Python 3 的是 python36.dll (Python 3.6)。要确信这一点,可编辑 "gvim.exe" 文件,并查找 "python\d*.dll\c"。 Unix 可用 'pythondll''pythonthreedll' 选项指定 Python 共享库文件的位置,替代编 译时指定的 DYNAMIC_PYTHON_DLL 或 DYNAMIC_PYTHON3_DLL 文件。共享库的版本必须和 Vim 编译使用的 Python 2.x 或 Python 3 版本 ( v:python3_version ) 保持一致,但 另见 python3-stable-abi稳定 ABI 以及混合 Python 版本 python-stable python-stable-abi python3-stable-abi 如果 Vim 编译时不使用稳定 ABI (仅限于 Python 3),Python 共享库的版本必须与 Vim 编译时的版本一致。不然,使用不同版本的混合会导致无法预测的崩溃和错误。如果用了 稳定 ABI,此限制可放宽,可以使用任何不低于 v:python3_version 的 Python 3 库 版本。要检查是否有稳定 ABI 的支持,参见 has-python ,也可查看 :version 的输 出里是否包含 +python3/dyn-stable 。 MS-Windows 上,'pythonthreedll' 会被设为 "python3.dll"。在注册表里查找 DLL 时,Vim 会查找 Python 的最新版本。

10. 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 类同。 可用四种方式编译 Vim (对应的 :version 输出结果): 1. 无 Python 支持 (-python、-python3) 2. 只有 Python 2 支持 (+python 或 +python/dyn、-python3) 3. 只有 Python 3 支持 (-python、+python3 或 +python3/dyn) 4. Python 2 和 3 支持 (+python/dyn、+python3/dyn) 关于第四种特殊情况的更多细节: python-2-and-3 要同时支持 Python 2 和 Python 3,两者必须都是动态载入。 在 Linux/Unix 系统上,如果通过这种方式提供 Python 支持并且导入了全局符号,在加 载第二个 Python 版本时可能会导致系统崩溃。所以,要么加载全局符号,但只激活一个 Python 版本,要么不加载任何全局符号。如果选择后者,在 Python 导入 ("import") 期待由 Vim 提供全局符号的库时会失败。 E836 E837 Vim 的配置脚本会根据一个特定的 Python 标准库 (termios) 来推测当前可用的库版 本。如果在两个 Python 版本里都能成功导入该库,那么 Vim 中就可以同时使用两个版 本。否则在同一个会话中,只允许使用先用到的版本。使用第二个版本会得到 E836 或 E837 的错误信息。 在这种情况下,Vim 的行为取决于系统的配置方式。如果两个 Python 版本在配置时都使 用了 --enable-shared,那么他们可以同时被启用。不过,那些没有链接进 libPython 的第三方库仍然可能会出现问题。 要回避这些问题,有以下几个方案: 1. 重新编译有问题的库,链接进相应的 libpython.so 库。 2. 重新编译 Vim,并只用一个 Python 版本。 3. 配置完后,手动修改 auto/config.h,撤销其中 PY_NO_RTLD_GLOBAL 定义。不过,这 可能会导致 Vim 崩溃。 E880 从 python 抛出 SystemExit 异常并不是退出 vim 的推荐方法,这么做会报告此错误。 要退出 vim,建议使用: :py vim.command("qall!") E1266 如果 Python 3 无法载入必需的模块,会报告此错误。这通常意味着没有正确安装 Python 3,或者相关设置有问题。请检查以下项目: 1. 确认 Python 3 被正确安装。并检查 python 版本。 2. 检查 'pythonthreedll' 选项是否设置正确。 3. 检查 'pythonthreehome' 选项是否设置正确。 4. 如果未设置 'pythonthreedll',请检查 PATH 环境变量。 MS-Windows 上,可用 where.exe 来检查将被加载的 dll 版本。例如 where.exe python310.dll 5. 检查 PYTHONPATH 和 PYTHONHOME 环境变量是否配置正确。 has-python 可用以下方法来测试哪个 Python 版本可用: if has('python') echo '有 Python 2.x' endif if has('python3') echo '有 Python 3.x' endif 注意 不过,当 Python 2 和 3 同时存在且都是动态载入时,这些 has() 调用会试图同 时载入两者。如果两个版本无法同时载入,仅仅检查 Python 2 或 3 是否可用,就会导 致另一个版本无法被加载。 如果只想检查 Vim 编译时是否有 python 支持,但避免载入动态库: if has('python_compiled') echo '编译时带 Python 2.x 支持' if has('python_dynamic') echo 'Python 2.x 已动态载入' endif endif if has('python3_compiled') echo '编译时带 Python 3.x 支持' if has('python3_dynamic') echo 'Python 3.x 已动态载入' endif endif 动态载入库时,Vim 在编译阶段也可选择支持 Python 3 稳定 ABI ( python3-stable-abi ),启用该支持后,Vim 可以载入和编译时所用版本不同的 Python 3 版本。要检查是否有此支持: if has('python3_dynamic') if has('python3_stable') echo '支持 Python 3 稳定 ABI。' else echo '不支持 Python 3 稳定 ABI。' echo '只支持 Python 3 版本 ' .. v:python3_version endif endif 这段代码也会报告 Python 是否成功被动态载入,如果找不到运行库,会报错。

11. Python X python_x pythonx

大多数 python 代码可以以同时兼容 Python 2.6+ 和 Python 3 的方式编写,为此,Vim 提供了 pyx+ 函数和命令。其工作方式和 Python 2 和 3 变种完全相同,但会根据 'pyxversion' 设置,自动选择使用的 Python 版本。 应在 .vimrc 中设置 'pyxversion',以为 Python 命令选择使用 Python 2 或 Python 3。如果在运行时改变此设置,可能会冒丢失插件状态 (如初始化状态) 的风险。 要用的模块可放在 {rtp}/pythonx 目录里。见 pythonx-directory :pyx :pythonx :pyx:pythonx 命令的工作方式类似于 :python 。要看 :pyx 命令是否可用 的简单检查: :pyx print("Hello") 要查看运行中的 Python 版本: :pyx import sys :pyx print(sys.version) :pyxfile python_x-special-comments :pyxfile 命令的工作方式类似于 :pyfile 。不过,可以加上以下注释之一,强制 Vim 使用 :pyfile:py3file 方式: #!/任何字符串/python2 " Shebang。必须是文件的首行。 #!/任何字符串/python3 " Shebang。必须是文件的首行。 # requires python 2.x " 检查的最大行数取决于 'modelines'。 # requires python 3.x " 检查的最大行数取决于 'modelines'。 和普通模式行不同,这里不会检查文件尾部。如果找不到相应的注释,则使用 'pyxversion' 的设置值。 W20 W21 如果 Vim 不支持所选的 Python 版本,安静地打印一行消息。用 :messages 可读该消 息。 :pyxdo :pyxdo 命令的工作方式类似于 :pydo has-pythonx 要测试 pyx* 系列命令是否可用,可执行: if has('pythonx') echo 'pyx* 命令可用。(Python ' .. &pyx .. ')' endif 编译时只给出 +python+python3 之一 时,此 has() 会返回 1。 编译时同时给出 +python+python3 时,此测试结果取决于 'pyxversion' 设 置。如果 'pyxversion' 为 0,先测试 Python 3,如果不可用,再测试 Python 2。如果 'pyxversion' 为 2 或 3,只测试对应的 Python 2 或 3。 注意 为了使 `has('pythonx')` 能工作,Vim 可能会试图动态载入 Python 3 或 2。当 Vim 无法同时加载两个版本时。这可能会有副作用。 如果用户希望首选 Python 2 而使用 Python 3 作后备,需要在 .vimrc 里显式设置 'pyxversion'。例如: if has('python') set pyx=2 elseif has('python3') set pyx=3 endif

12. 编译时带 Python 支持 python-building

编译时要加入 Python 2 或 3 支持,以下给出若干提示。 UNIX 关于如何打开 Python 接口的支持,见 src/Makefile。 Ubuntu 上需要为 Python 2 安装以下包: python python-dev Python 3: python3 python3-dev Python 3.6: python3.6 python3.6-dev 如果有多于一个 Python 3 版本,在运行 configure 前,应将 python3 符号链接到选中 的版本。

vim:tw=78:ts=8:noet:ft=help:norl: