Some custom emacs keybindings for LaTeX to assist in the writing process

Emacs
LaTeX
Author

Vinh Nguyen

Published

June 29, 2011

Here are some habits I think will assist in the writing of LaTeX documents:

  1. Always encapsulate your superscripts and subscripts with curly braces, even if they consist only of 1 characters. For example, it should x_{1} rather than x_1. The reason is that lot's of time, I go back to changing my subscripts, and I often use a command like replace-string in emacs to help do it for the entire document. If I change the subscript from 1 character to multiple characters, thing gets messed up. For example, x_1 to x_i1 where it should really be x_{i1}. Using curly braces just help prevent things from going wrong and having to go back to the errors.
  2. As mentioned on this post, it is best to keep each sentence on its own line to facilitate version controlling the document.

To help with these two tasks, I've binded my ".", "\^", and "_" keys to smart functions that will do what I want. Pressing the keys again will go back to the plain character.

;; following for latex, adapted from ess-smart-underscore
;; can also be implemented using sequential command http://www.emacswiki.org/emacs/SequentialCommand
(defun tex-smart-underscore ()
 "Smart \"_\" key: insert \"_{}\".
If the underscore key is pressed a second time, \"_{}\" is removed and replaced by the underscore."
 (interactive)
 (let ((assign-len (length "_{")))
 (if (and
 (>= (point) (+ assign-len (point-min))) ;check that we can move back
 (save-excursion
 (backward-char assign-len)
 (looking-at "_{}")))
 ;; If we are currently looking at ess-S-assign, replace it with _
 (progn
 (forward-char)
 (delete-backward-char (+ 1 assign-len))
 (insert "_"))
 (delete-horizontal-space)
 (insert "_{}")
 (backward-char))))

(defun tex-smart-caret ()
 "Smart \"\^\" key: insert \"\^{}\".
If the caret key is pressed a second time, \"\^{}\" is removed and replaced by the caret."
 (interactive)
 (let ((assign-len (length "\^{")))
 (if (and
 (>= (point) (+ assign-len (point-min))) ;check that we can move back
 (save-excursion
 (backward-char assign-len)
 (looking-at "\\\^{}"))) ;; looking-at reads regexp, so need to escape the caret character
 ;; If we are currently looking at ess-S-assign, replace it with \^
 (progn
 (forward-char)
 (delete-backward-char (+ 1 assign-len))
 (insert "\^"))
 (delete-horizontal-space)
 (insert "\^{}")
 (backward-char))))


(defun tex-smart-period ()
 "Smart \".\" key: insert \". \n\".
If the period key is pressed a second time, \". \n\" is removed and replaced by the period."
 (interactive)
 (let ((assign-len (length ". %%\n")))
 (if (and
 (>= (point) (+ assign-len (point-min))) ;check that we can move back
 (save-excursion
 (backward-char assign-len)
 (looking-at "\\. %%")))
 ;; If we are currently looking at ess-S-assign, replace it with _
 (progn
 (delete-backward-char assign-len)
 (insert "."))
 (delete-horizontal-space)
 (insert ". %%\n"))))


;; http://stackoverflow.com/questions/5500035/set-custom-keybinding-for-specific-emacs-mode
;; eval-after-load didn't fix this for me
;; http://www.emacswiki.org/emacs/LaTeX
(add-hook 'LaTeX-mode-hook (lambda ()
 (define-key LaTeX-mode-map (kbd "_") 'tex-smart-underscore)
 (define-key LaTeX-mode-map (kbd "\^") 'tex-smart-caret)
 (define-key LaTeX-mode-map (kbd ".") 'tex-smart-period)
 )
 )