75 encodeURI, encodeURIComponent

辞書引きスクリプト dicwin.vim が良かったので、自分でも似たようなのを作りたくなった。

まずは辞書の元データが必要なのだが、手ごろなのが見つからない。仕方がないのでウェブにアクセスして取得することにした。せっかくなので、alice.vim を活用する。

nnoremap \dy :call AL_open_url(
      \ 'http://dic.yahoo.co.jp/dsearch?enc=UTF-8&stype=0&dtype=2&p=' .
      \ expand('<cword>'), '')<CR>

とりあえず、ブラウザに表示することができるようになった。ただ、やはり日本語などを直接URLと結合するのは良くない気がしたので、JavaScript で言うところの encodeURI, encodeURIComponent を作成することにした。で、こちらにできあがったものがございます(三分間クッキング的な意味で)。

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: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

あまり JavaScript とか URLエンコードとかのことを知らないので、http://diaspar.jp/node/148 あたりを見ながら書いた。(ところで普段から Vim スクリプトを書いている方はどんな風にマルチバイト処理をしているのでしょうか)

作ったものを使って、再度マッピング

nnoremap \dy :call AL_open_url(
      \ 'http://dic.yahoo.co.jp/dsearch?enc=UTF-8&stype=0&dtype=2&p=' .
      \ <SID>encodeURIComponent(expand('<cword>')), '')<CR>

できたー。辞書引きよりもURLエンコードの方が中心になので題は encode* とした。