使用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 13 Python
python关键字and和or用法实例
May 28 Python
浅谈Python中列表生成式和生成器的区别
Aug 03 Python
详解Python的Flask框架中生成SECRET_KEY密钥的方法
Jun 07 Python
Python模拟简单电梯调度算法示例
Aug 20 Python
Python3中bytes类型转换为str类型
Sep 27 Python
python实现烟花小程序
Jan 30 Python
Python元组常见操作示例
Feb 19 Python
Scrapy框架爬取Boss直聘网Python职位信息的源码
Feb 22 Python
Python数据类型之列表和元组的方法实例详解
Jul 08 Python
对python中list的五种查找方法说明
Jul 13 Python
基于Python实现下载网易音乐代码实例
Aug 10 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
德生PL990的分析评价
2021/03/02 无线电
PHP系统流量分析的程序
2006/10/09 PHP
IIS下配置Php+Mysql+zend的图文教程
2006/12/08 PHP
ajax 的post方法实例(带循环)
2011/07/04 PHP
php中的curl使用入门教程和常见用法实例
2014/04/10 PHP
php实现HTML实体编号与非ASCII字符串相互转换类实例
2016/11/02 PHP
php自定义截取中文字符串-utf8版
2017/02/27 PHP
PHP框架自动加载类文件原理详解
2017/06/06 PHP
Laravel中七个非常有用但很少人知道的Carbon方法
2017/09/21 PHP
PHP+redis实现微博的拉模型案例详解
2019/07/10 PHP
用dom+xhtml+css制作的一个相册效果代码打包下载
2008/01/24 Javascript
JS 实现导航栏悬停效果
2013/09/23 Javascript
jquery遍历函数siblings()用法实例
2015/12/24 Javascript
基于 Node.js 实现前后端分离
2016/04/23 Javascript
详解Vue组件之间的数据通信实例
2017/06/17 Javascript
react实现一个优雅的图片占位模块组件详解
2017/10/30 Javascript
vue组件间通信子与父详解(二)
2017/11/07 Javascript
vue中的模态对话框组件实现过程
2018/05/01 Javascript
jQuery实现模糊查询的方法分析
2018/05/10 jQuery
layui表格内放置图片,并点击放大的实例
2019/09/10 Javascript
vue+element树组件 实现树懒加载的过程详解
2019/10/21 Javascript
JavaScript代码实现简单计算器
2020/12/27 Javascript
[03:16]DOTA2完美大师赛主赛事首日集锦
2017/11/23 DOTA
python生成随机密码或随机字符串的方法
2015/07/03 Python
python中使用序列的方法
2015/08/03 Python
python实现集中式的病毒扫描功能详解
2019/07/09 Python
用CSS3实现Win8风格的方格导航菜单效果
2013/04/10 HTML / CSS
css3实现图片遮罩效果鼠标hover以后出现文字
2013/11/05 HTML / CSS
css sprite简单实例
2016/05/23 HTML / CSS
Champion澳大利亚官网:美国冠军运动服装
2018/05/07 全球购物
简历的个人自我评价范文
2014/01/03 职场文书
四查四看剖析材料
2014/02/14 职场文书
2014政府领导班子对照检查材料思想汇报(3篇)
2014/09/26 职场文书
2014年教育实习工作总结
2014/11/22 职场文书
从np.random.normal()到正态分布的拟合操作
2021/06/02 Python
一起来看看Vue的核心原理剖析
2022/03/24 Vue.js