使用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脚本分享
Apr 21 Python
Python常用小技巧总结
Jun 01 Python
Python实现基本数据结构中栈的操作示例
Dec 04 Python
Python操作mysql数据库实现增删查改功能的方法
Jan 15 Python
Python针对给定字符串求解所有子序列是否为回文序列的方法
Apr 21 Python
解决pandas .to_excel不覆盖已有sheet的问题
Dec 10 Python
python3 cvs将数据读取为字典的方法
Dec 22 Python
Python的matplotlib绘图如何修改背景颜色的实现
Jul 16 Python
基于pytorch的保存和加载模型参数的方法
Aug 17 Python
TensorFlow设置日志级别的几种方式小结
Feb 04 Python
Python3开发实例之非关系型图数据库Neo4j安装方法及Python3连接操作Neo4j方法实例
Mar 18 Python
Python使用for生成列表实现过程解析
Sep 22 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
全文搜索和替换
2006/10/09 PHP
PHP解密Unicode及Escape加密字符串
2015/05/17 PHP
php微信公众平台开发(四)回复功能开发
2016/12/06 PHP
动态调用css文件——jquery的应用
2007/02/20 Javascript
JavaScript 面向对象之命名空间
2010/05/04 Javascript
jquery拖动插件(jquery.drag)使用介绍
2013/06/18 Javascript
js中document.write使用过程中的一点疑问解答
2014/03/20 Javascript
JS判断字符串包含的方法
2015/05/05 Javascript
AngularJS 作用域详解及示例代码
2016/08/17 Javascript
JS制作类似选项卡切换的年历
2016/12/03 Javascript
JS中静态页面实现微信分享功能
2017/02/06 Javascript
详解数组Array.sort()排序的方法
2020/05/09 Javascript
Vue中的数据监听和数据交互案例解析
2017/07/12 Javascript
layui 解决form表单点击无反应的问题
2019/10/25 Javascript
Vue实现手机扫描二维码预览页面效果
2020/05/28 Javascript
Django中模版的子目录与include标签的使用方法
2015/07/16 Python
利用Python进行数据可视化常见的9种方法!超实用!
2018/07/11 Python
python爬虫爬取幽默笑话网站
2019/10/24 Python
python3光学字符识别模块tesserocr与pytesseract的使用详解
2020/02/26 Python
win7上tensorflow2.2.0安装成功 引用DLL load failed时找不到指定模块 tensorflow has no attribute xxx 解决方法
2020/05/20 Python
tensorflow模型的save与restore,及checkpoint中读取变量方式
2020/05/26 Python
2021年的Python 时间轴和即将推出的功能详解
2020/07/27 Python
python生成word合同的实例方法
2021/01/12 Python
韩国CJ食品专卖网:CJonmart
2016/09/11 全球购物
英国儿童设计师服装的领先零售商:Base
2019/03/17 全球购物
美国主要的特色咖啡和茶公司:Peet’s Coffee
2020/02/14 全球购物
中海讯通笔试题
2015/09/15 面试题
计算机应用与科学个人的自我评价
2013/11/15 职场文书
竞选部门副经理的自荐书范文
2014/02/11 职场文书
优秀的2014年两会精神解读
2014/03/17 职场文书
2014年党员公开承诺书范文
2014/03/28 职场文书
机关领导干部作风整顿整改措施
2014/09/19 职场文书
个人借款协议书范本
2014/11/17 职场文书
优秀校长事迹材料
2014/12/24 职场文书
2015年度环卫处工作总结
2015/07/24 职场文书
JS前端可视化canvas动画原理及其推导实现
2022/08/05 Javascript