VIM 使用 vimrc 更改折叠 markdown 以显示行数和字数

VIM change folding markdown to show lines and number of words using vimrc

我在 windows 上使用 GVIM 来写科幻小说,我会折叠章节以便将它们隐藏起来。折叠章节 'lines' 时显示如下:

##1 – Spaceman Spoof Encounters the Watterson........ 115 lines [2.4%] +--+--

这很有用,但只有一点点。有些行可能只有几个字,而其他行可能超过 100 个字。我更喜欢这样的行数和字数:

##1 – Spaceman Spoof Encounters the Watterson........ l:115 w:1032 [4.4%] +--+--

百分比是单词的百分比,而不是行的百分比。任何帮助都将不胜感激。

这是我的 _vimrc 的折叠部分:

function! MarkdownFolds()
    let thisline = getline(v:lnum)
    if match(thisline, '^##') >= 0
        return ">2"
    elseif match(thisline, '^#') >= 0
        return ">1"
    else
        return "="
    endif
endfunction

setlocal foldmethod=expr
setlocal foldexpr=MarkdownFolds()

function! MarkdownFoldText()
    "get first non-blank line
    let fs = v:foldstart
    while getline(fs) =~ '^\s*$' | let fs = nextnonblank(fs + 1)
    endwhile
    if fs > v:foldend
        let line = getline(v:foldstart)
    else
        let line = substitute(getline(fs), '\t', repeat(' ', &tabstop), 'g')
    endif

    let w = winwidth(0) - &foldcolumn - (&number ? 8 : 0)
    let foldSize = 1 + v:foldend - v:foldstart
    let foldWords = v:foldend,v:foldstart!wc -w
    let foldSizeStr = " " . foldSize . " lines "
    let foldWordsStr = " " . foldWords . " w "
    let foldLevelStr = repeat("+--", v:foldlevel)
    let lineCount = line("$")
    let foldPercentage = printf("[%.1f", (foldSize*1.0)/lineCount*100) . "%] "
    " let expansionString = "."
    let expansionString = repeat(".", w - strwidth(foldSizeStr.line.foldLevelStr.foldPercentage))
    return line . expansionString . foldSizeStr . foldPercentage . foldLevelStr
    " return line . expansionString . foldSizeStr . foldPercentage . foldWordsStr . foldLevelStr
    " return line . "......" . foldSizeStr . foldPercentage . foldLevelStr
endfunction

setlocal foldtext=MarkdownFoldText()

解决方法如下:

function! MarkdownFoldText()
    "get first non-blank line
    let fs = v:foldstart
    while getline(fs) =~ '^\s*$' | let fs = nextnonblank(fs + 1)
    endwhile
    if fs > v:foldend
        let line = getline(v:foldstart)
    else
        let line = substitute(getline(fs), '\t', repeat(' ', &tabstop), 'g')
    endif

    let w = winwidth(0) - &foldcolumn - (&number ? 8 : 0)
    let foldSize = 1 + v:foldend - v:foldstart

    let i = 0
    let foldWords=0
    let wordCount=0
    while (i<line('$'))
      let lineWords = len(split(getline(i)))
      if (i<=v:foldend && i>= v:foldstart)
        let foldWords = foldWords + lineWords
      endif
      let wordCount += lineWords
      let i += 1
    endwhile

    let foldWordsStr = " " . foldWords . " w,"
    let foldSizeStr = foldWordsStr . foldSize . " lines "
    let foldLevelStr = repeat("+--", v:foldlevel)
    let foldPercentage = printf("[%.1f", (foldWords*1.0)/wordCount*100) . "%] "
    let expansionString = repeat(".", w - strwidth(foldSizeStr.line.foldLevelStr.foldPercentage))
    return line . expansionString . foldSizeStr . foldPercentage . foldLevelStr
endfunction

思路是统计全局字数,同时统计刚好在选中区域的字数。

然后我们按照要求用字数代替百分比。

这是另一个解决方案,这次使用 wordcount() 函数:

function! MarkdownFoldText()
    "get first non-blank line
    let fs = v:foldstart
    while getline(fs) =~ '^\s*$' | let fs = nextnonblank(fs + 1)
    endwhile
    if fs > v:foldend
        let line = getline(v:foldstart)
    else
        let line = substitute(getline(fs), '\t', repeat(' ', &tabstop), 'g')
    endif

    let w = winwidth(0) - &foldcolumn - (&number ? 8 : 0)
    let foldSize = 1 + v:foldend - v:foldstart

    let i = v:foldstart
    let foldWords=0
    while (i<v:foldend)
      let lineWords = len(split(getline(i)))
      let foldWords = foldWords + lineWords
      let i += 1
    endwhile
    let wordCount = wordcount()["words"]

    " let foldWords = v:foldend,v:foldstart!wc -w
    let foldWordsStr = " " . foldWords . " w,"
    let foldSizeStr = foldWordsStr . foldSize . " lines "
    let foldLevelStr = repeat("+--", v:foldlevel)
    let foldPercentage = printf("[%.1f", (foldWords*1.0)/wordCount*100) . "%] "
    " let expansionString = "."
    let expansionString = repeat(".", w - strwidth(foldSizeStr.line.foldLevelStr.foldPercentage))
    return line . expansionString . foldSizeStr . foldPercentage . foldLevelStr
    " return line . expansionString . foldSizeStr . foldPercentage . foldWordsStr . foldLevelStr
    " return line . "......" . foldSizeStr . foldPercentage . foldLevelStr
endfunction

应该会更快。并不是说百分比是这个文件夹与整个缓冲区相比所占的比例。使用 wordcount() 函数,我们离终点还有多远将变得微不足道。