GNU bug report logs - #79371
[PATCH] Make yank-in-context also can indent the yanked text.

Previous Next

Package: emacs;

Reported by: Elijah Gabe Pérez <eg642616 <at> gmail.com>

Date: Tue, 2 Sep 2025 15:57:02 UTC

Severity: normal

Tags: patch

To reply to this bug, email your comments to 79371 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 15:57:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Elijah Gabe Pérez <eg642616 <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Tue, 02 Sep 2025 15:57:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: [PATCH] Make yank-in-context also can indent the yanked text.
Date: Tue, 02 Sep 2025 09:55:55 -0600
[Message part 1 (text/plain, inline)]
Tags: patch

This patch makes `yank-in-context` can optionally indent the yanked
text.

The indentation is done calling `indent-region`, but the function to use
can be changed.

Additionally, i added support for `delete-selection-mode` in
`yank-in-context`.

[0001-Make-yank-in-context-can-also-indent-the-yanked-text.patch (text/x-patch, attachment)]
[Message part 3 (text/plain, inline)]
-- 
- E.G via Gnus and Org.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 16:24:02 GMT) Full text and rfc822 format available.

Message #8 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 79371 <at> debbugs.gnu.org
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the yanked
 text.
Date: Tue, 02 Sep 2025 19:22:52 +0300
> From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
> Date: Tue, 02 Sep 2025 09:55:55 -0600
> 
> This patch makes `yank-in-context` can optionally indent the yanked
> text.
> 
> The indentation is done calling `indent-region`, but the function to use
> can be changed.

Thanks, but I wonder whether this indeed justifies yet another user
option, given that indenting the yanked text, if that is desired, can
be obtained by typing C-M-\ immediately after yanking.

What do others think about this?

> Additionally, i added support for `delete-selection-mode` in
> `yank-in-context`.

This should be a separate change, because I believe it is correct to
do that by default regardless of anything else.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 16:56:01 GMT) Full text and rfc822 format available.

Message #11 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 02 Sep 2025 12:55:23 -0400
> This patch makes `yank-in-context` can optionally indent the yanked text.
[...]
> @@ -6432,8 +6452,12 @@ yank-in-context
>  variable to determine how strings should be escaped."
>    (interactive "*P")
>    (let ((yank-transform-functions (cons #'yank-in-context--transform
> -                                        yank-transform-functions)))
> -    (yank arg)))
> +                                        yank-transform-functions))
> +        (beg (point)) end)
> +    (yank arg)
> +    (setq end (point))
> +    (if yank-in-context-indent
> +        (funcall yank-in-context-indent-function beg end))))

Hmm... what's the intended use case?

`yank-in-context` differs from `yank` only inside strings and comments,
but in most major modes `indent-region` doesn't know how to indent
inside strings and comments because we don't know if it holds plain text
or code or whatnot.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 17:01:02 GMT) Full text and rfc822 format available.

Message #14 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Sean Whitton <spwhitton <at> spwhitton.name>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org,
 Elijah Gabe Pérez <eg642616 <at> gmail.com>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 02 Sep 2025 18:00:32 +0100
Hello,

On Tue 02 Sep 2025 at 07:22pm +03, Eli Zaretskii wrote:

>> From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
>> Date: Tue, 02 Sep 2025 09:55:55 -0600
>>
>> This patch makes `yank-in-context` can optionally indent the yanked
>> text.
>>
>> The indentation is done calling `indent-region`, but the function to use
>> can be changed.
>
> Thanks, but I wonder whether this indeed justifies yet another user
> option, given that indenting the yanked text, if that is desired, can
> be obtained by typing C-M-\ immediately after yanking.
>
> What do others think about this?

Sometimes you want indentation and sometimes you don't, so requiring the
user to type C-M-\ seems preferable to me, too.

-- 
Sean Whitton




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 18:15:01 GMT) Full text and rfc822 format available.

Message #17 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
 text editors" <bug-gnu-emacs <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org, , Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 02 Sep 2025 12:14:07 -0600
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

>> This patch makes `yank-in-context` can optionally indent the yanked text.
> [...]
>> @@ -6432,8 +6452,12 @@ yank-in-context
>>  variable to determine how strings should be escaped."
>>    (interactive "*P")
>>    (let ((yank-transform-functions (cons #'yank-in-context--transform
>> -                                        yank-transform-functions)))
>> -    (yank arg)))
>> +                                        yank-transform-functions))
>> +        (beg (point)) end)
>> +    (yank arg)
>> +    (setq end (point))
>> +    (if yank-in-context-indent
>> +        (funcall yank-in-context-indent-function beg end))))
>
> Hmm... what's the intended use case?
>
> `yank-in-context` differs from `yank` only inside strings and comments,
> but in most major modes `indent-region` doesn't know how to indent
> inside strings and comments because we don't know if it holds plain text
> or code or whatnot.

This can be fixed not indenting the yanked text if it's in a comment or string.

In my opinion, this feature can be useful since some users often prefer
commands to be automated rather than having to pressing multiple keys.
This can be inconvenient in some cases, but I think it can be useful for
people who know what they're doing.

Another alternative is to create a hook for yank or that electric-indent
can also handle this.

-- 
- E.G via Gnus and Org.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 18:15:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 18:41:02 GMT) Full text and rfc822 format available.

Message #23 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 02 Sep 2025 14:40:30 -0400
>>> This patch makes `yank-in-context` can optionally indent the yanked text.
>> [...]
>>> @@ -6432,8 +6452,12 @@ yank-in-context
>>>  variable to determine how strings should be escaped."
>>>    (interactive "*P")
>>>    (let ((yank-transform-functions (cons #'yank-in-context--transform
>>> -                                        yank-transform-functions)))
>>> -    (yank arg)))
>>> +                                        yank-transform-functions))
>>> +        (beg (point)) end)
>>> +    (yank arg)
>>> +    (setq end (point))
>>> +    (if yank-in-context-indent
>>> +        (funcall yank-in-context-indent-function beg end))))
>>
>> Hmm... what's the intended use case?
>>
>> `yank-in-context` differs from `yank` only inside strings and comments,
>> but in most major modes `indent-region` doesn't know how to indent
>> inside strings and comments because we don't know if it holds plain text
>> or code or whatnot.
>
> This can be fixed not indenting the yanked text if it's in a comment or string.

Ah... so your intended use case is using `yank-in-context` to yank inside code?
I see...

Then why limit it to `yank-in-context`?

[ I see that limiting it to `yank-in-context` means that it's limited to
  a command that already cares about the difference between
  code/comments/strings.  So there's some logic to it.  ]

> Another alternative is to create a hook for yank or that electric-indent
> can also handle this.

It also occurred to me that it could make sense to link it to
electric-indent.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 19:15:02 GMT) Full text and rfc822 format available.

Message #26 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
 text editors" <bug-gnu-emacs <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 02 Sep 2025 13:14:34 -0600
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

>>>> This patch makes `yank-in-context` can optionally indent the yanked text.
>>> [...]
>>>> @@ -6432,8 +6452,12 @@ yank-in-context
>>>>  variable to determine how strings should be escaped."
>>>>    (interactive "*P")
>>>>    (let ((yank-transform-functions (cons #'yank-in-context--transform
>>>> -                                        yank-transform-functions)))
>>>> -    (yank arg)))
>>>> +                                        yank-transform-functions))
>>>> +        (beg (point)) end)
>>>> +    (yank arg)
>>>> +    (setq end (point))
>>>> +    (if yank-in-context-indent
>>>> +        (funcall yank-in-context-indent-function beg end))))
>>>
>>> Hmm... what's the intended use case?
>>>
>>> `yank-in-context` differs from `yank` only inside strings and comments,
>>> but in most major modes `indent-region` doesn't know how to indent
>>> inside strings and comments because we don't know if it holds plain text
>>> or code or whatnot.
>>
>> This can be fixed not indenting the yanked text if it's in a comment or string.
>
> Ah... so your intended use case is using `yank-in-context` to yank inside code?
> I see...
>
> Then why limit it to `yank-in-context`?
>
> [ I see that limiting it to `yank-in-context` means that it's limited to
>   a command that already cares about the difference between
>   code/comments/strings.  So there's some logic to it.  ]

Originally, my idea was to implement this in yank (and its other
commands), but the yank code base is (for some reason) separated into
subr.el, so it was going to be difficult and inconvenient for me, i
decided to add it to `yank-in-context`, since this command is intended
for yanking code[1].

> It also occurred to me that it could make sense to link it to
> electric-indent.

Fine, I'll see how to implement it in electric-indent.


1. Although yank-in-context can also be used outside of prog modes for
non-code text (e.g message-mode), it is buggy for some reason.

-- 
- E.G via Gnus and Org.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 19:15:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 23:12:01 GMT) Full text and rfc822 format available.

Message #32 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org, "Stefan Monnier via Bug reports for GNU Emacs,
 the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 02 Sep 2025 19:11:32 -0400
>> [ I see that limiting it to `yank-in-context` means that it's limited to
>>   a command that already cares about the difference between
>>   code/comments/strings.  So there's some logic to it.  ]
>
> Originally, my idea was to implement this in yank (and its other
> commands), but the yank code base is (for some reason) separated into
> subr.el, so it was going to be difficult and inconvenient for me, i
> decided to add it to `yank-in-context`, since this command is intended
> for yanking code[1].

Yeah, I think it makes sense.

>> It also occurred to me that it could make sense to link it to
>> electric-indent.
> Fine, I'll see how to implement it in electric-indent.

I'm not sure that's such a good idea.

At some point I did consider implementing `electric-indent` in
a different way, which would automatically cover things like `yank`, but
in the end electric-indent is fairly "conservative" in terms of when it
reindents.  But conceptually the two are somewhat related, tho your
functionality might be closer to modes like  `aggressive-indent-mode`.

If you're careful to place an undo boundary before doing the
`indent-region`, it ends up being a choice between:

- Don't reindent by default, let user hit `C-M-\` if they want to reindent.
- Reindent by default, let user hit `C-/` if they didn't want to reindent.

IOW, I'm rather favorable to your proposition.  It seems worth a try.
Tho, maybe you want to pay attention to

    (or (memq indent-line-function
              electric-indent-functions-without-reindent)
        electric-indent-inhibit)

so as not to call `indent-region` when that function is unlikely to do
a good job.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 02 Sep 2025 23:12:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Fri, 05 Sep 2025 01:46:02 GMT) Full text and rfc822 format available.

Message #38 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 79371 <at> debbugs.gnu.org
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Thu, 04 Sep 2025 19:45:20 -0600
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

>> Fine, I'll see how to implement it in electric-indent.

> I'm not sure that's such a good idea.
>
> At some point I did consider implementing `electric-indent` in
> a different way, which would automatically cover things like `yank`, but
> in the end electric-indent is fairly "conservative" in terms of when it
> reindents.

Probably this should be an additional and optional feature for
electric-indent e.g. only indent a region when some command has been
called.

This could extend it to other things, e.g. indent the buffer on save.

> If you're careful to place an undo boundary before doing the
> `indent-region`, it ends up being a choice between:
>
> - Don't reindent by default, let user hit `C-M-\` if they want to reindent.
> - Reindent by default, let user hit `C-/` if they didn't want to reindent.
>
> IOW, I'm rather favorable to your proposition.  It seems worth a try.
> Tho, maybe you want to pay attention to
>
>     (or (memq indent-line-function
>               electric-indent-functions-without-reindent)
>         electric-indent-inhibit)
>
> so as not to call `indent-region` when that function is unlikely to do
> a good job.

Thanks, I'll keep that in mind.

-- 
- E.G via Gnus and Org.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Mon, 15 Sep 2025 02:01:02 GMT) Full text and rfc822 format available.

Message #41 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 79371 <at> debbugs.gnu.org
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Sun, 14 Sep 2025 19:59:53 -0600
[Message part 1 (text/plain, inline)]
I apologize for the delay; I have made a prototype of the idea, and from
what I have tested, it should work well, any comments about this?:

[0001-WIP.patch (text/x-patch, inline)]
From 8b10074baffb763ba31db85ce9904f91de666bd0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?El=C3=ADas=20Gabriel=20P=C3=A9rez?= <eg642616 <at> gmail.com>
Date: Thu, 11 Sep 2025 19:13:21 -0600
Subject: [PATCH] WIP

* lisp/electric.el (electric-indent-actions-alist)
(electric-indent-function): New user options.
(electric-indent--yank-advice, electric-indent-save-hook): New
functions.
(electric-indent-mode): Rework.
---
 lisp/electric.el | 72 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/lisp/electric.el b/lisp/electric.el
index 39e13e1ca0c..7ab1e47f54a 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -192,6 +192,37 @@ electric--after-char-pos
 
 ;;; Electric indentation.
 
+(defcustom electric-indent-actions-alist nil
+  "Alist of actions to indent.
+
+The current values can be:
+ - yank: Indent the yanked text only if point is not in a string or
+         comment and yanked region is longer than 1 line.
+ - save: Indent the whole buffer before saving it.
+
+The indentation will not work if:
+ - The current buffer is not derived from `prog-mode'.
+ - `indent-line-function' value is member of the functions in
+   `electric-indent-functions-without-reindent'.
+
+See also `electric-indent-function', for the function to use in these
+indentations."
+  :type '(repeat (choice (const :tag "After yanking" yank)
+                         (const :tag "Before saving" before-save)))
+  :set (lambda (var val)
+         (set-default var val)
+         (when electric-indent-mode
+           (electric-indent-mode -1)
+           (electric-indent-mode +1)))
+  :safe #'listp
+  :version "31.1")
+
+(defcustom electric-indent-function #'indent-region
+  "Function used to indent the actions in `electric-indent-actions-alist'.
+The function must take 2 arguments, which are the buffer beginning and
+end positions."
+  :type 'function)
+
 ;; Autoloading variables is generally undesirable, but major modes
 ;; should usually set this variable by adding elements to the default
 ;; value, which only works well if the variable is preloaded.
@@ -220,6 +251,42 @@ electric-indent-functions-without-reindent
 not try to reindent lines.  It is normally better to make the major
 mode set `electric-indent-inhibit', but this can be used as a workaround.")
 
+(defun electric-indent--yank-advice (fn &rest r)
+  (let ((p (point)))
+    (apply fn r)
+    (when (and (memq 'yank electric-indent-actions-alist)
+               (not (memq indent-line-function
+                          electric-indent-functions-without-reindent))
+               (derived-mode-p '(prog-mode))
+               (not (= (line-number-at-pos p) (line-number-at-pos (point))))
+               (save-excursion (save-match-data (not (nth 8 (syntax-ppss p))))))
+      (undo-boundary)
+      (ignore-errors (funcall electric-indent-function p (point))))))
+
+(defun electric-indent-save-hook ()
+  (when (and
+         ;; Ensure this hook is called interactively
+         (memq real-this-command '(save-buffer basic-save-buffer))
+         (memq 'before-save electric-indent-actions-alist)
+         (not buffer-read-only)
+         (derived-mode-p '(prog-mode))
+         (not (memq indent-line-function
+                    electric-indent-functions-without-reindent)))
+    (save-excursion
+      (ignore-errors
+        (funcall electric-indent-function (point-min) (point-max))))))
+
+(defun electric-indent-toggle-indent-actions (enable)
+  "Enable the actions specified in `electric-indent-actions-alist'."
+  (when (memq 'yank electric-indent-actions-alist)
+    (if enable
+        (advice-add #'yank :around #'electric-indent--yank-advice)
+      (advice-remove #'yank #'electric-indent--yank-advice)))
+  (when (memq 'before-save electric-indent-actions-alist)
+    (if enable
+        (add-hook 'before-save-hook #'electric-indent-save-hook)
+      (remove-hook 'before-save-hook #'electric-indent-save-hook))))
+
 (defun electric-indent-post-self-insert-function ()
   "Function that `electric-indent-mode' adds to `post-self-insert-hook'.
 This indents if the hook `electric-indent-functions' returns non-nil,
@@ -332,7 +399,10 @@ electric-indent-mode
                   (with-current-buffer buf
                     (if electric-indent-mode (throw 'found t)))))
         (remove-hook 'post-self-insert-hook
-                     #'electric-indent-post-self-insert-function))
+                     #'electric-indent-post-self-insert-function)
+        (electric-indent-toggle-indent-actions nil))
+
+    (electric-indent-toggle-indent-actions :enable)
     (add-hook 'post-self-insert-hook
               #'electric-indent-post-self-insert-function
               60)))
-- 
2.51.0

[Message part 3 (text/plain, inline)]
--
- E.G via Gnus and Org.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Mon, 15 Sep 2025 03:46:02 GMT) Full text and rfc822 format available.

Message #44 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Sun, 14 Sep 2025 23:45:13 -0400
> I apologize for the delay; I have made a prototype of the idea, and from
> what I have tested, it should work well, any comments about this?:

I think the main test whether reindentation can be performed should be:

    (or (memq indent-line-function
              electric-indent-functions-without-reindent)
        electric-indent-inhibit)

I suggest you move this out of
`electric-indent-post-self-insert-function` into its own function so you
can reuse it without having to copy&paste it.

> +(defun electric-indent--yank-advice (fn &rest r)
> +  (let ((p (point)))
> +    (apply fn r)
> +    (when (and (memq 'yank electric-indent-actions-alist)
> +               (not (memq indent-line-function
> +                          electric-indent-functions-without-reindent))
> +               (derived-mode-p '(prog-mode))
> +               (not (= (line-number-at-pos p) (line-number-at-pos (point))))
> +               (save-excursion (save-match-data (not (nth 8 (syntax-ppss p))))))
> +      (undo-boundary)
> +      (ignore-errors (funcall electric-indent-function p (point))))))

`line-number-at-pos-p` takes time proportional to O(pos), so you're
almost always better off avoiding it.  E.g. it'd be much more efficient
to compare `p` and (line-beginning-position), which only needs to look
for the nearest line break.

> +(defun electric-indent-save-hook ()
> +  (when (and
> +         ;; Ensure this hook is called interactively
> +         (memq real-this-command '(save-buffer basic-save-buffer))
> +         (memq 'before-save electric-indent-actions-alist)
> +         (not buffer-read-only)
> +         (derived-mode-p '(prog-mode))
> +         (not (memq indent-line-function
> +                    electric-indent-functions-without-reindent)))
> +    (save-excursion
> +      (ignore-errors
> +        (funcall electric-indent-function (point-min) (point-max))))))

Both advices should check whether `electric-indent-mode` is enabled in the
current buffer.

> +(defun electric-indent-toggle-indent-actions (enable)
> +  "Enable the actions specified in `electric-indent-actions-alist'."
> +  (when (memq 'yank electric-indent-actions-alist)

`(memq 'yank ...)` is not a correct operation to apply to an "alist", so
either you need to change the name of the var, or you need to change
its format.

> +    (if enable
> +        (advice-add #'yank :around #'electric-indent--yank-advice)
> +      (advice-remove #'yank #'electric-indent--yank-advice)))

Hmm... I'm not super happy we have to use an advice,  In theory we could
use `yank-transform-functions`, but yeah, that would be rather cumbersome.

>  (defun electric-indent-post-self-insert-function ()
>    "Function that `electric-indent-mode' adds to `post-self-insert-hook'.
>  This indents if the hook `electric-indent-functions' returns non-nil,
> @@ -332,7 +399,10 @@ electric-indent-mode
>                    (with-current-buffer buf
>                      (if electric-indent-mode (throw 'found t)))))
>          (remove-hook 'post-self-insert-hook
> -                     #'electric-indent-post-self-insert-function))
> +                     #'electric-indent-post-self-insert-function)
> +        (electric-indent-toggle-indent-actions nil))
> +
> +    (electric-indent-toggle-indent-actions :enable)

I think you can combine the two calls into a single one, passing
`electric-indent-mode` as argument.
Or don't bother passing the argument and check that var in the function.
Or just don't bother with a separate function and move the code right
here so you don't have to duplicate the test.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 16 Sep 2025 02:23:02 GMT) Full text and rfc822 format available.

Message #47 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
 text editors" <bug-gnu-emacs <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Mon, 15 Sep 2025 20:21:52 -0600
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

>> I apologize for the delay; I have made a prototype of the idea, and from
>> what I have tested, it should work well, any comments about this?:
>
> I think the main test whether reindentation can be performed should be:
>
>     (or (memq indent-line-function
>               electric-indent-functions-without-reindent)
>         electric-indent-inhibit)
>
> I suggest you move this out of
> `electric-indent-post-self-insert-function` into its own function so you
> can reuse it without having to copy&paste it.

Yes, originally i had this but, i'm not sure how to let the user to
change it, e.g. how can the user always enable this when the
reindentation done in a Python or C code block is what the user expected
to have? probably the only way is to advice or override that predicate
function.

>> +(defun electric-indent--yank-advice (fn &rest r)
>> +  (let ((p (point)))
>> +    (apply fn r)
>> +    (when (and (memq 'yank electric-indent-actions-alist)
>> +               (not (memq indent-line-function
>> +                          electric-indent-functions-without-reindent))
>> +               (derived-mode-p '(prog-mode))
>> +               (not (= (line-number-at-pos p) (line-number-at-pos (point))))
>> +               (save-excursion (save-match-data (not (nth 8 (syntax-ppss p))))))
>> +      (undo-boundary)
>> +      (ignore-errors (funcall electric-indent-function p (point))))))
>
> `line-number-at-pos-p` takes time proportional to O(pos), so you're
> almost always better off avoiding it.  E.g. it'd be much more efficient
> to compare `p` and (line-beginning-position), which only needs to look
> for the nearest line break.

I'm not sure how to apply it, i used `line-number-at-pos` because i
didn't wanted to use `(> (count-lines p (point)) 1)` (which probably
would give the same problem)

>> +(defun electric-indent-save-hook ()
>> +  (when (and
>> +         ;; Ensure this hook is called interactively
>> +         (memq real-this-command '(save-buffer basic-save-buffer))
>> +         (memq 'before-save electric-indent-actions-alist)
>> +         (not buffer-read-only)
>> +         (derived-mode-p '(prog-mode))
>> +         (not (memq indent-line-function
>> +                    electric-indent-functions-without-reindent)))
>> +    (save-excursion
>> +      (ignore-errors
>> +        (funcall electric-indent-function (point-min) (point-max))))))
>
> Both advices should check whether `electric-indent-mode` is enabled in the
> current buffer.

Thanks, I've added it.

>> +(defun electric-indent-toggle-indent-actions (enable)
>> +  "Enable the actions specified in `electric-indent-actions-alist'."
>> +  (when (memq 'yank electric-indent-actions-alist)
>
> `(memq 'yank ...)` is not a correct operation to apply to an "alist", so
> either you need to change the name of the var, or you need to change
> its format.

I'm not sure what you're suggesting.

>> +    (if enable
>> +        (advice-add #'yank :around #'electric-indent--yank-advice)
>> +      (advice-remove #'yank #'electric-indent--yank-advice)))
>
> Hmm... I'm not super happy we have to use an advice,  In theory we could
> use `yank-transform-functions`, but yeah, that would be rather cumbersome.

I tried to use `yank-transform-functions`, but it doesn't work for this
case.

>>  (defun electric-indent-post-self-insert-function ()
>>    "Function that `electric-indent-mode' adds to `post-self-insert-hook'.
>>  This indents if the hook `electric-indent-functions' returns non-nil,
>> @@ -332,7 +399,10 @@ electric-indent-mode
>>                    (with-current-buffer buf
>>                      (if electric-indent-mode (throw 'found t)))))
>>          (remove-hook 'post-self-insert-hook
>> -                     #'electric-indent-post-self-insert-function))
>> +                     #'electric-indent-post-self-insert-function)
>> +        (electric-indent-toggle-indent-actions nil))
>> +
>> +    (electric-indent-toggle-indent-actions :enable)
>
> I think you can combine the two calls into a single one, passing
> `electric-indent-mode` as argument.

Thanks, I've changed it to this idea.

-- 
- E.G via Gnus and Org.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 16 Sep 2025 02:23:03 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 16 Sep 2025 20:21:02 GMT) Full text and rfc822 format available.

Message #53 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org, "Stefan Monnier via Bug reports for GNU Emacs,
 the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 16 Sep 2025 16:20:33 -0400
>>> I apologize for the delay; I have made a prototype of the idea, and from
>>> what I have tested, it should work well, any comments about this?:
>>
>> I think the main test whether reindentation can be performed should be:
>>
>>     (or (memq indent-line-function
>>               electric-indent-functions-without-reindent)
>>         electric-indent-inhibit)
>>
>> I suggest you move this out of
>> `electric-indent-post-self-insert-function` into its own function so you
>> can reuse it without having to copy&paste it.
>
> Yes, originally i had this but, i'm not sure how to let the user to
> change it, e.g. how can the user always enable this when the
> reindentation done in a Python or C code block is what the user expected
> to have? probably the only way is to advice or override that predicate
> function.

AFAICT the only difference between that and the code you use is the test
of `electric-indent-inhibit`.  CC-mode uses its own electric indentation
code, so CC-mode will just have to wait for that mode to support
this feature.  In the mean time they can use another major mode, like
`c-ts-mode` or `sm-c-mode`.

For Python mode, and other languages that set `electric-indent-inhibit`
to non-nil because *re*indentation can't be done reliably, I think we
don't want to enable "reindent on yank" specifically because we don't
know how to do it reliably.

Maybe we could provide an option that disregards the major mode's
indentation function and instead uses a rigid kind of reindentation
(compare the column of the position where we insert the new text to the
initial indentation of the new text and add/insert the corresponding
number of columns to match).

>>> +(defun electric-indent--yank-advice (fn &rest r)
>>> +  (let ((p (point)))
>>> +    (apply fn r)
>>> +    (when (and (memq 'yank electric-indent-actions-alist)
>>> +               (not (memq indent-line-function
>>> +                          electric-indent-functions-without-reindent))
>>> +               (derived-mode-p '(prog-mode))
>>> +               (not (= (line-number-at-pos p) (line-number-at-pos (point))))
>>> +               (save-excursion (save-match-data (not (nth 8 (syntax-ppss p))))))
>>> +      (undo-boundary)
>>> +      (ignore-errors (funcall electric-indent-function p (point))))))
>>
>> `line-number-at-pos-p` takes time proportional to O(pos), so you're
>> almost always better off avoiding it.  E.g. it'd be much more efficient
>> to compare `p` and (line-beginning-position), which only needs to look
>> for the nearest line break.
>
> I'm not sure how to apply it,

(>= p (line-beginning-position)) should give the same answer as
(= (line-number-at-pos p) (line-number-at-pos (point)))

> i used `line-number-at-pos` because i
> didn't wanted to use `(> (count-lines p (point)) 1)` (which probably
> would give the same problem)

(> (count-lines p (point)) 1) would take time proportional to the size
of the inserted text, which is already better than what you have above.

>>> +(defun electric-indent-toggle-indent-actions (enable)
>>> +  "Enable the actions specified in `electric-indent-actions-alist'."
>>> +  (when (memq 'yank electric-indent-actions-alist)
>>
>> `(memq 'yank ...)` is not a correct operation to apply to an "alist", so
>> either you need to change the name of the var, or you need to change
>> its format.
>
> I'm not sure what you're suggesting.

I'm just saying that you call the var "...-alist" but it is not an
*a*list (which you'd typically lookup with things like `assq` or
`alist-get` rather than `memq`), it's just a list.  So either make it an
alist or change its name.

>>> +    (if enable
>>> +        (advice-add #'yank :around #'electric-indent--yank-advice)
>>> +      (advice-remove #'yank #'electric-indent--yank-advice)))
>>
>> Hmm... I'm not super happy we have to use an advice,  In theory we could
>> use `yank-transform-functions`, but yeah, that would be rather cumbersome.
>
> I tried to use `yank-transform-functions`, but it doesn't work for this
> case.

I think we could make it work, but you'd have to do silly gymnastics
(e.g. insert the text, reindent it, use `buffer-substring` to extract
the result, "un-insert" it, e.g. it using the undo info, and then return
the text extracted with  `buffer-substring`; another approach would be
to use an auxiliary temp buffer where you do the reindent).

OTOH, the rigid reindent I mention above would be doable from
`yank-transform-functions` with much less suffering (but if you have to
dynamically choose between the two reindentation approaches depending
on the major mode, then you don't want to use `yank-transform-functions`
in one and something else in the other, so it doesn't really help).


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 16 Sep 2025 20:22:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Wed, 17 Sep 2025 01:33:01 GMT) Full text and rfc822 format available.

Message #59 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
 text editors" <bug-gnu-emacs <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 16 Sep 2025 19:31:55 -0600
[Message part 1 (text/plain, inline)]
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

>> Yes, originally i had this but, i'm not sure how to let the user to
>> change it, e.g. how can the user always enable this when the
>> reindentation done in a Python or C code block is what the user expected
>> to have? probably the only way is to advice or override that predicate
>> function.
>
> AFAICT the only difference between that and the code you use is the test
> of `electric-indent-inhibit`.  CC-mode uses its own electric indentation
> code, so CC-mode will just have to wait for that mode to support
> this feature.  In the mean time they can use another major mode, like
> `c-ts-mode` or `sm-c-mode`.
>
> For Python mode, and other languages that set `electric-indent-inhibit`
> to non-nil because *re*indentation can't be done reliably, I think we
> don't want to enable "reindent on yank" specifically because we don't
> know how to do it reliably.

Makes sense, I agree.

> Maybe we could provide an option that disregards the major mode's
> indentation function and instead uses a rigid kind of reindentation
> (compare the column of the position where we insert the new text to the
> initial indentation of the new text and add/insert the corresponding
> number of columns to match).

Sounds, complex, i think major modes can provide its own reindentation
function for that.

Another additional way to detect when the reindentation can be done is
if `electric-indent-function` is set to `indent-region` (as shown in the
patch).

3rd-party packages or modes can set `electric-indent-function` to any
other function which can do better reindentation than `indent-region`.

Another alternative is to make `electric-indent-inhibit` can also be a
list, which can specify which reindentation should not be performed,
although I'm not sure about this idea.

>> I'm not sure how to apply it,
>
> (>= p (line-beginning-position)) should give the same answer as
> (= (line-number-at-pos p) (line-number-at-pos (point)))
>
>> i used `line-number-at-pos` because i
>> didn't wanted to use `(> (count-lines p (point)) 1)` (which probably
>> would give the same problem)
>
> (> (count-lines p (point)) 1) would take time proportional to the size
> of the inserted text, which is already better than what you have above.

This does seems to work, I've changed it to a /better/ alternative (i suppose).


>>>> +(defun electric-indent-toggle-indent-actions (enable)
>>>> +  "Enable the actions specified in `electric-indent-actions-alist'."
>>>> +  (when (memq 'yank electric-indent-actions-alist)
>>>
>>> `(memq 'yank ...)` is not a correct operation to apply to an "alist", so
>>> either you need to change the name of the var, or you need to change
>>> its format.
>>
>> I'm not sure what you're suggesting.
>
> I'm just saying that you call the var "...-alist" but it is not an
> *a*list (which you'd typically lookup with things like `assq` or
> `alist-get` rather than `memq`), it's just a list.  So either make it an
> alist or change its name.

Oh i see, I've changed the name.


>>>> +    (if enable
>>>> +        (advice-add #'yank :around #'electric-indent--yank-advice)
>>>> +      (advice-remove #'yank #'electric-indent--yank-advice)))
>>>
>>> Hmm... I'm not super happy we have to use an advice,  In theory we could
>>> use `yank-transform-functions`, but yeah, that would be rather cumbersome.
>>
>> I tried to use `yank-transform-functions`, but it doesn't work for this
>> case.
>
> I think we could make it work, but you'd have to do silly gymnastics
> (e.g. insert the text, reindent it, use `buffer-substring` to extract
> the result, "un-insert" it, e.g. it using the undo info, and then return
> the text extracted with  `buffer-substring`; another approach would be
> to use an auxiliary temp buffer where you do the reindent).
>
> OTOH, the rigid reindent I mention above would be doable from
> `yank-transform-functions` with much less suffering (but if you have to
> dynamically choose between the two reindentation approaches depending
> on the major mode, then you don't want to use `yank-transform-functions`
> in one and something else in the other, so it doesn't really help).

I see, yes this sounds complex, so for now, i will keep the advice until
there is a better alternative (possibly, it could use post-command-hook
instead, but for performance reasons, it would be unnecessary).


[0001-WIP.patch (text/x-patch, inline)]
From 6041532435d409444447e85b40a4ae88cad15bdf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?El=C3=ADas=20Gabriel=20P=C3=A9rez?= <eg642616 <at> gmail.com>
Date: Thu, 11 Sep 2025 19:13:21 -0600
Subject: [PATCH] WIP

* lisp/electric.el (electric-indent-actions-alist)
(electric-indent-function): New user options.
(electric-indent--yank-advice, electric-indent-save-hook): New
functions.
(electric-indent-mode): Rework.
---
 lisp/electric.el | 96 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 91 insertions(+), 5 deletions(-)

diff --git a/lisp/electric.el b/lisp/electric.el
index 39e13e1ca0c..32dc50a4a25 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -192,6 +192,39 @@ electric--after-char-pos
 
 ;;; Electric indentation.
 
+(defcustom electric-indent-actions nil
+  "List of actions to indent.
+
+The valid elements of this list can be:
+ - yank: Indent the yanked text only if point is not in a string or
+         comment and yanked region is longer than 1 line.
+ - save: Indent the whole buffer before saving it.
+
+The indentation will not work if:
+ - The current buffer is not derived from `prog-mode'.
+ - `indent-line-function' value is member of the functions in
+   `electric-indent-functions-without-reindent'.
+ - `electric-indent-inhibit' is non-nil.
+
+See also `electric-indent-function', for the function to use in these
+indentations."
+  :type '(repeat (choice (const :tag "After yanking" yank)
+                         (const :tag "Before saving" before-save)))
+  :set (lambda (var val)
+         (set-default var val)
+         (when electric-indent-mode
+           (electric-indent-mode -1)
+           (electric-indent-mode +1)))
+  :safe #'listp
+  :version "31.1")
+
+(defcustom electric-indent-function #'indent-region
+  "Function used to indent the actions in `electric-indent-actions'.
+The function must take 2 arguments, which are the buffer beginning and
+end positions."
+  :type 'function
+  :version "31.1")
+
 ;; Autoloading variables is generally undesirable, but major modes
 ;; should usually set this variable by adding elements to the default
 ;; value, which only works well if the variable is preloaded.
@@ -220,6 +253,58 @@ electric-indent-functions-without-reindent
 not try to reindent lines.  It is normally better to make the major
 mode set `electric-indent-inhibit', but this can be used as a workaround.")
 
+(defun electric-indent-should-reindent-p ()
+  "Return t if `electric-indent-mode' should performs reindentation.
+This mainly checks if `indent-line-function' value is not a member of
+`electric-indent-functions-without-reindent' or if
+`electric-indent-inhibit' is nil."
+  (not (or (memq indent-line-function
+                 electric-indent-functions-without-reindent)
+           electric-indent-inhibit)))
+
+(defun electric-indent--yank-advice (fn &rest r)
+  (let ((p (point))
+        (end (line-beginning-position)))
+    (apply fn r)
+    (when (and electric-indent-mode
+               (memq 'yank electric-indent-actions)
+               (if (eq electric-indent-function #'indent-region)
+                   (electric-indent-should-reindent-p)
+                 t)
+               (derived-mode-p '(prog-mode))
+               ;; Ensure yanked text is longer than 1 line
+               (not (= end (line-beginning-position)))
+               ;; And P is not in a comment or string
+               (save-excursion (save-match-data (not (nth 8 (syntax-ppss p))))))
+      (undo-boundary)
+      (ignore-errors (funcall electric-indent-function p (point))))))
+
+(defun electric-indent-save-hook ()
+  (when (and electric-indent-mode
+             ;; Ensure this hook is called interactively
+             (memq real-this-command '(save-buffer basic-save-buffer))
+             (memq 'before-save electric-indent-actions)
+             (not buffer-read-only)
+             (derived-mode-p '(prog-mode))
+             (if (eq electric-indent-function #'indent-region)
+                 (electric-indent-should-reindent-p)
+               t))
+    (save-excursion
+      (ignore-errors
+        (funcall electric-indent-function (point-min) (point-max))))))
+
+(defun electric-indent-toggle-indent-actions (enable)
+  "Enable the actions specified in `electric-indent-actions'."
+  (cond
+   ((memq 'yank electric-indent-actions)
+    (if enable
+        (advice-add #'yank :around #'electric-indent--yank-advice)
+      (advice-remove #'yank #'electric-indent--yank-advice)))
+   ((memq 'before-save electric-indent-actions)
+    (if enable
+        (add-hook 'before-save-hook #'electric-indent-save-hook)
+      (remove-hook 'before-save-hook #'electric-indent-save-hook)))))
+
 (defun electric-indent-post-self-insert-function ()
   "Function that `electric-indent-mode' adds to `post-self-insert-hook'.
 This indents if the hook `electric-indent-functions' returns non-nil,
@@ -258,10 +343,7 @@ electric-indent-post-self-insert-function
           (when at-newline
             (let ((before (copy-marker (1- pos) t)))
               (save-excursion
-                (unless
-                    (or (memq indent-line-function
-                              electric-indent-functions-without-reindent)
-                        electric-indent-inhibit)
+                (when (electric-indent-should-reindent-p)
                   ;; Don't reindent the previous line if the
                   ;; indentation function is not a real one.
                   (goto-char before)
@@ -333,9 +415,13 @@ electric-indent-mode
                     (if electric-indent-mode (throw 'found t)))))
         (remove-hook 'post-self-insert-hook
                      #'electric-indent-post-self-insert-function))
+
     (add-hook 'post-self-insert-hook
               #'electric-indent-post-self-insert-function
-              60)))
+              60))
+
+  ;; Toggle the reindentation on actions
+  (electric-indent-toggle-indent-actions electric-indent-mode))
 
 ;;;###autoload
 (define-minor-mode electric-indent-local-mode
-- 
2.51.0

[Message part 3 (text/plain, inline)]
-- 
- E.G via Gnus and Org.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Wed, 17 Sep 2025 01:33:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Wed, 17 Sep 2025 03:08:02 GMT) Full text and rfc822 format available.

Message #65 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org, "Stefan Monnier via Bug reports for GNU Emacs,
 the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 16 Sep 2025 23:07:07 -0400
>> Maybe we could provide an option that disregards the major mode's
>> indentation function and instead uses a rigid kind of reindentation
>> (compare the column of the position where we insert the new text to the
>> initial indentation of the new text and add/insert the corresponding
>> number of columns to match).
>
> Sounds, complex, i think major modes can provide its own reindentation
> function for that.

No, it's pretty easy: It's not a general reindentation function and is not specific to a major
mode.  It's focusing on the case where you insert a chunk of code which
was already correctly indented, except it's now inserted in another
context so you need to increase or decrease the indentation depth
according to the change in the context's indentation.
(- (current-column) (string-width (leading-space STR))) gives you
the amount of space to add/remove and you just need to pass it to
`indent-rigidly`.
[ The problem I see is not the difficulty but the fact that depending on
  exactly what is yanked, it may end up doing something incorrect,
  e.g. the `leading-space` might be empty and unrelated to the
  original indentation of the yanked code.  ]

> Another additional way to detect when the reindentation can be done is
> if `electric-indent-function` is set to `indent-region` (as shown in
> the patch).

Why would a major mode ever want to set this vat to anything else than
`indent-region`?  IOW, what is the use case for introducing this variable?

Note that a major mode would not want to set it to something based on
`indent-rigidly` since that would not do The Right Thing for the
`before-save-hook` case.

> 3rd-party packages or modes can set `electric-indent-function` to any
> other function which can do better reindentation than `indent-region`.

I think if they have a better function, they typically set
`indent-region-function` accordingly.

> Another alternative is to make `electric-indent-inhibit` can also be a
> list, which can specify which reindentation should not be performed,
> although I'm not sure about this idea.

I'd rather wait to see if there's really a clear need for such
a level of control.  I think we want to focus on automatically
reindenting only when we have a strong reason to believe the users will
usually be happy with the result.

If/when users then come complaining that auto-reindentation doesn't
happen for them in case FOO and BAR, we will take a closer look at those
cases to see how best to handle them.

> This does seems to work, I've changed it to a /better/ alternative (i suppose).

Yes, that works as well, thanks.

> I see, yes this sounds complex, so for now, i will keep the advice until
> there is a better alternative

+1

I think we're getting there.  Just a few more nitpicks below.


        Stefan


> +(defcustom electric-indent-actions nil
> +  "List of actions to indent.
> +
> +The valid elements of this list can be:
> + - yank: Indent the yanked text only if point is not in a string or
> +         comment and yanked region is longer than 1 line.
> + - save: Indent the whole buffer before saving it.
> +
> +The indentation will not work if:
> + - The current buffer is not derived from `prog-mode'.
> + - `indent-line-function' value is member of the functions in
> +   `electric-indent-functions-without-reindent'.
> + - `electric-indent-inhibit' is non-nil.
> +
> +See also `electric-indent-function', for the function to use in these
> +indentations."
> +  :type '(repeat (choice (const :tag "After yanking" yank)
> +                         (const :tag "Before saving" before-save)))
> +  :set (lambda (var val)
> +         (set-default var val)
> +         (when electric-indent-mode
> +           (electric-indent-mode -1)
> +           (electric-indent-mode +1)))
> +  :safe #'listp
> +  :version "31.1")

I think the "will not work if" should describe the conditions in more
conceptual terms rather than by paraphrasing the code.
I'd describe it as "The indentation will not happen when the major mode
is unable to reindent code reliably, such as in buffers where indentation
is significant."

And the `:safe #'listp` seems too permissive.  It should make sure
there's no funny value in it, even if we can't think of any harm such
funny value may cause.  I'd do something like at least as strict as:

    :safe (lambda (x)
            (and (proper-list-p x)
                 (null (seq-filter (lambda (e) (not (symbolp e))) x))))

> +(defcustom electric-indent-function #'indent-region
> +  "Function used to indent the actions in `electric-indent-actions'.
> +The function must take 2 arguments, which are the buffer beginning and
> +end positions."
> +  :type 'function
> +  :version "31.1")

As mentioned above, I have the impression that this is a "YAGNI".

> +(defun electric-indent-should-reindent-p ()

s/should/can/

> +  "Return t if `electric-indent-mode' should performs reindentation.
> +This mainly checks if `indent-line-function' value is not a member of
> +`electric-indent-functions-without-reindent' or if
> +`electric-indent-inhibit' is nil."

Same as above, please describe the intention rather than the way it's
implemented (after all, the code is easy to find when we need it, so
there's no point paraphrasing it).

> +(defun electric-indent--yank-advice (fn &rest r)
> +  (let ((p (point))
> +        (end (line-beginning-position)))
> +    (apply fn r)
> +    (when (and electric-indent-mode
> +               (memq 'yank electric-indent-actions)
> +               (if (eq electric-indent-function #'indent-region)
> +                   (electric-indent-should-reindent-p)
> +                 t)
> +               (derived-mode-p '(prog-mode))

Why check `prog-mode`?  `electric-indent-mode` doesn't have such
a restriction in general and I can't see why we shouldn't reindent when
yanking into non-prog-mode buffers that have a good indentation
function, such as XML or LaTeX buffers.

> +               ;; Ensure yanked text is longer than 1 line
> +               (not (= end (line-beginning-position)))
> +               ;; And P is not in a comment or string
> +               (save-excursion (save-match-data (not (nth 8 (syntax-ppss p))))))

[ I wonder if the syntax-ppss check is a good idea or not.
  Usually `indent-region` should try to be careful not to reindent the
  content of comments and strings, in which case it's better to call
  `indent-region` and let it figure out which parts can and which parts
  can't be reindented.  ]

> +      (undo-boundary)
> +      (ignore-errors (funcall electric-indent-function p (point))))))

I'd use `with-demoted-errors` since it can be helpful for the user to
see the error messages when the indentation function croaks.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Wed, 17 Sep 2025 03:08:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Fri, 19 Sep 2025 00:24:02 GMT) Full text and rfc822 format available.

Message #71 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
 text editors" <bug-gnu-emacs <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Thu, 18 Sep 2025 18:23:17 -0600
[Message part 1 (text/plain, inline)]
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

>>> Maybe we could provide an option that disregards the major mode's
>>> indentation function and instead uses a rigid kind of reindentation
>>> (compare the column of the position where we insert the new text to the
>>> initial indentation of the new text and add/insert the corresponding
>>> number of columns to match).
>>
>> Sounds, complex, i think major modes can provide its own reindentation
>> function for that.
>
> No, it's pretty easy: It's not a general reindentation function and is not specific to a major
> mode.  It's focusing on the case where you insert a chunk of code which
> was already correctly indented, except it's now inserted in another
> context so you need to increase or decrease the indentation depth
> according to the change in the context's indentation.
> (- (current-column) (string-width (leading-space STR))) gives you
> the amount of space to add/remove and you just need to pass it to
> `indent-rigidly`.

I've done something like this, but i'm not sure if this is what you had
in mind.

#+begin_src elisp
(defcustom electric-indent-yank-in-context nil)

(let ((indent-size
       (save-excursion
         (beginning-of-line)
         (skip-chars-forward " \t" (line-end-position)))))

  (if (not electric-indent-yank-in-context)
      (save-excursion
        (with-demoted-errors "Error reindenting: %S"
          (indent-region p (point))))
    (indent-rigidly
       p (point)
       (if (eq (current-bidi-paragraph-direction) 'right-to-left)
           (* indent-size -1) indent-size))))
#+end_src

> [ The problem I see is not the difficulty but the fact that depending on
>   exactly what is yanked, it may end up doing something incorrect,
>   e.g. the `leading-space` might be empty and unrelated to the
>   original indentation of the yanked code.  ]

Yes, these are the problems I see with this idea.

>> Another additional way to detect when the reindentation can be done is
>> if `electric-indent-function` is set to `indent-region` (as shown in
>> the patch).
>
> Why would a major mode ever want to set this vat to anything else than
> `indent-region`?  IOW, what is the use case for introducing this variable?
>
> Note that a major mode would not want to set it to something based on
> `indent-rigidly` since that would not do The Right Thing for the
> `before-save-hook` case.

Fine, I've removed it.


>> Another alternative is to make `electric-indent-inhibit` can also be a
>> list, which can specify which reindentation should not be performed,
>> although I'm not sure about this idea.
>
> I'd rather wait to see if there's really a clear need for such
> a level of control.  I think we want to focus on automatically
> reindenting only when we have a strong reason to believe the users will
> usually be happy with the result.
>
> If/when users then come complaining that auto-reindentation doesn't
> happen for them in case FOO and BAR, we will take a closer look at those
> cases to see how best to handle them.

Makes sense, I agree.

>> +(defcustom electric-indent-actions nil
>> +  "List of actions to indent.
>> +
>> +The valid elements of this list can be:
>> + - yank: Indent the yanked text only if point is not in a string or
>> +         comment and yanked region is longer than 1 line.
>> + - save: Indent the whole buffer before saving it.
>> +
>> +The indentation will not work if:
>> + - The current buffer is not derived from `prog-mode'.
>> + - `indent-line-function' value is member of the functions in
>> +   `electric-indent-functions-without-reindent'.
>> + - `electric-indent-inhibit' is non-nil.
>> +
>> +See also `electric-indent-function', for the function to use in these
>> +indentations."
>> +  :type '(repeat (choice (const :tag "After yanking" yank)
>> +                         (const :tag "Before saving" before-save)))
>> +  :set (lambda (var val)
>> +         (set-default var val)
>> +         (when electric-indent-mode
>> +           (electric-indent-mode -1)
>> +           (electric-indent-mode +1)))
>> +  :safe #'listp
>> +  :version "31.1")
>
> I think the "will not work if" should describe the conditions in more
> conceptual terms rather than by paraphrasing the code.
> I'd describe it as "The indentation will not happen when the major mode
> is unable to reindent code reliably, such as in buffers where indentation
> is significant."

Ok, i've changed it.

>> +  "Return t if `electric-indent-mode' should performs reindentation.
>> +This mainly checks if `indent-line-function' value is not a member of
>> +`electric-indent-functions-without-reindent' or if
>> +`electric-indent-inhibit' is nil."
>
> Same as above, please describe the intention rather than the way it's
> implemented (after all, the code is easy to find when we need it, so
> there's no point paraphrasing it).
>
>> +(defun electric-indent--yank-advice (fn &rest r)
>> +  (let ((p (point))
>> +        (end (line-beginning-position)))
>> +    (apply fn r)
>> +    (when (and electric-indent-mode
>> +               (memq 'yank electric-indent-actions)
>> +               (if (eq electric-indent-function #'indent-region)
>> +                   (electric-indent-should-reindent-p)
>> +                 t)
>> +               (derived-mode-p '(prog-mode))
>
> Why check `prog-mode`?  `electric-indent-mode` doesn't have such
> a restriction in general and I can't see why we shouldn't reindent when
> yanking into non-prog-mode buffers that have a good indentation
> function, such as XML or LaTeX buffers.

I've experiencied that electric-indent (and these features) are not
effective in some modes (such as org, markdown, and probably many more),
I'm not sure if `indent-region` works in e.g. yaml, xml, and like.

Anyways I've removed that line, but I hope there won't be any problems
in the future.

>> +               ;; Ensure yanked text is longer than 1 line
>> +               (not (= end (line-beginning-position)))
>> +               ;; And P is not in a comment or string
>> +               (save-excursion (save-match-data (not (nth 8 (syntax-ppss p))))))
>
> [ I wonder if the syntax-ppss check is a good idea or not.
>   Usually `indent-region` should try to be careful not to reindent the
>   content of comments and strings, in which case it's better to call
>   `indent-region` and let it figure out which parts can and which parts
>   can't be reindented.  ]

I'm not sure if `indent-region` already does this, if so then i'm
removing that line.

>> +      (undo-boundary)
>> +      (ignore-errors (funcall electric-indent-function p (point))))))
>
> I'd use `with-demoted-errors` since it can be helpful for the user to
> see the error messages when the indentation function croaks.

I agree.

[0001-Add-electric-indent-actions-to-reindent.-Bug-79371.patch (text/x-patch, attachment)]
[Message part 3 (text/plain, inline)]
--
- E.G via Gnus and Org.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Fri, 19 Sep 2025 00:24:03 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Sat, 20 Sep 2025 15:53:01 GMT) Full text and rfc822 format available.

Message #77 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org, "Stefan Monnier via Bug reports for GNU Emacs,
 the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Sat, 20 Sep 2025 11:52:39 -0400
> I've done something like this, but i'm not sure if this is what you had
> in mind.
>
> #+begin_src elisp
> (defcustom electric-indent-yank-in-context nil)
>
> (let ((indent-size
>        (save-excursion
>          (beginning-of-line)
>          (skip-chars-forward " \t" (line-end-position)))))
>
>   (if (not electric-indent-yank-in-context)
>       (save-excursion
>         (with-demoted-errors "Error reindenting: %S"
>           (indent-region p (point))))
>     (indent-rigidly
>        p (point)
>        (if (eq (current-bidi-paragraph-direction) 'right-to-left)
>            (* indent-size -1) indent-size))))
> #+end_src

I don't understand what that `indent-size` is trying to compute since it
seems to be measured on the last line of the inserted text (and I don't
understand what bidi has to do with it), but I guess it's more or less
what I meant, which I'd write more like:

    (defun insert-with-rigid-reindent (str)
      (let ((target-indent (current-column))
            (original-indent (string-width
                              (progn (string-match "\\`[ \t]*" str)
                                     (string-match 0 str))))
            (beg (point)))
        (insert str)
        (indent-rigidly beg (point) (- target-indent original-indent))))

>> [ The problem I see is not the difficulty but the fact that depending on
>>   exactly what is yanked, it may end up doing something incorrect,
>>   e.g. the `leading-space` might be empty and unrelated to the
>>   original indentation of the yanked code.  ]
> Yes, these are the problems I see with this idea.

Yeah, to make it work well enough we'd need to get more info both from
the "origin" and the "target" (for the "target", we can kind of get that
info, but for the "origin" it's usually just not available any more).
So I don't think we want to go down that route.

>> Why check `prog-mode`?  `electric-indent-mode` doesn't have such
>> a restriction in general and I can't see why we shouldn't reindent when
>> yanking into non-prog-mode buffers that have a good indentation
>> function, such as XML or LaTeX buffers.
> I've experiencied that electric-indent (and these features) are not
> effective in some modes (such as org, markdown, and probably many more),

What do you mean by "not effective"?   Do you mean that they reindent
lines when you don't want it, or that they don't reindent lines when
you'd want it?

If you find that they reindent lines when you don't want it, then please
report it as a bug.

OTOH, if they don't reindent lines when you'd want it, that doesn't seem
like a good reason to add a check for `prog-mode`.

> I'm not sure if `indent-region` works in e.g. yaml, xml, and like.

[ It definitely works in XML.  It usually doesn't in `yaml-mode` since
  that file format is indentation-sensitive, like Haskell and Python.  ]

If it doesn't work well in a specific mode, then it'll affect
electric-indent in general, so the mode should set
`electric-indent-inhibit`.
[ Tho I see that Dmitry added `yaml-mode` to
  `electric-indent-functions-without-reindent` instead, which is messier
  and discouraged, but well, that was more expedient.  ]

>> [ I wonder if the syntax-ppss check is a good idea or not.
>>   Usually `indent-region` should try to be careful not to reindent the
>>   content of comments and strings, in which case it's better to call
>>   `indent-region` and let it figure out which parts can and which parts
>>   can't be reindented.  ]
> I'm not sure if `indent-region` already does this, if so then i'm
> removing that line.

Depends on the major mode.  It's a "quality of implementation" issue, so
major modes that don't do it should be reported so we can improve them.

The "protocol" to make it work is described in the docstring of
`indent-line-function`:

    If it is called somewhere where it cannot auto-indent, the function
    should return ‘noindent’ to signal that it didn’t.

after which `indent-for-tab-command` and `indent-region` can "do the
right thing".

The patch looks good to me, now, thank you.
If there's no objection, I'll push it to `master` in a few days.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Sat, 20 Sep 2025 15:54:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Sun, 21 Sep 2025 02:52:02 GMT) Full text and rfc822 format available.

Message #83 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
 text editors" <bug-gnu-emacs <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Sat, 20 Sep 2025 20:50:56 -0600
[Message part 1 (text/plain, inline)]
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

>> I've done something like this, but i'm not sure if this is what you had
>> in mind.
>>
>> #+begin_src elisp
>> (defcustom electric-indent-yank-in-context nil)
>>
>> (let ((indent-size
>>        (save-excursion
>>          (beginning-of-line)
>>          (skip-chars-forward " \t" (line-end-position)))))
>>
>>   (if (not electric-indent-yank-in-context)
>>       (save-excursion
>>         (with-demoted-errors "Error reindenting: %S"
>>           (indent-region p (point))))
>>     (indent-rigidly
>>        p (point)
>>        (if (eq (current-bidi-paragraph-direction) 'right-to-left)
>>            (* indent-size -1) indent-size))))
>> #+end_src
>
> I don't understand what that `indent-size` is trying to compute since it
> seems to be measured on the last line of the inserted text

It was supposed to compute it in the first yanked line.

> (and I don't understand what bidi has to do with it),

It was extracted from `indent-rigidly-left`, i suppose if the buffer is
right-to-left, it must do the indentation according to that (Although
I'm not quite sure in which cases this would be useful, Anways I've
removed it.)

> but I guess it's more or less
> what I meant, which I'd write more like:
>
>     (defun insert-with-rigid-reindent (str)
>       (let ((target-indent (current-column))
>             (original-indent (string-width
>                               (progn (string-match "\\`[ \t]*" str)
>                                      (string-match 0 str))))
>             (beg (point)))
>         (insert str)
>         (indent-rigidly beg (point) (- target-indent original-indent))))

Thanks, I've adapted the function to the new patch.

>>> [ The problem I see is not the difficulty but the fact that depending on
>>>   exactly what is yanked, it may end up doing something incorrect,
>>>   e.g. the `leading-space` might be empty and unrelated to the
>>>   original indentation of the yanked code.  ]
>> Yes, these are the problems I see with this idea.
>
> Yeah, to make it work well enough we'd need to get more info both from
> the "origin" and the "target" (for the "target", we can kind of get that
> info, but for the "origin" it's usually just not available any more).
> So I don't think we want to go down that route.

I think it is better to add an additional option to use rigid
reindentation when yanking.

>>> Why check `prog-mode`?  `electric-indent-mode` doesn't have such
>>> a restriction in general and I can't see why we shouldn't reindent when
>>> yanking into non-prog-mode buffers that have a good indentation
>>> function, such as XML or LaTeX buffers.
>> I've experiencied that electric-indent (and these features) are not
>> effective in some modes (such as org, markdown, and probably many more),
>
> What do you mean by "not effective"?   Do you mean that they reindent
> lines when you don't want it, or that they don't reindent lines when
> you'd want it?

The first one; e.g. in Org it reindents the newline where it should not.

> If you find that they reindent lines when you don't want it, then please
> report it as a bug.

Thanks, I'll do it later.

> The patch looks good to me, now, thank you.
> If there's no objection, I'll push it to `master` in a few days.

I've attached an alternative patch at the end of this email, which
includes the optional rigid indentation.

[0001-Add-electric-indent-actions-to-reindent.-Bug-79371.patch (text/x-patch, attachment)]
[Message part 3 (text/plain, inline)]
-- 
- E.G via Gnus and Org.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Sun, 21 Sep 2025 02:52:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Sun, 21 Sep 2025 05:35:01 GMT) Full text and rfc822 format available.

Message #89 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org, monnier <at> iro.umontreal.ca
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the yanked
 text.
Date: Sun, 21 Sep 2025 08:34:36 +0300
> Cc: monnier <at> iro.umontreal.ca
> From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
> Date: Sat, 20 Sep 2025 20:50:56 -0600
> 
> >> #+begin_src elisp
> >> (defcustom electric-indent-yank-in-context nil)
> >>
> >> (let ((indent-size
> >>        (save-excursion
> >>          (beginning-of-line)
> >>          (skip-chars-forward " \t" (line-end-position)))))
> >>
> >>   (if (not electric-indent-yank-in-context)
> >>       (save-excursion
> >>         (with-demoted-errors "Error reindenting: %S"
> >>           (indent-region p (point))))
> >>     (indent-rigidly
> >>        p (point)
> >>        (if (eq (current-bidi-paragraph-direction) 'right-to-left)
> >>            (* indent-size -1) indent-size))))
> >> #+end_src
> >
> > I don't understand what that `indent-size` is trying to compute since it
> > seems to be measured on the last line of the inserted text
> 
> It was supposed to compute it in the first yanked line.
> 
> > (and I don't understand what bidi has to do with it),
> 
> It was extracted from `indent-rigidly-left`, i suppose if the buffer is
> right-to-left, it must do the indentation according to that (Although
> I'm not quite sure in which cases this would be useful, Anways I've
> removed it.)

That's a misunderstanding.  indent-rigidly-left does that because of
the "left" part in its name.  As long as the indentation command has
no "left" or "right" in its name, it shouldn't depend on the paragraph
directionality, because columns in RTL text are counted from right to
left.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Sun, 21 Sep 2025 22:13:02 GMT) Full text and rfc822 format available.

Message #92 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org, monnier <at> iro.umontreal.ca
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Sun, 21 Sep 2025 16:12:23 -0600
Eli Zaretskii <eliz <at> gnu.org> writes:

>> It was extracted from `indent-rigidly-left`, i suppose if the buffer is
>> right-to-left, it must do the indentation according to that (Although
>> I'm not quite sure in which cases this would be useful, Anways I've
>> removed it.)
>
> That's a misunderstanding.  indent-rigidly-left does that because of
> the "left" part in its name.  As long as the indentation command has
> no "left" or "right" in its name, it shouldn't depend on the paragraph
> directionality, because columns in RTL text are counted from right to
> left.

Oh i see, thanks for the explanation.

-- 
- E.G via Gnus and Org.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Tue, 23 Sep 2025 21:08:01 GMT) Full text and rfc822 format available.

Message #95 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Tue, 23 Sep 2025 17:07:10 -0400
>> but I guess it's more or less
>> what I meant, which I'd write more like:
>>
>>     (defun insert-with-rigid-reindent (str)
>>       (let ((target-indent (current-column))
>>             (original-indent (string-width
>>                               (progn (string-match "\\`[ \t]*" str)
>>                                      (string-match 0 str))))
>>             (beg (point)))
>>         (insert str)
>>         (indent-rigidly beg (point) (- target-indent original-indent))))
>
> Thanks, I've adapted the function to the new patch.

I pushed your earlier patch to `master` instead.
I'm not sure a `yank-rigidly` option is the way to go: I have the
impression that it would be better to let the `yank` option fallback to
reindenting rigidly when `indent-region` can't be used as in:

    diff --git a/lisp/electric.el b/lisp/electric.el
    index 6ecdea57d6b..b7ae8cf43b1 100644
    --- a/lisp/electric.el
    +++ b/lisp/electric.el
    @@ -247,19 +247,18 @@ electric-indent-can-reindent-p
                electric-indent-inhibit)))
     
     (defun electric-indent--yank-advice (fn &rest r)
    -  (let ((p (point))
    -        (end (line-beginning-position)))
    +  (let ((p (point)))
         (apply fn r)
         (when (and electric-indent-mode
                    (memq 'yank electric-indent-actions)
    -               (electric-indent-can-reindent-p)
    -               ;; Ensure yanked text is longer than 1 line
    -               (> (point) p)
    -               (not (= end (line-beginning-position))))
    +               ;; We inserted at least one newline.
    +               (< p (line-beginning-position)))
           (undo-boundary)
           (save-excursion
             (with-demoted-errors "Error reindenting: %S"
    -          (indent-region p (point)))))))
    +          (if (electric-indent-can-reindent-p)
    +              (indent-region p (point))
    +            (do-the-reindent-rigidly)))))))
     
     (defun electric-indent-save-hook ()
       (when (and electric-indent-mode

But even this is unsure.
Have you tried your indent rigidly code in practice?
My impression is that it will make things worse at least as often as it
will make it better.  For most of those cases, indenting rigidly could
be a good idea, but I can't see how to automatically figure out in
which direction and by how much the reindentation should take place.
The heuristic I proposed works only in specific cases.  🙁

>> What do you mean by "not effective"?   Do you mean that they reindent
>> lines when you don't want it, or that they don't reindent lines when
>> you'd want it?
> The first one; e.g. in Org it reindents the newline where it should not.

That's odd.  In my tests, such reindentation doesn't happen on Org when
I hit RET.
Are you confusing *re*indentation with plain indentation of new lines
(which electric-indent does unconditionally when you hit RET)?
We consider this case acceptable because the new line, by virtue of
being new, doesn't have a pre-existing indentation, so we *have* to
choose "arbitrarily" an indentation for that line.
When `electric-indent-mode` is off the arbitrary choice is to indent it
to column 0, but there's no reason to presume that's better than to let
`indent-line-function` pick another choice.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Thu, 25 Sep 2025 01:55:02 GMT) Full text and rfc822 format available.

Message #98 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
 text editors" <bug-gnu-emacs <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Wed, 24 Sep 2025 19:53:57 -0600
[Message part 1 (text/plain, inline)]
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

> I pushed your earlier patch to `master` instead.
> I'm not sure a `yank-rigidly` option is the way to go: I have the
> impression that it would be better to let the `yank` option fallback to
> reindenting rigidly when `indent-region` can't be used as in:
>
>     diff --git a/lisp/electric.el b/lisp/electric.el
>     index 6ecdea57d6b..b7ae8cf43b1 100644
>     --- a/lisp/electric.el
>     +++ b/lisp/electric.el
>     @@ -247,19 +247,18 @@ electric-indent-can-reindent-p
>                 electric-indent-inhibit)))
>      
>      (defun electric-indent--yank-advice (fn &rest r)
>     -  (let ((p (point))
>     -        (end (line-beginning-position)))
>     +  (let ((p (point)))
>          (apply fn r)
>          (when (and electric-indent-mode
>                     (memq 'yank electric-indent-actions)
>     -               (electric-indent-can-reindent-p)
>     -               ;; Ensure yanked text is longer than 1 line
>     -               (> (point) p)
>     -               (not (= end (line-beginning-position))))
>     +               ;; We inserted at least one newline.
>     +               (< p (line-beginning-position)))
>            (undo-boundary)
>            (save-excursion
>              (with-demoted-errors "Error reindenting: %S"
>     -          (indent-region p (point)))))))
>     +          (if (electric-indent-can-reindent-p)
>     +              (indent-region p (point))
>     +            (do-the-reindent-rigidly)))))))
>      
>      (defun electric-indent-save-hook ()
>        (when (and electric-indent-mode
>
> But even this is unsure.
> Have you tried your indent rigidly code in practice?
> My impression is that it will make things worse at least as often as it
> will make it better.  For most of those cases, indenting rigidly could
> be a good idea, but I can't see how to automatically figure out in
> which direction and by how much the reindentation should take place.
> The heuristic I proposed works only in specific cases.  🙁

Yes, I've tried my implementation and it worked (at least from what I
tested), but yeah, probably it should be better to wait until this
feature is properly implemented or requested.

>>> What do you mean by "not effective"?   Do you mean that they reindent
>>> lines when you don't want it, or that they don't reindent lines when
>>> you'd want it?
>> The first one; e.g. in Org it reindents the newline where it should not.
>
> That's odd.  In my tests, such reindentation doesn't happen on Org when
> I hit RET.
> Are you confusing *re*indentation with plain indentation of new lines
> (which electric-indent does unconditionally when you hit RET)?
> We consider this case acceptable because the new line, by virtue of
> being new, doesn't have a pre-existing indentation, so we *have* to
> choose "arbitrarily" an indentation for that line.
> When `electric-indent-mode` is off the arbitrary choice is to indent it
> to column 0, but there's no reason to presume that's better than to let
> `indent-line-function` pick another choice.

Uhmm, I thought it was a bug, thanks for the explanation.


Also, I've noticed this changes does not include the change in the NEWS
file (and a little error in the variable docstring), I'm attaching a
patch:

[patch.patch (text/x-patch, attachment)]
[Message part 3 (text/plain, inline)]
I also wonder if it is possible to enable the yanking and save
reindentation locally when `electric-indent-actions` is used in a
dir-locals file, by default this variable is unset, but as far as i
could test, it does not enable the features.

Probably something like this?:

#+begin_src elisp
  :safe (lambda (v)
          (and (proper-list-p v)
               (null (seq-filter (lambda (e) (not (symbolp e)) ) v))
               (when (bound-and-true-p electric-indent-mode)
                 (electric-indent--activate-indent-actions t))))
#+end_src

-- 
- E.G via Gnus and Org.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Thu, 25 Sep 2025 01:57:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Thu, 25 Sep 2025 17:58:02 GMT) Full text and rfc822 format available.

Message #104 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Thu, 25 Sep 2025 13:57:24 -0400
> Also, I've noticed this changes does not include the change in the NEWS
> file (and a little error in the variable docstring), I'm attaching a
> patch:

Thanks, installed.

> I also wonder if it is possible to enable the yanking and save
> reindentation locally when `electric-indent-actions` is used in a
> dir-locals file, by default this variable is unset, but as far as i
> could test, it does not enable the features.
>
> Probably something like this?:
>
> #+begin_src elisp
>   :safe (lambda (v)
>           (and (proper-list-p v)
>                (null (seq-filter (lambda (e) (not (symbolp e)) ) v))
>                (when (bound-and-true-p electric-indent-mode)
>                  (electric-indent--activate-indent-actions t))))
> #+end_src

The safety predicate should be pure, so that would be a really
nasty hack.  Also I don't think it'd work because that predicate is
called before setting the var.  We could likely make it work by delaying
the `electric-indent--activate-indent-actions` to post-command-hook or
a timer or somesuch, but ... yuck!

We could try to come up with a way to make it work, but I wonder if we
really wan to support that.  From where I stand, whether you want to
reindent after yank, just like `electric-indent-mode` itself, is a user
preference, i.e. something that depends on the human rather than the
project on which they're working.  So it doesn't seem to belong to
a `.dir-locals.el`.

For the `before-save`, the argument is admittedly different since it
might be a project-wide convention to always commit fully-reindented
files, so it does make sense in a `.dir-locals.el`.  But if so, it'd
have to be independent from  `electric-indent-mode` since users may want
to disable it.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Sat, 27 Sep 2025 01:18:01 GMT) Full text and rfc822 format available.

Message #107 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Elijah Gabe Pérez <eg642616 <at> gmail.com>
To: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
 text editors" <bug-gnu-emacs <at> gnu.org>
Cc: 79371 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Fri, 26 Sep 2025 19:17:31 -0600
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

>> I also wonder if it is possible to enable the yanking and save
>> reindentation locally when `electric-indent-actions` is used in a
>> dir-locals file, by default this variable is unset, but as far as i
>> could test, it does not enable the features.
>>
>> Probably something like this?:
>>
>> #+begin_src elisp
>>   :safe (lambda (v)
>>           (and (proper-list-p v)
>>                (null (seq-filter (lambda (e) (not (symbolp e)) ) v))
>>                (when (bound-and-true-p electric-indent-mode)
>>                  (electric-indent--activate-indent-actions t))))
>> #+end_src
> For the `before-save`, the argument is admittedly different since it
> might be a project-wide convention to always commit fully-reindented
> files, so it does make sense in a `.dir-locals.el`.  But if so, it'd
> have to be independent from  `electric-indent-mode` since users may want
> to disable it.

An alternative i see is to always enable the before-save-hook (and
probably the yank advice) when electric-indent is enabled, since the var
is unset by default it will not have any effect.

--
- E.G via Gnus and Org.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Sat, 27 Sep 2025 01:20:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79371; Package emacs. (Mon, 29 Sep 2025 15:12:02 GMT) Full text and rfc822 format available.

Message #113 received at 79371 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Elijah Gabe Pérez <eg642616 <at> gmail.com>
Cc: 79371 <at> debbugs.gnu.org
Subject: Re: bug#79371: [PATCH] Make yank-in-context also can indent the
 yanked text.
Date: Mon, 29 Sep 2025 11:11:38 -0400
>> For the `before-save`, the argument is admittedly different since it
>> might be a project-wide convention to always commit fully-reindented
>> files, so it does make sense in a `.dir-locals.el`.  But if so, it'd
>> have to be independent from  `electric-indent-mode` since users may want
>> to disable it.
> An alternative i see is to always enable the before-save-hook (and
> probably the yank advice) when electric-indent is enabled, since the var
> is unset by default it will not have any effect.

It would still make the dir-local `electric-indent-actions` setting
ineffective for those users who disable electric-indent, so it
presumably wouldn't have the intended effect.


        Stefan





This bug report was last modified 36 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.