In this post, we’ll cover…

This is a short guide on getting started with Elixir and setting up a development environment using the Atom Editor. I chose Atom because it is OpenSource, free, cross-platform, highly hackable and pretty darn cool to use too.

Oh, it also has packages that give good support for Elixir development.

Atom Editor Basics

Atom’s packages can be accessed here…

  • ctrl+, > Install
  • Atom > Packages > Settings View > Install Packages/Themes

There are a number of general interest packages that are a good idea to install first thing. Some of these are in the Featured Packages.

Here are a few that I like and recommend for getting started. I include a short description of their function so you can more easily decide if it matters to you.

  • minimap - SublimeText-like whole file overview in the sidebar
  • atom-beautify - Multi-language code reformatting for “beautify” it. Doesn’t have Elixir support.
  • Git related
    • git-plus - Nice git support for committing, pushing, pulling, changing branches, etc.

Atom Editor and Elixir Integration

The choices of Elixir-related packages is growing and changing. Since we are still in the early days of Elixir adoption, it is worth re-visiting the list of packages from time to time.

Packages Reviewed (as of Nov 10, 2015)

For working with Elixir code, there are a few options. Here’s an overview of where it stands at the time of this writing.

  • language-elixir - Syntax support
  • script - Only “runs” highlighted code or a single file. Not helpful for real development. Instead just use an ‘iex’ terminal.
  • build-elixir - Compiles a project. Shows errors but doesn’t link to the the broken point. Helpful for getting quick feedback on if it compiles and the error report for failure.
  • elixir-cmd - Can “build” and run “tests” where output shows up in a tab.
  • linter-elixirc - Displays in-line the error with parsed out error message text. Runs after saving the file. Works by compiling the project and displaying the first error it encounters. Works well.
  • elixir-docs - Open a panel with Elixir documentation for the highlighted text.
  • iex - Open an IEx terminal in Atom. Can easily run tests with a keystroke once the keybindings are setup.
  • autocomplete-elixir - Gives interactive auto-complete support. Works for both framework code and code in the project.

Find and install the following:

  • language-elixir - Syntax support
  • iex - show me Supports IEx terminal as a pane in Atom. Allows running tests and more within Atom. The keybindings need to be customized. Has some minor annoyances but worth trying out.
  • linter-elixirc - show me Displays in-line the error with parsed out error message text. Works well and is painless to try out.
  • elixir-docs - show me Worth trying out. Still very early but I find it can be helpful.
  • autocomplete-elixir - show me Runs a beam process to give interactive auto-complete.

iex Package

Appears to work well. Run an IEx terminal in a pane. Gives access to mix code directly. Easy way to run tests. Need to setup key bindings.

Fix Key bindings

In Atom, open the settings page using ctrl+, or cmd+,. Select “Keybindings” to see all the keybindings available to you. You can override/customize your keybindings in the keymap.cson file. There is a link to open it at the top.

My keymaps:

'atom-workspace':
  'ctrl-alt-l': 'iex:open'
  'ctrl-alt-l down': 'iex:open-split-down'
  'ctrl-alt-l up': 'iex:open-split-up'
  'ctrl-alt-l left': 'iex:open-split-left'
  'ctrl-alt-l right': 'iex:open-split-right'
  'ctrl-alt-e': 'iex:reset'
  'ctrl-alt-a': 'iex:run-all-tests'
  'ctrl-alt-p': 'iex:pretty-print'

'.editor':
  'ctrl-alt-h': 'iex:help'
  'ctrl-alt-o': 'iex:gotoDefinition'
  'ctrl-alt-x': 'iex:run-tests'
  'ctrl-alt-j': 'iex:run-test'
  'ctrl-alt-b': 'iex:pipe'

Personally, I like the ctrl-alt-l down keybinding to open an IEx terminal tab below my working files. I mostly just use it for running tests. Disable or change the ones that don’t make sense or conflict.

What doesn’t work well

There are a few features of the IEx Atom package that don’t work well. At least not at this time. Feel free to disable the keybindings for those specific features.

  • iex:help - With the cursor positioned at the front of a fully qualified type or function, using the keybinding will take whatever the text is and put an “h” in front of it in the console and execute it. So if the cursor is at the start of IO.puts it will put h IO.puts in the console. It doesn’t work that well and the Elixir Docs package does a better job.
  • iex:gotoDefinition - Again, the cursor has to be at the front of a fully qualified module or function. Pressing the keybinding may sit there and do nothing or after a delay it may open the file that defines that in a new tab. It only works for things declared in the project, meaning no libraries or framework things. Sometimes it just does nothing with no error or explanation.
  • iex:pretty-print - It writes IO.puts(v(-1)) to the IEx terminal for writing out the last command (from history) in a prettier way. I guess I just can’t figure out how it supposed to work because it doesn’t work well for me.
  • iex:pipe - I haven’t actually figured out how this is supposed to work or what it should do.

IEx Tab

Before you can do any of the helpful things, we need an IEx terminal pane open. Either use menu, ctrl+shift+p or your assigned shortcut to open an IEx terminal panel.

Below is pictured the IEx tab having run the tests for the current file.

IEx Panel open showing test results

Reloading IEx (for code changes)

When you have an IEx terminal open and you’ve made code changes that you want to be available to play with, you need to “reload” the changes.

ctrl+shift+e

iex(IEX-ddf5@mark-desktop)1> AtomIEx.reset

07:13:38.155 [info]  Application testing_mix_builds exited: :stopped
:ok

Running your tests

Using one of the IEx shortcuts for running you tests, do that. It outputs on the first line the command used to do it.

Running All Tests

ctrl+alt+a

iex(IEX-1635@mark-desktop)1> AtomIEx.run_all_tests
.

Finished in 0.05 seconds (0.05s on load, 0.00s on tests)
1 test, 0 failures

Randomized with seed 743326

:ok

Running a test file

ctrl+alt+x

iex(IEX-1635@mark-desktop)4> AtomIEx.run_test("/home/mark/dev/elixir/playing/testing_mix_builds/test/testing_mix_builds_test.exs")
.

Finished in 0.06 seconds (0.06s on load, 0.00s on tests)
1 test, 0 failures

Randomized with seed 493706

:ok

Running a specific test

ctrl+alt+j

iex(IEX-1635@mark-desktop)2> AtomIEx.run_test("/home/mark/dev/elixir/playing/testing_mix_builds/test/testing_mix_builds_test.exs",5)
Including tags: [line: "5"]
Excluding tags: [:test]

.

Finished in 0.06 seconds (0.06s on load, 0.00s on tests)
1 test, 0 failures

Randomized with seed 924760

:ok

linter-elixirc Package

A simple automatic package that compiles the project when a file is saved, parses any compiler errors and highlights the line with the error and adds a bubble with the compiler error message.

It requires the package “linter” to report the errors through, so make sure to install that too.

Example of linter-elixirc error display

Oops. Looks like a Rails hash habit crept in there, it should have been “{name, pid}”.

elixir-docs Package

By default, the keymap it uses for toggling the documentation panel conflicts with other keymaps for me. Needs some work, like an ability to close the documentation panel without a keyboard or ctrl+shift+p interaction. But here’s what it does and why it may be worth trying out.

In IEx, the h command will output the help for the fully namespaced function or type.

Example of help on the IO module.

iex(1)> h IO

                                       IO

Functions handling IO.

Many functions in this module expect an IO device as an argument. An IO device
must be a pid or an atom representing a process. For convenience, Elixir
provides :stdio and :stderr as shortcuts to Erlang's :standard_io and
:standard_error.

The majority of the functions expect char data, i.e. strings or lists of
characters and strings. In case another type is given, it will do a conversion
to string via the String.Chars protocol (as shown in typespecs).

The functions starting with bin* expect iodata as an argument, i.e. binaries or
lists of bytes and binaries.

IO devices

An IO device may be an atom or a pid. In case it is an atom, the atom must be
the name of a registered process. In addition, Elixir provides two shorcuts:

  • :stdio - a shortcut for :standard_io, which maps to the current
    Process.group_leader/0 in Erlang
  • :stderr - a shortcut for the named process :standard_error provided in
    Erlang

iex(2)>

Example of help on the IO.puts function.

iex(1)> h IO.puts

                    def puts(device \\ group_leader(), item)

Writes the argument to the device, similar to write/2, but adds a newline at
the end. The argument is expected to be a chardata.

iex(2)>

The elixir-docs package is doing the same thing. It is apparent that it taking the IEx help output, formatting it as HTML and putting it in a pane in Atom. Still, this can be helpful. Note it will also work for your own documentation.

defmodule TestProject do
  @moduledoc """
  Some documentation for my demonstration.
  """

  def say_hello do
    IO.puts "Hello everyone!"
  end

end
iex(2)> h TestProject

                                  TestProject

Some documentation for my demonstration.

iex(3)>

Using Elixir Docs

Currently, the docs pane must be opened. This can be toggled through the Atom Command Palette or configuring a keybinding. Once open, select a fully namespaced type or function and use the keybinding to activate the documentation for it. (Linux is ctrl+alt+i).

Selecting the function…

Selected text for activting elixir docs

The displayed documentation…

Elixir docs displayed

autocomplete-elixir Package

The Autocomplete-elixir package is a great one. It runs a BEAM that compiles your project and can inspect it. It shows an auto-complete popup with context-aware options for completing your statement.

Important Settings

To get it working, there are is a currently not-well-documented setting that needs to be set. In the autocomplete-elixir package’s Settings, there are two inputs for giving the path to your Elixir and Erlang directory.

Elixir docs displayed

As show, these are the settings for my Arch Linux system. /usr/bin. For Mac it may be /usr/local/bin. To find out, on a terminal type:

$ which elixir
/usr/bin/elixir

$ which erl
/usr/bin/erl

Then enter the path not including the binary program elixir and erl. So it is just the directory portion. Currently this isn’t documented well and it doesn’t give a friendly UI error if you enter an invalid directory. Instead, if in Atom you View > Developer > Toggle Developer Tools, you might see many errors about the path not being a directory. Additionally, on my system it spawned a bunch of beam.smp processes that I had to kill.

What it Does

Once the settings are correct, this is how it works.

Start typing and if your Autocomplete is set to auto-suggest (the default), then you should see it suggest some options…

Elixir docs displayed

As you go further, it continues. Notice at the bottom it tries to show the @spec information for the highlighted function.

Elixir docs displayed

When you make the final selection, it populates suggested arguments which remain selected so as you type they are automatically replaced.

Elixir docs displayed

This package is my favorite. It helps prevent simple typos and helps me discover modules and functions.

Conclusion

Elixir is still a young language. Atom is still a young tool. However, both are turning into mature platforms and something worth investigating further. Atom has a number of packages (aka plugins) that make working with Elixir more pleasant. While there are still things to improve in Atom, I’ve been enjoying it a lot.

Atom is OpenSource, cross-platform, and free. Also, it is the most hackable editor I’ve ever used. You can really dig in and tweak it to your liking.

Give Atom a try! Download it for your platform on Atom.io