From: Stephen Berman via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Arash Esbati <arash@gnu.org>
Cc: 71337@debbugs.gnu.org
Subject: bug#71337: 30.0.50; `electric-pair-mode' and custom keybinding
Date: Mon, 03 Jun 2024 15:50:55 +0200 [thread overview]
Message-ID: <87frtu9lts.fsf@gmx.net> (raw)
In-Reply-To: <m25xuqurlc.fsf@macmutant.fritz.box> (Arash Esbati's message of "Mon, 03 Jun 2024 14:40:47 +0200")
[-- Attachment #1: Type: text/plain, Size: 1655 bytes --]
On Mon, 03 Jun 2024 14:40:47 +0200 Arash Esbati <arash@gnu.org> wrote:
> Hi all,
>
> I have a custom keybinding "s-ß" with my German keyboard, but the issue
> I'm facing is also reproducible like this:
>
> • emacs -Q
> • In scratch, eval:
>
> (progn
> (setq debug-on-error t)
> (electric-pair-mode 1)
> (keymap-global-set "s-#" (lambda (arg)
> "Insert ARG backslash(es)."
> (interactive "*p")
> (self-insert-command arg ?\\))))
>
> • Now hit "s-#" and the debugger says (linebreaks added manually):
>
> Debugger entered--Lisp error: (wrong-type-argument characterp 8388643)
> #f(compiled-function () #<bytecode -0x15954a2c5d74b890>)()
> electric-pair--with-syntax-1(nil #f(compiled-function () #<bytecode -0x15954a2c5d74b890>))
> electric-pair-syntax-info(8388643)
> electric-pair-post-self-insert-function()
> self-insert-command(1 92)
> #f(lambda (arg) [t] "Insert ARG backslash(es)." (interactive "*p")
> (self-insert-command arg 92))(1)
> funcall-interactively(#f(lambda (arg) [t] "Insert ARG backslash(es)."
> (interactive "*p") (self-insert-command arg 92)) 1)
> command-execute(#f(lambda (arg) [t] "Insert ARG backslash(es)."
> (interactive "*p") (self-insert-command arg 92)))
>
> Running the exercise with (electric-pair-mode -1) doesn't throw an
> error.
If the pairing in electric-pair-mode should only be triggered by
self-inserting characters (as the current code seems to require), then
the attached patch appears to avoid the above problem.
Steve Berman
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: electric-pair-post-self-insert-function patch --]
[-- Type: text/x-patch, Size: 7441 bytes --]
diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el
index 40618e9ef38..1b5b6d401a9 100644
--- a/lisp/elec-pair.el
+++ b/lisp/elec-pair.el
@@ -528,71 +528,72 @@ electric-pair-post-self-insert-function
and `electric-pair-skip-whitespace' (which see)."
(let* ((pos (and electric-pair-mode (electric--after-char-pos)))
(skip-whitespace-info))
- (pcase (electric-pair-syntax-info last-command-event)
- (`(,syntax ,pair ,unconditional ,_)
- (cond
- ((null pos) nil)
- ;; Wrap a pair around the active region.
- ;;
- ((and (memq syntax '(?\( ?\) ?\" ?\$)) (use-region-p))
- ;; FIXME: To do this right, we'd need a post-self-insert-function
- ;; so we could add-function around it and insert the closer after
- ;; all the rest of the hook has run.
- (if (or (eq syntax ?\")
- (and (eq syntax ?\))
- (>= (point) (mark)))
- (and (not (eq syntax ?\)))
- (>= (mark) (point))))
- (save-excursion
- (goto-char (mark))
- (electric-pair--insert pair))
- (delete-region pos (1- pos))
- (electric-pair--insert pair)
- (goto-char (mark))
- (electric-pair--insert last-command-event)))
- ;; Backslash-escaped: no pairing, no skipping.
- ((save-excursion
- (goto-char (1- pos))
- (not (zerop (% (skip-syntax-backward "\\") 2))))
- nil)
- ;; Skip self.
- ((and (memq syntax '(?\) ?\" ?\$))
- (and (or unconditional
- (if (functionp electric-pair-skip-self)
- (electric-pair--save-literal-point-excursion
- (goto-char pos)
- (funcall electric-pair-skip-self last-command-event))
- electric-pair-skip-self))
- (save-excursion
- (when (and (not (and unconditional
- (eq syntax ?\")))
- (setq skip-whitespace-info
- (if (and (not (eq electric-pair-skip-whitespace 'chomp))
- (functionp electric-pair-skip-whitespace))
- (funcall electric-pair-skip-whitespace)
- electric-pair-skip-whitespace)))
- (funcall electric-pair-skip-whitespace-function))
- (eq (char-after) last-command-event))))
- ;; This is too late: rather than insert&delete we'd want to only
- ;; skip (or insert in overwrite mode). The difference is in what
- ;; goes in the undo-log and in the intermediate state which might
- ;; be visible to other post-self-insert-hook. We'll just have to
- ;; live with it for now.
- (when skip-whitespace-info
- (funcall electric-pair-skip-whitespace-function))
- (delete-region (1- pos) (if (eq skip-whitespace-info 'chomp)
- (point)
- pos))
- (forward-char))
- ;; Insert matching pair.
- ((and (memq syntax '(?\( ?\" ?\$))
- (not overwrite-mode)
- (or unconditional
- (not (electric-pair--save-literal-point-excursion
- (goto-char pos)
- (funcall electric-pair-inhibit-predicate
- last-command-event)))))
- (save-excursion (electric-pair--insert pair))))))))
+ (when (characterp last-command-event)
+ (pcase (electric-pair-syntax-info last-command-event)
+ (`(,syntax ,pair ,unconditional ,_)
+ (cond
+ ((null pos) nil)
+ ;; Wrap a pair around the active region.
+ ;;
+ ((and (memq syntax '(?\( ?\) ?\" ?\$)) (use-region-p))
+ ;; FIXME: To do this right, we'd need a post-self-insert-function
+ ;; so we could add-function around it and insert the closer after
+ ;; all the rest of the hook has run.
+ (if (or (eq syntax ?\")
+ (and (eq syntax ?\))
+ (>= (point) (mark)))
+ (and (not (eq syntax ?\)))
+ (>= (mark) (point))))
+ (save-excursion
+ (goto-char (mark))
+ (electric-pair--insert pair))
+ (delete-region pos (1- pos))
+ (electric-pair--insert pair)
+ (goto-char (mark))
+ (electric-pair--insert last-command-event)))
+ ;; Backslash-escaped: no pairing, no skipping.
+ ((save-excursion
+ (goto-char (1- pos))
+ (not (zerop (% (skip-syntax-backward "\\") 2))))
+ nil)
+ ;; Skip self.
+ ((and (memq syntax '(?\) ?\" ?\$))
+ (and (or unconditional
+ (if (functionp electric-pair-skip-self)
+ (electric-pair--save-literal-point-excursion
+ (goto-char pos)
+ (funcall electric-pair-skip-self last-command-event))
+ electric-pair-skip-self))
+ (save-excursion
+ (when (and (not (and unconditional
+ (eq syntax ?\")))
+ (setq skip-whitespace-info
+ (if (and (not (eq electric-pair-skip-whitespace 'chomp))
+ (functionp electric-pair-skip-whitespace))
+ (funcall electric-pair-skip-whitespace)
+ electric-pair-skip-whitespace)))
+ (funcall electric-pair-skip-whitespace-function))
+ (eq (char-after) last-command-event))))
+ ;; This is too late: rather than insert&delete we'd want to only
+ ;; skip (or insert in overwrite mode). The difference is in what
+ ;; goes in the undo-log and in the intermediate state which might
+ ;; be visible to other post-self-insert-hook. We'll just have to
+ ;; live with it for now.
+ (when skip-whitespace-info
+ (funcall electric-pair-skip-whitespace-function))
+ (delete-region (1- pos) (if (eq skip-whitespace-info 'chomp)
+ (point)
+ pos))
+ (forward-char))
+ ;; Insert matching pair.
+ ((and (memq syntax '(?\( ?\" ?\$))
+ (not overwrite-mode)
+ (or unconditional
+ (not (electric-pair--save-literal-point-excursion
+ (goto-char pos)
+ (funcall electric-pair-inhibit-predicate
+ last-command-event)))))
+ (save-excursion (electric-pair--insert pair)))))))))
(defun electric-pair-open-newline-between-pairs-psif ()
"Honor `electric-pair-open-newline-between-pairs'.
next prev parent reply other threads:[~2024-06-03 13:50 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-03 12:40 bug#71337: 30.0.50; `electric-pair-mode' and custom keybinding Arash Esbati
2024-06-03 13:50 ` Stephen Berman via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2024-06-04 5:53 ` Arash Esbati
2024-06-04 7:30 ` Stephen Berman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-04 7:37 ` João Távora
2024-06-04 8:08 ` João Távora
2024-06-04 8:18 ` Stephen Berman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-04 14:52 ` Eli Zaretskii
2024-06-04 9:24 ` Eli Zaretskii
2024-06-04 10:09 ` Stephen Berman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-04 10:49 ` João Távora
2024-06-04 11:04 ` Eli Zaretskii
2024-06-04 14:56 ` Eli Zaretskii
2024-06-04 15:43 ` Stephen Berman via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-04 12:33 ` Arash Esbati
2024-06-04 13:36 ` João Távora
2024-06-04 14:09 ` Arash Esbati
2024-06-04 14:21 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-15 8:10 ` Eli Zaretskii
2024-06-16 10:42 ` Arash Esbati
2024-06-04 8:09 ` Stephen Berman via Bug reports for GNU Emacs, the Swiss army knife of text editors
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87frtu9lts.fsf@gmx.net \
--to=bug-gnu-emacs@gnu.org \
--cc=71337@debbugs.gnu.org \
--cc=arash@gnu.org \
--cc=stephen.berman@gmx.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).