Snippets From My Personal Emacs Configuration

Today I decided to share some configurations and functions for GNU Emacs that I’ve found useful over the years. Some of these are of my own design, and others are from friends and online resources. I present them in no particular order, but I hope you find some of them useful and worth consideration.

Indenting Regions

I often find myself writing text, like this article, where I want to paste a chunk of text but indent that chunk as if I were using a different major mode. The most common use-case is when I am writing an article about programming. When I include, for example, a chunk of Lisp code then I want to indent that according to my settings for Lisp Mode and not the mode I’m using to writing the over-arching document. For that purpose I use this function:

(defun indent-region-as (beginning end other-mode)
  "Indent selected region as if in some other major mode."
  (interactive "r\naMode to use: ")
  (save-excursion
    (let ((old-mode major-mode))
      (narrow-to-region beginning end)
      (funcall other-mode)
      (indent-region beginning end nil)
      (funcall old-mode)))
  (widen))

The function makes use of the narrowing features in Emacs, which are handy whenever you need to restrict Emacs’ attention to a specific region of a buffer. The logic of the code is simple:

  1. Save the current position in the buffer.

  2. Narrow to the selected region.

  3. Switch to the other major mode.

  4. Indent that region per the settings of that mode.

  5. Switch back to the original mode and widen everything, i.e. undo the narrowing effects.

Only thing I need to do after that is bind the function to a key.

Creating Key Groups

Personally I like to create key-bindings in groups. When I say ‘group’ I mean a sequence of prefix keys that I can mnemonically relate to the purpose of the commands beginning with that prefix. For example, all of my bindings to switch major modes begin with C-c m, all of those relating to text-editing functions begin with C-c t, and so on. Emacs reserves C-c <N> for users, where <N> is a key without a modifier. It is a considered a bug when major or minor modes bind commands to anything like C-c n. A package could use C-c C-n because the second key has a modifier, but ‘plain’ C-c n is meant only for users.

All that said, here is the function I use to create groups of key-bindings:

(defun create-key-group (prefix &rest commands)
  "Creates a group of key bindings by making a sparse keymap
bound to the first argument, a vector describing a key.
The rest of the arguments should be cons pairs mapping
single characters to commands."
  (global-set-key prefix (make-sparse-keymap))
  (dolist (command commands)
    (global-set-key (vconcat prefix (vector (car command)))
                    (cdr command))))

Some examples of how I use it:

;;; Desktop Keys

(create-key-group
 [?\C-c ?d]
 '(?c . desktop-clear)
 '(?d . desktop-change-dir)
 '(?s . desktop-save))

;;; Flymake Keys

(create-key-group
 [?\C-c ?f]
 '(?n . flymake-goto-next-error)
 '(?p . flymake-goto-prev-error)
 '(?c . flymake-display-err-menu-for-current-line))

;;; Pomodoro Keys

(create-key-group
 [?\C-c ?p]
 '(?p . pomodoro-start)
 '(?s . pomodoro-stop))

This binds C-c d s to the desktop-save function, C-c p p to pomodoro-start, and so on.

Outline Mode for PostgreSQL Dumps

I often work with PostgreSQL and sometimes find myself looking at the output of its pg_dump utility. Large databases create equally large amounts of output. But the format of pg_dump output works well with Emacs outline mode. Here is a hook I use to enable outline mode whenever I am viewing such output:

(defun possibly-setup-pgdump-outline ()
  "Possibly enables outline-minor-mode when viewing the output of pg_dump."
   (interactive)
   (save-excursion
     (goto-char (point-min))
     (forward-line 1)
     (when (looking-at "-- PostgreSQL database dump")
       (set (make-local-variable 'outline-regexp)
       "-- \\(Data for \\)?Name:")
       (set (make-local-variable 'outline-level)
       (lambda nil 1))
       (outline-minor-mode 1)
       (hide-sublevels 1))))

(add-hook 'sql-mode-hook 'possibly-setup-pgdump-outline)

Copying and Cutting Lines by Default

These two uses of defadvice modify C-w and M-w so that they will, respectively, cut or copy the current line if I have not selected any region.

(defadvice kill-ring-save (before slick-copy activate compile)
  "When called interactively with no active region, copy a single line instead."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
     (message "Copied line")
     (list (line-beginning-position)
           (line-beginning-position 2)))))

(defadvice kill-region (before slick-cut activate compile)
  "When called interactively with no active region, kill a single line instead."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
     (list (line-beginning-position)
           (line-beginning-position 2)))))

I often find myself only needing to copy or cut a single line at a time so these save me some extra key presses.

Indenting Pasted Code

Similar to the above, when I am pasting code I want to automatically indent that code according to the current major mode of the buffer in which I’m pasting. This code wraps advice around yank and yank-pop so that they will automatically indent pasted code for a number of major modes:

(dolist (command '(yank yank-pop))
  (eval `(defadvice ,command (after indent-region activate)
           (and (not current-prefix-arg)
                (member major-mode '(asm-mode
                                     c++-mode
                                     c-mode
                                     clojure-mode
                                     cperl-mode
                                     csharp-mode
                                     espresso-mode
                                     factor-mode
                                     haskell-mode
                                     js-mode
                                     latex-mode
                                     lisp-mode
                                     lua-mode
                                     nxml-mode
                                     objc-mode
                                     php-mode
                                     plain-tex-mode
                                     python-mode
                                     rspec-mode
                                     ruby-mode
                                     rust-mode
                                     scheme-mode
                                     vbnet-mode
                                     emacs-lisp-mode))
                (let ((mark-even-if-inactive transient-mark-mode))
                  (indent-region (region-beginning) (region-end) nil))))))

To support another major mode all you need to do is add it to that long list.

Advertisements

Add Your Thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s