2018-01-07 A small editing tool for work with AMSrefs

As I mentioned many times, I often edit LaTeX files written by someone else for a journal. One thing which is notoriously difficult to get right when writing academic papers is bibliographies. At Wiadomości Matematyczne, we use AMSrefs, which is really nice (even if it has some rough edges here and there). (BTW, BibLaTeX was not as mature as it is today when we settled on our tool; also, AMSrefs might be a tad easier to customize, though I’m not sure about that anymore…) One of the commands AMSrefs offers is \citelist. Instead of writing things like papers \cite{1}, \cite{2} and~\cite{3}, you write papers \citelist{\cite{1}\cite{2}\cite{3}}, and AMSrefs sorts these entries and compresses runs into ranges (like in [1-3]).

The only problem is that most authors have no idea that this exists, and we often have to convert “manual” lists of citations into \citelist‘s.

Well, as usual, Emacs to the rescue. Here’s what I have written.

(defun skip-cite-at-point ()
  "Move point to the end of the \\cite at point."
  (when (looking-at "\\\\cite")
    (forward-char 5)
    (cond ((= (char-after) ?\[)
	   (forward-sexp 2))
	  ((= (char-after) ?\{)
	   (forward-sexp)
	   (when (and (not (eobp))
		      (= (char-after) ?*))
	     (forward-char)
	     (forward-sexp)))
	  (t (error "Malformed \\cite")))))

(defun cite-to-citelist ()
  "Convert region to a \\citelist command.
All \\cite's are preserved and things between them deleted.
This command will be fooled by things like \"\\\\cite\"."
  (interactive)
  (if (use-region-p)
      (let ((end (copy-marker (region-end))))
	(goto-char (region-beginning))
	(insert "\\citelist{")
	(while (< (point) end)
	  (skip-cite-at-point)
	  (delete-region (point)
			 (if (search-forward "\\cite" end t)
			     (progn
			       (backward-char 5)
			       (point))
			   end)))
	(insert "}"))
    (message "Region not active")))

It might contain some subtle bug, but I really hope it doesn’t – and it will get thoroughly tested very soon.

Notice how nice it is to craft such little editing tools in Emacs. You basically mimic your editing process, i.e., tell the machine what you do by hand to accomplish the goal. And not only do you have obvious things like forward-char, but also more complicated building blocks like forward-sexp.

Also, in case you wonder about the intricacies of the skip-cite-at-point function, AMSrefs’s \cite supports the traditional \cite[p. 123]{1} syntax, but also introduces its own: \cite{1}*{p. 123}. While quite unorthodox for a LaTeX command, it makes life easier for all people who want to put a \cite in an optional argument to things like \begin{theorem} ... \end{theorem} (which is a very common use case). Since LaTeX does not do proper pairing of brackets when parsing optional parameters, normally you need to enclose the whole \cite[...]{...} in additional curly braces – AMSrefs’ syntax makes that unnecessary.

Anyway, in the case anyone needs something like that, here it is. And even if nobody does, maybe this can be an encouragement to write your own snippets like this to help automate your common tasks.

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryTeX, CategoryLaTeX