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 追加が手軽に?なりました。

そろそろ

友人に「お前の修正についていけないから、そろそろ、まとめて公開してくれ」と言われた。どうするかな。連絡とって公開するか、パッチつくるかな。