76 dicwin2.vim (5-2) echo で表示できるようにした
辞書引きプラグイン作成のお話。手ごろな名前が思い浮かばないのでひとまず dicwin2.vim としておく。
昨日はごめん ( AL_urlencode() )
昨日、あたかも当然のように encodeURI, encodeURIComponent を書いたんだけど、よくよく見てみると alice.vim の AL_urlencode() なんてのがある。ほとんど同じ動作みたい。既存のものを有効活用してください。そちらをご利用ください。うん。
今日は HTML の取得、解釈、表示
さてさて、車輪のなんとかをしてしまったわけだが、気にしないで進む。昨日は、ブラウザで表示までができた。今日は、 HTML を取得して解釈して echo コマンドで表示と、ここまでやってみる。そしてこちらにできあが(ry
function! s:YahooKokugo(html) let s = iconv(a:html, 'utf-8', &enc) let s = get(matchlist(s, '<body\>\_.\{-}>\(\_.*\)</body>'), 1, '') let s = get(matchlist(s, '<div id="contents">\(\_.*\)</div>'), 1, '') let s = get(matchlist(s, '<div align="center">\(\_.*\)</div>'), 1, '') let s = get(matchlist(s, '<td valign="top">\(\_.*\)</td>'), 1, '') let t = get(matchlist(s, '<b>\(.\{-}\)</b>'), 1, '') let s = get(matchlist(s, '<table\(\_.\{-}\)</table>', 0, 3), 1, '') let d = get(matchlist(s, '<td>\(.\{-}\)</td>'), 1, '') let d = substitute(d, '<br\s*/\{0,1}>', "\n", 'g') let t = substitute(t, '<.\{-}>', '', 'g') let d = substitute(d, '<.\{-}>', '', 'g') return {'title': t, 'description': d} endfunction let g:dicwin2_dict = { \ 'url': \ 'http://dic.yahoo.co.jp/dsearch?enc=UTF-8&stype=0&dtype=0&p=%keyword%', \ 'parser': \ function('s:YahooKokugo') \ } silent! nnoremap <unique> <silent> \dy :call AL_open_url( \ 'http://dic.yahoo.co.jp/dsearch?enc=UTF-8&stype=0&dtype=2&p=' . \ <SID>encodeURIComponent(expand('<cword>')), '')<CR> silent! nnoremap <unique> <silent> \dY :call <SID>dicwin2()<CR> function! s:dicwin2() let dict = g:dicwin2_dict let keyword = s:encodeURIComponent(expand('<cword>')) let url = s:replace(dict['url'], '%keyword%', keyword) let cmd = 'curl "%URL%"' let cmd = s:replace(cmd, '%URL%', url) let html = system(cmd) let list = call(dict['parser'], [html]) echo list['title'] echo list['description'] endfunction function! s:encodeURI(str) let to_enc = 'utf8' let t = '' let s = iconv(a:str, &enc, to_enc) let save_enc = &enc let &enc = to_enc let i = 0 let c = s:strpart2(s, i, 1) while c != '' if c =~# '[0-9A-Za-z-._~!''()*]' || c =~# '[#$&+,/:;=?@]' let t = t . c elseif c =~# '[:cntrl:]' else let n = strlen(c) let j = 0 while j < n let t = t . printf('%%%02X', char2nr(strpart(c, j, 1))) let j = j + 1 endwhile endif let i = i + 1 let c = s:strpart2(s, i, 1) endwhile let &enc = save_enc let t = iconv(t, to_enc, &enc) return t endfunction function! s:encodeURIComponent(str) let to_enc = 'utf8' let t = '' let s = iconv(a:str, &enc, to_enc) let save_enc = &enc let &enc = to_enc let i = 0 let c = s:strpart2(s, i, 1) while c != '' if c =~# '[0-9A-Za-z-._~!''()*]' let t = t . c elseif c =~# '[:cntrl:]' else let n = strlen(c) let j = 0 while j < n let t = t . printf('%%%02X', char2nr(strpart(c, j, 1))) let j = j + 1 endwhile endif let i = i + 1 let c = s:strpart2(s, i, 1) endwhile let &enc = save_enc let t = iconv(t, to_enc, &enc) return t endfunction function! s:replace(s, t, r) return substitute(a:s, '\C\V' . escape(a:t, '\'), escape(a:r, '&~\'), 'g') endfunction function! s:strpart2(src, start, ...) let len = exists('a:1') ? a:1 : 0 let pat = '' let pat = pat . '^.\{' . a:start . '}\zs.' let pat = pat . (len > 0 ? '\{' . len . '}' : '*' ) . '\ze' return matchstr(a:src, pat) endfunction
ごちゃごちゃしているけど、まだ vimrc に書いてる段階だから気にしない。folding を使用すればこれくらいなら気にならない。
まず、マッピング \dY を追加した。これがスクリプトローカル関数 dicwin2() を呼び出す。この関数では、辞書型のグローバル変数 dicwin2_dict から、アクセスする先の URL である url と、それを解釈するための関数参照型である parser を取り出して、使用する。カーソルの下のキーワードを URL に適当に組み込んで、curl で HTML を取得する。取得した HTML を parser に渡す。辞書型が帰ってくるので、title と description を表示する。
とりあえず Yahoo の国語辞典を解釈できるようにしてみた。表示形式変わったら困るだろうけど、それはスクリプトローカル関数 YahooKokugo() の修正で対応する。これは、よくあるパターンのはず。
ごちゃごちゃ書いてるけど、要は、昨日ブラウザで表示されてたものが echo コマンドで表示されるようになったってこと。
見つからなかったときの処理がされていなかったり、 echo コマンドだから引用がしにくかったり。そのあたりをまた改良していくつもり。