Меню:


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.

erlang-mode

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 and customization of the package

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.

Work with source code

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.

Navigation in source code

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.

Code templates

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:

Compilation and work with 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

erlware-mode package is replacement for erlang-mode, using it as a base, but adding following new functionality:

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.

distel

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.

Installation & customization of distel

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)))))

Work with source code

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.

Obtaining information from documentation

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.

Execution and profiling of code

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.

Work with debugger

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.

Applications for work with Erlang environment

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.

Programming with distel

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.

Customize Flymake to work with Erlang

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

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.

ESense

The ESense package (ErlangSense) implements for Emacs + Erlang something like Intellisense function in Microsoft Visual Studio. The package implements following functions:

This package could be used as minor mode when you edit source code, or work in buffer, where Erlang's commands are executed.

Installation & customization

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.

Work with package

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:

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

blog comments powered by Disqus