# How to delete a LaTeX macro while preserving its text content?

In TeXStudio by hitting ALT+DEL in a LaTeX macro like this \macroname{content} while the cursor stands just before the first { will result in deleting all that except its content (as shown below).

Put the cursor (point) just before the first curly bracket:

Hit ALT+DEL and you get:

How to achieve this in Emacs?

Update
According to T.Verron's clarification there is a problem with C-c C-f C-d as it complains from error of unbalanced parenthesis when executed within some macros in LaTeX. Consider the below example:

throws this error: up-list: Scan error: "Unbalanced parentheses", 8074, 1. \textenglish{} belongs to polyglossia package.

How to get rid of this caveat?

• Hem, the caveat with the current answer is not about whether auctex fontifies the macro or not, it is about whether the macro is a latex font specification (probably as defined by TeX-font-list) or not. For example, try with \section or \footnote, AUCTeX knows about these macros and fontifies them, but C-c C-f C-d will complain about unbalanced parentheses. – T. Verron Jan 5 '15 at 13:38
• Even if I can update this TeX-font-list to include my newly introduced macros, this remains a suboptimal workaround. Otherwise, I don't know what prvents having an eLISP function to deal with it! – doctorate Jan 5 '15 at 13:54

Try this function:

(defun mg-TeX-delete-current-macro (&optional arg)
"Remove the current macro.
With an optional argument ARG, delete just the ARG-th macro
starting from the innermost."
(interactive "*p")
(let (macro end)
(when
(dotimes (i arg macro)
(goto-char (TeX-find-macro-start))
(setq macro (TeX-current-macro)
end (TeX-find-macro-end))
;; If we need to look for an outer macro we have to "exit" from the
;; current one.
(backward-char))
(forward-char)
(re-search-forward
(concat (regexp-quote TeX-esc) macro "\$$?:\$[^]]*\$\$$?"
TeX-grop "\$$\\(.\\|\n\$$*\\)")
end t)
(replace-match "\\1")
;; Delete the closing brace.
(delete-backward-char 1))))


Limitation: doesn't work with verbatim-like macros. This function will throw an error (Wrong type argument: integer-or-marker-p, nil) if the universal argument is greater than the number of macros enclosing point.

Bind the function to your favorite shortcut. For example

(eval-after-load "tex"
'(local-set-key (kbd "M-DEL") 'mg-TeX-delete-current-macro))


to bind it it M-DEL.

If your buffer has (! is point)

\onemacro{\anothermacro{!argument}}


then C-2 M-DEL will give you

\anothermacro{argument}

• If the point inside innermost group (gr1(gr2(gr3(gr4)))) do you mean by a prefix C-u then 2 it will give me: (gr1(gr2))? if it is so, that must be brilliant. I hope you had the time to do it. – doctorate Jan 6 '15 at 20:27
• I bound it to M-DEL like in TexStudio. Thanks. – doctorate Jan 6 '15 at 20:42
• @doctorate Well, no, my idea is to delete just the second macro, gr3 in your case. See the updated answer. You can implement what you suggested by wrapping a dotimes around when of the original version of the answer. – giordano Jan 6 '15 at 21:10
• Great function! Now it behaves like a smart macro-pacman! one caveat though; when the argument is big and it throws an error the point jumps somewhere backward. Can you make it complain while standing in its current place? – doctorate Jan 7 '15 at 8:55
• @giordano Any chance this will make it into AucTex? It's very useful! – Tyler Nov 1 '17 at 15:40

C-c C-f C-d

Delete the innermost font specification containing point.

• that was a very handy piece in the documentation that I missed. Thanks. – doctorate Jan 5 '15 at 12:55
• But it only works for font specifications (and the verification makes sense, for example for \emph{\randommacro{test}} it will delete the \emph). – T. Verron Jan 5 '15 at 13:03
• @T.Verron: good clarification. I'm not aware of a built-in way to do this for arbitrary LaTeX macros. – Dan Jan 5 '15 at 13:08

Here's a simple function to remove the containing macro at point:

(defun TeX-remove-macro ()
"Remove current macro and return t'.  If no macro at point,
return nil'."
(interactive)
(when (TeX-current-macro)
(let ((bounds (TeX-find-macro-boundaries))
(brace  (save-excursion
(goto-char (1- (TeX-find-macro-end)))
(TeX-find-opening-brace))))
(delete-region (1- (cdr bounds)) (cdr bounds))
(delete-region (car bounds) (1+ brace)))
t))


Hence, with * as point:

\footnote{Here's a * footnote}
=> Here's a footnote


Given the above function, it's a one-liner to remove all the macros at point:

(defun TeX-remove-all-macros ()
"Remove all containing macros for text at point."
(interactive)
(while (TeX-remove-macro)))


Hence, again with * as point:

\footnote{Here's a \textbf{footnote with \emph{emphasized * text}}}
=> Here's a footnote with emphasized text