使用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 相关文章推荐
python实现从web抓取文档的方法
Sep 26 Python
python模拟鼠标拖动操作的方法
Mar 11 Python
Python3 socket同步通信简单示例
Jun 07 Python
python中关于for循环的碎碎念
Jun 30 Python
深入理解Python分布式爬虫原理
Nov 23 Python
JavaScript实现一维数组转化为二维数组
Apr 17 Python
python opencv旋转图像(保持图像不被裁减)
Jul 26 Python
python实现合并多个list及合并多个django QuerySet的方法示例
Jun 11 Python
用Python实现BP神经网络(附代码)
Jul 10 Python
如何利用Python开发一个简单的猜数字游戏
Sep 22 Python
python 引用传递和值传递详解(实参,形参)
Jun 05 Python
关于python中导入文件到list的问题
Oct 31 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
PHP4实际应用经验篇(8)
2006/10/09 PHP
php中将网址转换为超链接的函数
2011/09/02 PHP
PHP的邮件群发系统phplist配置方法详细总结
2016/03/30 PHP
跨域请求之jQuery的ajax jsonp的使用解惑
2011/10/09 Javascript
原生js实现shift/ctrl/alt按键的获取
2013/04/08 Javascript
js判断是否为ie的方法小结
2014/01/13 Javascript
Javascript实现的简单右键菜单类
2015/09/23 Javascript
深入解析JavaScript的闭包机制
2015/10/20 Javascript
全面解析JavaScript的Backbone.js框架中的Router路由
2016/05/05 Javascript
jquery插件方式实现table查询功能的简单实例
2016/06/06 Javascript
Vue.js每天必学之过渡与动画
2016/09/06 Javascript
jQuery图片轮播(二)利用构造函数和原型创建对象以实现继承
2016/12/06 Javascript
NodeJs下的测试框架Mocha的简单介绍
2017/02/22 NodeJs
Angular4项目中添加i18n国际化插件ngx-translate的步骤详解
2017/07/02 Javascript
jQuery封装animate.css的实例
2018/01/04 jQuery
分享5个顶级的JavaScript Ajax组件库
2018/09/16 Javascript
详解vue2.6插槽更新v-slot用法总结
2019/03/09 Javascript
vue中使用 pako.js 解密 gzip加密字符串的方法
2019/06/10 Javascript
vue.js实现图书管理功能
2019/09/24 Javascript
微信小程序选择图片控件
2021/01/19 Javascript
[01:07]2015国际邀请赛 中国区预选赛精彩回顾
2015/06/15 DOTA
python算法表示概念扫盲教程
2017/04/13 Python
详解python中的hashlib模块的使用
2019/04/22 Python
python 使用while写猜年龄小游戏过程解析
2019/10/07 Python
Django values()和value_list()的使用
2020/03/31 Python
python构造IP报文实例
2020/05/05 Python
详解CSS3:overflow属性
2020/11/17 HTML / CSS
Office DEPOT法国官网:欧迪办公用品采购
2018/01/03 全球购物
戛纳奢侈品商店:Jacques Loup法国
2019/11/04 全球购物
美国家用和厨房电器销售网站:Appliances Connection
2020/01/24 全球购物
新加坡鲜花速递/新加坡网上花店:Ferns N Petals
2020/08/29 全球购物
电气工程及其自动化自我评价四篇
2013/09/24 职场文书
门诊手术室工作制度
2014/01/30 职场文书
小学校园之星事迹材料
2014/05/16 职场文书
物业保洁员管理制度
2015/08/05 职场文书
Nginx服务器添加Systemd自定义服务过程解析
2021/03/31 Servers