使用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获取Linux下文件版本信息、公司名和产品名的方法
Oct 05 Python
Python中输出ASCII大文字、艺术字、字符字小技巧
Apr 28 Python
Python随机读取文件实现实例
May 25 Python
python通过伪装头部数据抵抗反爬虫的实例
May 07 Python
Python 实现中值滤波、均值滤波的方法
Jan 09 Python
python django框架中使用FastDFS分布式文件系统的安装方法
Jun 10 Python
Python GUI编程 文本弹窗的实例
Jun 11 Python
Python文件路径名的操作方法
Oct 30 Python
Python字符串的修改方法实例
Dec 19 Python
浅析matlab中imadjust函数
Feb 27 Python
python实现图像全景拼接
Mar 27 Python
Android Q之气泡弹窗的实现示例
Jun 23 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错误WARNING: SESSION_START() [FUNCTION.SESSION-START]解决方法
2014/05/04 PHP
PHP递归的三种常用方式
2019/02/28 PHP
使用PHP反射机制来构造&quot;CREATE TABLE&quot;的sql语句
2019/03/21 PHP
TP5框架使用QueryList采集框架爬小说操作示例
2020/03/26 PHP
php让json_encode不自动转义斜杠“/”的方法
2020/04/27 PHP
javascript Prototype 对象扩展
2009/05/15 Javascript
js获得指定控件输入光标的坐标兼容IE,Chrome,火狐等多种主流浏览器
2013/05/21 Javascript
随窗体滑动的小插件sticky源码
2013/06/21 Javascript
jQuery中的通配符选择器使用总结
2016/05/30 Javascript
JS实现基于Sketch.js模拟成群游动的蝌蚪运动动画效果【附demo源码下载】
2017/08/18 Javascript
详解js几个绕不开的事件兼容写法
2017/08/30 Javascript
js实现rem自动匹配计算font-size的示例
2017/11/18 Javascript
JavaScript封闭函数及常用内置对象示例
2019/05/13 Javascript
Node.js 路由的实现方法
2019/06/05 Javascript
JQuery常用简单动画操作方法回顾与总结
2019/12/07 jQuery
echarts实现折线图的拖拽效果
2019/12/19 Javascript
pygame实现弹力球及其变速效果
2017/07/03 Python
基于python进行桶排序与基数排序的总结
2018/05/29 Python
基于Python实现迪杰斯特拉和弗洛伊德算法
2020/05/27 Python
python批量读取文件名并写入txt文件中
2020/09/05 Python
Django获取应用下的所有models的例子
2019/08/30 Python
matplotlib自定义鼠标光标坐标格式的实现
2021/01/08 Python
python中用Scrapy实现定时爬虫的实例讲解
2021/01/18 Python
详解如何将 Canvas 绘制过程转为视频
2021/01/25 HTML / CSS
Bjorn Borg官方网上商店:国际运动时尚品牌
2016/08/27 全球购物
墨尔本照明批发商店:Mica Lighting
2017/12/28 全球购物
C++面试题目
2013/06/25 面试题
介绍下Lucene建立索引的过程
2016/03/02 面试题
文员个人求职自荐信
2013/09/21 职场文书
物流专业求职计划书
2014/01/10 职场文书
优良学风班申请材料
2014/02/13 职场文书
优秀学生获奖感言
2014/02/15 职场文书
小学生九一八纪念日83周年演讲稿500字
2014/09/17 职场文书
爱心募捐感谢信
2015/01/22 职场文书
红高粱观后感
2015/06/10 职场文书
简单实现一个手持弹幕功能+文字抖动特效
2021/03/31 HTML / CSS