13

While this question concerns the formatting of LaTeX within Emacs (and maybe Auctex), I believe this can be applied to more general situations in Emacs concerning delimiters like parentheses, brackets, and braces.

I am looking to be able to do the following with Emacs (and elisp), and don't know where to begin. Say I have:

(This is in parentheses)

With some keybinding in Emacs, I want Emacs to find the matching delimiter to whichever one is by my cursor (something I know Emacs can do since it can highlight matching delimiters in various modes) and be able to change both of them to

\left( This is in parentheses \right)

The delimiters I would like this to work with are: (...), [...], \lvert ... \rvert, \langle ... \rangle, \{ ... \}. What elisp would I need to accomplish this task?

More general ways to handle matching delimiters are welcome.

qgp07
  • 305
  • 1
  • 5
  • 1
    +1 Nice idea! Such a thing would always be useful... – Kerrek SB Dec 16 '11 at 18:46
  • Please clarify where the modification came from? Is the modification always a matter of prepending "\left" and "\right" to the delimiters? – event_jr Dec 17 '11 at 01:59
  • The modification comes from LaTeX since the `\left` and `\right` make those delimiters scale to the size of the text/math contained within them (sometimes I'm not prescient enough to realize I'll need them). And yes, the modification would be a matter of prepending `\left` and `\right` to delimiters. However, if there are ways to do other things to them (change parentheses to brackets or braces, for example), that would be nice as well. – qgp07 Dec 17 '11 at 07:45

1 Answers1

9

Evaluate the command below in Emacs. After reloading you can put the point (text cursor) immediately after a closing paren. Then do M-x replace-matching-parens to replace the closing ) with \right) and the matching start paren ( with \left(.

(defun replace-matching-parens ()
  (interactive)
  (save-excursion
    (let ((end-point (point)))
      (backward-list)
      (let ((start-point (point)))
        (goto-char end-point)
        (re-search-backward ")" nil t)
        (replace-match " \\\\right)" nil nil)

        (goto-char start-point)
        (re-search-forward "(" nil t)
        (replace-match "\\\\left( " nil nil)))))

The interactive bit indicates that I want a "command", so it can be executed using M-x. To avoid the cursor ending up in a strange place after execution I'm wrapping the logic in save-excursion. The point jumps back to the opening paren using backward-list and holds on to the start and end positions of the paren-matched region. Lastly, starting at the end and working backwards I replace the strings. By replacing backwards rather than forwards I avoid invalidating end-point before I need it.

Generalizing this to handle different kinds of delimiters shouldn't be too bad. backward-list ought to work with any pair of strings emacs recognizes as analogues of ( and ). To add more parenthesis-like string pairs, check out set-syntax-table in this Parenthesis Matching article.

Use global-set-key to setup a key binding to replace-matching-parens.

Fair warning: replace-matching-parens is the first elisp command I've implemented, so it may not align with best practices. To all the gurus out there, I'm open to constructive criticism.

Sage Mitchell
  • 1,563
  • 8
  • 31