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

来源:互联网 发布:宇信数据科技有限公司 编辑:程序博客网 时间:2024/05/01 21:40

对我而言, 这是一个复杂的函数, 虽然详细注释, 但还是有些难懂, 注释也是参考原作者的。

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


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


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>


原创粉丝点击