Instantly share code, notes, and snippets.

Embed
What would you like to do?
This describes how I setup Atom for Clojure Development.

Atom Clojure Setup

This describes how I setup Atom for an ideal Clojure development workflow. This fixes indentation on newlines, handles parentheses, etc. The keybinding settings for enter (in keymap.cson) are important to get proper newlines with indentation at the right level. There are other helpers in init.coffee and keymap.cson that are useful for cutting, copying, pasting, deleting, and indenting Lisp expressions.

Install Atom

Download Atom

The Atom documentation is excellent. It's highly worth reading the flight manual.

Install Java and Leiningen

Install These Packages

These are the ones I install related to Clojure development.

  • proto-repl - Clojure REPL, autocompletion, etc.
  • proto-repl-charts - Graphs and Charts
  • ink - Proto REPL dependency used for inline display and the REPL output.
  • tool-bar - Proto REPL uses this to display a tool bar with options.
  • Parinfer - Handles parentheses and general Lisp editing.
  • lisp-paredit - Used only for proper indentation on newline and indenting blocks of code. (Hopefully Parinfer will handle all of these in the future)
  • highlight-selected - highlights selected keywords throughout an editor.
  • set-syntax - Easily change syntax with the command palette.

Package Settings

language-clojure

This is the built in package that comes with Atom for the Clojure Grammar. I find the default settings bad for the way that I work. I recommend changing them to the following.

  • Auto Indent: unchecked
  • Auto Indent On Paste: unchecked
  • Non Word Characters: ()"':,;~@#$%^&{}[]`
  • Scroll Past End: checked
  • Tab Length: 1

Everything else is left at the default.

bracket-matcher

Change autocomplete characters to (), [], {}, "", “”, ‘’, «», ‹› This disables closing of single quotes and back ticks.

Proto REPL

Enabled Checkboxes: auto pretty print, auto scroll, display executed code, enable completions, prefer lein, all the refresh check boxes, show inline results, use clojure syntax.

lisp-paredit

  • Enabled: checked
  • Strict: unchecked
  • Indentation Forms: try, catch, finally, /^let/, are, /^def/, fn, cond, condp, /^if.*/, /.*\/for/, for, for-all, /^when.*/, testing, doseq, dotimes, ns, routes, GET, POST, PUT, DELETE, extend-protocol, loop, do, case, with-bindings, checking, with-open
  • Keybindings Enable: unchecked

Atom Settings

These are main Atom Settings related to Clojure that are different than the default.

  • Auto Indent On Paste: unchecked
  • Scroll Past End: checked
    • Due to this autocomplete issue there is a lot of flashing from the autocomplete window that pops up. Scrolling down farther usually resolves the issue.

styles.less

Atom has a place for custom styles. Place the following in your styles.less. This disables unbalanced lisp-paredit parentheses indicators in the REPL.

.proto-repl-repl::shadow .lisp-syntax-error .region {
  background-color: rgba(0, 0, 0, 0) !important;
}

init.coffee and keymap.cson

The files included in this gist init.coffee and keymap.cson contain additional settings for Atom. You can paste their contents in the files after opening them in Atom.

# These add some convenience commands for cutting, copying, pasting, deleting, and indenting Lisp expressions.
# Applies the function f and then reverts the cursor positions back to their original location
maintainingCursorPosition = (f)->
editor = atom.workspace.getActiveTextEditor()
currSelected = editor.getSelectedBufferRanges()
f()
editor.setSelectedScreenRanges(currSelected)
# Cuts the current block of lisp code.
atom.commands.add 'atom-text-editor', 'jason:cut-sexp', ->
editor = atom.workspace.getActiveTextEditor()
atom.commands.dispatch(atom.views.getView(editor), 'lisp-paredit:up-sexp')
atom.commands.dispatch(atom.views.getView(editor), 'lisp-paredit:expand-selection')
atom.commands.dispatch(atom.views.getView(editor), 'core:cut')
# Copies the current block of lisp code.
atom.commands.add 'atom-text-editor', 'jason:copy-sexp', ->
maintainingCursorPosition ->
editor = atom.workspace.getActiveTextEditor()
atom.commands.dispatch(atom.views.getView(editor), 'lisp-paredit:up-sexp')
atom.commands.dispatch(atom.views.getView(editor), 'lisp-paredit:expand-selection')
atom.commands.dispatch(atom.views.getView(editor), 'core:copy')
# Pastes over current block of lisp code.
atom.commands.add 'atom-text-editor', 'jason:paste-sexp', ->
editor = atom.workspace.getActiveTextEditor()
atom.commands.dispatch(atom.views.getView(editor), 'lisp-paredit:up-sexp')
atom.commands.dispatch(atom.views.getView(editor), 'lisp-paredit:expand-selection')
atom.commands.dispatch(atom.views.getView(editor), 'core:paste')
# Deletes the current block of lisp code.
atom.commands.add 'atom-text-editor', 'jason:delete-sexp', ->
editor = atom.workspace.getActiveTextEditor()
atom.commands.dispatch(atom.views.getView(editor), 'lisp-paredit:up-sexp')
atom.commands.dispatch(atom.views.getView(editor), 'lisp-paredit:expand-selection')
atom.commands.dispatch(atom.views.getView(editor), 'core:delete')
# Indents the top level sexp.
atom.commands.add 'atom-text-editor', 'jason:indent-top-sexp', ->
maintainingCursorPosition ->
editor = atom.workspace.getActiveTextEditor()
range = protoRepl.EditorUtils.getCursorInClojureTopBlockRange(editor)
# Work around a lisp paredit bug where it can't indent a range if selected from the very beginning of the file
start = range.start
if start.column == 0 && start.row == 0
start.column = 1
editor.setSelectedScreenRange(range)
atom.commands.dispatch(atom.views.getView(editor), 'lisp-paredit:indent')
# Allows using enter to select an autocomplete suggestion.
'.platform-darwin atom-text-editor[data-grammar~="clojure"].autocomplete-active':
'enter': 'autocomplete-plus:confirm'
'.platform-darwin atom-text-editor[data-grammar~="clojure"]':
# Indent the current selection
'cmd-i': 'lisp-paredit:indent'
# Expand the selection up a block
'ctrl-shift-m': 'lisp-paredit:expand-selection'
# Provides proper indentation when enter is pressed. (I disable normal lisp-paredit keybindings)
'enter': 'lisp-paredit:newline'
# Helpers for cutting, copying, pasting, deleting, and indenting a Clojure code
'cmd-shift-x': 'jason:cut-sexp'
'cmd-shift-c': 'jason:copy-sexp'
'cmd-shift-v': 'jason:paste-sexp'
'cmd-shift-delete': 'jason:delete-sexp'
'cmd-shift-d': 'jason:delete-sexp'
'cmd-shift-i': 'jason:indent-top-sexp'
# Miscellaneous helpers. Less applicable to clojure code. (optional)
'.platform-darwin atom-workspace atom-text-editor':
'alt-up': 'editor:move-line-up'
'alt-down': 'editor:move-line-down'
'cmd-alt-down': 'editor:duplicate-lines'
'cmd-d': 'editor:delete-line'
'ctrl-s':'tree-view:toggle'
'cmd-e': 'find-and-replace:select-next'
'cmd-alt-ctrl-w': 'editor:toggle-soft-wrap'
'alt-backspace': 'editor:delete-to-previous-word-boundary'
'alt-delete': 'editor:delete-to-next-word-boundary'
'ctrl-d': 'proto-repl:exit-repl'
'cmd-l': 'go-to-line:toggle'
'ctrl-l': 'proto-repl:clear-repl'
@oakmac

This comment has been minimized.

Show comment
Hide comment
@oakmac

oakmac Mar 11, 2016

Thank you for compiling this information! Very helpful :)

oakmac commented Mar 11, 2016

Thank you for compiling this information! Very helpful :)

@LucasKA

This comment has been minimized.

Show comment
Hide comment
@LucasKA

LucasKA May 2, 2016

This is great, thanks for putting this together. ProtoREPL is great.

LucasKA commented May 2, 2016

This is great, thanks for putting this together. ProtoREPL is great.

@trival

This comment has been minimized.

Show comment
Hide comment
@trival

trival Jul 6, 2016

Thanks, this is very usefull!

trival commented Jul 6, 2016

Thanks, this is very usefull!

@Jjunior130

This comment has been minimized.

Show comment
Hide comment
@Jjunior130

Jjunior130 Jul 20, 2016

Thx, much help.

Jjunior130 commented Jul 20, 2016

Thx, much help.

@nishch

This comment has been minimized.

Show comment
Hide comment
@nishch

nishch Aug 30, 2016

Thank you so much for all the excellent work, this has been very useful.

nishch commented Aug 30, 2016

Thank you so much for all the excellent work, this has been very useful.

@lyndsysimon

This comment has been minimized.

Show comment
Hide comment
@lyndsysimon

lyndsysimon Dec 5, 2016

Thanks! This seems like an excellent start to using Atom for Clojure.

lyndsysimon commented Dec 5, 2016

Thanks! This seems like an excellent start to using Atom for Clojure.

@ioRekz

This comment has been minimized.

Show comment
Hide comment
@ioRekz

ioRekz Dec 12, 2016

Did you manage to have correct indentation when using default cmd-enter which is insert newline-below ?

ioRekz commented Dec 12, 2016

Did you manage to have correct indentation when using default cmd-enter which is insert newline-below ?

@akkinenivijay

This comment has been minimized.

Show comment
Hide comment
@akkinenivijay

akkinenivijay commented Dec 12, 2016

Thank you

@robertjchristian

This comment has been minimized.

Show comment
Hide comment
@robertjchristian

robertjchristian Dec 14, 2016

Brilliant setup. Thank you!

Note I had to modify project.cli with:

:dependencies [[org.clojure/clojure "1.8.0"] [proto-repl "0.3.1"], [org.clojure/tools.namespace "0.2.11"]]

robertjchristian commented Dec 14, 2016

Brilliant setup. Thank you!

Note I had to modify project.cli with:

:dependencies [[org.clojure/clojure "1.8.0"] [proto-repl "0.3.1"], [org.clojure/tools.namespace "0.2.11"]]

@bsiver

This comment has been minimized.

Show comment
Hide comment
@bsiver

bsiver Dec 28, 2016

Hi! Thanks for the awesome guide. I'm having some trouble inserting newlines at the end of closing form. As far as I can tell, I have the proper settings in lisp-paredit and the keymap.cson file.

essentially, this is my problem:

(ns my.namespace
  (:require [schema.core :as s]
            [something.else :as se]|)

If my cursor is at |, pressing enter there doesn’t insert a newline, but rather moves my cursor past the form.

bsiver commented Dec 28, 2016

Hi! Thanks for the awesome guide. I'm having some trouble inserting newlines at the end of closing form. As far as I can tell, I have the proper settings in lisp-paredit and the keymap.cson file.

essentially, this is my problem:

(ns my.namespace
  (:require [schema.core :as s]
            [something.else :as se]|)

If my cursor is at |, pressing enter there doesn’t insert a newline, but rather moves my cursor past the form.

@zaatas

This comment has been minimized.

Show comment
Hide comment
@zaatas

zaatas Dec 31, 2016

10,000 thanks !!!!

zaatas commented Dec 31, 2016

10,000 thanks !!!!

@jinwg

This comment has been minimized.

Show comment
Hide comment
@jinwg

jinwg Jan 1, 2017

awesome!!! best tool i am looking for...

jinwg commented Jan 1, 2017

awesome!!! best tool i am looking for...

@orlin

This comment has been minimized.

Show comment
Hide comment
@orlin

orlin Jan 14, 2017

Thank you so much for this! What themes do you guys use?

orlin commented Jan 14, 2017

Thank you so much for this! What themes do you guys use?

@phluks

This comment has been minimized.

Show comment
Hide comment
@phluks

phluks Feb 3, 2017

Thanks. I like to throw swackets in the mix. It makes it easier to grok the parens visually.

phluks commented Feb 3, 2017

Thanks. I like to throw swackets in the mix. It makes it easier to grok the parens visually.

@matanster

This comment has been minimized.

Show comment
Hide comment
@matanster

matanster May 15, 2017

This is awesomely useful and helpful. One thing outstanding however is it is hard to figure what's going on once the setup is done though, in particular, the automatic parentheses adding and the forced indentation (which one might even wish to sometimes turn off or better fathom why they do certain things and not others), and how to use some of the features (starting a repl or running lein tasks from within Atom).

Can someone possibly chime in on these details, for the sake of setup newbs? :-)

matanster commented May 15, 2017

This is awesomely useful and helpful. One thing outstanding however is it is hard to figure what's going on once the setup is done though, in particular, the automatic parentheses adding and the forced indentation (which one might even wish to sometimes turn off or better fathom why they do certain things and not others), and how to use some of the features (starting a repl or running lein tasks from within Atom).

Can someone possibly chime in on these details, for the sake of setup newbs? :-)

@AlexKVal

This comment has been minimized.

Show comment
Hide comment
@AlexKVal

AlexKVal Aug 17, 2017

Thank you 🍒

AlexKVal commented Aug 17, 2017

Thank you 🍒

@lucasdf

This comment has been minimized.

Show comment
Hide comment
@lucasdf

lucasdf May 11, 2018

Instead of changing the bracket-matcher autocomplete settings globally, it is also possible to change it in config.cson so the changes only apply to clojure files. That way you don't lose single quotes and back ticks autocomplete on other types of files.

".clojure.source":
  "bracket-matcher":
    autocompleteCharacters: [
      "()"
      "[]"
      "{}"
      "\"\""
      "“”"
      "‘’"
      "«»"
      "‹›"
    ]

lucasdf commented May 11, 2018

Instead of changing the bracket-matcher autocomplete settings globally, it is also possible to change it in config.cson so the changes only apply to clojure files. That way you don't lose single quotes and back ticks autocomplete on other types of files.

".clojure.source":
  "bracket-matcher":
    autocompleteCharacters: [
      "()"
      "[]"
      "{}"
      "\"\""
      "“”"
      "‘’"
      "«»"
      "‹›"
    ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment