branch: master
commit 3b0becf00535f77d47db8e39e17a726504254f53
Author: Artem Yurchenko <[email protected]>
Commit: Ikumi Keita <[email protected]>
Split out the electric version of `LaTeX-insert-left-brace'
Set the proper `delete-selection` property.
The backstory.
When a function bound to SYMBOL has optional «electric»
behavior, 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 behavior 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.
The changelog.
* tex.el (TeX--put-electric-delete-selection): New function, sets
the appropriate `delete-selection' property for electric functions.
* latex.el (LaTeX-insert-left-brace): Split out electric logic
into a few function `LaTeX-insert-left-brace-electric'
Set appropriate `delete-selection'.
---
latex.el | 123 ++++++++++++++++++++++++++++-----------------------------------
tex.el | 42 ++++++++++++++++++++++
2 files changed, 96 insertions(+), 69 deletions(-)
diff --git a/latex.el b/latex.el
index e66f4116..67680cee 100644
--- a/latex.el
+++ b/latex.el
@@ -3285,80 +3285,65 @@ supply the corresponding macro such as \\right before
the right brace macro."
(LaTeX-insert-corresponding-right-macro-and-brace
left-macro left-brace optional)))))
+(defun LaTeX-insert-left-brace-electric (brace)
+ "Insert typed left BRACE and a corresponding right brace.
+
+BRACE should be a character. See `LaTeX-insert-left-brace' for
+allowed BRACE values."
+ (when (and (TeX-active-mark) (> (point) (mark)))
+ (exchange-point-and-mark))
+ (let ((lbrace (char-to-string brace)) lmacro skip-p)
+ ;; Use `insert' rather than `self-insert-command' so that
+ ;; unexpected side effects from `post-self-insert-hook',
+ ;; e.g. `electric-pair-mode', won't mess up the following
+ ;; outcomes. (bug#47936)
+ (insert brace)
+ (save-excursion
+ (backward-char)
+ ;; The brace "{" is exceptional in two aspects.
+ ;; 1. "\{" should be considered as a single brace
+ ;; like "(" and "[".
+ ;; 2. "\left{" is nonsense while "\left\{" and
+ ;; "\left(" are not.
+ (if (string= lbrace TeX-grop)
+ ;; If "{" follows "\", set lbrace to "\{".
+ (if (TeX-escaped-p)
+ (progn
+ (backward-char)
+ (setq lbrace (concat TeX-esc TeX-grop)))
+ ;; Otherwise, don't search for left macros.
+ (setq skip-p t)))
+ (unless skip-p
+ ;; Obtain the name of preceding left macro, if any,
+ ;; such as "left", "bigl" etc.
+ (setq lmacro (LaTeX--find-preceding-left-macro-name))))
+ (let ((TeX-arg-right-insert-p t)
+ ;; "{" and "}" are paired temporally so that typing
+ ;; a single "{" should insert a pair "{}".
+ (TeX-braces-association
+ (cons (cons TeX-grop TeX-grcl) TeX-braces-association)))
+ (save-excursion
+ (if (TeX-active-mark)
+ (goto-char (mark)))
+ (LaTeX-insert-corresponding-right-macro-and-brace
+ lmacro lbrace)))))
+
(defun LaTeX-insert-left-brace (arg)
- "Insert typed left brace ARG times and possibly a correspondig right brace.
+ "Insert typed left brace ARG times and possibly a corresponding right brace.
Automatic right brace insertion is done only if no prefix ARG is given and
`LaTeX-electric-left-right-brace' is non-nil.
Normally bound to keys \(, { and [."
(interactive "*P")
- ;; If you change the condition for `auto-p', adjust the condition in
- ;; the `delete-selection' property, just below this defun, accordingly.
- (let ((auto-p (and LaTeX-electric-left-right-brace (not arg))))
- (if (and auto-p
- (TeX-active-mark)
- (> (point) (mark)))
- (exchange-point-and-mark))
- (if auto-p
- ;; Should supply corresponding right brace with possible
- ;; \right-like macro.
- (let ((lbrace (char-to-string last-command-event)) lmacro skip-p)
- ;; Use `insert' rather than `self-insert-command' so that
- ;; unexcpected side effects, e.g. `electric-pair-mode',
- ;; won't mess up the following outcomes. (bug#47936)
- (insert last-command-event)
- (save-excursion
- (backward-char)
- ;; The brace "{" is exceptional in two aspects.
- ;; 1. "\{" should be considered as a single brace
- ;; like "(" and "[".
- ;; 2. "\left{" is nonsense while "\left\{" and
- ;; "\left(" are not.
- (if (string= lbrace TeX-grop)
- ;; If "{" follows "\", set lbrace to "\{".
- (if (TeX-escaped-p)
- (progn
- (backward-char)
- (setq lbrace (concat TeX-esc TeX-grop)))
- ;; Otherwise, don't search for left macros.
- (setq skip-p t)))
- (unless skip-p
- ;; Obtain the name of preceding left macro, if any,
- ;; such as "left", "bigl" etc.
- (setq lmacro (LaTeX--find-preceding-left-macro-name))))
- (let ((TeX-arg-right-insert-p t)
- ;; "{" and "}" are paired temporally so that typing
- ;; a single "{" should insert a pair "{}".
- (TeX-braces-association
- (cons (cons TeX-grop TeX-grcl) TeX-braces-association)))
- (save-excursion
- (if (TeX-active-mark)
- (goto-char (mark)))
- (LaTeX-insert-corresponding-right-macro-and-brace
- lmacro lbrace))))
- ;; Don't supply right brace and just act as ordinary
- ;; `self-insert-command'.
- (self-insert-command (prefix-numeric-value arg)))))
-;; Cater for `delete-selection-mode' (bug#36385)
-;; See the header comment of delsel.el for detail.
-(put #'LaTeX-insert-left-brace 'delete-selection
- (lambda ()
- ;; Consult `delete-selection' property when
- ;; `LaTeX-insert-left-brace' works just the same as
- ;; `self-insert-command'.
- (and (or (not LaTeX-electric-left-right-brace)
- current-prefix-arg)
- (let ((f (get #'self-insert-command 'delete-selection)))
- ;; If `delete-selection' property of
- ;; `self-insert-command' is one of the predefined
- ;; special symbols, just return itself.
- (if (memq f '(yank supersede kill t nil))
- ;; FIXME: if this list of special symbols is
- ;; extended in future delsel.el, this discrimination
- ;; will become wrong.
- f
- ;; Otherwise, call it as a function and return
- ;; its value.
- (funcall f))))))
+ (if (and LaTeX-electric-left-right-brace (not arg))
+ (LaTeX-insert-left-brace-electric last-command-event)
+ (self-insert-command (prefix-numeric-value arg))))
+
+;; Cater for `delete-selection-mode' (bug#36385). See the header
+;; comment of delsel.el for detail. In short, whenever a function
+;; performs insertion, we ``inherit'' the `delete-selection' property.
+(TeX--put-electric-delete-selection
+ #'LaTeX-insert-left-brace
+ (lambda () (and LaTeX-electric-left-right-brace (not current-prefix-arg))))
(defun LaTeX-insert-corresponding-right-macro-and-brace
(lmacro lbrace &optional optional prompt)
diff --git a/tex.el b/tex.el
index 749037b5..2235df27 100644
--- a/tex.el
+++ b/tex.el
@@ -5091,6 +5091,48 @@ affected. See `TeX-electric-macro' for detail."
(const reindent-then-newline-and-indent)
(sexp :tag "Other")))
+(defun TeX--put-electric-delete-selection (symbol electricp)
+ "Set appropriate `delete-selection' property for electric functions.
+
+When the function bound to SYMBOL has «electric» behaviour, as
+determined by predicate ELECTRICP, `delete-selection' is set to
+nil. In the other case, `delete-selection' is delegated to that
+of the `self-insert-command'.
+
+Note, that it is assumed that SYMBOL uses `self-insert-command'
+to insert symbols on its non-electric path.
+
+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
+returns 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.
+
+This function implements the idea from the last paragraph."
+ (put symbol 'delete-selection
+ (lambda ()
+ (unless (funcall electricp)
+ (get #'self-insert-command 'delete-selection)))))
+
(defun TeX-insert-backslash (arg)
"Either insert typed key ARG times or call `TeX-electric-macro'.
`TeX-electric-macro' will be called if `TeX-electric-escape' is non-nil."