12

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).

enter image description here
Put the cursor (point) just before the first curly bracket:

enter image description here

Hit ALT+DEL and you get:

enter image description here

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:
enter image description here

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

How to get rid of this caveat?

doctorate
  • 1,789
  • 16
  • 39
  • 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 05 '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 05 '15 at 13:54

3 Answers3

11

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))
      ;; Return to the beginning of the macro to be deleted.
      (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}
giordano
  • 3,245
  • 13
  • 19
  • 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 06 '15 at 20:27
  • I bound it to `M-DEL` like in TexStudio. Thanks. – doctorate Jan 06 '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 06 '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 07 '15 at 08:55
  • @giordano Any chance this will make it into AucTex? It's very useful! – Tyler Nov 01 '17 at 15:40
  • @Tyler Thank you! I have no plan to include this function in AUCTeX, but you can propose it to the mailing list auctex@gnu.org ;-) – giordano Nov 01 '17 at 19:45
9

From the AUCTeX manual node on Changing the font:

C-c C-f C-d

Delete the innermost font specification containing point.
Dan
  • 32,584
  • 6
  • 98
  • 168
  • that was a very handy piece in the documentation that I missed. Thanks. – doctorate Jan 05 '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 05 '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 05 '15 at 13:08
4

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
Dan
  • 32,584
  • 6
  • 98
  • 168