使用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制作在地图上模拟瘟疫扩散的Gif图
Mar 31 Python
深入解读Python解析XML的几种方式
Feb 16 Python
Python运行报错UnicodeDecodeError的解决方法
Jun 07 Python
python 禁止函数修改列表的实现方法
Aug 03 Python
Python cookbook(数据结构与算法)实现优先级队列的方法示例
Feb 18 Python
基于python中theano库的线性回归
Aug 31 Python
解决Python下json.loads()中文字符出错的问题
Dec 19 Python
Python除法之传统除法、Floor除法及真除法实例详解
May 23 Python
django一对多模型以及如何在前端实现详解
Jul 24 Python
浅谈python3中input输入的使用
Aug 02 Python
Django中自定义admin Xadmin的实现代码
Aug 09 Python
通过Turtle库在Python中绘制一个鼠年福鼠
Feb 03 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
ajax实现无刷新分页(php)
2010/07/18 PHP
PHP通过串口实现发送短信
2015/07/08 PHP
php提取身份证号码中的生日日期以及验证是否为成年人的函数
2015/09/29 PHP
Javascript的构造函数和constructor属性
2010/01/09 Javascript
简短几句jquery代码的实现一个图片向上滚动切换
2011/09/02 Javascript
javascript学习笔记(八) js内置对象
2012/06/19 Javascript
JS完成代码前最好对其做5件事
2013/04/07 Javascript
js操作XML文件的实现方法兼容IE与FireFox
2016/06/25 Javascript
easyUI实现(alert)提示框自动关闭的实例代码
2016/11/07 Javascript
jQuery使用unlock.js插件实现滑动解锁
2017/04/04 jQuery
node通过express搭建自己的服务器
2017/09/30 Javascript
webpack4.x开发环境配置详解
2018/08/04 Javascript
JS匿名函数内部this指向问题详析
2019/05/10 Javascript
详解微信小程序开发(项目从零开始)
2019/06/06 Javascript
100行代码实现vue表单校验功能(小白自编)
2019/11/19 Javascript
JavaScript中this的学习笔记及用法整理
2020/02/17 Javascript
在Windows服务器下用Apache和mod_wsgi配置Python应用的教程
2015/05/06 Python
简单实现python进度条脚本
2017/12/18 Python
Python使用add_subplot与subplot画子图操作示例
2018/06/01 Python
python3实现域名查询和whois查询功能
2018/06/21 Python
python组合无重复三位数的实例
2018/11/13 Python
windows下python虚拟环境virtualenv安装和使用详解
2019/07/16 Python
Django 全局的static和templates的使用详解
2019/07/19 Python
Django Rest framework频率原理与限制
2019/07/26 Python
python使用ctypes调用扩展模块的实例方法
2020/01/28 Python
python的dict判断key是否存在的方法
2020/12/09 Python
史泰博(Staples)中国官方网站:办公用品一站式采购
2016/09/05 全球购物
日本著名化妆品零售网站:Cosme Land
2019/03/01 全球购物
英国排名第一的停车场运营商:NCP
2019/08/26 全球购物
英国领先的独立时装店:Van Mildert
2019/10/28 全球购物
Hotels.com韩国:海外国内旅行所需的酒店和住宿预订网站
2020/05/08 全球购物
一篇.NET面试题
2014/09/29 面试题
农场厂长岗位职责
2013/12/28 职场文书
创建文明城市倡议书
2015/04/28 职场文书
党支部鉴定意见
2015/06/02 职场文书
golang 定时任务方面time.Sleep和time.Tick的优劣对比分析
2021/05/05 Golang