cabal-devとghcmod.vim


[追記] Cabal 1.18 で sandobox という機能が入ったため、cabal-dev はその役目を終えたそうです。トホホ…

VimでHaskellプログラミングをする際、ghcmod.vimには大変お世話になっています。

ただ、cabal-devを使っている場合、なんか上手く動かないな、どうしたら上手く動くように設定できるのだろうなとずっと悩んでいました。その対処法がだいたい見えてきたので紹介します。

localrcとの合わせ技です。

まず、そもそもghc-modをコマンドラインで使うにはどうすればいいかです。かりにhello.hsのチェックをするとすれば以下のようになります。

ghc-mod check hello.hs

これはhello.hs内でcabal-devでinstallしたモジュールを使っているとエラーがでます。なので、cabalは見ないけどcabal-devは見るパッケージのconfを指定してやります(以下はGHC 7.6.3を用い、カレントディレクトリがプロジェクトルートの場合)。

ghc-mod check -g -package-conf=cabal-dev/packages-7.6.3.conf hello.hs

このコマンドラインで追加したオプションは、ghcmod.vimにおいてはghcmod_ghc_optionsで指定できます。ただ、Vimを開いた時にカレントディレクトリがどこになっているのかわかりませんので、できればパッケージのconfは絶対パスで指定したいものです。そこで、開いたHaskellソース・ファイルのパスからルートに向かって順次「cabal-dev/packages-7.6.3.conf」が存在するかを見ていき、存在した場合、フルパスを取得してオプションに引き渡すというやりかたにします。そのための関数が以下です(初めて書いたVimスクリプトなので不格好かもしれませんが)。これを.vimrcに記述します。GHCやcabal-devのバージョンが変わると「cabal-dev/packages-7.6.3.conf」というディレクトリ名が変わってしまうかもしれないので引数でもらうようにしています。

" ghcmod.vimをcabal-dev環境下で使うための設定関数
function! g:add_cabal_dev_conf(cabal_dev_conf)
  let l:kw = '%:p:h'
  let l:path = expand(l:kw)
  while l:path != ''
    if isdirectory(l:path . a:cabal_dev_conf)
      if !exists('b:ghcmod_ghc_options')
        let b:ghcmod_ghc_options = []
      endif
      call add(b:ghcmod_ghc_options, '-package-conf=' . l:path . a:cabal_dev_conf)
      break
    else
      if l:path == '/'
        break
      else
        let l:kw = l:kw . ':h'
        let l:path = expand(l:kw)
      endif
    endif
  endwhile
endfunction

次にcabal-devプロジェクトルートに.local.haskell.vimrcというファイルを以下の様な内容で作ります。これはlocalrcに読み込ませる設定ファイルです。

call g:add_cabal_dev_conf('/cabal-dev/packages-7.6.3.conf')

以上です。もっとCoolなやり方があったらぜひ教えて下さい。

Leave a Comment