From 23af10f540623c23ff086401c4abdbe013a0420c Mon Sep 17 00:00:00 2001
From: Artem Yurchenko <artemyurchenko@zoho.com>
Date: Sat, 6 Apr 2024 19:56:49 -0400
Subject: [PATCH 2/2] amend TeX electric commands to allow alternative electric
 modes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

1. In particular, we are splitting out the electric logic of
`TeX-insert-dollar'.

2. We've removed the special case where
> If [[`TeX-electric-math']] non-nil and point is inside math
> mode right between a couple of single dollars, pressing `$'
> will insert another pair of dollar signs and leave the point
> between them.

The reasoning is that it's going to work automatically if the user's
`TeX-electric-math' is set to dollars. If it's not, they are very
unlikely to end up in a situation where they need this.

3. We've changed `C-u $' to insert four dollars as opposed to
one. This behaviour is in-line with other symbols, in particular
`TeX-insert-quote' and `TeX-insert-backslash'. If someone needs one
literal `$', they can type `C-1 $' or `C-q $'.

4. We've set appropriate `delete-selection' properties for
`TeX-insert-backslash', `TeX-newline' and `TeX-insert-dollar'. See
the backstory below or the docstring for
`TeX--put-electric-delete-selection'.

5. We didn't fix `TeX-insert-quote'. Maybe later.

The backstory.

When a function bound to SYMBOL has optional «electric»
behaviour, it might interfere with other «electric» modes,
e.g. `electric-pair-mode', `smartparens-mode'; see bug#47936.

As a way to «override» those modes, we use raw `insert' instead
of `self-insert-command'.  That prevents those electric modes
from running their hooks tied to `self-insert-command'.

However, when /our/ electric behaviour is disabled (ELECTRICP is
nil), we want other electric modes to operate freely.  That
means, on the non-electric path, we should use
`self-insert-command' instead of `insert'.

Now, there arises an issue of `delete-selection'.  The electric
path usually doesn't want to delete selection, it wants to
operate some electricity on it; see bug#36385, bug#23177.  Now,
we could think that `delete-selection' for the non-electric path
should be t.  That would disable other electric modes from
working, as they also need to operate on selection.  The decision
is to inherit `delete-selection' from `self-insert-command',
which queries hooks from other electric modes to determine
whether deletion is necessary.
---
 tex.el | 177 ++++++++++++++++++++++++++++-----------------------------
 1 file changed, 86 insertions(+), 91 deletions(-)

diff --git a/tex.el b/tex.el
index 6b7dc154..7ce231e9 100644
--- a/tex.el
+++ b/tex.el
@@ -5088,6 +5088,9 @@ This function implements the idea from the last paragraph."
       (TeX-electric-macro)
     (self-insert-command arg)))
 
+(TeX--put-electric-delete-selection
+ #'TeX-insert-backslash (lambda () TeX-electric-escape))
+
 (defun TeX-insert-sub-or-superscript (arg)
   "Insert typed key ARG times and possibly a pair of braces.
 Brace insertion is only done if point is in a math construct and
@@ -5102,6 +5105,9 @@ Brace insertion is only done if point is in a math construct and
   "Call the function specified by the variable `TeX-newline-function'."
   (interactive) (call-interactively TeX-newline-function))
 
+(TeX--put-electric-delete-selection
+ #'TeX-newline (lambda () nil))
+
 (progn
   (let ((map TeX-mode-map))
     ;; Standard
@@ -6098,10 +6104,6 @@ closing inline equation and keep the region active, with point
 after closing symbol.  If you press `$' again, you can toggle
 between inline equation, display equation, and no equation.
 
-If non-nil and point is inside math mode right between a couple
-of single dollars, pressing `$' will insert another pair of
-dollar signs and leave the point between them.
-
 If nil, `TeX-insert-dollar' will simply insert \"$\" at point,
 this is the default.
 
@@ -6128,47 +6130,87 @@ same way as non-math mode."
   :group 'TeX-macro
   :type 'boolean)
 
-(defun TeX-insert-dollar (&optional arg)
+(defun TeX-insert-dollar-electric-region ()
+  "Perform electric math symbol insertion on a region.
+See `TeX-electric-math'."
+  (when (> (point) (mark))
+    (exchange-point-and-mark))
+  (cond
+   ;; $...$ to $$...$$
+   ((and (eq last-command #'TeX-insert-dollar)
+         (re-search-forward "\\=\\$\\([^$][^z-a]*[^$]\\)\\$" (mark) t))
+    (replace-match "$$\\1$$" t)
+    (set-mark (match-beginning 0)))
+   ;; \(...\) to \[...\]
+   ((and (eq last-command #'TeX-insert-dollar)
+         (re-search-forward "\\=\\\\(\\([^z-a]*\\)\\\\)" (mark) t))
+    (replace-match "\\\\[\\1\\\\]" t)
+    (set-mark (match-beginning 0)))
+   ;; Strip \[...\] or $$...$$
+   ((and (eq last-command #'TeX-insert-dollar)
+         (or (re-search-forward "\\=\\\\\\[\\([^z-a]*\\)\\\\\\]" (mark) t)
+             (re-search-forward "\\=\\$\\$\\([^z-a]*\\)\\$\\$" (mark) t)))
+    (replace-match "\\1" t)
+    (set-mark (match-beginning 0)))
+   (t
+    ;; We use `save-excursion' because point must be situated
+    ;; before opening symbol.
+    (save-excursion (insert (car TeX-electric-math)))
+    (exchange-point-and-mark)
+    (insert (cdr TeX-electric-math))))
+  (TeX-activate-region))
+
+(defun TeX-insert-dollar-electric ()
+  "Perform electric math symbol insertion.
+See `TeX-electric-math'."
+  (if (and (TeX-active-mark) (/= (point) (mark)))
+      (TeX-insert-dollar-electric-region)
+    (insert (car TeX-electric-math))
+    (save-excursion (insert (cdr TeX-electric-math)))
+    (if blink-matching-paren
+        (save-excursion
+          (backward-char)
+          (sit-for blink-matching-delay))))
+  (TeX-math-input-method-off))
+
+(defun TeX-insert-dollar-electric-p ()
+  "Non-nil if `TeX-insert-dollar' should use the electric behaviour."
+  (and (not current-prefix-arg)
+       (not (TeX-escaped-p))
+       (not (TeX-verbatim-p))
+       TeX-electric-math))
+
+(defun TeX-insert-dollar (arg)
   "Insert dollar sign.
 
-If current math mode was not entered with a dollar, refuse to
-insert one when `TeX-refuse-unmatched-dollar' is non-nil.
+When ARG is given, insert a literal `$' ARG times.  E.g., if you
+need exactly one `$', you can use `C-1 $'.
 
-Show matching dollar sign if this dollar sign ends the TeX math
-mode and `blink-matching-paren' is non-nil.
+Otherwise, when in a verbatim or an escaped (with `\\')
+environment, insert one literal `$'.
 
-When outside math mode, the behavior is controlled by the variable
-`TeX-electric-math'.
+Otherwise, when `TeX-electric-math' is non-nil, behave
+accordingly.
 
-With raw \\[universal-argument] prefix, insert exactly one dollar sign.
-With optional ARG, insert that many dollar signs."
+Otherwise, if current math mode was not entered with a dollar,
+refuse to insert one when `TeX-refuse-unmatched-dollar' is
+non-nil.
+
+Show matching dollar sign if this dollar sign ends the TeX math
+mode and `blink-matching-paren' is non-nil."
   (interactive "*P")
   (cond
-   ((and arg (listp arg))
-    ;; C-u always inserts one
-    (insert "$"))
-   (arg
-    ;; Numerical arg inserts that many
-    (insert-char ?\$ (prefix-numeric-value arg)))
-   ((or (TeX-escaped-p) (TeX-verbatim-p))
-    ;; Point is escaped with `\' or is in a verbatim-like construct,
-    ;; so just insert one $.
-    (insert "$"))
-   ((texmathp)
-    ;; We are inside math mode
+   ((TeX-insert-dollar-electric-p) (TeX-insert-dollar-electric))
+   (arg (self-insert-command (prefix-numeric-value arg)))
+   ((not (texmathp))                    ; supposedly, text mode
+    (self-insert-command 1)
+    (TeX-math-input-method-off))
+   (t                                   ; supposedly, math mode
     (cond
-     ((and TeX-electric-math
-           (eq (preceding-char) ?\$)
-           (eq (following-char) ?\$))
-      ;; Point is between "$$" and `TeX-electric-math' is non-nil -
-      ;; insert another pair of dollar signs and leave point between
-      ;; them.
-      (insert "$$")
-      (backward-char))
      ((and (stringp (car texmathp-why))
            (string-equal (substring (car texmathp-why) 0 1) "\$"))
       ;; Math mode was turned on with $ or $$ - insert a single $.
-      (insert "$")
+      (self-insert-command 1)
       ;; Compatibility, `TeX-math-close-double-dollar' has been
       ;; removed after AUCTeX 11.87.
       (if (boundp 'TeX-math-close-double-dollar)
@@ -6195,52 +6237,11 @@ With optional ARG, insert that many dollar signs."
      (t
       ;; We assume that `texmathp' was wrong and behave as if not in
       ;; math mode. (bug#57626)
-      (TeX--insert-dollar-1))))
-   (t
-    ;; Just somewhere in the text.
-    (TeX--insert-dollar-1))))
+      (self-insert-command 1)
+      (TeX-math-input-method-off))))))
 
-(defun TeX--insert-dollar-1 ()
-  "Do the job of `TeX-insert-dollar' in non-math mode."
-  (cond
-   ((and TeX-electric-math (TeX-active-mark)
-         (/= (point) (mark)))
-    (if (> (point) (mark))
-        (exchange-point-and-mark))
-    (cond
-     ;; $...$ to $$...$$
-     ((and (eq last-command #'TeX-insert-dollar)
-           (re-search-forward "\\=\\$\\([^$][^z-a]*[^$]\\)\\$" (mark) t))
-      (replace-match "$$\\1$$" t)
-      (set-mark (match-beginning 0)))
-     ;; \(...\) to \[...\]
-     ((and (eq last-command #'TeX-insert-dollar)
-           (re-search-forward "\\=\\\\(\\([^z-a]*\\)\\\\)" (mark) t))
-      (replace-match "\\\\[\\1\\\\]" t)
-      (set-mark (match-beginning 0)))
-     ;; Strip \[...\] or $$...$$
-     ((and (eq last-command #'TeX-insert-dollar)
-           (or (re-search-forward "\\=\\\\\\[\\([^z-a]*\\)\\\\\\]" (mark) t)
-               (re-search-forward "\\=\\$\\$\\([^z-a]*\\)\\$\\$" (mark) t)))
-      (replace-match "\\1" t)
-      (set-mark (match-beginning 0)))
-     (t
-      ;; We use `save-excursion' because point must be situated
-      ;; before opening symbol.
-      (save-excursion (insert (car TeX-electric-math)))
-      (exchange-point-and-mark)
-      (insert (cdr TeX-electric-math))))
-    (TeX-activate-region))
-   (TeX-electric-math
-    (insert (car TeX-electric-math))
-    (save-excursion (insert (cdr TeX-electric-math)))
-    (if blink-matching-paren
-        (save-excursion
-          (backward-char)
-          (sit-for blink-matching-delay))))
-   ;; In any other case just insert a single $.
-   ((insert "$")))
-  (TeX-math-input-method-off))
+(TeX--put-electric-delete-selection
+ #'TeX-insert-dollar TeX-insert-dollar-electric-p)
 
 (defcustom TeX-math-input-method-off-regexp
   (concat "^" (regexp-opt '("chinese" "japanese" "korean" "bulgarian" "russian") t))
@@ -6340,6 +6341,10 @@ the settings of style files.  Style files should therefore check
 if this symbol is present and not alter `TeX-quote-language' if
 it is.")
 
+;; TODO: rework according to the slogan from
+;; `TeX--put-electric-delete-selection'. That would splitting off the
+;; «electric» part that tries to do smart things and the plain part
+;; that just inserts a quote.
 (defun TeX-insert-quote (force)
   "Insert the appropriate quotation marks for TeX.
 Inserts the value of `TeX-open-quote' (normally \\=`\\=`) or `TeX-close-quote'
@@ -6425,6 +6430,8 @@ With prefix argument FORCE, always inserts \" characters."
                       (t
                        close-quote)))))))
 
+(put 'TeX-insert-quote 'delete-selection t)
+
 (defun TeX-insert-punctuation ()
   "Insert point or comma, cleaning up preceding space."
   (interactive)
@@ -6875,18 +6882,6 @@ The table inherits from USERTABLE if it is a valid abbrev table."
      (add-hook 'desktop-after-read-hook (lambda ()
                                           (TeX-set-mode-name t)))))
 
-;; delsel.el, `delete-selection-mode'
-(put 'TeX-newline 'delete-selection t)
-(put 'TeX-insert-quote 'delete-selection t)
-(put 'TeX-insert-backslash 'delete-selection t)
-;; When `TeX-electric-math' is non-nil, `TeX-insert-dollar' interferes with
-;; `delete-selection-mode', but when it's nil users may want to be able to
-;; delete active region if `delete-selection-mode' is active, see bug#23177.  We
-;; can dynamically determine the behavior of `delete-selection' with
-;; `TeX-insert-dollar' based on the value of `TeX-electric-math'.
-(put 'TeX-insert-dollar 'delete-selection
-     (lambda () (null TeX-electric-math)))
-
 (defun TeX--list-of-string-p (lst)
   "Return non-nil if LST is a list of strings.
 Used as function for validating a variable's `safe-local-variable' property."
-- 
2.44.0

