使用Python编写vim插件的简单示例


Posted in Python onApril 17, 2015

 Vim 插件是一个 .vim 的脚本文件,定义了函数、映射、语法规则和命令,可用于操作窗口、缓冲以及行。一般一个插件包含了命令定义和事件钩子。当使用 Python 编写 vim 插件时,函数外面是使用 VimL 编写,尽管 VimL 学起来很快,但 Python 更加灵活,例如可以用 urllib/httplib/simplejson 来访问某些 Web 服务,这也是为什么很多需要访问 Web 服务的插件都是使用 VimL + Python 编写的原因。

在开始编写插件之前,你需要确认 Vim 支持 Python,通过以下命令来判别:
 

vim --version | grep +python

接下来我们通过一个简单的例子来学习用 Python 编写 Vim 插件,该插件用来获取 Reddit 首页信息并显示在当前缓冲区上。

首先在 Vim 新建 vimmit.vim 文件,我们首先需要判断是否支持 Python,如果不支持给出提示信息:
 

if !has('python')
  echo "Error: Required vim compiled with +python"
  finish
endif

上面这段代码就是用 VimL 编写的,它将检查 Vim 是否支持 Python。

下面是用 Python 编写的 Reddit() 主函数:

 

" Vim comments start with a double quote.
" Function definition is VimL. We can mix VimL and Python in
" function definition.
function! Reddit()
 
" We start the python code like the next line.
 
python << EOF
# the vim module contains everything we need to interface with vim from
# python. We need urllib2 for the web service consumer.
import vim, urllib2
# we need json for parsing the response
import json
 
# we define a timeout that we'll use in the API call. We don't want
# users to wait much.
TIMEOUT = 20
URL = "http://reddit.com/.json"
 
try:
  # Get the posts and parse the json response
  response = urllib2.urlopen(URL, None, TIMEOUT).read()
  json_response = json.loads(response)
 
  posts = json_response.get("data", "").get("children", "")
 
  # vim.current.buffer is the current buffer. It's list-like object.
  # each line is an item in the list. We can loop through them delete
  # them, alter them etc.
  # Here we delete all lines in the current buffer
  del vim.current.buffer[:]
 
  # Here we append some lines above. Aesthetics.
  vim.current.buffer[0] = 80*"-"
 
  for post in posts:
    # In the next few lines, we get the post details
    post_data = post.get("data", {})
    up = post_data.get("ups", 0)
    down = post_data.get("downs", 0)
    title = post_data.get("title", "NO TITLE").encode("utf-8")
    score = post_data.get("score", 0)
    permalink = post_data.get("permalink").encode("utf-8")
    url = post_data.get("url").encode("utf-8")
    comments = post_data.get("num_comments")
 
    # And here we append line by line to the buffer.
    # First the upvotes
    vim.current.buffer.append("↑ %s"%up)
    # Then the title and the url
    vim.current.buffer.append("  %s [%s]"%(title, url,))
    # Then the downvotes and number of comments
    vim.current.buffer.append("↓ %s  | comments: %s [%s]"%(down, comments, permalink,))
    # And last we append some "-" for visual appeal.
    vim.current.buffer.append(80*"-")
 
except Exception, e:
  print e
 
EOF
" Here the python code is closed. We can continue writing VimL or python again.
endfunction

使用如下命令保存文件
 

:source vimmit.vim

然后调用该插件:
 

:call Reddit()

这个命令用起来不那么方便,因此我们再定义一个命令:

command! -nargs=0 Reddit call Reddit()

我们定义了命令:Reddit来调用这个函数。-nargs 参数声明命令行中有多少个参数。

关于函数参数的问题:

问:如何访问函数中的参数?
 

function! SomeName(arg1, arg2, arg3)
  " Get the first argument by name in VimL
  let firstarg=a:arg1
 
  " Get the second argument by position in Viml
  let secondarg=a:1
 
  " Get the arguments in python
 
  python << EOF
  import vim
 
  first_argument = vim.eval("a:arg1") #or vim.eval("a:0")
  second_argument = vim.eval("a:arg2") #or vim.eval("a:1")

你可以使用 ... 来处理可变个数参数来替换特定的参数名,可通过位置或者命名参数来访问,如:(arg1, arg2, ...)

问:如何在 Python 中调用 Vim 命令?
 

vim.command("[vim-command-here]")

问:如何定义全局变量,并在 VimL 和 Python 中访问?

全局变量使用形如 g:. 的前缀,定义全局变量前应该检查该变量是否已定义:
 

if !exists("g:reddit_apicall_timeout")
  let g:reddit_apicall_timeout=40
endif

然后你通过下面代码在 Python 中访问这个变量:
 

TIMEOUT = vim.eval("g:reddit_apicall_timeout")

可通过下面的方法来对全局变量进行重新赋值:
 

let g:reddit_apicall_timeout=60

更多关于使用 Python 编写 Vim 插件的说明请看官方文档。

备注:

一旦你用过VimL,就会发现它挺简单的,你用python写的代码也可以用它来实现。详细请参考vim python模块文档,这是一份重要的参考资料。

除了上述文档,你也可以在IBM developerWorks网站找到一些有用的资料。

Python 相关文章推荐
go语言计算两个时间的时间差方法
Mar 13 Python
使用Python编写类UNIX系统的命令行工具的教程
Apr 15 Python
Python中内置数据类型list,tuple,dict,set的区别和用法
Dec 14 Python
Python获取二维矩阵每列最大值的方法
Apr 03 Python
Python实现的读取/更改/写入xml文件操作示例
Aug 30 Python
PyQt5实现从主窗口打开子窗口的方法
Jun 19 Python
linux环境中没有网络怎么下载python
Jul 07 Python
通过python连接Linux命令行代码实例
Feb 18 Python
Python按照list dict key进行排序过程解析
Apr 04 Python
Pycharm新手使用教程(图文详解)
Sep 17 Python
python 实现Harris角点检测算法
Dec 11 Python
如何用Matlab和Python读取Netcdf文件
Feb 19 Python
用Python登录Gmail并发送Gmail邮件的教程
Apr 17 #Python
基于Python实现的百度贴吧网络爬虫实例
Apr 17 #Python
python中dir函数用法分析
Apr 17 #Python
python传递参数方式小结
Apr 17 #Python
使用70行Python代码实现一个递归下降解析器的教程
Apr 17 #Python
python类继承与子类实例初始化用法分析
Apr 17 #Python
python中split方法用法分析
Apr 17 #Python
You might like
php网站地图生成类示例
2014/01/13 PHP
thinkphp表单上传文件并将文件路径保存到数据库中
2016/07/28 PHP
JSON 学习之JSON in JavaScript详细使用说明
2010/02/23 Javascript
基于Jquery的简单图片切换效果
2011/01/06 Javascript
jQuery EasyUI API 中文文档 - ValidateBox验证框
2011/10/06 Javascript
JQuery跳出each循环的方法
2015/04/16 Javascript
IE中document.createElement的iframe无法设置属性name的解决方法
2015/09/14 Javascript
Windows下用PyCharm和Visual Studio开始Python编程
2015/10/26 Javascript
jQuery ajax MD5实现用户注册即时验证功能
2016/10/11 Javascript
解决拦截器对ajax请求的拦截实例详解
2016/12/21 Javascript
JavaScript函数基础详解
2017/02/03 Javascript
原生js实现打字动画游戏
2017/02/04 Javascript
js实现PC端和移动端刮卡效果
2020/03/27 Javascript
详解使用vscode+es6写nodejs服务端调试配置
2017/09/21 NodeJs
以v-model与promise两种方式实现vue弹窗组件
2018/05/21 Javascript
使用VUE实现在table中文字信息超过5个隐藏鼠标移到时弹窗显示全部
2019/09/16 Javascript
原生javascript实现类似vue的数据绑定功能示例【观察者模式】
2020/02/24 Javascript
在Python中使用Mako模版库的简单教程
2015/04/08 Python
Python列表list内建函数用法实例分析【insert、remove、index、pop等】
2017/07/24 Python
python实现TF-IDF算法解析
2018/01/02 Python
python 将数据保存为excel的xls格式(实例讲解)
2018/05/03 Python
使用python根据端口号关闭进程的方法
2018/11/06 Python
Python3连接Mysql8.0遇到的问题及处理步骤
2020/02/17 Python
Python Selenium安装及环境配置的实现
2020/03/17 Python
python字典通过值反查键的实现(简洁写法)
2020/09/30 Python
SheIn俄罗斯:时尚女装网上商店
2017/02/28 全球购物
印度尼西亚最大和最全面的网络商城:Blibli.com
2017/10/04 全球购物
美国在线购买空气净化器、除湿器、加湿器网站:AllergyBuyersClub
2021/03/16 全球购物
户外亲子活动策划方案
2014/02/07 职场文书
医学生就业推荐表自我鉴定
2014/03/26 职场文书
大一新生学期自我评价
2014/04/09 职场文书
服务明星事迹材料
2014/12/29 职场文书
党员理论学习心得体会
2016/01/21 职场文书
小学体育跳绳课教学反思
2016/02/16 职场文书
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
2022/03/16 Redis
js前端设计模式优化50%表单校验代码示例
2022/06/21 Javascript