This repo contains my customisations to make editing Clojure in Helix more comfortable.
For textobject and indent queries:
- Copy the Clojure language section from
./helix/languages.tomlinto your own~/.config/helix/languages.toml. - Copy
./helix/runtime/grammars/clojure.soto your~/.config/helix/runtime/grammarsfolder. - Copy
./helix/runtime/queries/clojure/*.scmto your~/.config/helix/runtime/queries/clojurefolder.
For ersatz repl integration:
- Install reple from my fork at https://github.com/waddie/reple/tree/fix/rlwrap
- Copy the keymap entries from
./helix/config.tomlto your own~/.config/helix/config.toml, or create your own equivalents to suit your preferences.
Jeka’s reple (https://github.com/j3ka/reple) is a basic workaround for Helix’s current lack of a plugin
system, which prevents a proper repl integration like CIDER for emacs or Calva for vscode. It lets you
send a form to a repl to evaluated.
clj wraps clojure in rlwrap to provide history, etc. When spawned with reple, it fails to launch
because the terminal dimensions aren’t passed through. You can use plain clojure, but then you don’t get
history. In practice, you will want to use the repl directly because the integration is so simple.
My fork simply adds reporting of the terminal size so clj will start properly.
To use it with the keymap included, simply select the entire form and hit Alt-Enter to send it to the repl.
This fork of the https://github.com/sogaiu/tree-sitter-clojure Clojure grammar includes support for parsing map entries as key/value pairs instead of single elements. This allows us to match around the key/value pair in Helix.
If you prefer to build from source, you can find my branch here: https://github.com/waddie/tree-sitter-clojure/tree/map-kv-pairs
textobjects.scm enables the following:
-
Inside: Function body only, excluding keyword, name, and parameter vector
-
Around: Entire form including opening/closing parens and keyword
-
Supported keywords:
defn,defn-,defmacro,defmethod,defmulti,definlinefn#()
-
Inside: Everything after the type name
-
Around: Entire form including opening/closing parens and keyword
-
Supported keywords:
deftype,defrecord,defprotocol,definterface,defstruct
-
Inside: Everything after the test name
-
Around: Entire form including opening/closing parens and keyword
-
Supported keywords:
deftest
- Inside: All parameters within the vector, excluding brackets
- Around: Entire parameter vector including brackets
Note: Works the same with any vec.
For lists, vectors and sets:
- Around/Inside: Individual elements within collections
For maps:
-
Inside: Key or value
-
Around: Key/value pair
-
Supported collections:
- Lists:
(a b c) - Vectors:
[a b c] - Maps:
{:a 1 :b 2} - Sets:
#{a b c}
- Lists:
-
Inside: Comment content excluding delimiters
-
Around: Entire comment form or consecutive comment lines
-
Supported forms:
- Line comments:
; comment - Discard expressions:
#_(+ 1 2) - Comment special form:
(comment ...)
- Line comments:
indents.scm enables the following:
Forms where the body is indented after the name/bindings:
- Definitions:
def,defn,defn-,defmacro,defmethod,defmulti,defonce,defprotocol,deftype,defrecord,defstruct,definline,definterface,deftest - Namespace:
ns - Bindings:
let,letfn,binding,loop - Iteration:
for,doseq,dotimes - Conditional bindings:
when-let,if-let,when-some,if-some - Resource management:
with-*(any symbol starting with "with-") - Functions:
fn
- Two elements on first line: Align to second element (excludes special forms above)
- First element is a list on its own line: Align outer list to inner list
- Literal as first element: Align to the literal (booleans, nil, strings, numbers, keywords)
- Vector/Map with two elements on first line: Align subsequent elements (e.g., let bindings)
- Vectors, maps, and sets are indented by one level
- Lists not matching special cases above are indented by one level