今读到 LinuxToy 上介绍 Tabular 的文章,不由得又折腾了下功能更加强大的 Align 插件。这个插件我装了很久了,也曾读过它的文档,但是实际用得却并不多,原因除了我一般写的时候就对齐好了之外,还有一点很重要——要让它精确地按照自己所希望的方式对齐一些文本可以,但得敲好长的命令,而且还需要思考,比如对齐CSS样式声明:Align! WP0p1l: :\@<=
。
于是我就想,能不能把常用的对齐指令都以某种方式记录下来,需要时再调用。我首先想到的是映射或者命令。实际上Align自带了一个 AlignMapsPlugin.vim,其中就定义了很多常见的映射,但是不太容易记忆,而且不知道怎么添加。每种对齐方式定义个命令有点麻烦,于是就考虑用一个命令加参数的办法,于是就写了以下函数:
function Lilydjwg_Align(type) range
try
let pat = g:Myalign_def[a:type]
catch /^Vim\%((\a\+)\)\=:E716/
echohl ErrorMsg
echo "对齐方式" . a:type . "没有定义"
echohl None
return
endtry
call Align#AlignPush()
call Align#AlignCtrl(pat[0])
if len(pat) == 3
call Align#AlignCtrl(pat[2])
endif
exe a:firstline.','.a:lastline."call Align#Align(0, '". pat[1] ."')"
call Align#AlignPop()
endfunction
其中对齐样式的定义是这样子的:
let g:Myalign_def = {
\ 'css': ['WP0p1l:', ':\@<=', 'v \v^\s*/\*|\{|\}'],
\ }
Myalign_def
的值是一个列表,各项分别是对齐方式的控制序列、分隔符正则、可选的用于筛选选区的控制序列。
想到以后定义的对齐方式多了之后,那些自定义的名字会有些不记得,于是补全函数不可少:
function Lilydjwg_Align_complete(ArgLead, CmdLine, CursorPos)
return keys(g:Myalign_def)
endfunction
现在函数和变量定义都有了,可以定义命令了:
command -nargs=1 -range -complete=customlist,Lilydjwg_Align_complete
\ LA <line1>,<line2>call Lilydjwg_Align("<args>")
用的时候只要选中需要对齐的文本,然后按:LA 已定义的对齐方式名
即可。
PS: Align 的中文对齐速度很慢,而且还有移动光标位置等“不良行为”,因此 patch 之:
--- autoload/Align.vim
+++ autoload/Align.vim
@@ -984,6 +984,11 @@
" nonzero value. Solution from Nicolai Weibull, vim docs
" (:help strlen()), Tony Mechelynck, and my own invention.
fun! s:Strlen(x)
+ " lilydjwg: vim7.3 有 strwidth 函数
+ if exists('*strwidth')
+ return strwidth(a:x)
+ endif
+
" call Dfunc("s:Strlen(x<".a:x.">")
if g:Align_xstrlen == 1
" number of codepoints (Latin a + combining circumflex is two codepoints)
@@ -1006,6 +1011,8 @@
call setline(line("."),a:x)
let ret= virtcol("$") - 1
d
+ " lilydjwg: 这样才不会让光标乱跑
+ normal k
let &l:mod= modkeep