どうも, 515 ひかるです.
なぜか知らないけれど, 気がついたら Emacs の環境が整っていたので何をしたのか書きます.
Haskell の開発環境
最近, なぜか『すごい Haskell たのしく学ぼう!』(オーム社) を読んでいて, 結構楽しんでいます. あまりにも三日坊主が多いので, 普段こういう話をするのは避けたいのだけど, 今回は数日間続いているので書いてもいいだろうと判断したわけです.
- 作者: Miran Lipovača,田中英行,村主崇行
- 出版社/メーカー: オーム社
- 発売日: 2012/05/23
- メディア: 単行本(ソフトカバー)
- 購入: 25人 クリック: 580回
- この商品を含むブログ (73件) を見る
それとは別に, 日記をつけようと思って Emacs の Org-mode を使い始めたのだけど, これが想像していたよりもずっと使いやすくて, もう日本語の文書作成は全てコレでいいのではという気分になってきています1. そこで, この 1 週間くらい Emacs で日本語を書いて, Haskell 書く時だけ違うエディタを使うという感じになっていました.
しかし, どうしてそうなったのかよく覚えていないんですが, 気がついたら Emacs にも Haskell の環境を整備してました. 大規模な開発環境というよりも「すごい H 本」を読むのに最適な環境がいつのまにかできていた, という感じだったので初心者の僕にはすごく嬉しい2. いや, 僕が作ったはずなんだけど.
というわけで, だいたい何をしないといけないのかをメモ程度に書いておく.
覚え書き
前提
以下, Stack か Cabal などで ghc-mod
と hlint
をインストールしていることを前提にします.
あと, この覚え書きはだいたい Haskell を快適に利用するための Emacs 環境の構築 を読みながらやりました.
haskell-mode
Emacs なのでまずはマイナーモードを入れましょう.
M-x package-install RET haskell-mode
インストールが済んだら次のように設定. 当然 ~/.emacs.d/init.el
に書きます.
(autoload 'haskell-mode "haskell-mode" nil t) (autoload 'haskell-cabal "haskell-cabal" nil t) (add-to-list 'auto-mode-alist '("\\.hs$" . haskell-mode)) (add-to-list 'auto-mode-alist '("\\.lhs$" . literate-haskell-mode)) (add-to-list 'auto-mode-alist '("\\.cabal$" . haskell-cabal-mode))
ghc-mod
こちらも init.el
に追加
(autoload 'ghc-init "ghc" nil t) (autoload 'ghc-debug "ghc" nil t)
flycheck
エラーとか警告とかを教えてくれる.
M-x package-install RET flycheck
init.el
には一行追加するだけ3.
(add-hook 'after-init-hook #'global-flycheck-mode)
より詳しくは Flycheckでモダンなシンタックス を見てください.
company for haskell
company-mode そのものについては, auto-completeユーザのためのcompany-modeの設定 を読んでください. ここでは手順のみ書きます.
インストールについては, 例のごとく
M-x package-install [RET] company M-x package-install [RET] company-ghc
をすれば O.K. 設定は, init.el
に
(global-company-mode 1) ;; company-mode を常に ON (add-to-list 'company-backends 'company-ghc)
を追加すれば動くはずです. ghc-mod の設定が必須. 詳しくは 公式リポジトリをみてください.
hooks
hook はいろいろあるけど, それぞれ目的が違うのでコメントに書いておきます.
(defun my-haskell-mode-hook () (interactive) ;; インデント (turn-on-haskell-indentation) (turn-on-haskell-doc-mode) (font-lock-mode) (imenu-add-menubar-index) ;; GHCi のコマンドを設定 (setq haskell-program-name "/usr/bin/stack ghci") ;; stack の場合 (inf-haskell-mode) ;; ghc-mod を使えるように (ghc-init) ;; flycheck を起動 (flycheck-mode)) (add-hook 'haskell-mode-hook 'my-haskell-mode-hook)
GHCi との連携
「すごい H 本」は, 読んだことある人はご存知だと思うけれど, 序盤(第 1 章 - 第 7 章)は関数定義以外はほとんどGHCi, つまり対話環境のコードがほとんど. そこで, ファイルを GHCi でロードすることが多いんだけど, 上の設定がうまくいっていれば, C-c C-l
で現在のファイル(カレントバッファのファイル)を読み込んだ GHCi を起動してくれる.
こんな感じ. ちょっと見にくいけど.
左が Haskell のコードで, C-c C-l
を叩くと右のバッファが出現する. その際に GHCi が起動するとき自動的に左のバッファの関数はすべて読み込んでくれるというわけ. これで関数定義と「すごい H 本」の GHCi とを行き来するのにかなり楽になった.
だいたい読んで参考にしたリンクは書いたと思うし, こんなもんかな.
実は Haskell の環境とは関係なく Evil-mode も試してみてるんだけど, これはまだ慣れてないので, もう少し慣れて設定とかできるようになったら書こうかと思います.
追記 (20160919)
\C-c\C-l
で関数をロードした GHCi は起動できるけど, IO アクション, もっというと main
を実行したいだろう. これは実は GHCi のプロンプト内で main
を実行すればいい. わざわざコンパイルや端末で runghc
する必要はなく, GHCi だけで対話型のプログラムなども動作チェックできる. 想定していたよりもかなり使える環境だった.
なんでか知らないけれどできないと思って quickrun.el
とか Emacs から fish シェルを使う設定とかしてしまったよ......まぁこれはこれで違う何かに使えそうだけれども,
追記 (20161001)
上の設定でそのまま \C-c\C-l
をすると, inferior-haskell-load-file
が働いてカレントバッファの haskell コードをロードした状態で ghci が起動するのはよい. けど, 残念ながらカーソルはカレントバッファ(つまりソース側)のままで, ghci 側に移動してくれない. Emacs の Window 切り替えは \C-x o
という超絶面倒なデフォルトキーバインドなのはご周知の通りで, 毎回 \C-c\C-l \C-x o
などとやるのは鬱陶しかったのでコマンドを定義した.
(define-key haskell-mode-map "\C-cl" (lambda () (interactive) (inferior-haskell-load-file) (other-window 1)))
これで, \C-c l
と入力するだけでロードとカーソル移動をやってくれる. 3 つ以上のウィンドウに分割してたら知らんよ.