Seven specialty Emacs settings with big payoffs

Let's skip the bread and butter Emacs modes and focus on settings that are hard to find, but which once activated provide a big payoff.

For reference, my complete Emacs settings are defined in init.el and lisp/packages.el


1. Monochrome rainbows are the best way to reveal unbalanced delimiters

I rely and paredit and formatting to keep my parenthesis honest, and for the most part that works out great. Occasionally I need to go outside the box. Emacs defaults are terrible for finding unbalanced forms when things go wrong. This setting makes it obvious that there is an error when I have fallen out with my grouping delimiters. See the red highlighting in this example:





The trick is to not use different colored delimiters! The reason I need the rainbow delimiters package is only to highlight unbalanced delimiters, which it does quickly and accurately. For those cases where I really want to differentiate a group, placing the cursor on the delimiter causes Emacs to highlight the other delimiter.

To activate this setting:


Install rainbow-delimiters, then
M-x customize-group rainbow-delimiters
Rainbow Delimiters Max Face Count: 1

(add-hook 'prog-mode-hook 'rainbow-delimiters-mode)
(require 'rainbow-delimiters)
(set-face-attribute 'rainbow-delimiters-unmatched-face nil
                    :foreground 'unspecified
                    :inherit 'error)

Depending on your theme you may wish to modify the delimiter colors to something relatively passive like grey.


2. Save on focus out

I love writing ClojureScript because it feels alive. When I change some code I instantly see the results reflected in the browser thanks to figwheel or boot-reload. It is even better than a REPL because you don't need to eval. This setting causes my file to be saved when I switch from Emacs to my browser. This is perfect because I don't need to mentally keep track of saving or compiling... I just code, switch to my browser and see the code reloaded. If something goes wrong figwheel notifies me with a popup or boot-reload with a noise, and I can go back to the code or check my build output. This also works great with ring reload middleware.

To activate this setting:


(defun save-all ()
  (interactive)
  (save-some-buffers t))
(add-hook 'focus-out-hook 'save-all)

You will never forget to save/eval again, and the saves happen at the right time in your workflow.


3. Chords

Emacs key-strokes are pretty gnarly. Especially for a VIM guy like me (Emacs evil-mode is the best VIM). Chords are so much more comfortable! For example I press j and x together instead of M-x. Just be careful when choosing chords that they are combinations you will never type normally. I mainly use chords for switching buffers, navigating windows, opening files, and transposing expressions.

To activate this setting:


Install key-chord

(key-chord-define-global "jx" 'smex)

(You can see more chords in my settings file)


4. Forward and backward transpose

I move code around a lot! This setting allows me to swap values quickly and move forms around. For example if I accidentally put function call arguments in the wrong order, I can swap them around. Or if I define my functions out of order, I can swap the entire form up or down. I just put my cursor at the start of the form I want to move, and press 'tk' to move it forward/down, or 'tj' to move it backward/up. Joel came up with this trick, and has lots of other Emacs foo up his sleeve (check out his matilde repo).

To activate this setting:


(defun noprompt/forward-transpose-sexps ()
  (interactive)
  (paredit-forward)
  (transpose-sexps 1)
  (paredit-backward))

(defun noprompt/backward-transpose-sexps ()
  (interactive)
  (transpose-sexps 1)
  (paredit-backward)
  (paredit-backward))

(key-chord-define-global "tk" 'noprompt/forward-transpose-sexps)
(key-chord-define-global "tj" 'noprompt/backward-transpose-sexps)



5. Choose a comfortable font

Perhaps this is obvious, but it took me a while to realize what a big impact a comfortable font has when you spend a lot of time in Emacs. The default font is rather small in my opinion, and there are better options. I find Source Code Pro a good choice.

To activate this setting:


(set-frame-font "Source Code Pro-16" nil t)


6. Send expressions to the REPL buffer

For Clojure coding, cider is great. But weirdly it doesn't have a way to send code the the REPL buffer... instead you just evaluate things and see the output. I really like seeing the code in the REPL buffer, and for pair programming it is essential for showing your pair exactly what you are doing (they can't see your zany Emacs keystrokes!) This setting binds C-; to send the current form to the REPL buffer and evaluate it.

To activate this setting:


(defun cider-eval-expression-at-point-in-repl ()
  (interactive)
  (let ((form (cider-defun-at-point)))
    ;; Strip excess whitespace
    (while (string-match "\\`\s+\\|\n+\\'" form)
           (setq form (replace-match "" t t form)))
    (set-buffer (cider-get-repl-buffer))
    (goto-char (point-max))
    (insert form)
    (cider-repl-return)))

(require 'cider-mode)
(define-key cider-mode-map
            (kbd "C-;") 'cider-eval-expression-at-point-in-repl)


7. Prevent annoying "Active processes exist" query when you quit Emacs.

When I exit Emacs, it is often in anger. I never want to keep a process alive. I explicitly want my processes and Emac to stop. So this prompt is infuriating. Especially when there are multiple processes. Emacs, just stop already!

To activate this setting:


(require 'cl)
(defadvice save-buffers-kill-emacs (around no-query-kill-emacs activate)
           (flet ((process-list ())) ad-do-it))


Final comments

These settings improved my workflow dramatically. Drop me an email or comment if you have any trouble with them. I put this list together after being inspired by Jake's blog. He has lots of great Emacs/workflow tips that you might like if Emacs is your editor of choice.

14 comments:

  1. I think cider-eval-expression-at-point-in-repl can be replaced with some calls to built-in cider functions. I think cider-insert-defun-in-repl called with an argument will have the same behavior.

    Great post. I've already copied quite a bit of it into my setup.

    ReplyDelete
  2. I love this use of rainbow-delimiters, thanks for this!

    ReplyDelete
  3. @Eli - glad you found it useful :)
    @Jake - thanks, I'll try that approach out.

    ReplyDelete
  4. One setting is ridiculousy bad:
    (key-chord-define-global "jx" 'smex)
    This will cause a huge delay when you're pressing j, because key-chord will be waiting on input. If it gets no input after a while, it will execute the Evil command anyway. But it will ruins your motion flow.

    ReplyDelete
  5. Hi Rene,

    I get no delay at all, motion flow is instant. Is this a problem you are experiencing?

    ReplyDelete
  6. Yes, when I use (key-chord-define-global "jx" 'smex), I takes a while for the cursor to move after press 'j'. Notice that you're probably didn't notice because you're pressing 'j' multiple in a row, instead pressing once.

    ReplyDelete
  7. Gotcha. Hmmm wierd, for me there is no delay even for just a single press.
    I have this in my settings:
    (key-chord-mode 1)
    I wonder if that affects it?
    I'll try with and without.

    ReplyDelete
  8. Hmmm nope, doesn't seem to make a difference. Sorry I don't know the answer.

    ReplyDelete
  9. You're right. I tested it with vanilla Emacs. Seems my config is flawed somewhere... Will debug it, thanks!

    ReplyDelete
  10. Thanks for the tips. I had to adjust your font setting to work correctly with emacs daemon/client:

    (setq default-frame-alist '((font . "Source Code Pro-14")))

    ReplyDelete
  11. Nice catch Ben, thank you for noting.

    ReplyDelete
  12. 1. It seems like you will never have unbalanced parens in the first place. What do you mean, why do you need to go outside the box? Paredit has unbalanced-insert, right?

    2. My philosophy is aggressively maintain Emacs state to file so I save when switching buffers, when jumping, lots of places.

    3. Chords are critical to performance. jk for smex, jn for switch buffer, mk for find-file, and bh for projctile. Performance cluster lol.

    4. Fonts are an important decision, eg: github.com/grettke/home/blob/master/Font.org

    ReplyDelete
  13. Programming is very interesting and creative thing if you do it with love. Your blog code helps a lot to beginners to learn programming from basic to advance level. I really love this blog because I learn a lot from here and this process is still continuing.
    Love from Pro Programmer

    ReplyDelete
  14. Thank you for the encouraging comment :)

    ReplyDelete