Subject: bug#78586: TeX-make-inline

From: "Paul D. Nelson" <[email-masked]>
Date: Thu, 29 May 2025 11:15:58 +0200

Hi Arash,

Thanks again for your feedback, and sounds good on all counts.  Please
see attached.

Thanks, best,

Paul

>From 129d469a2ab47f61b10f5eb9557de7e525a3830f Mon Sep 17 00:00:00 2001
From: Paul Nelson <[email-masked]>
Date: Thu, 29 May 2025 11:14:11 +0200
Subject: [PATCH] Add LaTeX-make-inline command

* latex.el (LaTeX-make-inline): New command.
(LaTeX--make-inline-finalize-region): New helper function.
* tests/latex/latex-make-inline-test.el: New test file.
(latex-make-inline-test--with-temp-buffer): New test macro.
(LaTeX-make-inline-bracket-period)
(LaTeX-make-inline-double-dollar)
(LaTeX-make-inline-electric-math, LaTeX-make-inline-equation-env)
(LaTeX-make-inline-noop): New test cases.

* doc/auctex.texi (Quotes): Document LaTeX-make-inline.
---
 doc/auctex.texi                       | 10 ++++
 latex.el                              | 82 +++++++++++++++++++++++++++
 tests/latex/latex-make-inline-test.el | 79 ++++++++++++++++++++++++++
 3 files changed, 171 insertions(+)
 create mode 100644 tests/latex/latex-make-inline-test.el

diff --git a/doc/auctex.texi b/doc/auctex.texi
index 0b486c8c..9602c062 100644
--- a/doc/auctex.texi
+++ b/doc/auctex.texi
@@ -484,6 +484,16 @@ to prevent unmatched dollar.
 Note that Texinfo mode does nothing special for @kbd{$}.  It inserts
 dollar sign(s) just in the same way as the other normal keys do.
 
+@AUCTeX{} provides the command @code{LaTeX-make-inline} which converts the
+display math environment at point to inline math.
+
+@deffn Command LaTeX-make-inline
+Convert @LaTeX{} display math environment at point to inline math.  This
+command replaces the enclosing math environment such as @samp{\[...\]} or
+@samp{\begin@{equation@}...\end@{equation@}} with the value of
+@code{TeX-electric-math} or @samp{$...$} by default.
+@end deffn
+
 @subheading Braces
 
 To avoid unbalanced braces, it is useful to insert them pairwise.  You
diff --git a/latex.el b/latex.el
index 797513f2..6e34dfc5 100644
--- a/latex.el
+++ b/latex.el
@@ -9551,6 +9551,88 @@ no caption key is found, an error is issued.  See also the docstring of
                           "LARGE" "huge" "Huge")
   "List of LaTeX font size declarations.")
 
+(defun LaTeX-make-inline ()
+  "Convert LaTeX display math environment at point to inline math.
+Remove the enclosing math environment (such as \\[...\\] or
+\\begin{equation}...\\end{equation}) and replace it with inline math
+surrounded by `TeX-electric-math' if non-nil, or \"$..$\", fitting the
+result onto one line.  Finally, leave any trailing punctuation outside
+the math delimiters."
+  (interactive)
+  (when (texmathp)
+    (when (fboundp 'preview-clearout-at-point)
+      (preview-clearout-at-point))
+    (save-excursion
+      (let ((env (car texmathp-why))
+            (pos (cdr texmathp-why))
+            (delims (or TeX-electric-math '("$" . "$"))))
+        (cond
+         ((member env '("\\(" "$")))
+         ((member env '("\\[" "$$"))
+          (goto-char pos)
+          (when (looking-back "\n[[:space:]]*")
+            (forward-char 2)
+            (save-excursion (join-line))
+            (forward-char -2))
+          (delete-char 2)
+          (let ((start (point))
+                (end-delim (if (equal env "\\[") "\\]" "$$")))
+            (search-forward end-delim)
+            (delete-char -2)
+            (if (looking-back "\n[[:space:]]*")
+                (goto-char (match-beginning 0)))
+            (LaTeX--make-inline-finalize-region start (point) delims)))
+         (t
+          (goto-char pos)
+          (kill-whole-line)
+          (let ((start (point)))
+            (search-forward (concat "\\end{" env "}"))
+            (beginning-of-line)
+            (kill-whole-line)
+            (backward-char)
+            (LaTeX--make-inline-finalize-region start (point) delims))))))))
+
+(defun LaTeX--make-inline-finalize-region (start end delims)
+  "Finalize the inline conversion from START to END using DELIMS."
+  (save-restriction
+    (narrow-to-region start end)
+
+    (goto-char (point-min))
+    (let ((re (concat "\\(?:"
+                      (if (bound-and-true-p reftex-label-regexps)
+                          (mapconcat #'identity reftex-label-regexps "\\|")
+                        "\\\\label{[^}]*}")
+                      "\\)")))
+      (while (re-search-forward re nil t)
+        (replace-match "")))
+
+    (goto-char (point-min))
+    (while (looking-at "\\s-*$")
+      (delete-line))
+    (beginning-of-line-text)
+    (delete-region (point-min) (point))
+
+    (goto-char (point-max))
+    (while (and (> (point) (point-min))
+                (progn (forward-line -1)
+                       (looking-at "\\s-*$")))
+      (delete-line))
+    (end-of-line)
+    (skip-chars-backward " \t")
+    (delete-region (point) (point-max))
+
+    (goto-char (point-min))
+    (insert (car delims))
+    (goto-char (point-max))
+
+    (while (looking-back "[.,;:!?]" (max (point-min) (- (point) 5)))
+      (backward-char))
+    (insert (cdr delims))
+
+    (while (> (count-lines (point-min) (point-max)) 1)
+      (join-line)))
+  (join-line))
+
 (provide 'latex)
 
 ;;; latex.el ends here
diff --git a/tests/latex/latex-make-inline-test.el b/tests/latex/latex-make-inline-test.el
new file mode 100644
index 00000000..f4dbadf0
--- /dev/null
+++ b/tests/latex/latex-make-inline-test.el
@@ -0,0 +1,79 @@
+;;; latex-make-inline-test.el --- tests for LaTeX-make-inline  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2025  Free Software Foundation, Inc.
+
+;; This file is part of AUCTeX.
+
+;; AUCTeX is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; AUCTeX is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with AUCTeX; see the file COPYING.  If not, write to the Free
+;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+;; 02110-1301, USA.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(require 'latex)
+
+(defmacro latex-make-inline-test--with-temp-buffer (contents &rest body)
+  (declare (indent 1) (debug t))
+  `(with-temp-buffer
+     (LaTeX-mode)
+     (insert ,contents)
+     (goto-char (point-min))
+     (cl-letf (((symbol-function 'preview-clearout-at-point) #'ignore))
+       ,@body)))
+
+(ert-deftest LaTeX-make-inline-bracket-period ()
+  "Convert \\[..\\] to $..$ and keep trailing period."
+  (latex-make-inline-test--with-temp-buffer
+      "We have\n\\[ a+b = c. \\]"
+    (search-forward "b")
+    (LaTeX-make-inline)
+    (should (equal (buffer-string) "We have $a+b = c$."))))
+
+(ert-deftest LaTeX-make-inline-double-dollar ()
+  "Convert $$..$$ to $..$."
+  (latex-make-inline-test--with-temp-buffer
+   "$$x!$$"
+   (search-forward "x")
+   (LaTeX-make-inline)
+   (should (equal (buffer-string) "$x$!"))))
+
+(ert-deftest LaTeX-make-inline-electric-math ()
+  "Respect `TeX-electric-math'."
+  (let ((TeX-electric-math '("\\(" . "\\)")))
+    (latex-make-inline-test--with-temp-buffer
+     "\\[ x \\]"
+     (search-forward "x")
+     (LaTeX-make-inline)
+     (should (equal (buffer-string) "\\(x\\)")))))
+
+(ert-deftest LaTeX-make-inline-equation-env ()
+  "Convert equation environment, drop \\label, keep comma."
+  (latex-make-inline-test--with-temp-buffer
+      "\\begin{equation}\n\\label{l}x+y,\n\\end{equation}\n"
+    (search-forward "x")
+    (let ((TeX-electric-math '("\\(" . "\\)")))
+      (LaTeX-make-inline)
+      (should (equal (buffer-string) "\\(x+y\\),\n")))))
+
+(ert-deftest LaTeX-make-inline-noop ()
+  "Call inside inline math leaves buffer unchanged."
+  (latex-make-inline-test--with-temp-buffer
+   "Already $z$ inline."
+   (search-forward "z")
+   (LaTeX-make-inline)
+   (should (equal (buffer-string) "Already $z$ inline."))))
+
+;;; latex-make-inline-test.el ends here
-- 
2.39.3 (Apple Git-145)