Simple window configuration management

Most of the time, I run Emacs in a single, maximized frame (and, sometimes, just inside a urxvt terminal). Inside that frame i create and destroy windows as needed to contain my buffers [0]. After a while working with Emacs one gets used to a fluid window setup, where windows come and go as need arises.

But I remember that in the early days I felt a bit confused: I started by creating a windows setup (split horizontally, then vertically, open files in each of the windows… that kind of thing) and was non-plussed when any operation (going to a Gnus buffer and reading messages, for instance) destroyed my carefully prepared layout. Over the years i’ve seen many a newbie feeling that way. My advice is usually to let go, and learn how to move around your windows, creating them as needed.

That said, i must admit that, sometimes, i want to recover a certain window configuration in a quick way. A particularly simple one is provided by winner-mode, a package which is part of Emacs. Winner keeps track of your window configurations, and provides functions to navigate your window configuration history.

As advertised, activating winner-mode (which is a global minor mode) is as easy as one can get: just type M-x winner-mode or put this line:

    (winner-mode 1)

in your .emacs. Use Emacs normally, and whenever one cherished window layout gets destroyed, press C-c <left> (where <left> refers to the left cursor key) to recover it–actually, this calls winner-undo, and you can invoke it as many times as you want to visit previous window configurations. As one would expect, C-c <right> (the default binding for winner-redo) navigates configurations in the opposite direction [1]. Simple and very useful, as it should be.

But maybe you want to be automatically tele-transported to a previous configuration without traversing the intermediate ones. No problem: Emacs provides functions to store and retrieve window configurations (which, in fact, are the ones winner-mode is using under the covers). You can store the current window configuration in register ‘a’ (registers are named using single letters or numbers) pressing C-x r w a, and restore it later by means of C-x r j a. Again, it’s that easy.

Although there exist several packages providing more sophisticated window management (named configs, save and restore, etc.), in my experience, the simple tricks described above are more than enough (and work out of the box in any Emacs). As always, YMMV.


[0] For those of you not familiar with Emacs lingo, an Emacs frame is what most window managers would call a window, while an Emacs window is any of the regions displaying a buffer inside a frame. Usual ways of creating windows in Emacs are C-x 2, C-x 3, C-x 4 f, and so on. See Windows and WindowsAndFrames for more.

[1] In Emacs 21, the default keybindings start with C-x instead of C-c.

Imenu, with a workaround

imenu is a very handy command i learnt not long ago. Just type M-x imenu in a source code buffer (an Elisp one, for instance) and start typing the name of a variable or function (or simply TAB for name completion). There you go: instant access to definitions in the buffer.

You can also get the list of completions in a menu item calling imenu-add-menubar-index. Or, if you want the menu to be automatically created for, say, all your C files, you can put something like

(add-hook 'c-mode-hook 'imenu-add-menubar-index)

in your initialisation files.

You can read more about imenu (which has obsoleted speedbar in my workflow) in the Emacs Wiki, including how to adapt it to your favorite language (if it’s not yet supported).

Oh, and the workaround: if you’re using Emacs 22 on Mac OS X, you may need to add this dummy definition to your .emacs to make imenu work:

(defun imenu-progress-message (a &optional c d))

(otherwise, you’ll get an error about imenu-progress-message being an invalid function).

Killing, yanking and copying lines

Kind reader William Annis noticed how clumsily i copied a line in the kill ring in my last screencast. I went to the beginning of the line (C-a), killed it (C-k) so i got it in my kill-ring, and yanked it back (C-y). Admittedly, a bit cumbersome, my only excuse being that i have this keystroke sequence hardwired in my nervous system from the dawn of my emacs times; approximately the same epoch when i put in my .emacs this setting to make kill-line eat also the final carry return:

(setq kill-whole-line t)

But, as William notices, there’re better ways of copying the current line. A quick one would be:

(defun jao-copy-line ()
  "Copy current line in the kill ring"
  (interactive)
  (kill-ring-save (line-beginning-position) 
                  (line-beginning-position 2))
  (message "Line copied"))

which can be easily extended to take as a prefix argument the number of lines to copy (with 1 as the default)

(defun jao-copy-line (arg)
  "Copy lines (as many as prefix argument) in the kill ring"
  (interactive "p")
  (kill-ring-save (line-beginning-position) 
                  (line-beginning-position (+ 1 arg)))
  (message "%d line%s copied" arg (if (= 1 arg) "" "s")))

Assign the new function to a handy shortcut, and you’re done. These functions have the additional benefit of leaving the point untouched.

Next thing you’ll do after using your new shiny shortcut will most probably be yanking those lines somewhere. And it may well happen that they’ll be mis-indented in their new location. A relatively quick way of realigning them is to take advantage of the fact that after a yank the region is set to the yanked text and use indent-region, which is bound to C-M-\. But i prefer to let Emacs do that for me, using this piece of advice in my .emacs:

(defadvice yank (after indent-region activate)
  (if (member major-mode '(emacs-lisp-mode scheme-mode lisp-mode
                           c-mode c++-mode objc-mode
                           LaTeX-mode TeX-mode))
      (indent-region (region-beginning) (region-end) nil)))

where, as you can see, i’m limiting the advice to some modes: just delete the major-mode check if you want it to work everywhere.

Type faster with Predictive

I had Predictive in my list of Emacs packages to try out and review, but Mathias Dahl has saved me the trouble by writing a nice tutorial on using Predictive, complete with screenshots and all. In a nutshell,

Predictive is a package for the GNU Emacs Editor that helps you write text faster. It does this by trying to predict what you are going to write by looking at the first few characters of each word you type, looking into a dictionary for matching words, and suggesting words from this dictionary.

Mathias goes on providing all the details you need to get stated with Predictive. Although i have not yet used it, looks pretty interesting.

predictive-02.png

Oh, as an aside, i recommend taking a look at Tony ‘Qubit’ Cubitt’s site for more Emacs (and non-Emacs) goodies, or just to enjoy a beautiful website.

Record, play, re-play

Gentle reader Marc Donner has sent me an email sharing one of his favorite emacs hacks:

(global-set-key [f10]  'start-kbd-macro)
(global-set-key [f11]  'end-kbd-macro)
(global-set-key [f12]  'call-last-kbd-macro)

Yes, I could type C-x ( to start the macro and C-x ) to end the macro and C-x e to execute the macro, but that requires that my fingers be more nimble than they really are. Particularly because ( and ) are shifted keys.

This way I can start a macro with a single button push, finish it with another, and then repetitively run it by pressing a third button over and over.

As it happens, Emacs 22 comes with the functionality Marc assigns to his F12 key built-in: press just e right after executing the macro the first time, as many times as you need. There’s also the possibility of using a numerical prefix to specify how many times the macro should be executed (as in M-10 C-x e to execute it ten times), and passing zero as the prefix will keep on (re)executing it until the end of the buffer is reached.

One can also achieve macro re-plays with the command repeat, bound by default to C-x z. repeat works quite a bit like Vim’s ‘.’: it, well, repeats the most recently executed command, and keeps repeating if you keep pressing z. So, instead of C-x e e e e e ..., one can C-x e C-z z z z.... Not as convenient, but this works in Emacs 21, and, besides, repeat is an interesting command on its own.

Saying that keyboard macro recording is a useful Emacs feature would be an understatement. You can record almost any Emacs operation and, therefore, keyboard macros can automate quite non-trivial tasks. For instance, i’ve just used them a couple hours ago to generate C function body stubs from their declarations in a header file. Just for the fun of it, here’s a screencast:

Note how you’re not limited to a single buffer, and how we use generic operations (like searching for next space to kill and yank the function’s return type). It’s also important to left the cursor in the right position for the next execution of the macro. At first you’ll make little mistakes, but fear not: you can actually edit the last recorded macro with kmacro-edit-lossage (Emacs 22 only). Just type C-xC-kl and you’ll be teletransported to a *Edit macro* buffer where you can edit your last keystrokes and record them as needed. Nifty, no?

As you get used to macros, you’ll surely discover many other tricks, but you can speed up your learning by means of the excellent pages KeyboardMacros and KeyboardMacrosTricks in the Emacs wiki. (One of my favourite tricks is using Elisp in macros to dynamically change what gets inserted). This Linux Journal article by Jesper Pedersen is also a good way to get you started as a power macro user.

Happy recording!

Emacs v. vi is rooted in the love of Lisp

In the comments section of an early post, Steven G. Harms has mentioned his little essay Emacs v. vi is rooted in the love of Lisp. I think it’s a pretty interesting take on what makes Emacs a powerful environment, and that it will probably be a pretty interesting reading for readers of mew. (And no, i have no interest at all in yet another boring Emacs vs. Vi religious war–i use vim almost daily, without feeling guilty or anything.)

Eval and replace anywhere

Being a living Elisp virtual machine, Emacs naturally provides the ability to evaluate any Elisp expression anywhere. Just put the cursor right after the expression to be evaluated and press C-xC-e: the result appears in the mini-buffer. I use this continuously, for instance while reading about a variable to know its value. For instance, imagine i see this line in one of my files:

(setq planner-project "planner")

and want to know if planner-project has been modified. I just need to put my cursor right after the variable name and get its value with C-xC-e.

As i said, C-xC-e works in any (well, almost) buffer. Imagine you’re writing a note and need to perform an arithmetic operation: you could write something like

   Yesterday I spent (+ 2234.34 3423.4 (* 12.0 12.2) 10) dollars at ...

put the cursor just before ‘dollars’, press the eval shortcut, and see the result of the arithmetic operation in the mini-buffer. You memorize it, delete the Elisp expression… hmm, wait, this should be easier, shouldn’t it? What we want is Emacs to eval and replace the expression for us.

I’m sure that you already know what comes next :-) As it happens, this time i didn’t need to write the Elisp snippet myself: i stole it instead from Jorgen “forcer” Schäfer’s configuration file:

(defun fc-eval-and-replace ()
  "Replace the preceding sexp with its value."
  (interactive)
  (backward-kill-sexp)
  (prin1 (eval (read (current-kill 0)))
         (current-buffer)))

Complemented with the mandatory shortcut:

(global-set-key (kbd "C-c e") 'fc-eval-and-replace)

this little gem has probably the highest usefulness to lines of code ratio in my Elisp toolbox. Give it a try!

Update: pdq notes in a comment that, if the expression to be evaluated is malformed (like, say, (+1 1)) it gets deleted, and it would be nice if it wouldn’t. A quick way to get this functionality is to catch errors in eval and undo the killing in a generic error handler. To wit:

(defun fc-eval-and-replace ()
  "Replace the preceding sexp with its value."
  (interactive)
  (backward-kill-sexp)
  (condition-case nil
      (prin1 (eval (read (current-kill 0)))
             (current-buffer))
    (error (message "Invalid expression")
           (insert (current-kill 0)))))
Follow

Get every new post delivered to your Inbox.