* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer @ 2022-01-16 5:13 Andrew Hyatt 2022-01-16 9:22 ` Eli Zaretskii 2022-02-16 17:41 ` Anders Johansson 0 siblings, 2 replies; 18+ messages in thread From: Andrew Hyatt @ 2022-01-16 5:13 UTC (permalink / raw) To: 53294 [-- Attachment #1: text-scale-patch --] [-- Type: application/octet-stream, Size: 590 bytes --] diff --git a/lisp/face-remap.el b/lisp/face-remap.el index 00560f9d2e..df35d88933 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -134,6 +134,11 @@ face-remap-add-relative (let ((faces (cdr entry))) (if (symbolp faces) (setq faces (list faces))) + (setq face-remapping-alist + (mapcar (lambda (kv) + (if (eq (car kv) face) + (cons face (face-remap-order (cons specs faces))) + kv)) face-remapping-alist)) (setcdr entry (face-remap-order (cons specs faces))) ;; Force redisplay of this buffer. (force-mode-line-update)) [-- Attachment #2: Type: text/plain, Size: 2185 bytes --] Hi all, I noticed a bug recently where if I scale up fonts in an org capture buffer, it affects the original buffer, which keeps getting bigger and bigger every time org-capture is run. However, you don't need org to reproduce this. Here's a quick way to reproduce, which works with emacs -Q: (require 'face-remap) (defun ash/big-font () "Creates a font that is big enough for about 20 lines of text." (interactive) (let ((text-scale-mode-amount (/ (frame-height) 20))) (text-scale-mode 1))) (defun ash/reproduce-with-indirect-buffer () (interactive) (let ((buf (get-buffer-create "*Orig buffer*"))) (set-buffer buf) (variable-pitch-mode 1) ;; same way org mode creates indirect buffer (set-buffer (make-indirect-buffer buf "*Indirect buffer*" 'clone)) (ash/big-font-new) (kill-buffer (current-buffer)))) Running ash/reproduce-with-indirect-buffer will increase the indirect buffer in size each time. If you look at face-remapping-alist, it's clear that the original buffer's value is being altered by the indirect buffer. I traced this down to the setcdr in face-remove-add-relative, which is incorrectly alterting a buffer local variable, by setting parts of a variable in a way that will affect the original variable. Evidently making something buffer local doesn't clone it, it just copies the value, and so you can alter the original by operations such as setcdr. Assuming that the fixing how variables becomes buffer local is too much, I've fixed this in face-remap.el. The patch is attached. In GNU Emacs 29.0.50 (build 1, aarch64-apple-darwin21.2.0, NS appkit-2113.20 Version 12.1 (Build 21C52)) of 2021-12-26 built on andrews-mbp.lan Repository revision: 978987f7ad58cd66fe51cefde53ba4771b189aeb Repository branch: master Windowing system distributor 'Apple', version 10.3.2113 System Description: macOS 12.1 Configured using: 'configure --with-native- Configured features: ACL GLIB GNUTLS JSON LCMS2 LIBXML2 MODULES NATIVE_COMP NOTIFY KQUEUE NS PDUMPER PNG RSVG SQLITE3 THREADS TOOLKIT_SCROLL_BARS XIM ZLIB Important settings: value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix ^ permalink raw reply related [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 5:13 bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer Andrew Hyatt @ 2022-01-16 9:22 ` Eli Zaretskii 2022-01-16 14:43 ` Andrew Hyatt 2022-02-16 17:41 ` Anders Johansson 1 sibling, 1 reply; 18+ messages in thread From: Eli Zaretskii @ 2022-01-16 9:22 UTC (permalink / raw) To: Andrew Hyatt; +Cc: 53294 > From: Andrew Hyatt <ahyatt@gmail.com> > Date: Sun, 16 Jan 2022 00:13:26 -0500 > > I noticed a bug recently where if I scale up fonts in an org > capture buffer, it affects the original buffer, which keeps > getting bigger and bigger every time org-capture is run. > > However, you don't need org to reproduce this. Here's a quick way > to reproduce, which works with emacs -Q: > > (require 'face-remap) (defun ash/big-font () > "Creates a font that is big enough for about 20 lines of text." > (interactive) (let ((text-scale-mode-amount (/ (frame-height) > 20))) > (text-scale-mode 1))) > > (defun ash/reproduce-with-indirect-buffer () > (interactive) (let ((buf (get-buffer-create "*Orig buffer*"))) > (set-buffer buf) (variable-pitch-mode 1) ;; same way org mode > creates indirect buffer (set-buffer (make-indirect-buffer buf > "*Indirect buffer*" 'clone)) (ash/big-font-new) (kill-buffer > (current-buffer)))) > > Running ash/reproduce-with-indirect-buffer will increase the > indirect buffer in size each time. If you look at > face-remapping-alist, it's clear that the original buffer's value > is being altered by the indirect buffer. I don't think I understand what I should see and pay attention to with this recipe (and it includes several errors that took me some time to fix, before I could run it), but isn't this because you used non-nil CLONE argument to make-indirect-buffer? ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 9:22 ` Eli Zaretskii @ 2022-01-16 14:43 ` Andrew Hyatt 2022-01-16 15:00 ` Eli Zaretskii 0 siblings, 1 reply; 18+ messages in thread From: Andrew Hyatt @ 2022-01-16 14:43 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 53294 On Sun, Jan 16, 2022 at 11:22 AM Eli Zaretskii <eliz@gnu.org> wrote: >> From: Andrew Hyatt <ahyatt@gmail.com> Date: Sun, 16 Jan 2022 >> 00:13:26 -0500 I noticed a bug recently where if I scale up >> fonts in an org capture buffer, it affects the original >> buffer, which keeps getting bigger and bigger every time >> org-capture is run. However, you don't need org to reproduce >> this. Here's a quick way to reproduce, which works with emacs >> -Q: (require 'face-remap) (defun ash/big-font () >> "Creates a font that is big enough for about 20 lines of >> text." (interactive) (let ((text-scale-mode-amount (/ >> (frame-height) 20))) >> (text-scale-mode 1))) >> >> (defun ash/reproduce-with-indirect-buffer () >> (interactive) (let ((buf (get-buffer-create "*Orig >> buffer*"))) >> (set-buffer buf) (variable-pitch-mode 1) ;; same way org >> mode creates indirect buffer (set-buffer >> (make-indirect-buffer buf "*Indirect buffer*" 'clone)) >> (ash/big-font-new) (kill-buffer (current-buffer)))) >> Running ash/reproduce-with-indirect-buffer will increase the >> indirect buffer in size each time. If you look at >> face-remapping-alist, it's clear that the original buffer's >> value is being altered by the indirect buffer. > > I don't think I understand what I should see and pay attention > to with this recipe (and it includes several errors that took me > some time to fix, before I could run it), but isn't this because > you used non-nil CLONE argument to make-indirect-buffer? Sorry for any errors, I simplified it a bit before I sent it out and perhaps made a few mistakes. What you should see, if you go the *Orig Buffer*, is that the font scale keeps increasing. If you look at the face-remapping-alist of that buffer, it will be growing with duplicate height specs, one for every time you called the ash/reproduce-with-indirect-buffer. Yes, the non-nil CLONE argument is essential to reproduce. But that just means the indirect buffer will inherit the state from the direct buffer. It doesn't imply that changes made to the indirect buffer's state will affect the original buffer, which is what is happening here. ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 14:43 ` Andrew Hyatt @ 2022-01-16 15:00 ` Eli Zaretskii 2022-01-16 15:28 ` Andrew Hyatt 0 siblings, 1 reply; 18+ messages in thread From: Eli Zaretskii @ 2022-01-16 15:00 UTC (permalink / raw) To: Andrew Hyatt, Stefan Monnier; +Cc: 53294 > From: Andrew Hyatt <ahyatt@gmail.com> > Cc: 53294@debbugs.gnu.org > Date: Sun, 16 Jan 2022 09:43:16 -0500 > > Yes, the non-nil CLONE argument is essential to reproduce. But > that just means the indirect buffer will inherit the state from > the direct buffer. It doesn't imply that changes made to the > indirect buffer's state will affect the original buffer, which is > what is happening here. But "inheriting" the state means the indirect buffer gets the copy of the variables of the original buffer, and that is not a deep copy, AFAIU. Stefan, any comments on this issue? ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 15:00 ` Eli Zaretskii @ 2022-01-16 15:28 ` Andrew Hyatt 2022-01-16 15:41 ` Eli Zaretskii 0 siblings, 1 reply; 18+ messages in thread From: Andrew Hyatt @ 2022-01-16 15:28 UTC (permalink / raw) To: Eli Zaretskii, Stefan Monnier; +Cc: 53294 On Sun, Jan 16, 2022 at 05:00 PM Eli Zaretskii <eliz@gnu.org> wrote: >> From: Andrew Hyatt <ahyatt@gmail.com> Cc: 53294@debbugs.gnu.org >> Date: Sun, 16 Jan 2022 09:43:16 -0500 Yes, the non-nil CLONE >> argument is essential to reproduce. But that just means the >> indirect buffer will inherit the state from the direct buffer. >> It doesn't imply that changes made to the indirect buffer's >> state will affect the original buffer, which is what is >> happening here. > > But "inheriting" the state means the indirect buffer gets the > copy of the variables of the original buffer, and that is not a > deep copy, AFAIU. > > Stefan, any comments on this issue? Sorry, I may have been unclear. I'm not disagreeing - what you just said is correct. But, because of that, it's a bug for code to make an indirect buffer, then perform operations on it via setcdr or setf like things, which then will affect the original buffer's variables. Alternatively, it'd perhaps would be a better fix to make the indirect buffer's copy a deep copy instead of the shallow copy it is now, so that these situations don't arise. I don't have a patch for that, though, but could create one if you thought it was a good idea. ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 15:28 ` Andrew Hyatt @ 2022-01-16 15:41 ` Eli Zaretskii 2022-01-16 17:11 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 18+ messages in thread From: Eli Zaretskii @ 2022-01-16 15:41 UTC (permalink / raw) To: Andrew Hyatt; +Cc: 53294, monnier > From: Andrew Hyatt <ahyatt@gmail.com> > Cc: 53294@debbugs.gnu.org > Date: Sun, 16 Jan 2022 10:28:40 -0500 > > > But "inheriting" the state means the indirect buffer gets the > > copy of the variables of the original buffer, and that is not a > > deep copy, AFAIU. > > > > Stefan, any comments on this issue? > > Sorry, I may have been unclear. I'm not disagreeing - what you > just said is correct. But, because of that, it's a bug for code to > make an indirect buffer, then perform operations on it via setcdr > or setf like things, which then will affect the original buffer's > variables. I'm not sure it's a bug. It could be a "feature", not limited to face-remapping-alist, but instead affecting every buffer-local variable that is not a simple scalar. ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 15:41 ` Eli Zaretskii @ 2022-01-16 17:11 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2022-01-16 18:16 ` Eli Zaretskii 0 siblings, 1 reply; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-01-16 17:11 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Andrew Hyatt, 53294 >> > But "inheriting" the state means the indirect buffer gets the >> > copy of the variables of the original buffer, and that is not a >> > deep copy, AFAIU. >> > Stefan, any comments on this issue? >> Sorry, I may have been unclear. I'm not disagreeing - what you >> just said is correct. But, because of that, it's a bug for code to >> make an indirect buffer, then perform operations on it via setcdr >> or setf like things, which then will affect the original buffer's >> variables. > I'm not sure it's a bug. It could be a "feature", not limited to > face-remapping-alist, but instead affecting every buffer-local > variable that is not a simple scalar. `make-indirect-buffer` can't do the right thing, indeed, because different variables need different handling. `clone-buffer` tries to handle these issues by relying on `clone-buffer-hook` to handle the various variables on a case-by-case basis, but `make-indirect-buffer` doesn't come with such a hook. Some ways we can fix this: - In `face-remap.el`, refrain from modifying the `face-remapping-alist` by side-effects (i.e. avoid `delq`, `setcdr`, and friends). - Add a `make-indirect-buffer-hook` and arrange for `face-remap.el` to add a function there that does a deep enough copy of `face-remapping-alist`. - Remember that indirect buffers are an attractive nuisance and should be deprecated (but note that I suspect the same bug affects `clone-buffer` because it doesn't make a deep enough copy of `face-remapping-alist` either). Stefan ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 17:11 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-01-16 18:16 ` Eli Zaretskii 2022-01-16 21:41 ` Andrew Hyatt 2022-01-17 21:47 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 2 replies; 18+ messages in thread From: Eli Zaretskii @ 2022-01-16 18:16 UTC (permalink / raw) To: Stefan Monnier; +Cc: ahyatt, 53294 > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: Andrew Hyatt <ahyatt@gmail.com>, 53294@debbugs.gnu.org > Date: Sun, 16 Jan 2022 12:11:39 -0500 > > Some ways we can fix this: > > - In `face-remap.el`, refrain from modifying the `face-remapping-alist` > by side-effects (i.e. avoid `delq`, `setcdr`, and friends). > > - Add a `make-indirect-buffer-hook` and arrange for `face-remap.el` to > add a function there that does a deep enough copy of > `face-remapping-alist`. > > - Remember that indirect buffers are an attractive nuisance and should > be deprecated (but note that I suspect the same bug affects > `clone-buffer` because it doesn't make a deep enough copy of > `face-remapping-alist` either). The last one tells me we are better with leaving this sleeping dog lie. ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 18:16 ` Eli Zaretskii @ 2022-01-16 21:41 ` Andrew Hyatt 2022-01-17 21:47 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 0 replies; 18+ messages in thread From: Andrew Hyatt @ 2022-01-16 21:41 UTC (permalink / raw) To: Eli Zaretskii, Stefan Monnier; +Cc: 53294 On Sun, Jan 16, 2022 at 08:16 PM Eli Zaretskii <eliz@gnu.org> wrote: >> From: Stefan Monnier <monnier@iro.umontreal.ca> Cc: Andrew >> Hyatt <ahyatt@gmail.com>, 53294@debbugs.gnu.org Date: Sun, 16 >> Jan 2022 12:11:39 -0500 Some ways we can fix this: - In >> `face-remap.el`, refrain from modifying the >> `face-remapping-alist` >> by side-effects (i.e. avoid `delq`, `setcdr`, and friends). >> - Add a `make-indirect-buffer-hook` and arrange for >> `face-remap.el` to >> add a function there that does a deep enough copy of >> `face-remapping-alist`. >> - Remember that indirect buffers are an attractive nuisance >> and should >> be deprecated (but note that I suspect the same bug affects >> `clone-buffer` because it doesn't make a deep enough copy of >> `face-remapping-alist` either). > > The last one tells me we are better with leaving this sleeping > dog lie. I agree the use of indirect buffers is problematic, but this problem actually results in user-visible bugs. Anyone who likes their org-mode buffer to be variable-pitch, and likes their capture buffer to be in a larger font (both pretty reasonable things), will run into this problem. My patch fixes this in a way whose only downside is that it would be less efficient notably when you have a lot of face-remappings. But it's not clear to me that face-remapping-alist ever gets so big or is changed so often that this would be a problem. The only other option is to fix this in org-mode, but they are cloning their indirect buffer presumably so that the capture buffer looks and behaves like the parent buffer, which is reasonable. I'd have to break that, or maybe just add a hack to deep copy face-remapping-alist. Both options seem a bit wrong. ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 18:16 ` Eli Zaretskii 2022-01-16 21:41 ` Andrew Hyatt @ 2022-01-17 21:47 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2022-01-18 2:24 ` Andrew Hyatt 1 sibling, 1 reply; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-01-17 21:47 UTC (permalink / raw) To: Eli Zaretskii; +Cc: ahyatt, 53294 >> - In `face-remap.el`, refrain from modifying the `face-remapping-alist` >> by side-effects (i.e. avoid `delq`, `setcdr`, and friends). >> >> - Add a `make-indirect-buffer-hook` and arrange for `face-remap.el` to >> add a function there that does a deep enough copy of >> `face-remapping-alist`. >> >> - Remember that indirect buffers are an attractive nuisance and should >> be deprecated (but note that I suspect the same bug affects >> `clone-buffer` because it doesn't make a deep enough copy of >> `face-remapping-alist` either). > > The last one tells me we are better with leaving this sleeping dog > lie. Actually, looking back at the code, I see we already have the needed hook (tho called from `clone-indirect-buffer`), so I think the better option is to change `make-indirect-buffer` so it runs `clone-indirect-buffer-hook` (when called with a non-nil `clone` arg) instead of having `clone-indirect-buffer` run it. And then in `face-remap.el` add a function to that hook which copies `face-remapping-alist`. An intermediate option is to change the Org code to use `clone-indirect-buffer` instead of `make-indirect-buffer` (but that still requires the `face-remap.el` addition to the hook). [ Sorry Andrew for not noticing your earlier patch which does something similar to my first suggestion above. ] Andrew, would you be willing to write that patch? Stefan ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-17 21:47 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-01-18 2:24 ` Andrew Hyatt 2022-01-18 2:47 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 18+ messages in thread From: Andrew Hyatt @ 2022-01-18 2:24 UTC (permalink / raw) To: Stefan Monnier, Eli Zaretskii; +Cc: 53294 [-- Attachment #1: Type: text/plain, Size: 2090 bytes --] On Mon, Jan 17, 2022 at 04:47 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote: >>> - In `face-remap.el`, refrain from modifying the >>> `face-remapping-alist` >>> by side-effects (i.e. avoid `delq`, `setcdr`, and friends). >>> - Add a `make-indirect-buffer-hook` and arrange for >>> `face-remap.el` to >>> add a function there that does a deep enough copy of >>> `face-remapping-alist`. >>> - Remember that indirect buffers are an attractive nuisance >>> and should >>> be deprecated (but note that I suspect the same bug affects >>> `clone-buffer` because it doesn't make a deep enough copy of >>> `face-remapping-alist` either). >> >> The last one tells me we are better with leaving this sleeping >> dog lie. > > Actually, looking back at the code, I see we already have the > needed hook (tho called from `clone-indirect-buffer`), so I > think the better option is to change `make-indirect-buffer` so > it runs `clone-indirect-buffer-hook` (when called with a non-nil > `clone` arg) instead of having `clone-indirect-buffer` run it. > And then in `face-remap.el` add a function to that hook which > copies `face-remapping-alist`. > > An intermediate option is to change the Org code to use > `clone-indirect-buffer` instead of `make-indirect-buffer` (but > that still requires the `face-remap.el` addition to the hook). > > [ Sorry Andrew for not noticing your earlier patch which does > something > similar to my first suggestion above. ] > > Andrew, would you be willing to write that patch? > > Stefan That sounds reasonable, I can do that. In fact, I just did this based on your suggestions, and it does work well. The only weird thing is that I had to pull `clone-indirect-buffer-hook' into the c code, because that's where `make-indirect-buffer' is. Let me know if that seems wrong. I've attached the patch, please let me know if there is an issue. I have commit access, so I can just commit it myself after your OK (if so, I'll wait for a week or so to see if Eli has a comment as well before checkin). [-- Attachment #2: text-scale-patch-v2 --] [-- Type: application/octet-stream, Size: 2895 bytes --] diff --git a/lisp/face-remap.el b/lisp/face-remap.el index 00560f9d2e..fc0edb7119 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -70,6 +70,14 @@ internal-lisp-face-attributes :foreground :background :stipple :overline :strike-through :box :font :inherit :fontset :distant-foreground :extend :vector]) +(defun face-attrs--make-indirect-safe () + "Do a deep copy of `face-remapping-alist' to keep the original buffer safe." + (setq-local face-remapping-alist + (copy-tree + (buffer-local-value 'face-remapping-alist (buffer-base-buffer))))) + +(add-hook 'clone-indirect-buffer-hook #'face-attrs--make-indirect-safe) + (defun face-attrs-more-relative-p (attrs1 attrs2) "Return true if ATTRS1 contains a greater number of relative face-attributes than ATTRS2. A face attribute is considered diff --git a/lisp/simple.el b/lisp/simple.el index cbcde9fb8d..3ef9cca249 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -9441,9 +9441,6 @@ function-key-map (defvar clone-buffer-hook nil "Normal hook to run in the new buffer at the end of `clone-buffer'.") -(defvar clone-indirect-buffer-hook nil - "Normal hook to run in the new buffer at the end of `clone-indirect-buffer'.") - (defun clone-process (process &optional newname) "Create a twin copy of PROCESS. If NEWNAME is nil, it defaults to PROCESS' name; diff --git a/src/buffer.c b/src/buffer.c index 10ac91915c..00646f8779 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -912,6 +912,10 @@ DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer, Fset (intern ("buffer-save-without-query"), Qnil); Fset (intern ("buffer-file-number"), Qnil); Fset (intern ("buffer-stale-function"), Qnil); + /* Cloned buffers need extra setup, to do things such as deep + variable copies for list variables that might be mangled due + to destructive operations in the indirect buffer. */ + safe_run_hooks (Qclone_indirect_buffer_hook); set_buffer_internal_1 (old_b); } @@ -5568,6 +5572,9 @@ syms_of_buffer (void) pure_list (Qprotected_field, Qerror)); Fput (Qprotected_field, Qerror_message, build_pure_c_string ("Attempt to modify a protected field")); + + DEFSYM (Qclone_indirect_buffer_hook, "clone-indirect-buffer-hook"); + DEFVAR_PER_BUFFER ("tab-line-format", &BVAR (current_buffer, tab_line_format), @@ -6392,6 +6399,10 @@ Functions (implicitly) running this hook are `get-buffer-create', This is the default. If nil, auto-save file deletion is inhibited. */); delete_auto_save_files = 1; + DEFVAR_LISP ("clone-indirect-buffer-hook", Vclone_indirect_buffer_hook, + doc: /* Normal hook to run in the new buffer at the end of `clone-indirect-buffer'. */); + Vclone_indirect_buffer_hook = Qnil; + defsubr (&Sbuffer_live_p); defsubr (&Sbuffer_list); defsubr (&Sget_buffer); ^ permalink raw reply related [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-18 2:24 ` Andrew Hyatt @ 2022-01-18 2:47 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2022-01-19 2:37 ` Andrew Hyatt 0 siblings, 1 reply; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-01-18 2:47 UTC (permalink / raw) To: Andrew Hyatt; +Cc: Eli Zaretskii, 53294 > That sounds reasonable, I can do that. In fact, I just did this based on > your suggestions, and it does work well. The only weird thing is that I had > to pull `clone-indirect-buffer-hook' into the c code, because that's where > `make-indirect-buffer' is. You could leave the `defvar` in Lisp and only pull the DEFSYM, but yes, you need to pull at least part of it into C. > Let me know if that seems wrong. Nope. > I've attached the patch, please let me know if there is an issue. I have > commit access, so I can just commit it myself after your OK (if so, I'll > wait for a week or so to see if Eli has a comment as well before checkin). Comments below, thanks, Stefan > diff --git a/lisp/face-remap.el b/lisp/face-remap.el > index 00560f9d2e..fc0edb7119 100644 > --- a/lisp/face-remap.el > +++ b/lisp/face-remap.el > @@ -70,6 +70,14 @@ internal-lisp-face-attributes > :foreground :background :stipple :overline :strike-through :box > :font :inherit :fontset :distant-foreground :extend :vector]) > > +(defun face-attrs--make-indirect-safe () > + "Do a deep copy of `face-remapping-alist' to keep the original buffer safe." > + (setq-local face-remapping-alist > + (copy-tree > + (buffer-local-value 'face-remapping-alist (buffer-base-buffer))))) I think `mapcar #'copy-sequence` is slightly more correct than `copy-tree`, and you shouldn't need (buffer-local-value 'face-remapping-alist (buffer-base-buffer)) because that buffer's value should already have been copied to the current buffer. > @@ -912,6 +912,10 @@ DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer, > Fset (intern ("buffer-save-without-query"), Qnil); > Fset (intern ("buffer-file-number"), Qnil); > Fset (intern ("buffer-stale-function"), Qnil); > + /* Cloned buffers need extra setup, to do things such as deep > + variable copies for list variables that might be mangled due > + to destructive operations in the indirect buffer. */ > + safe_run_hooks (Qclone_indirect_buffer_hook); I think you want to use just `run_hook` here because there's no need to catch errors. More importantly, you need to remove the corresponding `run-hook` from `clone-indirect-buffer`. Stefan ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-18 2:47 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-01-19 2:37 ` Andrew Hyatt 2022-01-19 3:42 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 18+ messages in thread From: Andrew Hyatt @ 2022-01-19 2:37 UTC (permalink / raw) To: Stefan Monnier; +Cc: 53294 [-- Attachment #1: Type: text/plain, Size: 2568 bytes --] On Mon, Jan 17, 2022 at 09:47 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote: >> That sounds reasonable, I can do that. In fact, I just did this >> based on your suggestions, and it does work well. The only >> weird thing is that I had to pull `clone-indirect-buffer-hook' >> into the c code, because that's where `make-indirect-buffer' >> is. > > You could leave the `defvar` in Lisp and only pull the DEFSYM, > but yes, you need to pull at least part of it into C. > >> Let me know if that seems wrong. > > Nope. > >> I've attached the patch, please let me know if there is an >> issue. I have commit access, so I can just commit it myself >> after your OK (if so, I'll wait for a week or so to see if Eli >> has a comment as well before checkin). > > Comments below, thanks, > > Stefan > >> diff --git a/lisp/face-remap.el b/lisp/face-remap.el index >> 00560f9d2e..fc0edb7119 100644 --- a/lisp/face-remap.el +++ >> b/lisp/face-remap.el @@ -70,6 +70,14 @@ >> internal-lisp-face-attributes >> :foreground :background :stipple :overline :strike-through >> :box :font :inherit :fontset :distant-foreground :extend >> :vector]) >> >> +(defun face-attrs--make-indirect-safe () + "Do a deep copy of >> `face-remapping-alist' to keep the original buffer safe." + >> (setq-local face-remapping-alist + (copy-tree + >> (buffer-local-value 'face-remapping-alist >> (buffer-base-buffer))))) > > I think `mapcar #'copy-sequence` is slightly more correct than > `copy-tree`, and you shouldn't need (buffer-local-value > 'face-remapping-alist (buffer-base-buffer)) because that > buffer's value should already have been copied to the current > buffer. > >> @@ -912,6 +912,10 @@ DEFUN ("make-indirect-buffer", >> Fmake_indirect_buffer, Smake_indirect_buffer, >> Fset (intern ("buffer-save-without-query"), Qnil); Fset >> (intern ("buffer-file-number"), Qnil); Fset (intern >> ("buffer-stale-function"), Qnil); >> + /* Cloned buffers need extra setup, to do things such as >> deep + variable copies for list variables that might be >> mangled due + to destructive operations in the indirect >> buffer. */ + safe_run_hooks (Qclone_indirect_buffer_hook); > > I think you want to use just `run_hook` here because there's no > need to catch errors. > > More importantly, you need to remove the corresponding > `run-hook` from `clone-indirect-buffer`. > > Stefan Makes sense, thanks for the suggestions. I've included the revised patch. [-- Attachment #2: text-scale-patch-v3 --] [-- Type: application/octet-stream, Size: 3178 bytes --] diff --git a/lisp/face-remap.el b/lisp/face-remap.el index 00560f9d2e..95dffcadd6 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -70,6 +70,13 @@ internal-lisp-face-attributes :foreground :background :stipple :overline :strike-through :box :font :inherit :fontset :distant-foreground :extend :vector]) +(defun face-attrs--make-indirect-safe () + "Deep copy `face-remapping-alist' on cloning for safety." + (setq-local face-remapping-alist + (mapcar #'copy-sequence face-remapping-alist))) + +(add-hook 'clone-indirect-buffer-hook #'face-attrs--make-indirect-safe) + (defun face-attrs-more-relative-p (attrs1 attrs2) "Return true if ATTRS1 contains a greater number of relative face-attributes than ATTRS2. A face attribute is considered diff --git a/lisp/simple.el b/lisp/simple.el index cbcde9fb8d..8d0520d663 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -9441,9 +9441,6 @@ function-key-map (defvar clone-buffer-hook nil "Normal hook to run in the new buffer at the end of `clone-buffer'.") -(defvar clone-indirect-buffer-hook nil - "Normal hook to run in the new buffer at the end of `clone-indirect-buffer'.") - (defun clone-process (process &optional newname) "Create a twin copy of PROCESS. If NEWNAME is nil, it defaults to PROCESS' name; @@ -9596,8 +9593,6 @@ clone-indirect-buffer (setq newname (substring newname 0 (match-beginning 0)))) (let* ((name (generate-new-buffer-name newname)) (buffer (make-indirect-buffer (current-buffer) name t))) - (with-current-buffer buffer - (run-hooks 'clone-indirect-buffer-hook)) (when display-flag (pop-to-buffer buffer nil norecord)) buffer)) diff --git a/src/buffer.c b/src/buffer.c index 10ac91915c..3b17d6c9ce 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -912,6 +912,10 @@ DEFUN ("make-indirect-buffer", Fmake_indirect_buffer, Smake_indirect_buffer, Fset (intern ("buffer-save-without-query"), Qnil); Fset (intern ("buffer-file-number"), Qnil); Fset (intern ("buffer-stale-function"), Qnil); + /* Cloned buffers need extra setup, to do things such as deep + variable copies for list variables that might be mangled due + to destructive operations in the indirect buffer. */ + run_hook (Qclone_indirect_buffer_hook); set_buffer_internal_1 (old_b); } @@ -5569,6 +5573,9 @@ syms_of_buffer (void) Fput (Qprotected_field, Qerror_message, build_pure_c_string ("Attempt to modify a protected field")); + DEFSYM (Qclone_indirect_buffer_hook, "clone-indirect-buffer-hook"); + + DEFVAR_PER_BUFFER ("tab-line-format", &BVAR (current_buffer, tab_line_format), Qnil, @@ -6392,6 +6399,10 @@ Functions (implicitly) running this hook are `get-buffer-create', This is the default. If nil, auto-save file deletion is inhibited. */); delete_auto_save_files = 1; + DEFVAR_LISP ("clone-indirect-buffer-hook", Vclone_indirect_buffer_hook, + doc: /* Normal hook to run in the new buffer at the end of `clone-indirect-buffer'. */); + Vclone_indirect_buffer_hook = Qnil; + defsubr (&Sbuffer_live_p); defsubr (&Sbuffer_list); defsubr (&Sget_buffer); ^ permalink raw reply related [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-19 2:37 ` Andrew Hyatt @ 2022-01-19 3:42 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2022-01-20 13:42 ` Lars Ingebrigtsen 0 siblings, 1 reply; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-01-19 3:42 UTC (permalink / raw) To: Andrew Hyatt; +Cc: Eli Zaretskii, 53294 > Makes sense, thanks for the suggestions. I've included the revised patch. Looks good to me, thanks, Stefan ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-19 3:42 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-01-20 13:42 ` Lars Ingebrigtsen 0 siblings, 0 replies; 18+ messages in thread From: Lars Ingebrigtsen @ 2022-01-20 13:42 UTC (permalink / raw) To: Stefan Monnier; +Cc: Andrew Hyatt, 53294 Stefan Monnier <monnier@iro.umontreal.ca> writes: >> Makes sense, thanks for the suggestions. I've included the revised patch. > > Looks good to me, thanks, So I've pushed the patch to Emacs 29. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-01-16 5:13 bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer Andrew Hyatt 2022-01-16 9:22 ` Eli Zaretskii @ 2022-02-16 17:41 ` Anders Johansson 2022-02-17 11:41 ` Lars Ingebrigtsen 2022-02-17 13:38 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 2 replies; 18+ messages in thread From: Anders Johansson @ 2022-02-16 17:41 UTC (permalink / raw) To: Lars Ingebrigtsen, Stefan Monnier, Andrew Hyatt, 53294, Eli Zaretskii Hi, Stefan wrote: > I think `mapcar #'copy-sequence` is slightly more correct than > `copy-tree`, This gives me "Wrong type argument: listp, mini-modeline-mode-line-active" For a face-remapping-alist that looks like: ((mode-line-active . mini-modeline-mode-line-active) (mode-line-inactive . mini-modeline-mode-line-inactive)) According to my reading of the docstring of face-remapping-alist, this should be allowed, and does work (except for indirect buffers perhaps) face-remap-add-relative would generate: ((mode-line-active mini-modeline-mode-line-active) (mode-line-inactive mini-modeline-mode-line-inactive)) mini-modeline (https://github.com/kiennq/emacs-mini-modeline/) sets face-remapping-alist directly for various reasons. I guess this is not really recommended. But this fix seems to cause problems in an otherwise "correct" use of face-remapping-alist. Best, Anders Johansson ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-02-16 17:41 ` Anders Johansson @ 2022-02-17 11:41 ` Lars Ingebrigtsen 2022-02-17 13:38 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 0 replies; 18+ messages in thread From: Lars Ingebrigtsen @ 2022-02-17 11:41 UTC (permalink / raw) To: Anders Johansson; +Cc: Andrew Hyatt, 53294, Stefan Monnier Anders Johansson <mejlaandersj@gmail.com> writes: > This gives me "Wrong type argument: listp, mini-modeline-mode-line-active" > For a face-remapping-alist that looks like: > ((mode-line-active . mini-modeline-mode-line-active) > (mode-line-inactive . mini-modeline-mode-line-inactive)) Do you have a recipe to reproduce the problem, starting from "emacs -Q"? -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer 2022-02-16 17:41 ` Anders Johansson 2022-02-17 11:41 ` Lars Ingebrigtsen @ 2022-02-17 13:38 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 0 replies; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-02-17 13:38 UTC (permalink / raw) To: Anders Johansson; +Cc: Lars Ingebrigtsen, 53294, Andrew Hyatt, Eli Zaretskii >> I think `mapcar #'copy-sequence` is slightly more correct than >> `copy-tree`, > > This gives me "Wrong type argument: listp, mini-modeline-mode-line-active" > For a face-remapping-alist that looks like: > ((mode-line-active . mini-modeline-mode-line-active) > (mode-line-inactive . mini-modeline-mode-line-inactive)) I pushed a patch to `master` which should fix it. Can you confirm that it fixes it for you? Stefan ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2022-02-17 13:38 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-01-16 5:13 bug#53294: 29.0.50; Indirect font changes incorrectly affecting original buffer Andrew Hyatt 2022-01-16 9:22 ` Eli Zaretskii 2022-01-16 14:43 ` Andrew Hyatt 2022-01-16 15:00 ` Eli Zaretskii 2022-01-16 15:28 ` Andrew Hyatt 2022-01-16 15:41 ` Eli Zaretskii 2022-01-16 17:11 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2022-01-16 18:16 ` Eli Zaretskii 2022-01-16 21:41 ` Andrew Hyatt 2022-01-17 21:47 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2022-01-18 2:24 ` Andrew Hyatt 2022-01-18 2:47 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2022-01-19 2:37 ` Andrew Hyatt 2022-01-19 3:42 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2022-01-20 13:42 ` Lars Ingebrigtsen 2022-02-16 17:41 ` Anders Johansson 2022-02-17 11:41 ` Lars Ingebrigtsen 2022-02-17 13:38 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
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).