使用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 相关文章推荐
python3使用tkinter实现ui界面简单实例
Jan 10 Python
Python迭代器和生成器介绍
Mar 06 Python
Python数据分析之真实IP请求Pandas详解
Nov 18 Python
Python编程生成随机用户名及密码的方法示例
May 05 Python
Sanic框架流式传输操作示例
Jul 18 Python
Python2和Python3之间的str处理方式导致乱码的讲解
Jan 03 Python
Kali Linux安装ipython2 和 ipython3的方法
Jul 11 Python
pandas 中对特征进行硬编码和onehot编码的实现
Dec 20 Python
Pycharm2020最新激活码|永久激活(附最新激活码和插件的详细教程)
Sep 29 Python
Python类绑定方法及非绑定方法实例解析
Oct 09 Python
python判断all函数输出结果是否为true的方法
Dec 03 Python
OpenCV3.3+Python3.6实现图片高斯模糊
May 18 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
绿山咖啡和蓝山咖啡
2021/03/04 新手入门
谈谈PHP语法(4)
2006/10/09 PHP
使用PHP实现密保卡功能实现代码&amp;lt;打包下载直接运行&amp;gt;
2011/10/09 PHP
php curl_init函数用法
2014/01/31 PHP
php中curl使用指南
2015/02/05 PHP
PHP数据库连接mysql与mysqli对比分析
2016/01/04 PHP
PHP html_entity_decode()函数讲解
2019/02/25 PHP
基于Jquery的实现回车键Enter切换焦点
2010/09/14 Javascript
纯js和css实现渐变色包括静态渐变和动态渐变
2014/05/29 Javascript
js实现横向百叶窗效果网页切换动画效果的方法
2015/03/02 Javascript
js中对函数设置默认参数值的3种方法
2015/10/23 Javascript
js图片轮播手动切换效果
2015/11/10 Javascript
zTree插件下拉树使用入门教程
2016/04/11 Javascript
微信小程序 swiper组件详解及实例代码
2016/10/25 Javascript
jquery配合.NET实现点击指定绑定数据并且能够一键下载
2016/10/28 Javascript
jQuery post数据至ashx实例详解
2016/11/18 Javascript
Vue-resource实现ajax请求和跨域请求示例
2017/02/23 Javascript
基于JavaScript实现滑动门效果
2017/03/16 Javascript
JS实现多物体运动的方法详解
2018/01/23 Javascript
Vue.directive()的用法和实例详解
2018/03/04 Javascript
详解vue高级特性
2020/06/09 Javascript
python时间整形转标准格式的示例分享
2014/02/14 Python
python抓取网页中链接的静态图片
2018/01/29 Python
Python面向对象之类和实例用法分析
2019/06/08 Python
Django admin.py 在修改/添加表单界面显示额外字段的方法
2019/08/22 Python
CSS3之transition实现下划线的示例代码
2018/05/30 HTML / CSS
利用canvas实现图片下载功能来实现浏览器兼容问题
2019/05/31 HTML / CSS
html5 的a标签 Href 拨电话的写法
2013/11/04 HTML / CSS
配置管理计划的主要内容有哪些
2014/06/20 面试题
自动化专业本科毕业生求职信
2013/10/20 职场文书
毕业生自我鉴定
2013/12/04 职场文书
活动总结报告格式
2014/05/09 职场文书
2014第二批党员干部对照“四风”找差距检查材料思想汇报
2014/09/18 职场文书
2015年班级元旦晚会活动总结
2014/11/28 职场文书
小学安全工作总结2015
2015/05/18 职场文书
Ajax异步刷新功能及简单案例
2021/11/20 Javascript