Friday, August 17, 2012

Happiness is an emacs trifecta

Today was a good emacs day. Actually, any day I spend in emacs is good, but today was especially good, since I found three new little gems to stick in my init.el.


/* ---[ Show only one buffer on startup ]--- */

First, I wanted emacs to only open with a single buffer showing when I pass multiple files to it on the command line. A few minutes later, solution #1 found:

[Update 20-Aug-2012]: gist updated with shorter version based on feedback from Steven Purcell.


/* ---[ Override a paredit keybinding ]--- */

I've come to love paredit when working in Clojure and emacs-lisp. Except for one problem: for years I've used Cntl-<left> and Cntl-<right> a lot to quickly navigate around. Those keystrokes are deeply ingrained in my motor memory. The paredit author's way of working differs from mine though, since he bound those to "barf" and "slurp" (mmmmm), respectively. When you then try to zip quickly around the screen using Cntl-<left> and Cntl-<right> with paredit-mode enabled, your cursor goes nowhere and instead you make a holy mess of your parens and brackets in the file.

So I wanted to rebind barf and slurp to Meta-<left> and Meta-<right> and unbind the existing mappings with the Control key. For a while I've just been editing the paredit.el file, but now that we have a package system in emacs24, that will get overridden when I upgrade. Thus, I need a clean way to do this that works for any future upgrades. So, a few minutes later, solution #2 found:

I hadn't seen the eval-after-load function before. It is a particularly satisfying way to override bindings in another package.


/* ---[ Toggle between multiple windows and a single window ]--- */

I've been teaching emacs to an intern at my job and today after showing him macros, how to toggle comment blocks and ace-jump-mode (which is awesome!), he asked: currently, I've got 4 buffers showing, but what if I want to expand one window to fill the window, work on it and then restore emacs back to having the 4 buffers I had showing before?

My response: blink, blink.

Umm, that would awesome, why didn't I think of that? So a few minutes later, thanks to Ignacio Paz Posse (about the coolest name I've ever seen), beautiful solution #3:

This is my favorite emacs thing now.

That is, until I find the next shiny bit of emacs-lisp to make my day happier than usual.


[Update 20-Aug-2012]: Steve Purcell in the comments pointed out that there is another way to restore your window configuration that has been built into emacs since version 20: Winner Mode.

So if you have trouble with the toggle-windows-split or would rather use something built-in, try this instead. In your .emacs or init.el add:

(winner-mode 1)

Then when you have multiple buffers showing and you want to maximize one of them enter C-x 1 as usual to close all other windows except the one with cursor focus. To restore your previous window configuration enter C-c <left>. Sweetness.

5 comments:

  1. toggle-windows-split: Nicely done!

    Every time I read about registers I think "Neat!", and then I promptly forget how to use them.

    This hopefully will work better :-)

    ReplyDelete
  2. The startup hook could more concisely be written:

    (add-hook 'emacs-startup-hook 'delete-other-windows t)

    For the window splitting, try putting "(winner-mode 1)" in your startup files. With it, you can use "C-x 1" to delete the other windows, then use "C-c left" to jump back to the previous window configuration.

    ReplyDelete
    Replies
    1. Steve - double thanks for both suggestions. I tried them and they work great. I hadn't tried winner mode before. So there are (at least) two nice ways to restore your window configuration - winner mode or the 'toggle-window-split' function.

      I've updated my blog with these points.

      Delete
  3. Both you and Ingnacio forget to mention that `toggle-windows-split` depends on `my-iswitchb-close`, which I've only been able to find on EmacsWiki at http://emacswiki.org/emacs/IgnacioPazPosse:

    (defun my-iswitchb-close()
    "Open iswitchb or, if in minibuffer go to next match. Handy way to cycle through the ring."
    (interactive)
    (if (window-minibuffer-p (selected-window))
    (keyboard-escape-quit)))

    ReplyDelete
    Replies
    1. Thanks for the addition. The strange thing is that both on my emacs 23 setup on Windows and my emacs 24 setup on Linux, 'toggle-windows-split' worked for me without including 'my-iswitchb-close'. Not sure why. I searched through all the files in my .emacs.d and didn't find it defined anywhere.

      I've included your contribution in the third gist above. Much obliged for the feedback.

      Delete