前言

vim是个伟大的编辑器,不仅在于她特立独行的编辑方式,还在于她强大的扩展能力。然而,vim自身用于写插件的语言vimL功能有很大的局限性,实现功能复杂的插件往往力不从心,而且运行效率也不高。幸好,vim早就想到了这一点,她提供了很多外部语言接口,比如Python,ruby,lua,Perl等,可以很方便的编写vim插件。本文主要介绍如何使用Python编写vim插件。

准备工作

1. 编译vim,使vim支持Python

在编译之前,configure的时候加上--enable-pythoninterp--enable-python3interp选项,使之分别支持Python2和Python3 编译好之后,可以通过vim --version | grep +python来查看是否已经支持Python,结果中应该包含+python+python3,当然也可以编译成只支持Python2或Python3。

现在好多平台都有直接编译好的版本,已经包含Python支持,直接下载就可以了:

  • Windows:可以在这里下载。
  • Mac OS:可以直接brew install vim来安装。
  • Linux:也有快捷的安装方式,就不赘言了。

2. 如何让Python能正常工作

虽然vim已经支持Python,但是可能:echo has("python"):echo has("python3")的结果仍是0,说明Python还不能正常工作。
此时需要检查:

  1. 系统上是否装了Python?
  2. Python是32位还是64位跟vim是否匹配?
  3. Python的版本跟编译时的版本是否一致(编译时的版本可以使用:version查看)
  4. 通过pythondllpythonthreedll来分别指定Python2和Python3所使用的动态库。 例如,可以在vimrc里添加 set pythondll=/Users/yggdroot/.python2.7.6/lib/libpython2.7.so

经此4步,99%能让Python工作起来,剩下的1%就看人品了。

补充一点: 对于neovim,执行

pip2 install --user --upgrade pynvim
pip3 install --user --upgrade pynvim

就可以添加Python2和Python3的支持,具体参见:h provider-python

从hello world开始

在命令行窗口执行:pyx print("hello world!"),输出“hello world!”,说明Python工作正常,此时我们已经可以使用Python来作为vim的EX命令了。

操作vim像vimL一样容易

怎么用Python来访问vim的信息以及操作vim呢?很简单,vim的Python接口提供了一个叫vim的模块(module)。vim模块是Python和vim沟通的桥梁,通过它,Python可以访问vim的一切信息以及操作vim,就像使用vimL一样。所以写脚本,首先要import vim

vim模块

vim模块提供了两个非常有用的函数接口:

  • vim.command(str)

执行vim中的命令str(ex-mode),返回值为None,例如:

:py vim.command("%s/s+$//g")
:py vim.command("set shiftwidth=4")
:py vim.command("normal! dd") 

  • vim.eval(str)

求vim表达式str的值,(什么是vim表达式,参见:h expr),返回结果类型为:

  1. string: 如果vim表达式的值的类型是stringnumber
  2. list:如果vim表达式的值的类型是一个vim list(:h list
  3. dictionary:如果vim表达式的值的类型是一个vim dictionary(:h dict

例如:

:py sw = vim.eval("&shiftwidth")
:py print vim.eval("expand('%:p')")
:py print vim.eval("@a") 

vim模块还提供了一些有用的对象:

  • Tabpage对象(:h python-tabpage
    一个Tabpage对象对应vim的一个Tabpage。
  • Window对象(:h python-window
    一个Window对象对应vim的一个Window。
  • Buffer对象(:h python-buffer
    一个Buffer对象对应vim的一个buffer,Buffer对象提供了一些属性和方法,可以很方便操作buffer。
    例如 (假定b是当前的buffer) :
: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<     

  • vim.current对象(:h python-currentvim.current对象提供了一些属性,可以方便的访问“当前”的vim对象
    | 属性                | 含义                       | 类型    ||---------------------|----------------------------|---------|| vim.current.line    | The current line (RW)      | String  || vim.current.buffer  | The current buffer (RW)    | Buffer  || vim.current.window  | The current window (RW)    | Window  || vim.current.tabpage | The current tab page (RW)  | TabPage || vim.current.range   | The current line range (RO)| Range   | 

python访问vim中的变量

访问vim中的变量,可以通过前面介绍的vim.eval(str)来访问,例如:

:py print vim.eval("v:version")

但是, 还有更pythonic的方法:

  • 预定义vim变量(v:var
    可以通过vim.vvars来访问预定义vim变量,vim.vvars是个类似Dictionary的对象。
    例如,访问v:version
:py print vim.vvars["version"] 

  • 全局变量(g:var
    可以通过vim.vars来访问全局变量,vim.vars也是个类似Dictionary的对象。
    例如,改变全局变量g:global_var的值:
:py vim.vars["global_var"] = 123 

  • tabpage变量(t:var
    例如:
:py vim.current.tabpage.vars["var"] = "Tabpage" 

  • window变量(w:var
    例如:
:py vim.current.window.vars["var"] = "Window" 

  • buffer变量(b:var
    例如:
:py vim.current.buffer.vars["var"] = "Buffer"

python访问vim中的选项(options

访问vim中的选项,可以通过前面介绍的vim.command(str)vim.eval(str)来访问,例如:

:py vim.command("set shiftwidth=4")
:py print vim.eval("&shiftwidth")

当然, 还有更pythonic的方法:

  • 全局选项设置(:h python-options
    例如::py vim.options["autochdir"] = True

注意:如果是window-local或者buffer-local选项,此种方法会报KeyError异常。对于window-localbuffer-local选项,请往下看。

  • window-local选项设置
    例如::py vim.current.window.options["number"] = True
  • buffer-local选项设置
    例如::py vim.current.buffer.options["shiftwidth"] = 4

两种方式写vim插件

  • 内嵌式
py[thon] << {endmarker}
{script}
{endmarker}

{script}中的内容为Python代码,{endmarker}是一个标记符号,可以是任何字符串,不过{endmarker}前面不能有任何的空白字符,也就是要顶格写。

例如,写一个函数,打印出当前buffer所有的行(Demo.vim):

function! Demo()
py << EOF
import vim
for line in vim.current.buffer:print line
EOF
endfunction
call Demo()

运行:source %查看结果。

  • 独立式
    把Python代码写到*.py中,vimL只用来定义全局变量、map、command等,LeaderF就是采用这种方式。个人更喜欢这种方式,可以把全部精力集中在写Python代码上。

异步

  • 多线程
    可以通过Python的threading模块来实现多线程。但是,线程里面只能实现与vim无关的逻辑,任何试图在线程里面操作vim的行为都可能(也许用“肯定会”更合适)导致vim崩溃,甚至包括只一个vim选项。虽然如此,也比vimL好多了,毕竟聊胜于无。
  • subprocess
    可以通过Python的subprocess模块来调用外部命令。
    例如:
:py import subprocess
:py print subprocess.Popen("ls -l", shell=True, stdout=subprocess.PIPE).stdout.read()

也就是说,从支持Python起,vim就已经支持异步了(虽然直到vim7.4才基本没有bug),Neovim所增加的异步功能,对用Python写插件的小伙伴来说,没有任何吸引力。好多Neovim粉竟以引入异步(job)而引以为傲,它什么时候能引入真正的多线程支持我才会服它。

案例

著名的补全插件YCM和模糊查找神器LeaderF都是使用Python编写的。

缺陷

由于GIL的原因,Python线程无法并行处理;而vim又不支持Python的进程(https://github.com/vim/vim/issues/906),计算密集型任务想利用多核来提高性能已不可能。

更新一下:使用Python的C扩展,可以充分利用cpu多核来运行计算密集型的任务,LeaderF 就是这么做的。故此缺陷已可忽略。

奇技淫巧

  • 把buffer中所有单词首字母变为大写字母
:%pydo return line.title() 

  • 把buffer中所有的行镜像显示
    例如,把
vim is very useful
123 456 789
abc def ghi
who am I

变为

lufesu yrev si miv
987 654 321
ihg fed cba
I ma ohw

可以执行此命令:

:%pydo return line[::-1] 

总结

以上只是简单的介绍,更详细的资料可以参考:h python

eval() python_如何使用 Python 编写 vim 插件相关推荐

  1. 用python编写AutoCAD插件日志

    用python编写AutoCAD插件日志 一 如何打开已经存在的文件 import comtypes.clienttry:acad = comtypes.client.GetActiveObject( ...

  2. 如何用python写html的插件,使用python开发vim插件及心得分享

    如何使vim下开发python调试更方便 如何用 Python 给 Vim 写插件 如何使 Vim 下开发 Python 调试更方便 怎么用python调用matlab? 打算用vim写Python ...

  3. linux jedi-vim安装,python学习-vim插件安装

    centos7上自带python2.7,我们需要优化一下python环境.一.使用豆瓣源加速软件安装pip install -i   flask    #使用-i 选项 mkdir ~./pip &a ...

  4. 乘法口诀表python_如何用python编写乘法口诀表

    如何用python编写乘法口诀表?首先要明确一下思路,我们可以确定x,y两个变量,弄清楚其变化的规律,再使用循环嵌套实现.下面是如何用Python编写乘法口诀表的具体方法. 第一种:使用for遍历循环 ...

  5. maya python 开根号_Python 编写Maya插件,从0到1(一)

    最近生活有点鬼畜,在忙着搞SD材质库的同时,还要负责美术工具的开发.没错--每一个初级TA都绕不过的坎儿-写工具-- 最关键是--我没写过--emmm--所以最近生活有点苦--踩坑踩的脚都瘸了-- 网 ...

  6. 如何编写 Nagios 插件 (http://zener.blog.51cto.com/937811/727685)

    如何编写 Nagios 插件 Nagios 的最激动人心的方面是可以轻松地编写您自己的插件,只需要了解一些简单的指导原则即可.为了管理插件,Nagios 每次在查询一个服务的状态时,产生一个子进程,并 ...

  7. maya! board_Python 编写Maya插件,从0到1(一)

    最近生活有点鬼畜,在忙着搞SD材质库的同时,还要负责美术工具的开发.没错--每一个初级TA都绕不过的坎儿-写工具-- 最关键是--我没写过--emmm--所以最近生活有点苦--踩坑踩的脚都瘸了-- 网 ...

  8. Python 之vim编写python自动补全

    Pydiction :vim - python自动补全插件 插件的安装如下: 1.下载插件包 https://github.com/vim-scripts/Pydiction 可以直接下载,也可git ...

  9. vim与Python推荐之插件Autopep8

    摘要:需要在python和vim端同时安装pep8包:使用命令为Autopep8. 第一步:在Python端需要安装pep8包: 第二步:在vim端安装autopep8插件 第三步:使用命令:Auto ...

最新文章

  1. 一致性哈希算法 应用场景
  2. 2018北大计算机复试线,2018年北京大学考研复试分数线已公布
  3. 最开始教学html5的人,初识html5的个人看法
  4. 13. 星际争霸之php设计模式--正面模式
  5. 工控补丁星期二:西门子、施耐德电气修复40个漏洞
  6. Fragment控件初始化
  7. SqlTransaction事务和Response.Redirect
  8. Java编程在现实生活中如何应用
  9. 鸡啄米VS2010/MFC编程入门教程——学习3(安装VS2010)
  10. 中芯国际公布最新人事调整(5张数据表揭开公司真实情况)
  11. STM32学习总结(二)
  12. 什么是敏感信息检测,敏感信息检测,安全视图 | 云效
  13. 一图带你了解全球疫情爆发背后的隐藏机会
  14. (原创)微信公众号开发的简单模板及配置流程简介
  15. 2022年秋招 Java后端程序员如何应对面试?
  16. 阿里云和腾讯云这两家对比哪个比较好一些?
  17. 怎样通过flash模板安装Facebook专页
  18. ESP8266-01WIFI模块——内网通信
  19. [Unity] GPU动画实现(三)——材质合并
  20. Arcgis实例操作8---地形高程分析、提取该DEM数据的水文坡长、提取山顶点数据

热门文章

  1. springboot细节挖掘(jar和war打包)
  2. mybatis--一对一、一对多、多对多(七)
  3. python读取文件夹下所有文件的名称_python2.7 学习之读取文件夹下所有文件名称及内容...
  4. php yii框架连接数据库,Yii 框架使用数据库(databases)的方法示例
  5. 计算机与打印机整体方案,打印机的一些使用方案
  6. 删除mysql 执行计划_如何清除某条SQL的执行计划
  7. ECS之Component组件
  8. Leecode刷题热题HOT100(11)——盛水最多的容器
  9. OpenShift 4 - 用Compliance Operator对OpenShift进行安全合规扫描
  10. 删除Terminating状态的Pod