Vim の Rubyインターフェースを使ってみた

Rubyインターフェースを使い、ファイルのパスをゴニョゴニョするための一連のユーティリティ関数を書いてみた。それぐらい Vim script で書けよ、というものが大半*1だけど、一度使ってみたかったということもあり、練習も兼ねて。ていうか、色々と楽でいいやw*2

if has("ruby")
  function! util#path_expand(path)
    ruby << EOF
    path = File.expand_path(VIM.evaluate('a:path'))
    path.gsub!(/(["\\])/) { '\\' + $1 }
    VIM.command('let path = "' + path + '"')
EOF
    return path
  endfunction

  function! util#path_split(path)
    ruby << EOF
    dir, base = File.split(VIM.evaluate('a:path'))
    dir .gsub!(/(["\\])/) { '\\' + $1 }
    base.gsub!(/(["\\])/) { '\\' + $1 }
    VIM.command('let dir  = "' + dir  + '"')
    VIM.command('let base = "' + base + '"')
EOF
    return [dir, base]
  endfunction

  function! util#path_join(...)
    let args = join(a:000, "\n")
    ruby << EOF
    path = File.join(*VIM.evaluate('args').split("\n"))
    path.gsub!(/(["\\])/) { '\\' + $1 }
    VIM.command('let path = "' + path + '"')
EOF
    return path
  endfunction

  function! util#path_dir(path)
    ruby << EOF
    path = File.dirname(VIM.evaluate('a:path'))
    path.gsub!(/(["\\])/) { '\\' + $1 }
    VIM.command('let path = "' + path + '"')
EOF
    return path
  endfunction

  function! util#path_base(path, ...)
    if a:0
      ruby << EOF
      path = File.basename(VIM.evaluate('a:path'), ".*")
      path.gsub!(/(["\\])/) { '\\' + $1 }
      VIM.command('let path = "' + path + '"')
EOF
    else
      ruby << EOF
      path = File.basename(VIM.evaluate('a:path'))
      path.gsub!(/(["\\])/) { '\\' + $1 }
      VIM.command('let path = "' + path + '"')
EOF
    end
    return path
  endfunction

  function! util#path_ext(path)
    ruby << EOF
    path = File.extname(VIM.evaluate('a:path'))
    path.gsub!(/(["\\])/) { '\\' + $1 }
    VIM.command('let path = "' + path + '"')
EOF
    return path
  endfunction
endif

Vim script と Ruby との間で変数の値をどうやって受け渡したらいいのかしばらく悩んだけど、

Vim script → Ruby
ruby_var = VIM.evaluate('vim_var')

RubyVim script
VIM.command("let vim_var = '#{ruby_value}'")

でいけた。というか、その辺のことは「Vim-users.jp - Hack #136: Pythonインタフェースを使う(2)」にばっちり書いてあった(汗) 先に読んでおけばよかった。

↑この Vim Hacks のエントリは Pythonインターフェイスの使い方を解説したものだけど、値の受け渡し方法の他にも、エンコーディングに関することや外部ファイルを読み込む場合の注意点など、Rubyインターフェースを使う上でも有用なことが書いてあるので、興味のある人は :help ruby とあわせて読むことをお勧めします。

追記

パスに ' とか " が含まれていた場合のことを考慮していなかったので、エスケープ処理を加えてみた。なんだかなーな感じになった。多分、○○インターフェースというのは、返値ではなく副作用の方が重要な関数で使うべきものなんだろうなと思った。

*1:しかし、「ちゃんと」やろうとするとかなり面倒くさいと思う。

*2:撤回w 値を文字列として受け渡ししなければならないので、適切なエスケープとか考え出すと結構めんどい。