This is another attempt at providing Paredit support for Light Table.
The plugin is scoped to only support Clojure(/ClojureScript/EDN), this limitation has opened a completely different route for implementing paredit support than previous attempts in Light Table. The plugin makes heavy use of the rewrite-cljs library. The library allows us to treat the code as an virtual AST rather than a stream of characters and provides some truly exceptional flexibility in terms of implementing paredit features (and way beyond).
It’s still some way to go, but the basic features are mostly working pretty nicely !
You will find the plugin through the Light Table plugin manager under the name clj-light-refactor
If you want try it out the lastest stuff you can clone it to the plugins folder for LightTable (check the LT docs for where)
I’m planning to make it even easier than it currently is to easily add new or modified features. If you know your way around a clojure zipper you have a very good starting point. With the user plugin it should be fairly easy to add your own commands and behaviors.
No sweeping this under the carpet:
-
If you write illegal Clojure code, the features will fail (do nothing or throw errors)
-
It’s not blisering fast (hoping th atom shell/electron release might help some here)
-
To keep the features snappy enough, keep your top level form size sensible (top level forms beyond 3-400 lines will not work nicely)
-
There is no strict mode option (and none coming in the immediate future)
-
Most if not all features require you to work in the context of top-level forms
All commands are available in the command browser. They are prefixed with Parembrace:
There are no predefined keyboard shortcuts. So you have to figure out what makes sense to you. (And configure your User keymap Maybe you prefer something close to the defaults from paredit.el or maybe vims keybindings are more to your taste.
Command | Description | Sample |
---|---|---|
Open list/vector/set/map |
Create a list/vector/set/map pair append space and position cursor |
|
Open doublequote |
Create a doublequote pair |
|
Open anonymous function |
Create an empty anonymous function |
|
The navigation commands have similarities to Emacs, but it’s better to compare with the movement functions in clojure.zip. It should be supereasy for you to add custom navigation commands if you are somewhat familiar with clojure.zip
Command | Description | Sample |
---|---|---|
Move right |
Move cursor to start of right sibling |
(+ |1 2) ⇒ (+ 1 |2) |
Move left |
Move cursor to start of left sibling |
(+ 1 |2) ⇒ (+ |1 2) |
Move down |
Move cursor down into S-expr and position at first node |
(let |[a 1]) ⇒ (let [|a 1]) |
Move up |
Move cursor up from current S-expr to enclosing S-expr and position at start |
(let [|a 1]) ⇒ (let |[a 1]) |
Move up right |
Move cursor up from current S-expr to enclosing S-expr and position at end |
(let [|a 1]) ⇒ (let [a 1]|) |
Move next |
Move to next node given a depth first traversal. |
[|1 [2 [3]] 4] ⇒ [1 |[2 [3]] 4] |
Move previous |
Move to previous node given a depth first traversal. |
Reverse of move next |
Command | Description | Sample |
---|---|---|
Kill |
Kill all sibling nodes to the right of the current node (when in seq node) |
|
Kill to end of comment (when in comment) |
({:a 1 ; Hello| world
:b 2} ({:a 1 ; Hello| \n
:b 2} |
|
Kill to end of string (when in string) |
|
|
Kill in empty string - nukes |
|
|
Kill one |
Kill the node at position |
|
Kill word in comment at position |
|
|
Kill word in string at position |
(str "Foo
|Bar
Do") (str "Foo
|Do") |
Command | Description | Sample |
---|---|---|
Slurp forward |
Pull in next right outer node (if none at first level, tries next etc) into current S-expression |
|
Slurp backward |
Pull in prev left outer node (if none at first level, tries next etc) into current S-expression |
|
Slurp forward fully |
Pull in all right outer-nodes into current S-expression, but only the ones at the same level as the the first one |
(defn foo []
(let [a 1]|)
(println "a") ; useful
(println "b")) (defn foo []
(let [a 1]
(println "a") ; useful
(println "b"))) |
Slurp backward fully |
Pull in all lef outer-nodes into current S-expression, but only the ones at the same level as the the first one |
|
Barf forward |
Push out the rightmost node of the current S-expression into outer right form |
|
Barf backward |
Push out the leftmost node of the current S-expression into outer left form |
|
Command | Description | Sample |
---|---|---|
Wrap around - (list/vector/map/set) |
Wrap node at cursor in given sequence type |
|
Wrap around slurping forward - (list/vector/map/set) |
Create a new seq node of given type left of cursor pos then slurp fully into the new node |
|
Splice |
Unwrap nodes in current S-expr into enclosing S-expr |
|
Splice - killing bacward |
Remove left siblings of current given node in S-Expression and unwrap remaining into enclosing S-expression |
(foo (let ((x 5))
|(sqrt n)) bar) (foo (sqrt n) bar) |
Splice - killing forward |
Remove current given node and its right siblings in S-Expression and unwrap remaining into enclosing S-expression |
|
Split |
Split current s-sexpression in two at given node |
|
Join |
Join S-expression to the left and right of current loc. |
|
Raise |
Kill siblings and raise current node up one level to enclosing expression. |
|
Note
|
Except for the wrapping commands, placement of the cursor position after the command above is not very cleverly placed (: |
Command | Description | Sample |
---|---|---|
Select expression |
Select node(s) at given pos, if already a selection the selection is expanded |
|
Move node to previous |
Move node at current location to the position of previous location given a depth first traversal |
|
Pull requests are most welcome. Please do not include the transpiled files (_compiled) in the PR.
-
0.1.0 Initial release With a wide range of paredit features supported. A few novel/different commands available too !