Up and running with Emacs, Erlang, and Distel
August 15, 2008
Umm… did I mention that I yearn for hacking Erlang code, too? Following Bill Clementson’s lead, I set up Emacs+Erlang on my Ubuntu hardy box.
Step 1: Install erlang and erlang-mode
I used the version of erlang and erlang-mode for emacs in Ubuntu’s repositories. I might come to regret it some day, but for now the following was just too simple to resist:
$ sudo aptitude install erlang # The above will install erlang-mode too; # if it does not just "apt-get install erlang-mode"
Step 2: Configure erlang-mode in Emacs
I just put the following in my .emacs:
;; Erlang-mode
(require 'erlang-start)
(add-to-hook 'erlang-mode-hook
(lambda ()
;; when starting an Erlang shell in Emacs, the node name
;; by default should be "emacs"
(setq inferior-erlang-machine-options '("-sname" "emacs"))
;; add Erlang functions to an imenu menu
(imenu-add-to-menubar "imenu")))
Now I can launch Emacs and open an erlang file, which puts me in Erlang mode. I can start and Erlang shell with “C-c C-z”, compile the Erlang code with “C-c C-k”, and view the compilation result in the Erlang buffer (if the buffer is hidden) with “C-c C-l”. Or, I can just switch to the Erlang shell with “C-c C-z”. The customizations above enable me to get a menu item in the Emacs menubar with a list of functions defined in the file I am visiting, which is a big help. I am used to “ecb-mode” when coding Python; ECB does not grok Erlang yet, so the imenu is a handy substitute when coding Erlang.
Step 3: Install Distel
Distel is to Erlang and erlang-mode what SLIME is to Lisp and lisp-mode.
To get distel:
$ cd ~/.emacs.d/
$ svn co http://distel.googlecode.com/svn/trunk/ distel
$ cd distel
$ make
$ cd doc
$ make postscript && make postscript # must run twice
$ make info && sudo make install # install the Info documentation
$ info distel # read the distel info documentation
Step 4: Configure Emacs to use Distel
I just need to put this in my .emacs:
(push "/home/parijat/.emacs.d/distel/elisp/" load-path) (require 'distel) (distel-setup)
Step 5: Configure Erlang
Distel is designed to work in a distributed Erlang system. It can connect to specified Erlang nodes. My strategy is to use the standard erlang-mode command “C-c C-z” to start an Erlang shell, and connect to it using Distel by “C-c C-d n”. The latter asks for a nodename, which is going to be “emacs@beowulf” (because beowulf is the short hostname of my laptop).
But before we start using remote Erlang nodes, we should create on each physical machine that we will use a ~/.erlang.cookie file with a password, for inter-Erlang node authentication:
$ echo "secret" > ~/.erlang.cookie $ chmod 0400 ~/.erlang.cookie
Step 6: Play with Distel
So, now we can launch an Erlang node, either via Emacs using “C-c C-z”, or on the command line using “erl -sname mynode”. Then, from within Emacs, we can connect Distel to this node using “C-c C-d n” specifiying the nodename on the prompt. Now we can ask Distel to interrogate the Erlang node for various things.
C-c C-d l ; list erlang processes PID/Name Initial Call Reds Msgs init otp_ring0:start/2 3821 0 erl_prim_loader erlang:apply/2 87239 0 error_logger proc_lib:init_p/5 229 0 application_controlle erlang:apply/2 2501 0 <0.7.0> proc_lib:init_p/5 45 0 <0.8.0> application_master:start_it/4 91 0 kernel_sup proc_lib:init_p/5 1498 0 rex proc_lib:init_p/5 493 0 global_name_server proc_lib:init_p/5 69 0 <0.12.0> erlang:apply/2 25 0 <0.13.0> erlang:apply/2 4 0 <0.14.0> erlang:apply/2 3 0 inet_db proc_lib:init_p/5 129 0 net_sup proc_lib:init_p/5 312 0 erl_epmd proc_lib:init_p/5 147 0
Up and running with Emacs, sbcl, and SLIME
August 14, 2008
While I normally program in Python, a part of me wants to quickly hack some lisp code every now and then. Especially during those long minutes when my automated tests are running.
I realized that long neglect had left me without a working lisp setup. Here is how I got it up and running again.
Step 1: Get rid of system lisp and slime
The version of sbcl and SLIME in my Ubuntu system is not recent enough for my liking. So I get rid of them:
$ sudo apt-get -y remove sbcl slime common-lisp-controller $ sudo apt-get -y autoremove # get rid of packages we don't need anymore $ sudo rm -rf /var/cache/common-lisp-controller
Step 2: Install common requirements
cd ~/ sudo apt-get update sudo apt-get -y install emacs22 sudo apt-get -y install cvs sudo apt-get -y install git-core sudo apt-get -y install darcs sudo apt-get -y install subversion sudo apt-get -y install build-essential sudo apt-get -y install autoconf sudo apt-get -y install curl sudo apt-get -y install sbcl sudo apt-get -y install texinfo sudo apt-get -y install tetex-bin sudo apt-get -y install xloadimage
Step 3: Get clbuild
$ mkdir lisp $ cd lisp # for fresh install of clbuild $ darcs get http://common-lisp.net/project/clbuild/clbuild $ cd clbuild # Or, to update existing clbuild $ cd clbuild $ darcs pull
Step 4: Get latest SBCL
$ ./clbuild update sbcl $ cd source/sbcl $ sh make.sh $ cd doc/manual $ make $ cd ../.. $ echo > ~/.sbclrc (require :asdf) (push "/home/parijat/lisp/clbuild/systems/" asdf:*central-registry*) ^D $
Step 5: Setup SLIME
$ ./clbuild update slime
Now, we need to add this slime configuration to our .emacs file:
(push "/home/parijat/lisp/clbuild/source/slime" load-path)
;; Common Lisp Mode
(setq inferior-lisp-program "/usr/local/bin/sbcl")
(add-to-list 'auto-mode-alist '("\\.lisp$" . lisp-mode))
(add-to-list 'auto-mode-alist '("\\.cl$" . lisp-mode))
(add-to-list 'auto-mode-alist '("\\.asd$" . lisp-mode))
(require 'slime)
(slime-setup)
(eval-after-load "slime"
'(progn
(setq slime-complete-symbol*-fancy t
slime-complete-symbol-function 'slime-fuzzy-complete-symbol
slime-when-complete-filename-expand t
slime-truncate-lines nil
slime-autodoc-use-multiline-p t)
(slime-setup '(slime-fancy slime-asdf))
(define-key slime-repl-mode-map (kbd "C-c ;")
'slime-insert-balanced-comments)
(define-key slime-repl-mode-map (kbd "C-c M-;")
'slime-remove-balanced-comments)
(define-key slime-mode-map (kbd "C-c ;")
'slime-insert-balanced-comments)
(define-key slime-mode-map (kbd "C-c M-;")
'slime-remove-balanced-comments)
(define-key slime-mode-map (kbd "RET") 'newline-and-indent)
(define-key slime-mode-map (kbd "C-j") 'newline)))
(add-hook 'lisp-mode-hook (lambda ()
(cond ((not (featurep 'slime))
(require 'slime)
(normal-mode)))
(indent-tabs-mode nil)
(pair-mode t)))
Note: pair-mode is a nice package for inserting balanced parentheses, quotes, braces and square-brackets, etc., which I installed earlier by hand.
Now we can launch emacs, and start slime with “M-x slime”.
Caveat
For some reason, after doing the above, slime would still not start. Doing a “M-x slime” would throw me into the sbcl debugger with the error message that sbcl could not find “/usr/share/common-lisp/systems/slime/swank-loader.lisp”, or something like that (I could be wrong about the exact path). After much head-scratching (and grepping my ~/lisp directory), I figured out I had to change the emacs customization variable slime-backend. This can be done by doing “M-x customize-group RET slime-lisp RET” and changing the value of “Slime Backend” to simply “swank-loader.lisp” (the file should be in the same directory as “slime.el”). We can also give an absolute path to the file. I found that the value of this variable was set wrongly (an artifact of using apt-get installed slime, I guess) and hence sbcl was not able to load the correct file.