例えば、YAML フォーマット (1_4) – SymfonyにあるYAML

“symfony 1.0”:
    
end\_of\_maintenance: 2010-01-01
    
is_stable: true
    
release_manager: “Gregoire Hubert”
    
description: >
      
This stable version is the right choice for projects
      
that need to be maintained for a long period of time.
    
latest_beta: ~
    
latest_minor: 1.0.20
    
supported_orms: [Propel]
    
archives: { source: [zip, tgz], sandbox: [zip, tgz] }

“symfony 1.2”:
    
end\_of\_maintenance: 2008-11-01
    
is_stable: true
    
release_manager: ‘Fabian Lange’
    
description: >
      
This stable version is the right choice
      
if you start a new project today.
    
latest_beta: null
    
latest_minor: 1.2.5
    
supported_orms:
      
– Propel
      
– Doctrine
    
archives:
      
source:
        
– zip
        
– tgz
      
sandbox:
        
– zip
        
– tgz

を例にするとfoldmethod=indentに設定している場合、折りたたみのレベルが1の場合

“symfony 1.0”:
  
+– 10 行: end\_of\_maintenance: 2010-01-01—————————
  
_
  
“symfony 1.2”:
  
+– 18 行: end\_of\_maintenance: 2008-11-01—————————

のようになり、レベル2の場合

“symfony 1.0”:
    
end\_of\_maintenance: 2010-01-01
    
is_stable: true
    
release_manager: “Gregoire Hubert”
    
description: >
  
+— 2 行: This stable version is the right choice for projects—-
    
latest_beta: ~
    
latest_minor: 1.0.20
    
supported_orms: [Propel]
    
archives: { source: [zip, tgz], sandbox: [zip, tgz] }
  
_
  
“symfony 1.2”:
    
end\_of\_maintenance: 2008-11-01
    
is_stable: true
    
release_manager: ‘Fabian Lange’
    
description: >
  
+— 2 行: This stable version is the right choice—————–
    
latest_beta: null
    
latest_minor: 1.2.5
    
supported_orms:
  
+— 2 行: – Propel————————————————
    
archives:
  
+— 6 行: source:————————————————-

のようになるが、これを、レベル1の場合

+– 11 行: “symfony 1.0”:——————————————-
  
_
  
+– 19 行: “symfony 1.2”:——————————————-

とし、レベル2の場合

“symfony 1.0”:
    
end\_of\_maintenance: 2010-01-01
    
is_stable: true
    
release_manager: “Gregoire Hubert”
  
+— 3 行: description: >——————————————
    
latest_beta: ~
    
latest_minor: 1.0.20
    
supported_orms: [Propel]
    
archives: { source: [zip, tgz], sandbox: [zip, tgz] }

“symfony 1.2”:
    
end\_of\_maintenance: 2008-11-01
    
is_stable: true
    
release_manager: ‘Fabian Lange’
  
+— 3 行: description: >——————————————
    
latest_beta: null
    
latest_minor: 1.2.5
  
+— 3 行: supported_orms:—————————————–
  
+— 7 行: archives:———————————————–

のようにしたい。

Advanced Folding / Learn Vimscript the Hard Wayにそのようなfoldingをさせるためのfoldexprの方が載っている。

ただし、s:NextNoBlankLine()の処理の部分は組み込みのnextnonblank()に変更した。

以下のようなファイルを作成し、

function! s:IndentLevel(lnum)
    return indent(a:lnum) / &shiftwidth
endfunction

function! s:NextNonBlankLine(lnum)
    let lnum = nextnonblank(a:lnum)
    if lnum == 0
        return -2
    else
        return lnum
endifendfunction

function! fold#indent(lnum)
    if getline(a:lnum) =~? '\v^\s*$'
        return '-1'
    endif

    let this_indent = s:IndentLevel(a:lnum)
    let next_indent = s:IndentLevel(s:NextNonBlankLine(a:lnum))

    if next_indent == this_indent
        return this_indent
    elseif next_indent < this_indent
        return this_indent
    elseif next_indent > this_indent
        return '>' . next_indent
    endif
endfunction

たとえばYAMLで適応したい場合はftpluginとして、

if exists('b:did_my_after_ftplugin_yaml')
  finish
endif
let b:did_my_after_ftplugin_yaml = 1

setlocal foldmethod=expr foldexpr=fold#indent(v:lnum) softtabstop=2 shiftwidth=2

を作成する。softtabstop=2 shiftwidth=2はお好みで。

ただ、インデントのレベルを出すために、s:IndentLevelの中でshiftwidthの値を使っているため、自分の設定ファイルでは2にしていても、開いたファイルがスペース4のインデントになっていた場合うまくいかない。そこで、開いたファイルを解析して、自動的にshiftwidthを設定するプラグインを使う。

これをインストールしてファイルを開いたら自動的にコマンドを実行するようにvimrcに

augroup MyVimrc
    autocmd!
augroup END

autocmd MyVimrc BufWinEnter *
\   let g:detectindent_preferred_indent = &shiftwidth
\|  if &expandtab == 0
\|      unlet g:detectindent_preferred_expandtab
\|  else
\|      let g:detectindent_preferred_expandtab = 1
\|  endif
\|  DetectIndent

と書いておく。ftpluginをロードした後に実行したいので、autocmdにBufWinEnterを使う。

解析できなかった時のshiftwidthの値として、現在のshiftwidthを使うように6行目で設定、expandtabについても7行目から11行目で設定している。

そして12行目でコマンド実行。

これでよし。