while ("im the true Vim master");

2009-08-29

Re: オプションをトグルする関数 - bugfix

08:28

スマートな解の方は既に発見されていたので、最初に書かれたスクリプトの駄目なところの解説。

 1  " 関数の概要
 2  " void Toggle_option(String)
 3  " Stringで与えられたbooleanオプションをトグルする。
 4  " 使い方:
 5  " Toggle_option('number')
 6  " Toggle_option('nonumber')
 7  function! Toggle_option(target_opt)
 8    " 次の場合エラーになる可能性がある
 9    " 1. a:target_optが'no'から始まるが、その後に続く文字列が
10    "    Vimのオプションに存在するものでない場合
11    "    a:target_optの例) noabcdefg
12    " 2. a:target_optが'no'から始まらず、文字列全体が
13    "    Vimのオプションに存在するものでない場合
14    "    a:target_optの例) abcdefg
15    if (a:target_opt =~# "no.*")
16      let s:target_inv_opt = a:target_opt[2:]
17      let s:opt_added_amp = '&' . eval('s:target_inv_opt')
18    else
19      let s:target_inv_opt = 'no' . a:target_opt
20      let s:opt_added_amp = '&' . eval('a:target_opt')
21    endif
22  
23    if eval(s:opt_added_amp)
24      execute 'setlocal' s:target_inv_opt
25    else
26      execute 'setlocal' a:target_opt
27    endif
28    unlet s:target_inv_opt
29    unlet s:opt_added_amp
30  endfunction
オプションをトグルする関数 - bugfix

(行番号は説明のためこちらで追加しました)

  • 関数内は関数内ローカル変数(l:)が使えるから、このケースでスクリプトローカル変数(s:)を使う必要はない。
    • l:は基本的に不要。
  • 15行目の条件式a:target_opt =~# "no.*" 'ignorecase'などにもマッチする。正しくはa:target_opt =~# '^no'
  • 17行目/20行目/23行目のeval()は不要。もしこれが必要だというのであれば変数の値を参照している箇所全て(例えば16行目や19行目)でeval()を使わないとおかしい。
    • eval()を実際に使う場合はeval('variable')ではなくeval(variable)としないと意味がない。
  • 最近発覚した、10年以上もの間Vimに潜んでいたバグに対処できていない。実はviとの互換性のために用意された'novice'というオプションがありまして、これはnoで始まるので……
トラックバック - http://vim.g.hatena.ne.jp/ka-nacht/20090829
最近のコメント
あわせて読みたいブログパーツ
AX