vim插件pathogen介绍

插件作者

vim-pathogen是一个操作vim的runtimepath的插件,通过灵活的操作runtimepath,可以对安装的vim插件进行方便的管理。 vim原始的安装插件的方式需要将插件文件复制到vim下的对应目录中,所有的插件混合在一个目录,不便于管理。 使用vim-pathogen后,可以将插件放在原始的独立目录内,由pathogen插件通过操作runtimepath加载其余的插件。 插件的github地址为:tpope/vim-pathogen · GitHub
作者是tpope,tpope贡献了很多实用的vim插件,他的github:tpope (Tim Pope) · GitHub

安装插件

pathogen插件的安装可以按照原始的方式,直接将插件文件复制到~/.vim/autoload中,然后将需要由pathogen加载的插件放入~/.vim/bundle。 要启用pathogen插件,还需要在vimrc文件里, filetype plugin indent on之前的任何地方,加入下面的命令:

" 执行pathogen.vim中的infect函数
execute pathogen#infect()
" 注意:需要在下面设置之前添加上面的执行语句
syntax on
filetype plugin indent on

如果你有强迫症,想把pathogen插件也放入~/.vim/bundle目录中,可以在vimrc中添加如下命令:

" 通过runtime命令将pathogen.vim加入vim的运行时环境
runtime bundle/vim-pathogen.git/autoload/pathogen.vim
" 执行pathogen.vim中的infect函数
execute pathogen#infect()

通过上面的命令,也可以大概猜测出pathogen加载插件的机制,应该也是通过runtime命令,去动态的将~/vim/bundle目录中的插件添加到 vim的运行时环境。

定制插件存放目录

可以通过下面的方式指定pathogen去加载指定目录下的插件:

execute pathogen#infect('bundle/{}', '~/src/vim/bundle/{}')

生成插件tags文件

由于插件现在是存放在独立的目录中,使用:helptags命令生成文档的tags文件就不是太方便。插件提供了:Helptags函数来解决这个问题, 通过该函数可以很方便的生成插件文档的tags文件。

使用github管理插件

可以使用个人帐号在github新建一个仓库,专门用来托管vim插件和设置,然后将所需的vim插件作为子模块添加到工程中, vim.org和github.com进行了合作,所有的vim插件都会自动获得一个github地址,pathogen这种组织插件的方式可以结合git的submodule机制, 便捷的将个人所安装的插件全部托管在github上,将vim插件的git项目作为git submodule加入到自己的插件托管项目中, 通过git submodule命令对插件进行统一的管理和更新,具体操作方式参考下面的命令:

" 添加新的vim插件vim-pathogen作为子模块到.vim/bundle目录
git submodule add git@github.com:tpope/vim-pathogen.git .vim/bundule/pathogen
" 通过git submodule更新所有插件
git submodule foreach git pull origin master

vim插件surround介绍

插件作者

vim-surround是一个处理成对出现的“包围结构”的插件,比如处理括号、引号和html标签。对文本的外包的结构进行增加、修改和删除。 由于插件提供的命令接受vim文本对象和vim的移动命令,使用起来比较方便,额外的学习成本比较低。 插件的github地址为:tpope/vim-surround · GitHub
作者是tpope,tpope贡献了很多实用的vim插件,他的github:tpope (Tim Pope) · GitHub

普通模式命令

普通模式下,插件提供下列按键绑定:

替换:change surround

cs命令是change surround的缩写,可以对指定的文本的外部包围字符进行替换,命令接受两个参数: 第一个是被替换的外部包围字符,第二个是要替换为的字符。替换时光标需要移动到被包围的文本内。 比如需要将字符串'test'外部的包围字符'替换为",可以将光标移动到文本区域内,然后使用cs'"即可 下面是一些例子,部分来自帮助文件,其中的*号代表光标位置
注意 命令中使用形如()、{}、[]的字符的左半部分和右半部分是有区别的, 区别在于处理中的头部和尾部的空格的处理,考虑例子6、7、8、9的情况,处理字符串(   test   ), 字符串有3个头部空格,有2个尾部空格。
规则 规则可以总结如下:
1.第一个参数使用符号的左半部分,会自动删除所有的头部和尾部 的空格,使用右半部分则不对空格进行处理
2.第二个参数使用符号的左半部分,会自动在左半部分的后面和右半部分的前面插入一个空格
注意例子8中的空格个数,被自动插入了空格

样例序号 原始文本 执行命令 执行结果
1 "Hello*world!" cs"' 'Helloworld!'
2 "Hello*world!" cs"<q> <q>Helloworld!</q>
3 (( Hello*world! )) cs(* (*Hello*world!*)
4 (( Hello*world! )) cs( * (* Hello*world! *)
5 <div>Yo!*</div> cst<p> <p>Yo!</p>
6 (   test   ) cs([ [ test ]
7 (   test   ) cs(] [test]
8 (   test   ) cs)[ [    test    ]
9 (   test   ) cs)] [   test   ]

删除:delete surround

ds命令是delete surround的缩写,该命令只接受一个参数,即为需要删除的外部包围字符 如果需要删除文本外部的标签,可以使用字符t来指代标签,不需要输入标签全称 下面是一些例子:
注意 命令中使用形如()、{}、[]的字符的左半部分和右半部分是有区别的, 规则同cs命令的规则1,即同样遵守第一个参数的规则,不再举例示范

样例序号 原始文本 执行命令 执行结果
1 "Hello*world!" ds" Hello world!
2 ((Hello*world!)) ds{ (Hello*world!)
2 (123+4*56)/2 ds) 123+456/2
3 <div>Yo!*</div> dst Yo!

添加:you surround

ys命令是you surround(按作者的说法),可以对指定的文本进行包围,命令接受两个参数: 第一个是指示文本范围或者移动位置的文本对象,第二个是包围操作使用的字符。插入时光标需要移动到被包围的文本内。 比如需要将字符串test添加外部包围字符',可以将光标移动到文本区域内,然后使用ysaw"即可,其中aw会被当作vim文本对象, ys模式有一种变形,即yss和ySS,操作的对象是当前行,不过yss的包围符号添加在行首行尾,而ySS的符号会插入两个新行来包围。 下面是一些例子,部分来自帮助文件,其中的*号代表光标位置
指定范围的两种方法
1.文本对象,规则基本同vim的文本对象规则一样
2.移动位置,可以使用^、$、f等命令来指定位置,作用范围是当前光标到指定的位置
注意 命令中使用形如()、{}、[]的字符的左半部分和右半部分是有区别的, 规则同cs命令的规则2,即同样遵守第二个参数的规则,不再举例示范

样例序号 原始文本 执行命令 执行结果
1 test ysiw' 'test'
2 'test' ysi') '(test)'
3 'test' ysa') ('test')
4 foo*testbar ystb) foo(test)bar
5 test ysaw<p class="example"> <p class="example">test</p>

可视模式命令

可视模式下可以选择需要的文本块,然后使用命令S,就可以输入用来进行包围的字符,不再赘述。

插入模式命令

插件的插入模式还处于试验状态,可以在插入模式下插入字符对,不过我并没有测试成功。通过map命令查看文档中的按键绑定,发现并未绑定函数。

定制插件行为

插件提供对符号的行为进行定制的功能,如果需要定制'-'符号在php文件中的功能,则按下面步骤操作

" 1.使用vim函数获得ascii码
:echo char2nr("-")
" 2.在vim文件中添加绑定,并使用文件类型侦测
" 注意b:surround_45使用了'-'的ascii码值45
autocmd FileType php let b:surround_45 = "<?php \r ?>"

如果文件类型是php,则在字符串 print "Hello *world!"上执行yss-即可得到<?php print "Hello world!" ?>。使用如下方式还可以请求用户输入,jekyll的语法高亮使用highlight语法来完成,每次输入较麻烦,可以在vimrc中加入下面的设置

let g:surround_45 = "{% hightlight \1代码语言: \1 %}\r{% endhighlight %}"

这样就自定义了字符"-"的包围语法模板,比如在testtest上使用ySS-,会显示“代码语言:”并等待用户输入,输入bash,则得到下面的代码 其中的"\1代码语言: \1"被替换为用户输入的字符串,"\r"被替换为用户选择的需要被包围的文本,其余的均原样输出, 如果需要,可以在语法模板中使用换行等转义字符。语法模板也支持正则表达式的处理,但是语法过于古怪和丑陋,个人认为没有使用的价值。

{% highlight bash %}
testtest
{% endhighlight %}
  

推送git项目到多个远程仓库

最近开源中国 - 找到您想要的开源项目,分享和交流也推出了git项目托管服务, 想把部分github中的项目同步到git@osc,在网上搜索了一下,找到了一种比较简单的同步办法,方法分享在下面。

首先强烈推荐实用ssh的方式来完成push过程中的认证,这样不用每次都输入用户名和密码,十分方便。具体方式可以参考github的 官方教程GitHub Help

如果已经配置好了ssh验证方式,在开源中国的git托管也可以使用同一个的key,然后打开github项目中中的.git/config文件 在[remote "origin"]节点的原始url下面直接添加开源中国git中对应项目的ssh地址即可,例如:

[remote "origin"]
	url = git@github.com:codepiano/pull-all-git-project.git
	url = git@git.oschina.net:codepiano/pull-all-git-project.git
	fetch = +refs/heads/*:refs/remotes/origin/*

当然,使用命令行也可以直接添加,命令格式如下:

git remote set-url --add origin git@git.oschina.net:codepiano/pull-all-git-project.git

vim zencoding插件的一个bug的跟踪和解决过程

前几天用vim写博客的过程中发现一个bug,当使用<c-y>a自动生成a标签的时候,会丢失href元素, 就跟踪了下那个函数的调用过程。找着bug的原因后,在github上给zencoding的作者发了一个pull request, 不过由于作者想更深层修复缺陷,没有merge,给转成issue了。把具体的跟踪过程和分析记录在这里

<c-y>a是个很好用的命令,比如你准备插入一个a标签,只用输入http://www.vim.org, 然后使用zencoding扩展,会自动生成a标签,插件会联网读取那个网址的title标签, 并使用标签内容作为a标签的显示内容:

<a href="http://www.vim.org">welcome home : vim online</a>

不过我使用的时候遇到一个bug,生成的a标签会丢失href属性,想寻找bug出现的原因就要跟踪代码调用过程。 使用<c-y>a标签的时候在vim状态栏可以看到调用了zencoding#anchorizeURL函数,并传入了一个参数, 值为0。而zencoding插件的初始化操作在plugin/zencoding.vim文件中,顶层函数放在autoload/zencoding.vim中, 具体的处理标签的底层操作逻辑分散放在autoload/zencoding目录中。先从autoload/zencoding.vim入手, 找到了zencoding#anchorizeURL函数,通过阅读代码找到如下逻辑:

" file:autoload/zencoding.vim

" a:flag即为传入的参数,当调用<c-y>a时为0,调用<c-y>A时为1
if a:flag == 0
  " 生成a标签的属性字典
  let a = zencoding#lang#html#parseTag('<a>')
  let a.attr.href = url
  let a.value = '{' . title . '}'
  " 根据属性字典生成html代码
  let expand = zencoding#toString(a, rtype, 0, [])
  " 去除代表光标位置的标志符号
  let expand = substitute(expand, '\${cursor}', '', 'g')
else
  " ...
endif

通过分析上面这段代码,可以知道问题应该处在zencoding#toString函数中,不过通过分析该函数的代码, 发现这个函数只是一个顶层函数,根据上步调用传入的属性字典的name或者snippts属性来决定是调用底层工具函数来生成代码, 还是通过自定义snippts进行扩展。结合传入参数和程序逻辑,在这个功能中,是调用了底层工具函数zencoding#lang#html#toString, 该函数位于autoload/zencoding/lang/html.vim中。函数中有下面这段代码

" file:autoload/zencoding/lang/html.vim

if len(current_name) > 0
  let str .= '<' . current_name
  for attr in zencoding#util#unique(current.attrs_order)
    if !has_key(current.attr, attr)
      continue
    endif
    " ...
  endfor
  " ...
endif

出现href属性丢失的原因是因为current.attrs_order为空,没有'href'属性名字符串, 所以生成的标签也不存在href属性。 也就是说由于程序缺陷,导致属性字典中代表标签属性列表的数组attrs_order为空。 由于我并没有深层次的去读插件的源码,所以不了解这个数组为空的原因, 而autoload/zencoding.vim中的zencoding#anchorizeURL函数只处理a标签的扩展, 所以我直接在顶层函数zencoding#anchorizeURL中给attrs_order中add了一个值'href', 这样可以解决这一个小问题。后来给插件作者发了pull request,说明了bug的原因, 并指出不确定是不是最好的解决方式,插件作者回复说他想从本质上解决这个问题, 把我的pull request转成了issue。一开始我以为作者会去解决attrs_order数组为空的问题, 不过pull最新的代码,发现作者也没去修改attrs_order数组,而是在底层的工具函数上打了个补丁, 修改后的代码如下

" file:autoload/zencoding/lang/html.vim

if len(current_name) > 0
  let str .= '<' . current_name
  " 打了个keys(current.attr)的补丁,补全了属性
  for attr in zencoding#util#unique(current.attrs_order + keys(current.attr))
    let val = current.attr[attr]
    " ...
  endfor
  " ...
endif

关于这次的bug修改,让我想起看过的伞哥 @田春冰河 的一条微博说过的一种情况, 微博找不到了,大意是说:一个工具模块的代码缺陷A,导致不同的功能中出现bug的并集U, 测试人员通过测试发现其中一个子集u,然后开发人员修复子集u中的bug, 而真正好的解决方式是通过bug集u找到问题的源头,即缺陷A,从而修复整个bug集U。 这次的情况也类似,我只修复了a标签生成这一个bug,作者修改底层模块后也修复了潜在的其他bug


—  原创作品许可 — 署名-非商业性使用-禁止演绎 3.0 未本地化版本 — CC BY-NC-ND 3.0   —