Basic support of Erlang in Emacs is provided by erlang-mode package, that comes with Erlang distribution. This package implements base operations for work with Erlang's source code — syntax highlighting, indentation, etc.
Besides this, there are also other packages — they provide implementation of useful operations, not existing in erlang-mode — debugging, profiling, etc. The Distel1 package is an add-on to the erlang-mode, while erlware-mode package is a fork of the erlang-mode, with implementation of additional commands.
The erlang-mode package comes with Erlang distribution, and available for use right after
Erlang's installation. Documentation for this package is available either from
Erlang's site, or from Erlang's manual pages, accessible with erl -man erlang_mode
command. Documentation has detailed description of all commands.
Almost all commands, implemented by package are available to user via Erlang
menu, and
most often used also have key bindings (described below) for quick access to them.
Installation of the package is quite simple — you need to specify path to the erlang-mode
(usually this is sub-directory inside Erlang's distribution), and load package
erlang-start
, as here, for example:
(add-to-list 'load-path ".....") (require 'erlang-start) (add-to-list 'auto-mode-alist '("\\.erl?$" . erlang-mode)) (add-to-list 'auto-mode-alist '("\\.hrl?$" . erlang-mode)) (setq erlang-root-dir "/opt/local/lib/erlang") (add-to-list 'exec-path "/opt/local/lib/erlang/bin") (setq erlang-man-root-dir "/opt/local/lib/erlang/man")
in this example, we additionally set list of file extensions, that will be associated with
erlang-mode. And we also change list of directories where search for executable files is
performed, so all Erlang's utilities will work without any problems. Another two
variables —
erlang-root-dir
and erlang-man-root-dir
set root directory of Erlang's
distribution, and directory, where manual pages for Erlang are stored.
Besides this, user can tune package's behaviour with erlang-mode-hook
, for example with
following code:
(defun my-erlang-mode-hook () ;; 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") ;; customize keys (local-set-key [return] 'newline-and-indent) ) ;; Some Erlang customizations (add-hook 'erlang-mode-hook 'my-erlang-mode-hook)
This code sets list of options, that will passed to Erlang process, and also change key bindings for erlang-mode, and add list of defined Erlang's functions into menu, generated by Imenu package.
erlang-mode provides to user set of the commands for work with source code. This set includes commands for source code navigation, code editing & indenting.
When you work with source code of function, consisting from several clauses (parts), then
you can use command erlang-generate-new-clause
(it bound to C-c C-j
) to insert new clause
in current point — this command takes name of function from previous clause, and after
inserting name, it put cursor in argument list. If most of function's parameters are same
as in previous clause, then you can use the erlang-clone-arguments
(C-c C-y
) command to
copy parameters from previous clause and inserting them into current expression.
Depending on than current context, keys ',
', ';
',
'<
' and '>
' have different behaviour. So, if you at the end of
expression, and press ;
, then template for new expression will be inserted, as you
explicitly call erlang-generate-new-clause
command. And, if you press ,
at the end of
expression, then this will lead to moving to new line and setting proper indent for code.
To make Erlang's source code more readable user can use the erlang-align-arrows
(C-c C-a
)
command, that aligns all arrows (->
) after clauses — this makes code more readable, as
clauses boundaries are explicitly shown.
Users is often need to mark source code of function or current clause. erlang-mode
defines two commands for these operations: the erlang-mark-clause
command (M-h
or C-c M-h
)
is used to mark current clause, while the erlang-mark-function
command (M-C-h
) could be
used to mark whole function.
To work with comments there are several commands. To comment out selected region, user
can use the comment-region
command (C-c C-c
), that will insert one comment sign (%
) into
start of each line. If you want to delete comment from selected region, you can execute
the erlang-uncomment-region
command (C-c C-u
). You can also use the comment-dwim
command
(M-;
) to mark selected region, or insert one line comment into end of existing line of
code.
Besides this, erlang-mode provides the erlang-fill-paragraph
command (M-q
) that tries to
properly format current paragraph with commentary, and increase readability of the source
code.
erlang-mode also provides number of commands for proper indenting of source code. By
pressing to TAB
key you run the erlang-indent-command
command, that will set proper
indentation for current line of code. For selected region you can use standard command
indent-region
(M-C-\
). There are also separate commands for set indentation for current
clause —
erlang-indent-clause
, function —
erlang-indent-function
(C-c C-q
) and for whole
buffer —
erlang-indent-current-buffer
.
In addition to standard commands for navigation inside source code — next/previous
bracket, etc., erlang-mode implements several additional commands that allow to navigate
between Erlang's objects — clauses & functions. Commands erlang-beginning-of-function
(C-a M-a
) and erlang-end-of-function
(C-a M-e
) move cursor to start or end of current
Erlang's function2, and commands erlang-beginning-of-clause
(M-C-a
) and
erlang-end-of-clause
(M-C-e
) move cursor to start/end of the current clause.
erlang-mode also extends set of standard commands for work with tags. To use these
commands, you'll need to create special file TAGS
, that could be generated either with
etags
command from Emacs's distribution, either with tags
module from Erlang's
distribution.
Using existing TAGS
file you can use standard commands to work with tags —
find-tag
(M-.
), tags-apropos
, tags-search
(C-x t s
) and other. erlang-mode add following commands
—
erlang-find-tag
, that works like find-tag
, but allows to specify name of the module
where search will performed (if tag is specified as module:
or module:tag
),
erlang-find-next-tag
(M-+
), that search for next tag with given name, and two commands —
erlang-find-tag-other-frame
(C-x 5 .
) and erlang-find-tag-other-window
(C-x 4 .
), that
open tag's definition in new frame or window.
Use can also use the erlang-complete-tag
command (M-TAB
) to complete names of existing
functions using data, collected in TAGS
file.
To make work of user more easy, erlang-mode has number of code templates (snippets), that
could be inserted into source code using the Skeletons
items from Erlang
menu, or directly
calling tempo-template-erlang-XXX
, where XXX
is a name of the template. To insert
templates the tempo package included into Emacs. Currently, package provides following
templates:
if
, case
, receive
, etc.;gen_server
, application
, gen_fsm
, etc.erl
User can execute Erlang's commands interactively using erl
process running in the Emacs's
buffer (process is running with comint
, so user can use standard commands of this package,
for example, navigation through history of commands with M-p
& M-n
keys). This process is
also used by erlang-mode to compile source code.
To run new erl
process, user can use the erlang-shell
command, but it will implicitly run
when user run compilation of source code, or try to switch to *erlang*
buffer with
erlang-shell-display
command (C-c C-z
).
Compilation and loading of compiled code is performed with erlang-compile
command (C-c
C-k
). If user gives prefix argument to this command, then compilation will performed with
options debug_info
& export_all
. To view compilation results, user can run
erlang-compile-display
command (C-c C-l
). To move between errors, the erlang-next-error
command (C-x `
) is could be used. In this case, if you want to move to first error, you
need to give prefix argument to this command, for example with C-u C-x `
.
erlware-mode package is replacement for erlang-mode, using it as a base, but adding following new functionality:
edoc
utility;This package is available from project's site, and its installation & customization isn't differs from erlang-mode's installation & customization.
Execution of basic commands also not differs from execution of the erlang-mode commands. Description of new commands will added in future, as they will released.
The distel package, available from http://code.google.com/p/distel/, is a library in Emacs Lisp, that allows to write Emacs code in distributed style, and also allows to communicate with code, written in Erlang. This allows to implement set of commands, not existing in erlang-mode, that allow to perform following tasks:
Short review of package features you can find at article of Bill Clementson. Package comes together with very detailed documentation, describing both basic concepts, and functions, implemented in package.
To install package, you need to download it from the project's site and unpack it into selected place, and than add following code into initialization file:
(add-to-list 'load-path "~/emacs/distel/elisp") (require 'distel) (distel-setup)
This code will perform loading and base customization of the package. In additional we can perform more precise customization using hooks. For example, following code3 will add new key bindings to mode, that is used to interactive work with Erlang, making this work more comfortable:
;; 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)))))
The distel package add to erlang-mode several commands for work with source code. But i
need to mention, that some of them requires running Erlang environment, and when you'll
execute them first time, they will ask you for a name of the node, that will be used to
get all necessary information. User can switch between nodes with the erl-choose-nodename
command(C-c C-d n
). And for checking availability of the concrete node the erl-ping
command(C-c C-d g
) could be used. The command will ask you for name of the node, and if
it available, it will load to node all modules are needed to work with distel. Name of
the current node is displayed in the status line.
Besides direct execution of commands, user can run them from the Distel
item in Erlang
menu.
Distel implements its own set of commands for completion of modules & functions names. To
get this information, package retrieve it from running Erlang environment. To use name
completion you can run erl-complete
command (M-TAB
or M-?
). If already entered part of
name corresponds several names, then package will create a new buffer and user should
select between suggested variants.
The package also overrides commands for work with tags, but it make this differently
(comparing with erlang-mode) — you don't need to keep your TAGS
file updated, as distel
use information from the running Erlang environment to get information about function's
definition. To go to the function's definition, you can use the
erl-find-source-under-point
command (M-.
) — by default, this command use name under
cursor as a variant to search. But you can change this behaviour if you'll pass it prefix
argument (C-u
), or if the variable distel-tags-compliant
has non-nil
value — in these
cases, you'll be prompted for name of function. To return back, you can use the
erl-find-source-unwind
command (M-,
or M-*
).
Besides this, distel has rudimentary support for refactoring of source code. Using the
erl-refactor-subfunction
command (C-c C-d f
) user can select part of source code (user
should select corresponding block of code with standard commands) of a function into
separate function. When command is executed, user will asked for name of new function,
the list of the parameters will detected, and selected part of code will replaced with
call to new function. Text of new function will put into kill buffer, and user can insert
it into appropriate place with the yank
command (C-y
). In distel documentation you can
find example of usage of this command.
To more comfortable work with documentation, the distel package use external programs, written in Erlang, that perform preprocessing of documentation, and later use collected information for access to documentation.
To preprocess documentation in HTML format, there is otp_doc
module, that performs
analysis of the files, and generates set of pairs "function's signature/link to
documentation". With the erl-find-sig
command user can get list of the function's
signatures, corresponding to given expression, and than could use the erl-find-doc
command
to get documentation for given function (you need to have the w3m package installed). In
this case, if you have several functions, corresponding to your request, then you'll need
to select needed function from list.
User can also get short description of the loaded modules. For this task the fdoc
module
is used, that also performs analysis of the source code of the loaded modules, and stores
collected data to the later use. You can get description of the module or function from
the fdoc's
database the erl-fdoc-describe
command (C-c C-d d
). And with the
erl-fdoc-apropos
command (C-c C-d a
) you can get list of functions, whose names or
descriptions are matched to the given regular expression. In this case, if one of these
commands is called with prefix argument, then it rebuild fdoc
database first, and than
perform requested operation.
Distel extends set of the erlang-mode commands that are used to execution of the Erlang
code. With the erl-eval-expression
command (C-c C-d :
) user can enter in mini-buffer any
Erlang expression, and get result of its evaluation. If user mark some region of code,
then this part will suggested as expression to evaluate. Besides this, there are two
additional commands, that allow to reload modules on selected node. This is the
erl-reload-module
command (C-c C-d L
), that reloads module with given name, and the
erl-reload-modules
command (C-c C-d r
), that reloads all updated modules.
More powerful facilities for interactive Erlang's code evaluation are implemented as part
of "interactive sessions" — something like the *scratch*
buffer for Emacs Lisp, in which
you can enter and execute separate Erlang's expressions without creation of files with
source code (an example of work with such buffer, you can see on picture below). To start
interactive session you need to run the erl-ie-show-session
command (C-c C-d e
), that
either will create new buffer, or will switch to existing buffer, where user will can
enter Erlang's expressions. By default, this buffer has name *ie sessions node_name*
.
Inside this buffer, user can enter separate expressions & function's definitions. To
evaluate expression, before point, the erl-ie-eval-expression
command (C-j
) is used. And
to evaluate function's definition, there is the erl-ie-eval-defun
command (C-M-x
).
The distel package use fprof
module to get information from profiler. To work with this
module, the package provides two commands. With the fpropf
command (C-c C-d p
) user can
enter Erlang's expression and get profiling information. And with the fprof-analyse
command (C-c C-d P
) you can load file with existing profiler data and perform their
analysis in convenient form. After finishing of analysis user gets buffer, in which all
called functions are listed, together with detailed information about them: Calls
—
number of calls for concrete function; ACC
— how much time (in milliseconds) was spent
for execution of concrete function, including calls for other functions; Own
— how much
time was spent for execution of function's body, without calls to other functions. An
example of result's representation you can see on picture below.
To implement interface to debugger, the distel package uses same modules, as debugger from
Erlang's distribution. To use debug facilities you need to compile modules with debug
information enabled (you need to specify +debug-info
option for erlc
, or execute the
erlang-compile
command with prefix argument).
When you run debugger, several additional buffers are created — one buffer for list of
interpreted (run under debug) processes (the Monitor
buffer) and separate buffers for each
of module, run under debugger (Attach
buffers).
To enable debugging of current module, you need to switch it into process of
interpretation. This is performed with the edb-toggle-interpret
command (C-c C-d i
), and
after this, you can set breakpoints in the source code with the edb-toggle-breakpoint
command (C-x SPC
).
Debugging is performed in the Attach
buffer, that you can visit via Monitor
buffer. To
switch to the Monitor
buffer you can use the edb-monitor
command (C-c C-d m
). This buffer
list all modules executed in debug mode, and user can use several commands in this buffer:
RET
opens the Attach
buffer for module under cursor; q
hides monitor buffer, and k
deletes
monitor buffer, remove all breakpoints and disconnects from the debugging module on
selected node.
The Attach
buffer allows step-by-step execution of code in concrete module. In this
buffer you can see source code of the module, together with label, displaying on line for
next command to execute (if execution was stopped on one of breakpoints). In this buffer
following commands are available for user:
command | key | description |
---|---|---|
edb-attach-step |
SPC |
execute next expression, with entering into calling function (if you stay on function call) |
edb-attach-next |
n |
execute next expression without entering into calling function |
edb-attach-continue |
c |
continue execution until next breakpoint |
edb-attach-up |
u |
show previous stack frame |
edb-attach-down |
d |
show next stack frame |
edb-toggle-breakpoint |
b |
switch breakpoint on current line of code |
edb-attach-help |
h |
show help for current buffer |
q |
remove Attach buffer without debug finishing |
During debug user can change source code, so positions of breakpoints in source code and
in debugging process could differ. To synchronize them, distel provides the
edb-synch-breakpoints
command (C-c C-d s
), that you need to execute after re-compilation &
reloading of the module. Besides this, it's recommended to use the erl-reload-module
command to module reloading, as this command will keep all breakpoints & debug statuses.
distel also allows to store current state of debugger and restore it on another selected
node, that is very useful when you need to restart Erlang's node and continue debugging
from the same place. To do this you need to use the edb-save-dbg-state
command (C-c C-d
S
) to store debugger state, and the edb-restore-dbg-state
command (C-c C-d R
) to restore
stored state.
distel distribution also has several additional utilities that could be useful for developer, who work with Erlang. For example, there is manager of processes executing on the Erlang's node, to which distel is connected.
The process manager is run by erl-process-list
command (C-c C-d l
), and creates new buffer
with information about processes (you can see an example on picture below). In this
buffer user can execute different commands, that allow to get detailed information about
process (RET
or i
keys), view content of message queue (m
key), perform tracing of
selected process (b
key). User can also terminate process with the k
key. To leave this
buffer user need to press q
key, and to update information in buffer — press the u
key.
Distel allows to write code in Emacs Lisp in Erlang style, and also to communicate with Erlang processes. Short introduction to programming with distel you can find in article Distel: Distributed Emacs Lisp and/or in article in Bill Clementson's blog.
The flymake package, supplied with Emacs, allows to perform source code checking on the fly. Erlang isn't supported out of box, but we can fix this problem as described below4.
If you never used flymake before, then first you need to load it with following command:
(require 'flymake)
Than you need to write function, that will perform flymake initialization, so it will properly handle Erlang's source code. This function will catch source code as you'll type it in the buffer, and pass code to Erlang script, that will perform checking of the code. This function looks like:
(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 "~/emacs/bin/eflymake" (list local-file))))
The path to the Erlang script is hardcoded in the body of function, so you'll need to change it, if you put it in other place. This script is pretty simple — it receive name of the file with source code, and tries to compile it, returning list of errors and warnings:
#!/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]).
After writing these function & script, you need to point to flymake, that it should use
given function for check of the files with .erl
extension. This is done with following
piece of code.
(add-to-list 'flymake-allowed-file-name-masks
'("\\.erl\\'" flymake-erlang-init))
That's all, and you can either enable flymake globally, with the file open hook:
(add-hook 'find-file-hook 'flymake-find-file-hook)
or you can enable flymake mode only for some modes with corresponding hooks:
(defun my-erlang-mode-hook () (flymake-mode 1)) (add-hook 'erlang-mode-hook 'my-erlang-mode-hook)
After this, if you will open file with .erl
extension, the flymake mode will enabled
automatically, and you will see results as you will type your code. By default, lines
containing errors are marked with pink color, while lines with warnings will marked with
light blue5. An example you can see on picture:
In this case, the some_wrong_function
function isn't defined, so Erlang can't find it, and
report about error. And function's declaration is highlighted, as the Fun
argument isn't
used in the function's body, so this lead to the warning.
The wrangler package implements basic support for refactoring of programs, written in Erlang. The package is available from project's site, but development is on early stages, so authors don't recommend it for serious work. You can find documentation for package at following address.
The ESense package (ErlangSense) implements for Emacs + Erlang something like Intellisense function in Microsoft Visual Studio. The package implements following functions:
-include
directive;This package could be used as minor mode when you edit source code, or work in buffer, where Erlang's commands are executed.
You can download ESense from the project's site. For its work you need to have HTML
parser module from the Yaws distribution6 . After downloading, you need to unpack
package, and compile it with make
, building the utility that will used for indexing of
source code.
After this, you need to copy all files with .el
extension, to place where Emacs will find
it, and add following code to your initialization file:
(require 'esense-start) (setq esense-indexer-program "/path/to/esense.sh")
You also need to change value at second line, so it will point to place, where esense.sh
script is located. This script is used to indexing of source code. Other settings you
can specify using customization group called esense
.
Before first run you'll need to generate indexes, that will be used during work of the
package. This task is performed with esense.sh
script, that accepts directory with source
code as a first argument. (Initially it's better to generate indexes for Erlang's source
code, as some information is need to proper work of package). By default, index files are
stored in ~/.esense
directory.
After index generation, you can either restart Emacs, or run the esense-initialize
command, that will update information about existing index files. After generation of
indexes for source code, you can also generate indexes for documentation in HTML format,
so links to it, could be used during the work.
By default, ESense uses the F1
key (the esense-do-something-at-point
command) to execute
almost all operations. Depending on cursor's location, the package performs one of
following operations:
RET
;-include
directive, then corresponding file will shown.If you press C-F1
, then this will lead to call of the esense-go-to-documentation
command,
that will jump to definition of the name under cursor (you can return back with standard,
for etags
, key binding —
M-*
). You can use M-F1
(esense-go-to-function-documentation
) if
you want to enter name of object, for which you want to find definition.
Pressing to the :
, #
, .
and ?
keys also lead to displaying list of possible completions
for names of function, records, fields and records and macros.
1. In general, this package provides implementation of the Erlang-style programming for Emacs Lisp. erlang-extended-mode, implemented by this package, is built on the base of the library, that provides communication with Erlang processes.
2. You can also provide numerical prefix for these commands, so it will lead to skipping given number of Erlang's functions.
3. This code was published in the Bill Clementson's blog
4. This section is based on the information from the Hypothetical Labs blog.
5. You can also specify another colors by changing definitions for flymake-errline
&
<code>flymake-warnline faces.
6. You could be need to add directory, where Yaws is installed, to the list of
directories, that will searched for the concrete modules. You can do this by adding
the code:add_path
command with corresponding directory to the ~/.erlang
file.
Last change: 05.03.2013 16:54