您的位置:首页 > 其它

对一个vim 函数的详细注释。

2013-12-09 15:24 543 查看
对我而言, 这是一个复杂的函数, 虽然详细注释, 但还是有些难懂, 注释也是参考原作者的。

我只是简单的整理了一下。将注释添加到了函数中,方便阅读理解。

函数功能, 能够自动对齐赋值运算符的位置。 查找,替换是核心目的。(调试通过)

function! AlignAssignments ()

"Patterns needed to locate assignment operators...

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"ASSIGN_OP 中的模式匹配任何标准的赋值运算符:=、+=、-=、*=,等等,

"但是注意不要匹配其他包含 = 的运算符,比如 == 和 =~。

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let ASSIGN_OP = '[-+*/%|&]\?=\@<!=[=~]\@!'

echo "ASSIGN_OP = " ASSIGN_OP

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"ASSIGN_LINE 中的模式只在行的起始部分(^)开始匹配,首先匹配最小字符数(.\{-}),

"然后匹配任何空白(\s*),最后匹配赋值运算符。

"注意,最初的 “最小字符数” 子模式和运算符子模式都在捕捉圆括号内进行了指定:\(...\)。

"这两个正则表达式组件捕获的子字符串稍后将通过调用内置 submatch() 函数来提取;

"具体来讲,通过调用 submatch(1) 来提取运算符前面的所有内容,

"然后调用 submatch(2) 来提取运算符本身。

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let ASSIGN_LINE = '^\(.\{-}\)\s*\(' . ASSIGN_OP . '\)'

echo "ASSIGN_LINE =" ASSIGN_LINE

"Locate block of code to be considered (same indentation, no blanks)

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"直接计算行范围。实现方法,

"它首先调用内置 matchstr() 函数来确定出现在当前行(getline('.'))起始部分的前导空白('^\s*')。

"随后在 indent_pat 中构建一个新的正则表达式,精确匹配任何非空行的起始处的相同序列的空白(即拖尾 '\S')。

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let indent_pat = '^' . matchstr(getline('.'), '^\s*') . '\S'

echo "indent_pat = " indent_pat

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"内置 search() 函数向上搜索(使用标记 'bnW')并定位位于游标上方的第一个不具有相同缩进的行。

"向此行号加 1 将得出感兴趣的范围的起始行号,也就是说,具有相同缩进的第一个相邻行就作为第一行

"内置 search() 函数向下搜索('nW')来判断 lastline:具有相同缩进的最后一个相邻行。

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let firstline = search('^\%('. indent_pat . '\)\@!','bnW') + 1

let lastline = search('^\%('. indent_pat . '\)\@!', 'nW') - 1

echo "firstline =" firstline

echo "lastline = " lastline

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"搜索可能会到达文件的末尾,并且没有找到具有不同缩进的行,这种情况下 search() 将返回 -1。

"要正确地处理这种情况, if 语句需要显式地将 lastline 设置为文件末端的行号

"即设置为由 line('$') 返回的行号

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

if lastline < 0

let lastline = line('$')

endif

"Find the column at which the operators should be aligned...

let max_align_col = 0

let max_op_width = 0

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"for 循环功能: 获取赋值运算符应当对齐的列。

"实现方法:

"遍历所选范围内的行列表(由 getline(firstline, lastline) 取回的行)

"并检查每个行是否包含赋值运算符(运算符的前面可能包含空格):

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

for linetext in getline(firstline, lastline)

"Does this line have an assignment in it?

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"如果该行中没有运算符,那么内置 match() 函数将无法找到匹配,因此将返回 -1。

"对于这种情况,循环将直接跳到下一行。

"如果存在 运算符,那么 match() 将返回在其中显示运算符的(正)指数。

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let left_width = match(linetext, '\s*' . ASSIGN_OP)

"If so, track the maximal assignment column and operator width...

if left_width >= 0

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"使用内置 max() 函数判断这个最近的列位置是否比此前找到的运算符更靠右,

"从而跟踪所需的最大列位置来对齐范围内的所有赋值运算符:

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let max_align_col = max([max_align_col, left_width])

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"使用内置 matchstr() 函数检索实际的运算符,

"然后使用内置 strlen() 函数判断行的长度("=" 的长度为 1,'+='、'-=' 的长度为 2,等等)。

"max_op_width 变量随后被用来跟踪所需的最大宽度,以对范围内的各种运算符执行对齐:

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let op_width = strlen(matchstr(linetext, ASSIGN_OP))

let max_op_width = max([max_op_width, op_width+1])

endif

endfor

"Code needed to reformat lines so as to align operators...

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"vim 的printf 函数, 类似于c/perl 的sprintf 函数, 返回一个字符串

"这个内嵌的 printf() 将把运算符左侧的所有内容(submatch(1))靠左对齐(使用 %-*s 占位符)

"并将结果放到字符宽度为 max_align_col 的字段中。

"随后将运算符本身(submatch(2))右对齐(使用%*s)到第二个字段,其字符宽度为 max_op_width。

"参考 :help printf(),了解 - 和 * 选项如何修改

"这里使用的两个 %s 格式说明符(specifier)

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let FORMATTER = '\=printf("%-*s%*s", max_align_col, submatch(1), max_op_width, submatch(2))'

" Reformat lines with operators aligned in the appropriate column...

for linenum in range(firstline, lastline)

let oldline = getline(linenum)

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"substitute() 中 "\=expr"。

"前导 \= 要求对随后的表达式求值并使用结果作为替换文本。

"注意,这类似于 Insert 模式下的 <C-R>= 机制,

"这种奇妙的行为只针对内置 substitute() 函数的替换字符串(或在标准 :s/.../.../ Vim 命令中)

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let newline = substitute(oldline, ASSIGN_LINE, FORMATTER, "")

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"与当前编辑的文本缓冲区进行交互(通过 getline() 和 setline())

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

call setline(linenum, newline)

endfor

endfunction

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

"创建一个键映射来调用 AlignAssignments()

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

nmap <silent> ;= :call AlignAssignments()<CR>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: