Vim 的 Outline 模式

今天要写一个逻辑结构比较明朗的文档,Emacs 的 outline mode 是很好的,但是太久不用了,实在习惯不了 Emacs 的操作方式,Vim 怎么就没有这样的模式呢?Google 了一下,找到了这个: Emacs outline mode for Vim,就在 vim.org 的网站上。把这个 outline.vim 下载下来之后放到 ~/.vim/syntax/ 下面就行了,用的时候 :set ft=outline 就激活这个模式,可以自己调整一下颜色。Outline 模式的格式很简单:

* 一级标题
** 二级标题
*** 三级标题
**** 四级标题

依此类推。

Win32 版本的 gvim 是要放到自己的主目录下的 vimfiles\syntax\ 下面,主目录就是 USERPROFILE 这个环境变量的值,一般就是 C:\Documents and Settings\USERNAME

这里的 ~/.vim 和 vimfiles 目录可以在 vim 里用 :set runtimepath 看到。

贴一下代码,以防原链接失效。

File: syntax/outline.vim
"
" Description:
"
"   This uses folding to mimic outline-mode in Emacs.  Set filetype to
"   'outline' to activate this functinality.  Put it in the modeline to
"   preserve outlines between edits.  For example:
"
"            vim:set ft=outline:
"
" Installation:
"
" Place this file in your home directory under ~/.vim/syntax/, or in the
" system location under the syntax/ directory to provide it to all users
"
" Maintainer: Tye Z. 
"
" Customization:
"
"   The colors of the outline headers can be changed by linking them to
"   whatever you like.  For example:
"
"       hi! link Outline_1 Statement
"
" History:
"
"   Version 1.1:
"
"       - Initial version
"

"
" Highlighting for the section header lines. Add to more levels here.
"
syn match Outline_1   /^\*\{1\}[^*].*$/
syn match Outline_2   /^\*\{2\}[^*].*$/
syn match Outline_3   /^\*\{3\}[^*].*$/
syn match Outline_4   /^\*\{4\}[^*].*$/

"hi! default link Outline_1 Comment
"hi! default link Outline_2 Identifier
"hi! default link Outline_3 PreProc
"hi! default link Outline_4 Type

hi Outline_1 cterm=underline ctermfg=4 gui=bold,underline guifg=Blue
hi Outline_2 cterm=underline ctermfg=3 gui=bold,underline guifg=Brown
hi Outline_3 cterm=underline ctermfg=5 gui=bold,underline guifg=Magenta
hi Outline_4 cterm=underline ctermfg=6 gui=bold,underline guifg=SeaGreen

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

setl foldmethod=expr
setl foldexpr=OutlineFoldFunc()

function! OutlineFoldFunc()
let line = getline(v:lnum)
" If the current line starts with a '*', then this is start of a fold
if line =~ '^\*'
    return ">" . matchend(line, "^\**")
else
    " Since this is not the start of a fold, see if this is the END of
    " one. We are at the end of a fold when the next line has nothing
    " but whitespace, and the following line is the start of a fold.
    " We look two lines ahead so we can display only the LAST blank
    " line.  If there are no blank lines, then the start of the next
    " fold will automatically end this one.
    let line2 = getline(v:lnum+1)
    if line2 =~ '^\s*$'
        let line3 = getline(v:lnum+2)
        if line3 =~ '^\*'
            return "<" . matchend(line3, "^\**")
        endif
    endif
endif
return "="  " fold-level has not changed
endfunction

它的折叠功能还不够完善,如果不喜欢,把 setl foldmethod=expr 那句注释掉就行了。