环境:Emacs 24.2、linux-kernel 3.7
关于emacs的Ocaml配置其实有很多, 本人刚刚上手, 不想搞得太复杂, 暂时只配了这些。
turareg可以说是必备的, 提供基本的语法高亮和repl等基本功能, 官方有个ocaml-mode, 不过很少人用, 普遍都是用turareg。
;; tuareg-mode
(setq auto-mode-alist (cons '("\\.ml\\w?" . tuareg-mode) auto-mode-alist))
(autoload 'tuareg-mode "tuareg" "Major mode for editing Caml code" t)
(autoload 'camldebug "camldebug" "Run the Caml debugger" t)
静态强类型的语言没有动态语言灵活, 不过优点也显而易见: 能在编译时而不是运行时发现错误, 现代的开发工具能把错误的发现提前至写代码的时候。如果你喜欢边写代码边频繁地在repl里运行调试, 我觉得这个就不用配了。flymake是emacs自带的, 这里只需要配置一下。
;; flymake-ocaml
(require 'flymake)
(defun flymake-ocaml-init ()
(flymake-simple-make-init-impl
'flymake-create-temp-with-folder-structure nil nil
(file-name-nondirectory buffer-file-name)
'flymake-get-ocaml-cmdline))
(defun flymake-get-ocaml-cmdline (source base-dir)
(list "ocaml_flycheck.pl"
;; 这里flymake需要调用一个名为"ocaml_flycheck.pl"的perl脚本。
;; 自己调整perl脚本的位置, 默认与源代码同目录。
(list source base-dir)))
(push '(".+\\.ml[yilp]?$" flymake-ocaml-init flymake-simple-java-cleanup)
flymake-allowed-file-name-masks)
(push
'("^\\(\.+\.ml[yilp]?\\|\.lhs\\):\\([0-9]+\\):\\([0-9]+\\):\\(.+\\)"
1 2 3 4) flymake-err-line-patterns)
;; 如果你要flymake自动执行的话……
(add-hook
'tuareg-mode-hook
'(lambda ()
(if (not (null buffer-file-name)) (flymake-mode))))
以下为ocaml_flycheck.pl的代码, 记得加上可执行权限。
#!/usr/bin/env perl
# ocaml_flycheck.pl
use strict;
use warnings;
### Please rewrite the following 2 variables
### ($ocamlc, @ocamlc_options)
my $ocamlc = 'ocamlc'; # where is ocamlc
my @ocamlc_options = ('-c -thread unix.cma threads.cma graphics.cma'); # e.g. ('-fglasgow-exts');
my @ocamlc_packages = ();
### the following should not been edited ###
use File::Temp qw /tempfile tempdir/;
File::Temp->safe_level( File::Temp::HIGH );
my ($source, $base_dir) = @ARGV;
my @command = ($ocamlc);
while (@ocamlc_options) {
push(@command, shift @ocamlc_options);
}
push (@command, $source);
while (@ocamlc_packages) {
push(@command, '-package');
push(@command, shift @ocamlc_packages);
}
my $dir = tempdir( CLEANUP => 1 );
my ($fh, $filename) = tempfile( DIR => $dir );
system("@command >$filename 2>&1");
open(MESSAGE, $filename);
my $column = "";
while (<MESSAGE>) {
# example message {File "robocupenv.ml", line 133, characters 6-10:
if (/^File "(\S+\.ml[yilp]?)", line (\d+), characters (\d+)-(\d+):\s?(.*)/) {
print $column;
my $error = (<MESSAGE>); # get the next line
chomp $error;
print "\n";
print "$1:$2:$3:";
$column = " [$3-$4]";
if ($error =~ /Warning(.*)/) {
print "$error";
} else {
print "$error ";
}
next;
}
if (/\s+(.*)/) {
my $rest = $1;
chomp $rest;
print $rest;
print " ";
next;
}
}
close($fh);
print "$column\n";
话说ocaml社区和perl社区是有什么勾搭么, 连吉祥物都是骆驼……