FlymakeErlang

Aquamacs configuration

I was told at SO that the recommended configuration in the “Emacs configuration” section below was old and that all you need is:

    (require 'erlang-flymake)

I’m using Aquamacs 3.3 and flymake for writing Erlang programs. My preferences file:

    ~/Library/Preferences/Aquamacs\ Emacs/Preferences.el

looks like this:

;; This is the Aquamacs Preferences file.
;; Add Emacs-Lisp code here that should be executed whenever
;; you start Aquamacs Emacs. If errors occur, Aquamacs will stop
;; evaluating this file and print errors in the *Messages* buffer.
;; Use this file in place of ~/.emacs (which is loaded as well.)


;Confirm that this file is actually being read:
(message "************ Aquamacs **************")

;Make Erlang files open with line numbers:
(add-hook 'erlang-mode-hook 
  (lambda () 
    (linum-mode 1)))

;Set font size:
;Doesn't work: (set-default-font "Monaco-14")
(set-face-attribute 'default nil :font "Monaco-16" )
;Also works: (set-frame-font "Monaco-16" nil t)

;Erlang syntax highlighting/indenting:
(setq load-path (cons  "/usr/local/lib/erlang/lib/tools-2.7.2/emacs"
load-path))
(setq erlang-root-dir "/usr/local/lib/erlang")
(setq exec-path (cons "/usr/local/lib/erlang/bin" exec-path))
(require 'erlang-start)

;For flymake:
(require 'erlang-flymake)

The paths in the Erlang syntax highlighting/indenting section are based on where your Erlang install is located. My Erlang install is at:

           /usr/local/lib/erlang/

You also need to get the right version of tools in the path:

         /usr/local/lib/erlang/lib/tools-2.7.2/emacs

Check your /path/to/erlang/lib/ directory for the version of tools-X.X.X in there and use that version.

Edit: Erlang-mode is terrible and does not indent “end” correctly, which makes it almost useless. Aquamacs with Erlang-mode is not a practical combination for editing Erlang programs. Look elsewhere.


This description is based on entry at Hypothetical Labs blog

To configure flymake to work with Erlang you need to add some elisp-code to your initialization file, and also create custom script, that will called from elisp code.

Emacs configuration

Following code should be added to your emacs initialization file. The "path_to_eflymake_script" should be replaced with real path to the script, that will perform checking of code

(require 'flymake)
(defun flymake-erlang-init ()
  (let* ((temp-file (flymake-init-create-temp-buffer-copy
		     'flymake-create-temp-inplace))
	 (local-file (file-relative-name temp-file
		(file-name-directory buffer-file-name))))
    (list "path_to_eflymake_script" (list local-file))))

(add-to-list 'flymake-allowed-file-name-masks '("\\.erl\\'" flymake-erlang-init))

Script for syntax checking

Following code is used to check validity of Erlang code. Please put it into some file, and make it executable. Path to this find should be specified in the elisp code above

#!/usr/bin/env escript
-export([main/1]).

main([File_Name]) ->
    compile:file(File_Name, [warn_obsolete_guard, warn_unused_import, 
                             warn_shadow_vars, warn_export_vars,
  			     strong_validation, report,
  			     {i, "../include"}]).

I use rebar and have hrl files not in the ../include path. Here is a quick hack I did to get all the appropriate include paths assuming a rebar based project. It could be smarter about finding things, but I just wanted to fix the 80% case.

#!/usr/bin/env escript
-export([main/1]).

main([File_Name]) ->

    {ok, Cwd} = file:get_cwd(),

    BaseDir =
    case re:run(Cwd, "^(.+)(/src).?", [{capture, [1], list}]) of
    {match, [B]} ->
	    B ++ "/";
    nomatch ->
	    Cwd ++ "/"
    end,

    {ok, Deps} = file:list_dir(BaseDir ++ "deps"),
    {ok, SrcDirs} = file:list_dir(BaseDir ++ "src"),

    Includes = 

	[{i, BaseDir ++ "include"}, {i, BaseDir ++ "deps"}, {i, BaseDir ++ "src"}]

	++

        [{i, Si} || S <- SrcDirs,
		    begin
                                  Si = BaseDir ++ "src/" ++ S,
                                  filelib:is_dir(Si)

		    end]

	++

        [{i,Di} || D <- Deps,
                              begin
                                  Di = BaseDir ++ "deps/"++D++"/include",
                                  filelib:is_dir(Di)
                              end],
    
    compile:file(File_Name, [warn_obsolete_guard, warn_unused_import,
			     warnings_as_errors,
                             warn_shadow_vars, warn_export_vars,
                             strong_validation, report | Includes]).

Would it be possible to alter this script to get output from dialyzer as well?

bkil: I’ve successfully connected it with Dialyzer! Get it from here: http://code.google.com/p/bkil-open/source/browse/trunk/volatile#volatile%2Fpg%2Fflyerl

Would it be possible to check also .hrl header files?

ten0s: Check out https://github.com/ten0s/syntaxerl

FlyMake