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.
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:
Narrow to the selected region.
Switch to the other major mode.
Indent that region per the settings of that mode.
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))
C-c d s to the
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
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-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.