2011年12月31日土曜日

[vim][python] ふははは!読める!読めるぞ!

その経緯


pythonを書くとき、classやdefを折りたたむためのスクリプトを書こうと思いました。

とりあえず探してみると、あった。
python_fold : Folding expression for python

中身を見てみて、少しテンションあがった。

読める!。downloadしてきたプラグインが読める!

少しはvim scriptが読めるようになってきました。

このpython_foldを読んでみた感想は・・・。
長い。そして、if文の嵐。
個人的に使うならもっとコンパクトにまとめれそうな気がしました。



理想


ロジックとしては、以下のような感じ。
① classやdefを見つけたら、その行のインデントにあわせて、fold開始。
② 直下が空行かつ、次の非空行のインデントが現在のfoldlevelより小さければ、foldを閉じる。
③ それ以外の場合は、前の行と同じ操作。

これをvim scriptで書くとこんな感じになるはず。

" 折り畳みレベルを設定する関数(python)
function! PYTHONFoldSetting(lnum)

    " 現在の行
    let line = getline(a:lnum)
    let ind  = indent(a:lnum)
    let flev = foldlevel(a:lnum)

    " 次の行
    let line1 = getline(a:lnum + 1)

    " 次の非空行
    let nind = indent(nextnonblank(a:lnum + 1))

    " Classes and functions get their own folds
    if line =~ '^\s*\(class\|def\)\s'
        return '>'. (ind / &sw + 1)
    elseif empty(line1) && (nind / &sw + 1) <= flev
        return '<'.flev
    else
        return '='
    endif
endfunction
しかし、動かないorz。 foldlevel関数でとってこれてないのかな・・。


妥協

どうしても動かないので、 仕方なしで以下のように妥協。
function! PYTHONFoldSetting(lnum)
    " foldlevelは3まで
    set foldnestmax=3

    " 現在の行
    let line = getline(a:lnum)
    let ind  = indent(a:lnum)
    let flev = foldlevel(a:lnum)

    " 次の行
    let line1 = getline(a:lnum + 1)

    " 次の非空行
    let nind = indent( nextnonblank(a:lnum + 1) )

    " Classes and functions get their own folds
    if line =~ '^\s*\(class\|def\)\s'
        return '>'. (ind / &sw + 1)
    elseif ind > nind && empty(line1) && (nind / &sw + 1) == 1
        return '<'.1
    elseif ind > nind && empty(line1) && (nind / &sw + 1) == 2
        return '<2'
    elseif ind > nind && empty(line1) && (nind / &sw + 1) == 3
        return '<3'
    else
        return '='
    endif
endfunction

まぁ動作としては変わらないし、3段階以上ネストすることもないだろうから、
実用上これで良いかもしれないが、
やっぱ気持ち悪いな・・・。

0 件のコメント:

コメントを投稿