59 howm-mode.vim (2-30) WebImport() のパーセントエンコードの扱いを修正

いつものように howm-mode.vim 。s:ActionLockWebImport() で Wikipedia の日本語記事が取り込めないことに気付いた。原因はすぐに分かった。% のエスケープだった。

なにか実行するときはエスケープをしよう

:h cmdline-special
:h cmdline
:h :_%
:h :_#
:h :_##

Exコマンド上で % や # などの文字はファイル名に置換される。それが考慮されていないため、s:ActionLockWebImport() は、URL に % や # を含む場合に正しく動作しない。本来は なども回避すべきだろうけど、URL に < や > は、本来含まれていないはずなので、今回はスルー。今回、問題になった実行部分を以下のように修正

silent! exe "0r!" . escape(cmd, '%#')

ついでに substitute() でもエスケープをしよう

:h sub-replace-special
:h substitute()
:h :s

ついでに書くと substitute() の sub は通常の文字列ではなく特殊文字 ( sub-replace-special ) として解釈されるので、\ をエスケープしておいた方が良い。magic のときは、& や ~ も危険。substitute() の場合は常に magic として扱われるので、常にこれらもエスケープする。まとめると、ごくごく普通の文字列置換をする場合、置換後の文字列に対しては以下のような処理をすべき。 ( ちなみに今回の URL の場合は \ は含まれることがない文字なので、実際はエスケープする必要はない )

let str = substitute(str, pat, escape(sub, '~&\'), 'g')

で、今回の修正内容

function! s:ActionLockWebImport(str, head)
  " ...
  vnoremap <silent> <buffer> <CR> "zy :call <SID>WebImport()<CR>
  let cmd = substitute(g:howm_html2txtcmd, '%s', escape(url, '~&\'), "g")
  silent! exe "0r!" . escape(cmd, '%#')
  setlocal nomodifiable
  call cursor(1, 1)
endfunction

あと、おわび

昨日、公開したパッチがバグで動かなかったので修正して上げなおしておきました。すいません。いや、たぶん誰も使ってないだろうけど。あ、ちなみに、今日書いた分( webimport )は含まれてません。