43 howm-mode.vim (2-21) action-lock の強化
http://howm.sourceforge.jp/cgi-bin/hiki/hiki.cgi?UsageActionLock の action-lock 追加の例を見ていいなと思ったので、これができるようにしてみた。目標としては、vimrc にリストを書くと action-lock に追加されること。
plugin/howm-mode.vim
まずは plugin/howm-mode.vim の修正。グローバル変数を追加する。
if v:version >= 700 && !exists('g:howm_actionlock_list') let g:howm_actionlock_list = [] endif
次に、s:DoActionLock() に、先に追加したグローバル変数を解釈するコードを追加する。ほとんど、コピペ。既存の action-lock にマッチせず、Vim7 のときだけ実行します。
function! s:DoActionLock() " ... endwhile if v:version >= 700 && func == '' for actionlock in g:howm_actionlock_list if has_key(actionlock, 'func') && has_key(actionlock, 'pat') let j = 0 let head = match(str, actionlock['pat']) let tail = matchend(str, actionlock['pat']) while head != -1 && cur >= j && func == '' if head <= cur && cur < tail call call(actionlock['func'], [matchstr(str, actionlock['pat'], j), head + 1]) return elseif j != tail let j = tail let head = match(str, actionlock['pat'], j) let tail = matchend(str, actionlock['pat'], j) else break endif endwhile elseif has_key(actionlock, 'list') " actionlock['list'] のうちからマッチするか確認し、 " マッチしたら、マッチした次の要素と切り替える let head = -1 let idx = -1 let len = -1 for i in range(len(actionlock['list'])) let word = actionlock['list'][i] let len = strlen(word) let sidx = stridx(str, word) while sidx != -1 if (sidx <= cur) && (cur < sidx + len) let head = sidx break endif let sidx = stridx(str, word, sidx + len) endwhile if head != -1 let idx = i break endif endfor if idx != -1 && head != -1 && len != -1 let next = actionlock['list'][(idx + 1) % len(actionlock['list'])] call cursor(line('.'), head + 1) silent! exe "normal! c".len."l".next."\<ESC>" call cursor(line('.'), cur + 1) return endif else " TODO: エラーメッセージ endif endfor endif if func != '' " ... endfunction
vimrc
今度はリストの作成。これは vimrc に追加する。howm-mode.vim に追加するのは面倒すぎて誰もやらない。vimrc なら移行も簡単!例の wiki のものの他に例を二つほど挙げてみた。
function! HowmActionlockSnoopy(str, head) echo 'よく見るとスヌーピーには似ていない' endfunction let g:howm_actionlock_list = [ \ { \ 'list': [ \ '[ ]', \ '[ : 0%]', \ '[+ : 10%]', \ '[++ : 20%]', \ '[+++ : 30%]', \ '[++++ : 40%]', \ '[+++++ : 50%]', \ '[++++++ : 60%]', \ '[+++++++ : 70%]', \ '[++++++++ : 80%]', \ '[+++++++++ : 90%]', \ '[++++++++++:100%]' \ ], \ }, \ { \ 'func': function('HowmActionlockSnoopy'), \ 'pat': 'でつ' \ }, \ { 'list': ['[o]', '[x]'] } \ ]
syntax/howm_memo.vim
ここまでで動くのは動くけど、やっぱり action-lock なら action-lock のハイライトしてほしい。というわけで syntax/howm_memo.vim に追加。
if v:version >= 700 for actionlock in g:howm_actionlock_list if has_key(actionlock, 'pat') exe 'syntax match howmActionLock display "'.actionlock['pat'].'"' elseif has_key(actionlock, 'list') for word in actionlock['list'] exe 'syntax match howmActionLock display "\V'.escape(word,'\').'"' endfor endif endfor endif
これで完成。目標どおりに以下のように動いてくれる。
[ ] → [ : 0%] → [+ : 10%] → ...
他の例もちゃんと動く。「でつ」にカーソルを置いて ENTER を叩くとメッセージが表示される。「[o]」と「[x]」は交互に入れ替わる形になる。
使い方の説明
g:howm_actionlock_list には List 型の変数を入れる。この List の要素は Dictionary 型の変数である。この Dictionary 型のキーのうち三つのキーが特別な意味をもつ。
- list ... 文字列のリスト。これらの文字列にカーソルを置いて ENTER を叩くと、文字列をリストの次の要素に置換する。最後の要素まで行くと最初の要素に戻る。
- pat ... func と組み合わせて使う。Vim の正規表現。このパターン上で ENTER を叩くと、組み合わせてある func にマッチした文字列とその先頭位置が渡される。
- func ... pat と組み合わせて使う。既存の action-lock の関数と同様に動作する。第一引数にマッチした文字列、第二引数にマッチした文字列の先頭位置が渡される。
これで action-lock 追加が手軽に?なりました。
そろそろ
友人に「お前の修正についていけないから、そろそろ、まとめて公開してくれ」と言われた。どうするかな。連絡とって公開するか、パッチつくるかな。