A tiny collection of clojure refactoring functions. Please send help.
I highly recommend installing clj-refactor through elpa.
It's available on marmalade and melpa:
M-x package-install clj-refactor
You can also install the dependencies on your own, and just dump clj-refactor in your path somewhere:
(require 'clj-refactor)
(add-hook 'clojure-mode-hook (lambda ()
(clj-refactor-mode 1)
;; insert keybinding setup here
))
You'll also have to set up the keybindings in the lambda. Read on.
All functions in clj-refactor have a two-letter mnemonic shortcut. For
instance, rename-file is rf
. You get to choose how those are bound.
Here's how:
(cljr-add-keybindings-with-prefix "C-c C-m")
;; eg. rename files with `C-c C-m rf`.
If you would rather have a modifier key, instead of a prefix, do:
(cljr-add-keybindings-with-modifier "C-s-")
;; eg. rename files with `C-s-r C-s-f`.
If neither of these appeal to your sense of keyboard layout aesthetics, feel free to pick and choose your own keybindings with a smattering of:
(define-key clj-refactor-map (kbd "C-x C-r") 'cljr-rename-file)
This is it so far:
th
: thread another expressionuw
: unwind a threaded expressionua
: fully unwind a threaded expressiontf
: wrap in thread-first (->) and fully threadtl
: wrap in thread-last (->>) and fully threadil
: introduce letel
: expand letml
: move to letrf
: rename file, update ns-declaration, and then query-replace new ns in project.ar
: add require to namespace declaration, then jump back (see optional setup)au
: add "use" (ie require refer all) to namespace declaration, then jump backai
: add import to namespace declaration, then jump back
Combine with your keybinding prefix/modifier.
Given this:
(map square (filter even? [1 2 3 4 5]))
Start by wrapping it in a threading macro:
(->> (map square (filter even? [1 2 3 4 5])))
And start threading away, using cljr-thread
:
(->> (filter even? [1 2 3 4 5])
(map square))
And again:
(->> [1 2 3 4 5]
(filter even?)
(map square))
You can also do all of these steps in one go.
Start again with:
(map square (filter even? [1 2 3 4 5]))
Put your cursor in front of the s-exp, and call cljr-thread-last-all
:
(->> [1 2 3 4 5]
(filter even?)
(map square))
There is a corresponding cljr-thread-last-all
as well.
To revert this, there's cljr-unwind
to unwind one step at a time. (Just read the examples in the other direction.) Or there's cljr-unwind-all
to unwind th entire expression at once.
Given this:
(defn handle-request
{:status 200
:body (find-body abc)})
With the cursor in front of (find-body abc)
, I do cljr-introduce-let
:
(defn handle-request
{:status 200
:body (let [X (find-body abc)]
X)})
Now I have two cursors where the X
es are. Just type out the name,
and press enter. Of course, that's not where I wanted the let
statement. So I do cljr-expand-let
:
(defn handle-request
(let [body (find-body abc)]
{:status 200
:body body}))
Yay.
Next with the cursor in front of 200
, I do cljr-move-to-let
:
(defn handle-request
(let [body (find-body abc)
X 200]
{:status X
:body body}))
Again I have two cursors where the X
es are, so I type out the name,
and press enter:
(defn handle-request
(let [body (find-body abc)
status 200]
{:status status
:body body}))
Pretty handy. And it works with if-let
and when-let
too.
If you're not using yasnippet, then the "jumping back"-part of adding to namespace won't work. To remedy that, enable the mode with either:
(yas/global-mode 1)
or
(add-hook 'clojure-mode-hook (lambda () (yas/minor-mode 1)))
It is an excellent package, so I recommend looking into it. Here are some snippet packages for Clojure:
- David Nolen has created some clojure-snippets
- I've made some datomic-snippets
When you open a blank .clj
-file, clj-refactor inserts the namespace
declaration for you.
It will also add the relevant :use
clauses in test files, normally
using clojure.test
, but if you're depending on midje in your
project.clj
it uses that instead.
Like clojure-mode, clj-refactor presumes that you are postfixing your
test files with _test
.
Prefer to insert your own ns-declarations? Then:
(setq clj-add-ns-to-blank-clj-files nil)
You might also like
- align-cljlet - which is an Emacs package for aligning let-like forms.
- Add
cljr-move-to-let
(Alex Baranosky)
Yes, please do. There's a suite of tests, so remember to add tests for your specific feature, or I might break it later.
You'll find the repo at:
https://github.com/magnars/clj-refactor.el
To fetch the test dependencies, install cask if you haven't already, then:
$ cd /path/to/clj-refactor
$ cask
Run the tests with:
$ ./run-tests.sh
- AlexBaranosky added support for
some->
in thread and unwind, and addedcljr-move-to-let
Thanks!
Copyright © 2012-2013 Magnar Sveen
Authors: Magnar Sveen magnars@gmail.com Keywords: clojure convenience
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.