追記

perlスクリプトが不要な以下の方法がおすすめです。

Flymake-mode for Haskell (Emacs) without perl script – 落書き、時々落学

flymake-mode はエラーがあるとそれを知らせていくれる.

haskellで使うには少し設定が必要.

参考

EmacsWiki: Flymake Haskell

nushio's diary

環境

  • Ubuntu 8.10
  • emacs 23.0.60.1
  • flymake 0.3
  • ghc 6.8.2

下準備

/usr/local/binなどパスがとおったところにperlスクリプトをおく

#!/usr/bin/env perl
# flycheck_haskell.pl
### Please rewrite the following 3 variables
### ($ghc, @ghc_options and @ghc_packages)
$ghc = '/usr/bin/ghc'; # where is ghc
@ghc_options  = ();   # e.g. ('-fglasgow-exts')
@ghc_packages = ();          # e.g. ('QuickCheck')
### the following should not been edited ###
use File::Temp qw /tempfile tempdir/;
File::Temp->safe_level( File::Temp::HIGH );
($source, $base_dir) = @ARGV;
$source =~ s/ / /g;
$base_dir =~ s/ / /g;
@command = ($ghc,
'--make',
'-fbyte-code',
"-i$base_dir",
"-i$base_dir/..",
"-i$base_dir/../..",
"-i$base_dir/../../..",
"-i$base_dir/../../../..",
"-i$base_dir/../../../../..",
$source);
while(@ghc_options) {
push(@command, shift @ghc_options);
}
while(@ghc_packages) {
push(@command, '-package');
push(@command, shift @ghc_packages);
}
$dir = tempdir( CLEANUP => 1 );
($fh, $filename) = tempfile( DIR => $dir );
system("@command >$filename 2>&1");
open(MESSAGE, $filename);
while(<MESSAGE>) {
if(/(^S+.hs|.lhs)(:d*:d*:)s?(.*)/) {
print "n";
print $1;
print $2;
$rest = $3;
chomp $rest;
print $rest;
next;
}
if(/s+(.*)/) {
$rest = $1;
chomp $rest;
print $rest;
print " ";
next;
}
}
close($fh);
print "n";

.emacs の編集

;======================================================================
; flymake-mode for haskell
;======================================================================
(require 'flymake)
(defun flymake-Haskell-init ()
(flymake-simple-make-init-impl
'flymake-create-temp-with-folder-structure nil nil
(file-name-nondirectory buffer-file-name)
'flymake-get-Haskell-cmdline))
(defun flymake-get-Haskell-cmdline (source base-dir)
(list "flycheck_haskell.pl"
(list source base-dir)))
(push '(".+.hs$" flymake-Haskell-init flymake-simple-java-cleanup)
flymake-allowed-file-name-masks)
(push '(".+.lhs$" flymake-Haskell-init flymake-simple-java-cleanup)
flymake-allowed-file-name-masks)
(push
'("^(.+.hs|.lhs):([0-9]+):([0-9]+):(.+)"
1 2 3 4) flymake-err-line-patterns)
(add-hook 'haskell-mode-hook
'(lambda ()
(if (not (null buffer-file-name)) (flymake-mode))))
;; Display messages at the minibuffer
(global-set-key "C-cd"
'flymake-show-and-sit )
(defun flymake-show-and-sit ()
"Displays the error/warning for the current line in the minibuffer"
(interactive)
(progn
(let* ( (line-no             (flymake-current-line-no) )
(line-err-info-list  (nth  (flymake-find-err-info flymake-err-info line-no)))
(count               (length line-err-info-list))
)
(while (> count )
(when line-err-info-list
(let* ((file       (flymake-ler-file (nth (1- count) line-err-info-list)))
(full-file  (flymake-ler-full-file (nth (1- count) line-err-info-list)))
(text (flymake-ler-text (nth (1- count) line-err-info-list)))
(line       (flymake-ler-line (nth (1- count) line-err-info-list))))
(message "[%s] %s" line text)
)
)
(setq count (1- count)))))
(sit-for 60.0)
)
;;

実際に使ってみた

こんなかんじ.

f🆔jeneshicc:20090309164922p:image