Vim Advent Calendar 2013 126日目:Vim で一時的に変更したオプションの値を安全に戻す
この記事は Vim Advent Calendar 2013 126日目の記事になります。
さて、プラグインなどを作っている場合、オプションなどの値を一時的に変更したい事があると思います。
function! Func() " 一時的に値を変更する let old_selection = &selection let &selection = 'inclusive' " ... なにか処理 ... " 値を戻す let &selection = old_selection endfunction
しかし、上記のようなコードでは途中で例外が発生した場合、そこで処理が中断されてしまう可能性がある為、元の値に正しく戻さない可能性があります。
function! Func() " 一時的に値を変更する let old_selection = &selection let &selection = 'inclusive' " throw した場合、以降の処理が呼ばれない throw "homu" " 値が戻らない let &selection = old_selection endfunction
こういう場合は finally を使用することで回避する事ができます。
function! Func() " 一時的に値を変更する let old_selection = &selection let &selection = 'inclusive' try " 例外が発生しても finally の処理は呼ばれる throw "homu" finally " 例外が発生しても呼ばれる let &selection = old_selection endtry endfunction
また、 finally は例外以外にも途中で return した場合にも呼ばれます。
function! Func() " 一時的に値を変更する let old_selection = &selection let &selection = 'inclusive' try " 途中で関数を抜ける if g:flag return endif finally " 途中で return しても呼ばれる let &selection = old_selection endtry endfunction
このようにオプションなどを一時的に変更する場合は finally を使用するとより安全に戻す事ができます。
[おまけ]
最近気づいたのですが、以下のように return した値を finally で書き換えるとどうなるのでしょうか。
function! Func() let old_selection = &selection let &selection = 'inclusive' try return &selection finally " return する値を書き換える let &selection = old_selection endtry endfunction let &selection = 'exclusive' echo Func() echo &selection
[答え]
inclusive exclusive
どうやら return を呼び出した時点での値を返すようですね。
[おまけ2]
では、辞書の場合はどうだろうか。
function! Func() let result = { "name" : "homu" } try return result finally " 辞書の値に代入する let result.name = "mami" endtry endfunction echo Func().name
[答え]
mami
finally のタイミングで辞書の値を書き換えた場合は反映されるようですね。
ちなみにこれは copy() なりで防ぐことは可能です。
" copy() を返す return copy(result)
面白そうなので何かに利用できないかなー。