romain.bardou.fr - blog RSS

Life-Changing Emacs Configuration Tips

Once in a while I show my Emacs configuration file (.emacs) to a friend and there is always something that they didn't know or for which they have a better solution. So I thought I would go through my .emacs and extract the most useful, general parts of it to share them with you. This should be an interesting read even if you don't use Emacs, as you may want to try to apply them to your own favorite editor. Or maybe you have a more elegant solution?

A General Recommendation

Each time you add something to your .emacs I advise you to add a comment. Explain what the piece of code does and where you got it from. It will prove useful a few years from now when you want to clean up or update.

More Room For Programming

Let's start with the basics:

(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1)

This disables the tool bar, the menu bar and all scroll bars. This gives more space for what is actually important: editing.

Now, you may ask: but how can I use my editor without those bars? Well, this assumes that you are familiar with your key bindings. Once you are, not only will you work faster but you will also not need buttons to replace them, so the tool and menu bars become nothing but a waste of space. Regarding the scroll bars, the position in the file is actually indicated as a percentage below each buffer, so you don't need them either.

You may restore those bars temporarily by typing M-x tool-bar-mode for instance. This can be useful if you forget a key binding, or if you want to browse features which are provided by a mode you do not use often.

Switch Buffer And Load File Using ido-mode

Activate ido-mode:

(ido-mode t)

This improves buffer switching (using C-x b) and file loading (using C-x C-f). The default Emacs behavior (without ido-mode) has you type the whole buffer or file name. It has auto-completion, but it assumes that what you typed is a prefix of what you are searching for, and it is case-sensitive. So if you want to select "README.txt" you cannot type "read" then auto-complete. Also, you have to press the Tab key twice to get a list of possibilities.

However with ido-mode the list of possibilities is always visible and reduces as you type. It reduces to all names which contain what you typed. For instance, if you type "me" it will show "README.txt", as well as "memo.txt" or "Camera". It has auto-completion and always shows, in brackets, what auto-completion will add if you press Tab. Last but not least, you can press C-s and C-r to select the next or the previous name for the proposed list.

For instance, let's say you have the following list of files:

lib_main.ml
lib_main.mli
lib_misc.ml
lib_misc.mli
lib_heap.ml
lib_heap.mli

If you type .mli the list will only contain the three .mli files and you can then select the one you want using C-s. Or, if you want to load lib_misc.ml, instead of having to type lib_mi before being able to autocomplete, just type mi and the list will be reduced to lib_misc.ml and lib_misc.mli. If the one which is currently selected is not the one you want, press C-s RET. Else, just press RET. You may also type Tab and it will auto-complete to the longest common prefix which is lib_misc.ml, leaving you the choice to type the i or not.

Compiling From Emacs

Before, to compile I used to go to a terminal and type make. I was taught to compile from Emacs, which is much better as jumping to errors is then painless.

(global-set-key [f5] 'compile)
(global-set-key [(meta f5)] 'kill-compilation)
(global-set-key [f6] 'recompile)
(global-set-key [f7] 'next-error)

I press F5 to compile, which prompts for a command to run, like make (default is make -k). If compilation takes forever or freezes, I can stop it easily with M-F5. To run the same compilation again, I press F6. And if compilation fails with an error, F7 will move the cursor to where the error is located.

Commenting And Uncommenting

(global-set-key [f9] 'comment-region)
(global-set-key [f10] 'uncomment-region)

Commenting and uncommenting code is a very easy task if you can just do it by pressing F9 or F10. This comments line by line, like this:

(* Line 1 *)
(* Line 2 *)
(* Line 3 *)

This makes it easy to uncomment only part of what you commented, to toggle parts of your code for instance.

Miscellaneous Key-Bindings

My .emacs contain several personal key-bindings. No user will probably want the same set, but knowing how to bind a key is very useful, as well as being aware of the kind of commands that exist. Let me show you some examples from my .emacs.

(global-set-key [f2] 'switch-to-buffer)
(global-set-key [f3] 'find-file)

F2 now does the same as C-x b (switch to another buffer), and F3 now does the same as C-x C-f (load file). I run those commands all the time, so having to perform three kind of convoluted keystrokes is absurd. Function keys make it much simpler, especially in combination with ido-mode (see above). Also, function keys work for all keyboard layouts.

(global-set-key [f1] 'other-window)

F1 now does the same as C-x o (select other window). Once again this is something which you use all the time if you split your Emacs using e.g. C-x 2. Note that F1 is normally bound to help.

(global-set-key [f4] 'kill-buffer)

Being able to close the current buffer easily saves time.

(global-set-key [(meta g)] 'goto-line)

Sometimes I want to go to a specific line number, and I just type M-g. This is less useful if you compile from within Emacs though.

(global-set-key [(meta f7)] 'ispell-region)

Check for spelling errors by typing M-F7. Maybe I should add a binding to switch language...

(global-set-key [f8] 'revert-buffer)

Sometimes the file I'm currently editing has changed on disk. Or, I want to discard unsaved changes. I can revert the buffer by pressing F8. It will prompt for confirmation.

(global-set-key (kbd "<M-down>") 'scroll-up-line)
(global-set-key (kbd "<M-up>") 'scroll-down-line)

I may scroll up or down using M-down or M-up. The point is that the cursor stays in the same position in the buffer. This is convenient to have a peek at what is above or below the currently visible part of your buffer. As it only moves by one line it is more convenient to have a fast key repetition delay, but that is another topic.

(global-set-key (kbd "<C-delete>") 'delete-pair)
(global-set-key (kbd "<C-backspace>") 'backward-delete-pair)

Deleting a pair of parentheses requires a lot of keystrokes and moving around, especially if the contents of the parentheses is large. With those binding it becomes much easier. Put the cursor on the left parenthesis and press C-delete, or on the right parenthesis and press C-backspace. This works with several kinds of paired symbols, including (), [], even "".

(global-set-key (kbd "C-z") nil)
(global-set-key (kbd "C-x C-z") nil)

This disables C-z which, when Emacs is used in a terminal, suspends it. Sometimes I run Emacs in a screen with no shell and Emacs then cannot even be resumed.

Join Lines

After a while, binding keys to existing functions becomes limited and you start combining several functions into one key binding. This first example is subtle but it saves so much time.

(global-set-key
 (kbd "<M-delete>")
 (lambda () (interactive)
   (save-excursion
     (move-end-of-line nil)
     (kill-line)
     (just-one-space))))

Press M-delete and it will go the end of the current line, delete the end-of-line character so that the next line is now there instead, and reduce indentation from said line to just one space. Then it will go back to where you where before, so your cursor will not have moved.

For instance, let's say you want to put the following code in one line:

line
  ~x1: 42
  ~y1: 69
  ~x2: 111
  ~y2: 666
  ()

Just move the cursor somewhere in the first line and press M-delete five times in a row:

line ~x1: 42 ~y1: 69 ~x2: 111 ~y2: 666 ()

This kind of subtle trick is why I love an editor where you can program your own macros. Turn a repetitive chore into a trivial task!

Rename Current Buffer File

This is another example where no built-in function exists and you have to write your own, although I actually found it on Stack Overflow. To rename a file you have to close the buffer, rename the file from a shell, and reload the file. If you're like me and you change the filename several times before settling on a good one, this gets annoying very fast. In fact, it may even make you settle on a bad name just because it is annoying to change. Here is how to fix that.

(global-set-key [(meta f3)] 'rename-current-buffer-file)
(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (let ((new-name (read-file-name "New name: " filename)))
        (if (get-buffer new-name)
            (error "A buffer named '%s' already exists!" new-name)
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil)
          (message "File '%s' successfully renamed to '%s'"
                   name (file-name-nondirectory new-name)))))))

Now you just have to type M-F3.

Indenting And Dedenting

This one I found on the Emacs Wiki. It allows to indent or dedent a whole region, by adding or removing a space at the beginning of each line.

(global-set-key (kbd "<C-+>") (function push-region))
(global-set-key (kbd "<C-->") (function pull-region))
(defun move-region (beg en dir)
  "Move the region defined by (beg en) by dir characters.
 dir may be positive or negative; positive dir means right."
  (save-excursion
    (let ((deactivate-mark nil))
      (move-beginning-of-line nil)
      (indent-rigidly beg en dir)
      (push-mark beg t t))))
(defun push-region (beg en)
  (interactive "r")
  (move-region beg en 1))
(defun pull-region (beg en)
  (interactive "r")
  (move-region beg en -1))

C-+ (Control-Plus) indents the selected lines, and C-- (Control-Minus) dedents them. If you are programming, you may not need to indent by hand as M-q often does the job. But sometimes M-q is just not going to do what you want.

That's It... For Now

The above tips have something in common: they discharge you of the boring repetitive tasks and let you focus on your actual goal, whether it is by giving you more space or by reducing the amount of keystrokes that you need. If you see yourself doing the same sequence of actions again and again, consider automating it into a simple key binding.

There is a particular action which I perform a lot, which is to split Emacs into three columns. I naturally programmed a function to perform the splitting for me. However, this was not satisfactory at first as there are several small details which are needed to make it really usable in practice, like: make it easy to swap columns, ensure that special buffers like *compilation* or *grep* always appear in the same column... What was originally a small function has started to become a mode of its own, and it deserves a separate article.