0

I have the following Emacs macro, which evaluates the AucTex command TeX-insert-macro on selected text:

(eval-after-load "latex"
  '(progn
     (define-key LaTeX-mode-map (kbd "C-c (")
       (lambda ()
     (interactive)
     (TeX-insert-macro "command")))))

However, how would I perform a regexp on the selected text and pass that to TeX-insert-macro?

See this question for more details.

For example: Suppose I have the following text:

…as shown in figure (24).

Now, suppose I select "(24)." Then, I want a command to convert it to:

…as shown in figure \command{eq:24}.

Viz., how would I define a new Emacs command that I could place in ~/.emacs that would run C-C RET command RET on a regexp'ed version of the selected text?

Why doesn't the following with regexp work?

(eval-after-load "latex"
  '(progn
     (define-key LaTeX-mode-map (kbd "C-c )")
       (lambda ()
     (interactive)
     (query-replace-regexp "\(([0-9]+)\)" "\1")
     (TeX-insert-macro "eq")
))))

Minor improvement:

This works well if I select, e.g., "(45)" from the left to the right and then run the code by typing C-c )

(eval-after-load "latex"
  '(progn
     (define-key LaTeX-mode-map (kbd "C-c )")
       (lambda ()
     (interactive)
     (exchange-point-and-mark)
     (replace-regexp "[\(\)]" "")
     (TeX-insert-macro "eq")
))))

However, if I select "(45)" from the right to the left, it doesn't work because the point and mark are flipped. Is there a way to make sure the point and mark aren't flipped, such as by running exchange-point-and-mark when they are flipped?

Also, there are other issue with the regexp, e.g., if there are other parentheses nearby it gets greedy.

thanks

Community
  • 1
  • 1
Geremia
  • 4,745
  • 37
  • 43
  • The question is a bit confused. There are no macros here, other than (one presumes) `TeX-insert-macro`; and you cannot "perform" a regular expression. – phils Oct 06 '13 at 04:32
  • @phils: What is the Lisp code above called, if not a macro? – Geremia Oct 06 '13 at 04:39
  • @phils: I've edited the question with more detail. – Geremia Oct 06 '13 at 04:44
  • 1
    There's no special name. It's just lisp code. A "macro" is lisp code which generates and evaluates more lisp code, and is defined with `defmacro` (or it can also refer to a "keyboard macro", which is a recorded sequence of keystrokes that can be played back as a single operation). – phils Oct 06 '13 at 04:53
  • 1
    And in retrospect, the name `TeX-insert-macro` is referring to LaTeX macros, so that's undoubtedly just a plain function. You'll note that in all cases a "macro" is something which expands into something else. – phils Oct 06 '13 at 05:00

1 Answers1

1

I don't have the requisite libraries installed, or know how the TeX functions work, but something like this might do the trick.

(eval-after-load "latex"
  '(progn
     (defun my-insert-latex-command-macro (beginning end)
       (interactive "r")
       (goto-char beginning)
       (when (not (looking-at "(\\(.+?\\))"))
         (error "Region does not match expected pattern."))
       (push-mark)
       (replace-match "eq:\\1")
       (exchange-point-and-mark)
       (TeX-insert-macro "command")
       (goto-char (mark))
       (pop-mark))
     (define-key LaTeX-mode-map (kbd "C-c (") 'my-insert-latex-command-macro)))

Using the "r" argument for interactive conveniently gives you the region boundaries in ascending order, regardless of which direction you marked it in.

To avoid greedy matching in a regexp, use the non-greedy operators (*?, +?, ??).

Note that you do not have sufficient backslash escapes in your regexps. In order to get a backslash into a regexp string in the first place, you first need to account for string escaping. Basically, double the backslashes. e.g.: This:

(query-replace-regexp "\(([0-9]+)\)" "\1")

needs to be this:

(query-replace-regexp "\\(([0-9]+)\\)" "\\1")
phils
  • 71,335
  • 11
  • 153
  • 198
  • regexp is necessary to remove the parenthesis so "(46)" would go to "eq:46" which `TeX-insert-macro` would then take to produce `\eq{eq:46}`. – Geremia Oct 06 '13 at 06:09
  • See the code above under the ***Why doesn't the following with regexp work?*** heading. – Geremia Oct 06 '13 at 06:19
  • Ah, I missed the parenthesis part, and regexp replacement does seem reasonable in that case. Try the edited code. – phils Oct 06 '13 at 11:46