Wednesday, August 19, 2009

Emacs Latex Macros

Oftentimes I write LaTeX notes in the emacs editor, and I often do it on an Asus EEE PC 900 HA. Unfortunately, the keyboard is rather small, and my hands rather large, which leads to some complications. To make things worse, the "\" key is as wide as a fingernail's width (which is a nightmare for LaTeX coding!).

Fortunately there is a solution with Emacs: macros! I've written up a few macros that simplifies my life. First I have an texHelp.el file in my ~/.emacs.d/ directory which consists of the following stuff:

;; macro to help me write stuff
(defun write (mystring)
  (insert-string mystring)
  (newline))

;; starts the document class
(defun docclass ()
  (interactive)
  (write "\\documentclass{amsart}"))

;; use a package
(defun use-package (package)
  (interactive)
  (write (concat
    "\\usepackage{"
    package
    "}")))

;; all the packages of interest
(defun my-packages ()
  (interactive)
  (use-package "url")
  (use-package "manfnt")
  (use-package "amsthm")
  (use-package "amsmath")
  (use-package "amsthm")
  (use-package "amssymb")
  (use-package "amsfonts")
  (use-package "amscd")
  (use-package "graphicx")
  (write "\\DeclareGraphicsRule{*}{mps}{*}{}")
  (use-package "mathrsfs")
  (newline))

;; amsthm package configuration
(defun thm-style ()
  (interactive)
  (write "\\theoremstyle{definition}")
  (write "\\newtheorem{defn}{Definition}")
  (write "\\newtheorem{thm}{Theorem}")
  (write "\\newtheorem{rmk}{Remark}")
  (write "\\newtheorem{lem}{Lemma}")
  (write "\\newtheorem{cor}{Corollary}")
  (write "\\newtheorem{ex}{Example}")
  (write "\\newtheorem{nonex}[ex]{NON-Example}")
  (write "\\newtheorem{prop}{Proposition}")
  (write "\\newtheorem{sch}{Scholium}")
  (write "\\newtheorem{axm}{Axiom}")
  (write "\\newtheorem*{prob}{Problem}")
  (newline))

;; number equations within the section
(defun eqn-numbering ()
  (interactive)
  (write "\\numberwithin{equation}{section}")
  (newline))

;; my custom defined macros
(defun macros ()
  (interactive)
  ;;;;;;;;;;;;;;;;;;;;;;
  ;; code snipped out ;;
  ;;;;;;;;;;;;;;;;;;;;;;
  (newline))

(defun doc-stuff ()
  (interactive)
  (write "\\title[]{}")
  (write (concat "\\date{" (format-time-string "%B %d, %Y") "}"))
  (write (concat "\\email{" user-email-address "}"))
  (write (concat "\\author{" user-full-name "}"))
  (write "\\begin{document}")
  (write "\\maketitle")
  (newline)
  (newline)
  (write "\\end{document}"))

;; call this function when starting a new LaTeX document
(defun start-tex ()
  (interactive)
  (docclass)
  (my-packages)
  (eqn-numbering)
  (thm-style)
  (macros)
  (doc-stuff)
  (previous-line 5))

I only need to create the directory (usually I have a ~/notebk directory, and subdirectories ordered in the way arXiv is ordered, so I usually create sub-sub-directories of ~/notebk/*), then create the file with C-x C-f path and start TeXnical stuff with M-x start-tex (remember that M-x means "Alt-x").

This does not solve the problem of the tex macros, I would still have to write "\begin{equation}...\end{equation". Woah is me!

Fortunately Emacs macros comes to the rescue yet again! I have another file, ~/.emacs.d/texMacros.el which consists of the helper functions:

;; for subequations
(defun subeqn()
  (interactive)
  (insert "\\begin{subequations}\n")
  (insert "\\begin{align}\n")
  (insert "\n")
  (insert "\\end{align}\n")
  (insert "\\end{subequations}")
  (previous-line 2))

;; for equations
(defun eqn()
  (interactive)
  (insert "\\begin{equation}%\\label{eq:}\n")
  (insert "\n")
  (insert "\\end{equation}")
  (previous-line 1))

;; all the amsthm environment
(defun thm()
  (interactive)
  (insert "\\begin{thm}%\\label{thm:}\n")
  (insert "\n")
  (insert "\\end{thm}\n")
  (insert "\\begin{proof}\n\n")
  (insert "\\end{proof}")
  (previous-line 4))
(defun defn()
  (interactive)
  (insert "\\begin{defn}%\\label{defn:}\n")
  (insert "\n")
  (insert "\\end{defn}")
  (previous-line 1))
(defun cor()
  (interactive)
  (insert "\\begin{cor}%\\label{cor:}\n")
  (insert "\n")
  (insert "\\end{cor}")
  (previous-line 1))
(defun lem()
  (interactive)
  (insert "\\begin{lem}%\\label{lem:}\n")
  (insert "\n")
  (insert "\\end{lem}")
  (previous-line 1))
(defun rmk()
  (interactive)
  (insert "\\begin{rmk}\n")
  (insert "\n")
  (insert "\\end{rmk}")
  (previous-line 1))
(defun prop()
  (interactive)
  (insert "\\begin{prop}%\\label{prop:}\n")
  (insert "\n")
  (insert "\\end{prop}")
  (previous-line 1))
(defun ex()
  (interactive)
  (insert "\\begin{ex}\n")
  (insert "\n")
  (insert "\\end{ex}")
  (previous-line 1))
(defun nonex()
  (interactive)
  (insert "\\begin{nonex}\n")
  (insert "\n")
  (insert "\\end{nonex}")
  (previous-line 1))

;; lists macros
(defun enumerate()
  (interactive)
  (insert "\\begin{enumerate}\n")
  (insert "\\item \n")
  (insert "\\end{enumerate}")
  (previous-line 1))
(defun itemize()
  (interactive)
  (insert "\\begin{itemize}\n")
  (insert "\\item \n")
  (insert "\\end{itemize}")
  (previous-line 1))
(defun item()
  (interactive)
  (insert "\\item "))

;; proofs, from the amsthm package
(defun pf()
  (interactive)
  (insert "\\begin{proof}\n")
  (insert "\n")
  (insert "\\end{proof}")
  (previous-line 1))
(defun axm()
  (interactive)
  (insert "\\begin{axm}%\\label{axm:}\n")
  (insert "\n")
  (insert "\\end{axm}")
  (previous-line 1))
(defun prob()
  (interactive)
  (insert "\\begin{prob}\n")
  (insert "\n")
  (insert "\\end{prob}")
  (previous-line 1))

;; reference to an equation
(defun eqref()
  (interactive)
  (insert "\\eqref{}")
  (backward-char 1))
(defun pmatrix()
  (interactive)
  (insert "\\begin{pmatrix}\n")
  (insert "\n")
  (insert "\\end{pmatrix}")
  (previous-line 1))
(defun diagram()
  (interactive)
  (insert "\\begin{figure}[H]\n")
  (insert "\\includegraphics{}\n")
  (insert "\\end{figure}")
  (previous-line 2)
  (forward-char 23))
(defun fig()
  (interactive)
  (diagram))
(defun figure()
  (interactive)
  (fig))
(defun src()
  (interactive)
  (insert "\\begin{Verbatim}[fontsize=\\footnotesize,frame=lines,numbers=left,numbersep=3pt,firstnumber=]\n")
  (insert "\n")
  (insert "\\end{Verbatim}")
  (previous-line 2)
  (forward-char 77))
(defun quotation()
  (interactive)
  (insert "\\begin{quote}\n")
  (insert "\n")
  (insert "\\end{quote}")
  (previous-line 1))

And shazam! I'm off to the races, avoiding usage of the "\" key with only a handful of exceptions.

If one wants to have a bunch of keybindings for these functions, one can use the following in their ~/.emacs file:

;; load texMacros when doing LaTeX stuff
(load "~/.emacs.d/texHelp.el")
(load-file "~/.emacs.d/texMacros.el")  ; load these LaTeX preferences
(defun my-LaTeX-startup ()
  (interactive)
  (local-unset-key "\C-c\C-e")
  (local-set-key "\C-c\C-e" 'eqn)
  (local-unset-key "\C-c\C-s")
  (local-set-key "\C-c\C-s" 'subeqn)
  (local-unset-key "\C-c\C-t")
  (local-set-key "\C-c\C-t" 'thm)
  (local-unset-key "\C-c\C-d")
  (local-set-key "\C-c\C-d" 'defn)
  (local-unset-key "\C-c\C-r")
  (local-set-key "\C-c\C-r" 'rmk)
  (local-unset-key "\C-c\C-l")
  (local-set-key "\C-c\C-l" 'lem)
  (local-unset-key "\C-c\C-k")
  (local-set-key "\C-c\C-k" 'cor)
  (local-unset-key "\C-c\C-p")
  (local-set-key "\C-c\C-p" 'prop)
  (local-unset-key "\C-c\C-x")
  (local-set-key "\C-c\C-x" 'ex)
  (local-unset-key "\C-c\C-n")
  (local-set-key "\C-c\C-n" 'nonex))
(add-hook 'LaTeX-mode-hook 'my-LaTeX-startup)
(add-hook 'latex-mode-hook 'my-LaTeX-startup)
(add-hook 'TeX-mode-hook 'my-LaTeX-startup)

Of course, one is more than welcome to change the keybindings to their own preference!

Addendum: Making the Definition Macro Better!

Recall for our object oriented approach, we have a mathematical object consist of "stuff" equipped with some "structure" such that a bunch of "properties" hold. We can modify the definition environment to simplify this format. In ~/.emacs.d/texMacros.el, change the (defun defn() ...) lines to be:

(defun defn()
  (interactive)
  (insert "\\begin{defn}%\\label{defn:}\n")
  (insert "A \\textbf{} consists of\n")
  (insert "\\begin{enumerate}\n\\item\n\\end{enumerate}")
  (insert "\n equipped with\n")
  (insert "\\begin{enumerate}\n\\item\n\\end{enumerate}")
  (insert "\n such that\n")  
  (insert "\\begin{enumerate}\n\\item\n\\end{enumerate}")
  (insert "\n\\end{defn}")
  (previous-line 10))

You're set to start defining objects left and right!

No comments:

Post a Comment