42 howm-mode.vim (2-20) s:ShowSchedule() のなぞのエラーを修正

Vim を起動した直後に ,y などで検索一覧 ( s:ShowSchedule() ) を実行する。その後プレビューを表示させてから、:q 。これでエラーが出る。自分の環境だけかもしれないけど、不快なので修正する。エラーは以下。

E315: ml_get: 無効なlnumです: 93
E315: ml_get: 無効なlnumです: 93
E315: ml_get: 無効なlnumです: 93
続けるにはENTERを押すかコマンドを入力してください

ここから、さらに放置すると( 設定によっては ) s:ShowPreview() ががんばってくれて、追加で大量のエラーが出る。

E121: 未定義の変数です: b:file1
...

s:ShowPreview() の修正

まず、原因がはっきりしている s:ShowPreview() を修正する。これは変数の有無を確認せずに使っているためにおきるエラーなので、exists() で確認をしてやる。追加するのは一行。以前の変更もあわせて整理してみた。

" TODO:howm_dir 以下のファイルは howm_fileencoding でプレビューして,それ以
" 外の判別は Vim に任せる?
function! s:ShowPreview()
  let l = line('.')
  if exists('b:lastPreviewLine') && (b:lastPreviewLine == l) | return | endif
  let b:lastPreviewLine = l
  if !exists('b:file'.l) || !exists('b:line'.l) | return | endif
  let previewList = b:file{l}.':'.b:line{l}."\<NL>"
  let buf = bufname('%')
  call s:OpenTemporalWindow(escape(s:prefix_howm.s:buftitle_preview, ' '), 1)
  call s:HighlightPreview()
  call s:ParsePreviewList(previewList)
  call s:FormatPreviewList()
  let head = strpart(b:region1, 0, matchend(b:region1, '\d*')) + 0
  call cursor(b:line1 - head + s:num_previewheader_lines + 1, 1)
  silent! normal! zz
  silent! exe bufwinnr(buf).'wincmd w'
endfunction

E315 の原因を調べる。

E315 の原因を調べる。といっても自分にはそんな知識はないので、どんな状況で起きるかだけを調べる。

  • :q したときに起きる
  • プレビュー機能を利用すると起きる
  • 検索結果一覧では起きないが予定一覧では起きる
  • s:ShowSchedule() の中の cursor() をコメントアウトすると起きない

適当に試してみたけど、よくわからない。cursor() のせいな気もするけど、特におかしいことをしているようには見えない。そもそも、cursor() に不正な引数を渡したとしても E315 は出ない。とりあえず、最後に閉じるウィンドウが検索結果のそれだからまずいし、それをうまく閉じれていないようなので、そこを修正する。

autocmd の部分を見て、s
EliminateWindow() が呼ばれているのを確認。s:EliminateWindow() は指定したバッファ名のウィンドウを閉じるらしい。でも、なにやらよくわからないこと*1をしている。あと、最後の一つをうまく閉じれないみたい。間に自作関数をはさんでみる。
exe 'autocmd BufDelete '.escape(s:prefix_howm.s:buftitle_ftresult, ' ').' call s:ClosePreviewWindow()'

function! s:ClosePreviewWindow()
  let pwin = escape(s:prefix_howm.s:buftitle_preview, ' ')
  let rwin = escape(s:prefix_howm.s:buftitle_ftresult, ' ')
  let n = winnr('$')
  let i = 1
  while i <= n
    exe i "wincmd \<C-w>"
    let bname = bufname('%')
    echo bname
    if (bname !~# pwin) && (bname !~# rwin)
      break
    endif
    let i = i + 1
  endwhile
  if i > n | new | endif
  call s:EliminateWindow(pwin)
endfunction

ウィンドウが検索結果とプレビューだけだった場合は :new を実行するように。それだけ。あんまりちゃんと動作確認してないけど、とりあえず、エラー消えたのでよし。

*1::closeを使っているのに &modified を確認したり、s:GetWinNum() とウィンドウの個数を返す関数を自作したり