branch: main
commit c1aa60c6cc87173d690e7e1f2b5930f4e92d351a
Author: Paul Nelson <[email protected]>
Commit: Paul Nelson <[email protected]>
Add command LaTeX-repeat-recent-math
* latex.el (LaTeX-repeat-recent-math): New command.
* doc/auctex.texi (Mathematics): Document it.
---
doc/auctex.texi | 29 +++++++++++++++++++++++++++++
latex.el | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+)
diff --git a/doc/auctex.texi b/doc/auctex.texi
index 99454cff..0c1f8698 100644
--- a/doc/auctex.texi
+++ b/doc/auctex.texi
@@ -1406,6 +1406,35 @@ e.g.@: by adding the following to your init file:
@xref{Quotes,,LaTeX-make-inline}, for a built-in convenience wrapper that
converts display constructs to inline math.
+@subheading Repeating recent math
+
+@cindex LaTeX-repeat-recent-math
+@cindex Math, repeating
+@cindex Environments, repeating
+
+Sometimes you want the next equation to be a slight modification of a
+previous one. The command @code{LaTeX-repeat-recent-math} looks backward
+for a recent top-level display math construct and inserts a copy.
+
+@deffn Command LaTeX-repeat-recent-math @var{n}
+Search backward for the @var{n}th most recent outer-level math construct
+(@samp{\[...\]}, @samp{$$...$$}, or any math environment recognized by
+@code{texmathp}, such as @code{equation}, @code{align*}, @dots{}). Copy
+that construct to the current line, indent it, and strip any labels.
+
+With no prefix argument, @var{n} defaults to @code{1} (the most recent
+construct).
+@end deffn
+
+We can bind this command to a key, as follows:
+
+@lisp
+(keymap-set LaTeX-mode-map "C-c r" #'LaTeX-repeat-recent-math)
+@end lisp
+
+Then @kbd{C-c r} duplicates the last equation, @kbd{C-2 C-c r} duplicates
+the second-to-last equation, and so on.
+
@node Completion
@section Completion
@cindex Completion
diff --git a/latex.el b/latex.el
index 7726019c..61bdb7bb 100644
--- a/latex.el
+++ b/latex.el
@@ -9771,6 +9771,59 @@ trailing punctuation outside the math delimiters."
(cons TeX-electric-math 'inline)
"$")))
+(defun LaTeX-repeat-recent-math (&optional n)
+ "Insert a copy of the Nth most recent top-level math construct.
+N should be a positive integer. The recognized constructs are
+\"\\=\\[ ... \\]\", \"$$ ... $$\" and \"\\begin{ENV} ... \\end{ENV}\"
+with ENV a math environment detected by `texmathp'. Any
+\"\\label{...}\" macros inside the copied region are stripped."
+ (interactive "*p")
+ (setq n (or n 1))
+ (unless (> n 0) (user-error "N must be positive"))
+ (let* ((env-re (concat (regexp-quote TeX-esc) "begin"
+ TeX-grop
+ "\\(" (regexp-opt (LaTeX--math-environment-list))
"\\)"
+ TeX-grcl))
+ (search-re (concat env-re "\\|"
+ "\\(" (regexp-quote "$$") "\\|"
+ (regexp-quote (concat TeX-esc "[")) "\\)"))
+ beg end)
+ (save-excursion
+ (catch 'found
+ (while (re-search-backward search-re nil t)
+ (unless (nth 4 (syntax-ppss))
+ (let ((open (match-string-no-properties 0)))
+ (when (save-excursion
+ (goto-char (match-end 0))
+ (texmathp))
+ (cl-decf n)
+ (when (zerop n)
+ (setq beg (point))
+ (goto-char (match-end 0))
+ (let ((end-re
+ (let ((type (if (string-match env-re open)
+ (match-string-no-properties 1 open)
+ open)))
+ (regexp-quote (LaTeX--closing type)))))
+ (re-search-forward end-re))
+ (setq end (point))
+ (throw 'found t))))))))
+ (unless (and beg end)
+ (user-error "Nth most recent top-level math construct not found"))
+ (let ((contents (buffer-substring-no-properties beg end)))
+ (beginning-of-line)
+ (if (looking-at-p "[[:blank:]]*$")
+ (delete-region (point) (line-end-position))
+ (end-of-line)
+ (delete-horizontal-space)
+ (insert "\n"))
+ (save-excursion (insert contents))
+ (save-restriction
+ (narrow-to-region (point) (+ (point) (length contents)))
+ (indent-region (point-min) (point-max))
+ (save-excursion (LaTeX--strip-labels))
+ (forward-line)))))
+
(provide 'latex)
;;; latex.el ends here