Emacs setup for Elm (with autocompletion and lint)

I recently decided to retrain myself as a terminal Emacs user (I'm nostalgic for the '80s and my old glorious green and black terminal :P)

So I switched all my Elm editing from Sublime Text (which works and is pretty nice) to Emacs (which also works and is pretty nice).
This is a guide to set a good environment up.

You'll probably want to setup package management with Cask and pallet for your Emacs, follow this guide for that.

Pre-requisites

Install deps

The first thing you'll want to do is hit M-x package-list-packages and install:

  • elm-mode
  • flycheck
  • flycheck-elm
  • company
  • elm-oracle

or you can put them in your Cask file and do a cask install from the cli.

Elm-mode

The main thing we need is elm-mode, assuming you have installed it, set it up by adding to your .emacs or equivalent:

(require 'elm-mode)

Now if you open a .elm file you'll have syntax highlighting.

On newline elm-mode will give you a list of possible indentations, cycle between them with TAB. If you have just written a type signature, one option will be the name of the function, so you don't need to rewrite it yourself:

update : Action -> Model -> Model
update 

which is quite convenient.

A few useful elm-mode commands:

  • C-c C-c will compile the buffer
  • C-c C-n will preview it in a browser
  • C-c C-d will show the doc of a function
  • C-c M-k opens the package catalog (cool! :D)

From the package catalog you can install the Elm packages you need without having to use elm-package from the command line.

For more, take a look at the elm-mode README.

Flycheck

We want lint support as well, for that we can use Flycheck.
Assuming you installed it before, add this to your .emacs file:

(require 'flycheck)
(with-eval-after-load 'flycheck
      '(add-hook 'flycheck-mode-hook #'flycheck-elm-setup))

If you open a .elm file you should get FlyC: in your mode, and errors and warnings should be highlighted.

Gotchas

flycheck-elm is a bit hard to make work.
Just following the instructions on github didn't work for me.
Let's take a look at the things that can go wrong:

elm-make may not work

If it doesn't, flycheck-elm won't work either.
To check, try C-c C-c to compile the buffer with elm-mode. You should get another buffer with the compilation messages.
If not, go to your project directory and check if elm-make works there (check your Elm install works guide).

flycheck may not load at all

For some reason the hook to elm-mode is not actually triggering. To force it to load for every buffer add this to .emacs:

(add-hook 'after-init-hook #'global-flycheck-mode)
Flycheck loads but elm is not a valid syntax checker

That means that flycheck-elm-setup is not getting triggered.
This worked for me:

(add-hook 'flycheck-mode-hook 'flycheck-elm-setup)

In place of:

(with-eval-after-load 'flycheck
      '(add-hook 'flycheck-mode-hook #'flycheck-elm-setup))

Hopefully this will fix your issues.

Other issues

If you have some strange error message, try adding

(setq debug-on-error t)
``` to your `.emacs` files. It'll drop you into the debugger and you'll be able to investigate a bit.

#### Autocompletion

Last, but not least, autocompletion support can be obtain by cooperating with `elm-oracle`.

You need to:

1. have `company` installed
2. install [elm-oracle](https://github.com/ElmCast/elm-oracle) with npm:

npm install -g elm-oracle


Add this to your .emacs file:

(with-eval-after-load 'company
(add-to-list 'company-backends 'company-elm))
(add-hook 'elm-mode-hook #'elm-oracle-setup-completion)


To try out if this works, put the cursor on a type signature and do `C-c C-t`.

You should get either `unknown type` or a type signature. That means it works.

After having checked that, try the autocomplete on a type signature.
Just write 3 characters of a type and wait. It should autocomplete. If it's not, it should be because it doesn't have a candidate. Try `M-x company-complete` to force it to run, to be sure.

Watch out if you use company-mode for more than one language, you'll likely need to hook it to the mode, instead of just adding it to the backends list:

(add-hook 'elm-mode-hook
(lambda ()
(setq company-backends '(company-elm))))


That's all, now you should have an Emacs setup for Elm. Happy coding!

#### Troubleshooting

The project needs to compile with `elm-reactor` at least once for much of the functionality to work. If you can't get `C-c C-n` to compile and run please clean the project from `elm.js` and `elm-stuff/`and run `elm-reactor` in the project root once. If that works `elm-mode` should also work.

Also you can compare with my `.emacs` to see if there's something missing: [My .emacs](https://github.com/doppioslash/dotfiles/blob/master/emacs/.emacs).

Please let me know if this didn't work for you! I'm usually on the elm Slack, #elm on freenode and on twitter as @doppioslash and @lambda-cat.