Wednesday, May 5, 2010

Setting up Emacs + erlang-mode + distel on Snow Leopard

I've spent a considerable amount of time trying to set up Aquamacs with erlang-mode + distel and wanted to share my success -- I briefly switched to Emacs for OS X after working with one of my Erlang colleagues, Chris Duesing, on getting all of this set up -- but found the recent release of Aquamacs 2.0 to have more useful features for my tastes.

Here's some pre-requisites:
  • Download Aquamacs from http://aquamacs.org/ -or- Emacs for Mac OS X from http://emacsformacosx.com/. This is purely a personal preference, and I have found that I *really* like Aquamacs 2.0 that was recently released -- switched from Aquamacs to Emacs for OS X, then 2.0 came out and switched back.
  • Download, build, and install Erlang. You can use MacPorts to install Erlang, but Homebrew is an incredible replacement to MacPorts so I'm going to recommend that you try it out. Follow this guide to setting up Homebrew which will be used to install Erlang and the the Erlware tools Faxien and Sinan:

    http://simergence.blogspot.com/2010/04/erlang-on-mac-for-lazy.html

    NOTE: Spend some time reading that blog entry which will show you how to build out projects with ease, create proper Erlang releases, and easily install various published Erlang applications including your own.

  • Download, build, and install Distel:

    svn co http://distel.googlecode.com/svn/trunk distel
    cd distel
    make
    make install

NOTE: At the time of this writing, we're using Erlang R13B04. Make sure your paths match the version of Erlang you are targeting.
  • If you have installed using Homebrew, Erlang will be located in the following folder:

    Erlang root: /usr/local/Cellar/erlang/R13B04
    Emacs files: [erlang-root]/lib/erlang/lib/tools-2.6.5.1/emacs
    Erlang bin: [erlang-root]/bin
  • If you have installed using MacPorts, Erlang will be located in the following folder:

    Erlang root: /opt/local/lib/erlang
    Emacs files: [erlang-root]/lib/tools-2.6.5.1/emacs
    Erlang bin: [erlang-root]/bin
  • Distel will be installed in the following folder:

    /usr/local/share/distel
NOTE: We will use the Homebrew locations for the remainder of this example, so make sure your configuration uses to correct locations for your installation.

We will need to pull down a couple of files that are missing from the Erlang installation to get erlang-mode working in Emacs (R14+ has these files, please ignore):

cd /usr/local/Cellar/erlang/R13B04/lib/erlang/lib/tools-2.6.5.1/emacs/
wget "http://github.com/erlang/otp/raw/dev/lib/tools/emacs/erlang-skels.el"
wget "http://github.com/erlang/otp/raw/dev/lib/tools/emacs/erlang-skels-old.el"

Lastly, we need to create a .emacs init file to load erlang-mode when Emacs starts. The .emacs file is located in your home folder. Create the .emacs file with the following contents (there may be wrapping issues):

;;
;; Standard Emacs settings
;;

;; Set my email address.
(setq user-mail-address "jpatton@gmail.com")

;; Set the shell emacs uses.
(setq explicit-shell-file-name "/bin/bash")

;; Use column and line numbering.
(line-number-mode 1)
(column-number-mode 1)

;; Display time in the minibuffer
(display-time)

;; Specify a color theme
(require 'color-theme)
(color-theme-initialize)
(color-theme-euphoria)

;;
;; Erlang mode and Distel settings
;;

;; This is needed for Erlang mode setup
(setq load-path (cons "/usr/local/Cellar/erlang/R13B04/lib/erlang/lib/tools-2.6.5.1/emacs" load-path))
(setq erlang-root-dir "/usr/local/Cellar/erlang/R13B04")
(setq exec-path (cons "/usr/local/Cellar/erlang/R13B04/bin" exec-path))
(require 'erlang-start)

;; Tell Emacs not to wait the usual 60 seconds for an Erlang prompt
(defvar inferior-erlang-prompt-timeout t)

;; This is needed for Distel setup
(let ((distel-dir "/usr/local/share/distel/elisp"))
(unless (member distel-dir load-path)
;; Add distel-dir to the end of load-path
(setq load-path (append load-path (list distel-dir)))))

(require 'distel)
(distel-setup)

;; Some Erlang customizations
(add-hook 'erlang-mode-hook
(lambda ()
;; when starting an Erlang shell in Emacs, default in the node name
(setq inferior-erlang-machine-options '("-sname" "emacs"))
;; add Erlang functions to an imenu menu
(imenu-add-to-menubar "imenu")))

;; A number of the erlang-extended-mode key bindings are useful in the shell too
(defconst distel-shell-keys
'(("\C-\M-i" erl-complete)
("\M-?" erl-complete)
("\M-." erl-find-source-under-point)
("\M-," erl-find-source-unwind)
("\M-*" erl-find-source-unwind)
)
"Additional keys to bind when in Erlang shell.")

(add-hook 'erlang-shell-mode-hook
(lambda ()
;; add some Distel bindings to the Erlang shell
(dolist (spec distel-shell-keys)
(define-key erlang-shell-mode-map (car spec) (cadr spec)))))
Now, you should be able to launch Aquamacs -or- Emacs for Mac OS X and have no errors in the *Messages* buffer. Once you have all of this working, you can read up on how to use erlang-mode in Emacs. Here are some links that I used to put this entry together that have more information about erlang-mode and Distel extensions:


    Also, if you're in the Chicago area, join the Chicago Erlang User's Group (CEUG) and help be a part of our growing community!

    Hopefully, something in the blog post helped you get things working.

    Happy erlanging!

    2 comments:

    1. Thank you for this walk through. I'm just getting started with erlang and it saved me some headaches.

      ReplyDelete
    2. I've came across a few posts on how to get up and running on OS X with Emacs, erlang, & distel, this is the best one so far. Thank you. However no matter who's instructions I follow, I can never get it working. Specifically, I can't seem to be able to connect Distel to a running Erlang process/shell, it always throws the "nodedown" error. Pretty certain I have my .erlang.cookie setup properly (I'm able to make 2 erlang shells ping each other). It's gotta be something simple but I'm not sure what else to try. Any guidance or help would be much appreciated.

      ReplyDelete