* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. [not found] ` <E1Zbs2z-0000By-Qe@vcs.savannah.gnu.org> @ 2015-09-15 16:57 ` Stefan Monnier 2015-09-17 8:08 ` Phillip Lord 0 siblings, 1 reply; 12+ messages in thread From: Stefan Monnier @ 2015-09-15 16:57 UTC (permalink / raw) To: emacs-devel; +Cc: Phillip Lord Hi Philip, Here are some nitpicks and suggestions on your code. > + if(n){ Please try to reproduce the code layout you see around. (and/or (re)read the GNU Coding Standards which describe the coding style to use). In the above: - Add a space before the open paren. - Please the open brace on its own line. > + // we have a boundary, so check we do not have too many Please capitalize and punctuate your comments. > + if (XCAR (elt) == Qnil) Don't compare Lisp_Objects with == but with "EQ (x, y)" or in this case with "NILP (elt)". While hacking on the C code I recommend you ./configure --enable-checking --enable-check-lisp-object-type which will help you catch those problems and a few others. > + if(NILP (Vundo_buffer_undoably_changed)){ > + Fset (Qundo_buffer_undoably_changed,Qt); > + safe_run_hooks (Qundo_first_undoable_change_hook); > + } Why do you need Vundo_buffer_undoably_changed? Doesn't (car-safe buffer-undo-list) give you the same information? > + doc: /* Normal hook run when a buffer has its first recent undo-able change. Rather than "recent undo-able change", I'd talk about the "first undo record after a boundary". > +This hook will be run with `current-buffer' as the buffer that > +has changed. Recent means since the value of `undo-buffer-undoably-changed' ^^^ Please try and follow the sentence-end-double-space convention. Stefan ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-15 16:57 ` [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries Stefan Monnier @ 2015-09-17 8:08 ` Phillip Lord 2015-09-17 12:53 ` Stefan Monnier 0 siblings, 1 reply; 12+ messages in thread From: Phillip Lord @ 2015-09-17 8:08 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: > Here are some nitpicks and suggestions on your code. > >> + if(n){ > > Please try to reproduce the code layout you see around. > >> + // we have a boundary, so check we do not have too many > > Please capitalize and punctuate your comments. > >> + if (XCAR (elt) == Qnil) > > Don't compare Lisp_Objects with == but with "EQ (x, y)" or in this case > with "NILP (elt)". While hacking on the C code I recommend you > > ./configure --enable-checking > (and/or (re)read the GNU Coding Standards which describe the coding > style to use). > > In the above: > - Add a space before the open paren. > - Please the open brace on its own line. --enable-check-lisp-object-type > > which will help you catch those problems and a few others. All those should be fixed now. > >> + if(NILP (Vundo_buffer_undoably_changed)){ >> + Fset (Qundo_buffer_undoably_changed,Qt); >> + safe_run_hooks (Qundo_first_undoable_change_hook); >> + } > > Why do you need Vundo_buffer_undoably_changed? > Doesn't (car-safe buffer-undo-list) give you the same information? No. The point is that this can be reset when ever I choose, and so it may well occur *not* after a boundary. Still your question tells me that my name is not very good. "first-recent-change" hook might be better, and "buffer-recently-changed", perhaps. You should be able to see how this all fits together now. Part of my purpose is that the meaning and semantics of "recent" are now in the hands of the lisp developer, since they can reset "buffer-unably-changed" as they want, which will result in a new call to the hook. I have chosen not to add a "undoable-change" hook, because I didn't need it. The first change hook calls rarely, so the performance issues with handling this change in lisp are, I think, unimportant. >> + doc: /* Normal hook run when a buffer has its first recent undo-able change. > > Rather than "recent undo-able change", I'd talk about the "first undo > record after a boundary". I would have, iff it did this. >> +This hook will be run with `current-buffer' as the buffer that >> +has changed. Recent means since the value of `undo-buffer-undoably-changed' > ^^^ > Please try and follow the sentence-end-double-space convention. Fixed now, hopefully. Phil ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-17 8:08 ` Phillip Lord @ 2015-09-17 12:53 ` Stefan Monnier 2015-09-17 15:04 ` Phillip Lord 0 siblings, 1 reply; 12+ messages in thread From: Stefan Monnier @ 2015-09-17 12:53 UTC (permalink / raw) To: Phillip Lord; +Cc: emacs-devel >>> + if(NILP (Vundo_buffer_undoably_changed)){ >>> + Fset (Qundo_buffer_undoably_changed,Qt); >>> + safe_run_hooks (Qundo_first_undoable_change_hook); >>> + } >> Why do you need Vundo_buffer_undoably_changed? >> Doesn't (car-safe buffer-undo-list) give you the same information? > No. The point is that this can be reset when ever I choose, and so it > may well occur *not* after a boundary. But why would you want to set it not after a boundary? > hands of the lisp developer, since they can reset > "buffer-unably-changed" as they want, which will result in a new call > to the hook. When is this needed/useful? > I have chosen not to add a "undoable-change" hook, because I didn't need > it. The first change hook calls rarely, so the performance issues with > handling this change in lisp are, I think, unimportant. Agreed. Stefan ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-17 12:53 ` Stefan Monnier @ 2015-09-17 15:04 ` Phillip Lord 2015-09-18 20:26 ` Stefan Monnier 0 siblings, 1 reply; 12+ messages in thread From: Phillip Lord @ 2015-09-17 15:04 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >>>> + if(NILP (Vundo_buffer_undoably_changed)){ >>>> + Fset (Qundo_buffer_undoably_changed,Qt); >>>> + safe_run_hooks (Qundo_first_undoable_change_hook); >>>> + } >>> Why do you need Vundo_buffer_undoably_changed? >>> Doesn't (car-safe buffer-undo-list) give you the same information? >> No. The point is that this can be reset when ever I choose, and so it >> may well occur *not* after a boundary. > > But why would you want to set it not after a boundary? Because I am using it to provide a backdrop, default, automatically add a boundary heuristic. Waiting for a boundary to be added defeats the point. >> hands of the lisp developer, since they can reset >> "buffer-unably-changed" as they want, which will result in a new call >> to the hook. > > When is this needed/useful? When you want to store a list of all the buffers which have had undoable changes recently. In this case, I am using this to work out which buffers may need boundary. That's the point. Also, it kicks off the timer which checks all buffers in this list to see if any of them need a boundary. Having it in lisp, I don't think you would need it. But you might need it NOT to happen. The old heuristic of "add an undo if the any other buffer has been written" caused my problems with lentic. This heuristic will break sometime, somewhere (it's in the nature of heuristics). If it is in lisp, it can be prevented, fixed or changed without having to change the Emacs C layer and on a per buffer basis. >> I have chosen not to add a "undoable-change" hook, because I didn't need >> it. The first change hook calls rarely, so the performance issues with >> handling this change in lisp are, I think, unimportant. > > Agreed. Phil ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-17 15:04 ` Phillip Lord @ 2015-09-18 20:26 ` Stefan Monnier 2015-09-22 10:45 ` Phillip Lord 0 siblings, 1 reply; 12+ messages in thread From: Stefan Monnier @ 2015-09-18 20:26 UTC (permalink / raw) To: Phillip Lord; +Cc: emacs-devel > Because I am using it to provide a backdrop, default, automatically add > a boundary heuristic. Waiting for a boundary to be added defeats the point. I think we're misunderstanding each other. What I'm suggesting is to replace: if(NILP (Vundo_buffer_undoably_changed)){ Fset (Qundo_buffer_undoably_changed,Qt); safe_run_hooks (Qundo_first_undoable_change_hook); } with if (NILP (CAR (BVAR (current_buffer, undo_list))) safe_run_hooks (Qundo_first_undoable_change_hook); and do it right before we add something to the undo-list (so the test of undo_list indeed tells us if this is the first new change pushed since the last boundary). It should give us the same behavior but without the need for that variable. Stefan ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-18 20:26 ` Stefan Monnier @ 2015-09-22 10:45 ` Phillip Lord 2015-09-22 12:49 ` Stefan Monnier 0 siblings, 1 reply; 12+ messages in thread From: Phillip Lord @ 2015-09-22 10:45 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> Because I am using it to provide a backdrop, default, automatically add >> a boundary heuristic. Waiting for a boundary to be added defeats the point. > > I think we're misunderstanding each other. > > What I'm suggesting is to replace: > > if(NILP (Vundo_buffer_undoably_changed)){ > Fset (Qundo_buffer_undoably_changed,Qt); > safe_run_hooks (Qundo_first_undoable_change_hook); > } > > with > > if (NILP (CAR (BVAR (current_buffer, undo_list))) > safe_run_hooks (Qundo_first_undoable_change_hook); > > and do it right before we add something to the undo-list (so the test of > undo_list indeed tells us if this is the first new change pushed since > the last boundary). It should give us the same behavior but without the > need for that variable. Because, that triggers the hook only after a boundary. With "undo-buffer-undoably-changed", the hook is triggered after undo-buffer-undoably-changed is set to nil which may or may not relate to the addition of a boundary. And actually, currently it doesn't. Anyway, my code is current safe but doesn't work (I didn't realise that the GC buffer compaction normally leaves the first element in the buffer-undo-list), so I need to fix that which is going to take a couple of days. Hopefully, it will all make sense once it's finished! Phil ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-22 10:45 ` Phillip Lord @ 2015-09-22 12:49 ` Stefan Monnier 2015-09-22 21:41 ` Phillip Lord 0 siblings, 1 reply; 12+ messages in thread From: Stefan Monnier @ 2015-09-22 12:49 UTC (permalink / raw) To: Phillip Lord; +Cc: emacs-devel >> and do it right before we add something to the undo-list (so the test of >> undo_list indeed tells us if this is the first new change pushed since >> the last boundary). It should give us the same behavior but without the >> need for that variable. > Because, that triggers the hook only after a boundary. With > "undo-buffer-undoably-changed", the hook is triggered after > undo-buffer-undoably-changed is set to nil which may or may not relate > to the addition of a boundary. And actually, currently it doesn't. So the question becomes: why doesn't it? Stefan ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-22 12:49 ` Stefan Monnier @ 2015-09-22 21:41 ` Phillip Lord 2015-09-23 1:23 ` Stefan Monnier 0 siblings, 1 reply; 12+ messages in thread From: Phillip Lord @ 2015-09-22 21:41 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >>> and do it right before we add something to the undo-list (so the test of >>> undo_list indeed tells us if this is the first new change pushed since >>> the last boundary). It should give us the same behavior but without the >>> need for that variable. >> Because, that triggers the hook only after a boundary. With >> "undo-buffer-undoably-changed", the hook is triggered after >> undo-buffer-undoably-changed is set to nil which may or may not relate >> to the addition of a boundary. And actually, currently it doesn't. > > So the question becomes: why doesn't it? Okay. So, I'll recap, and then explain the logic that I am trying to implement. I've removed the behaviour from undo.c which calls undo-boundary in a buffer whenever a change has happened in any other buffer because it breaks my use case (and others using post-command-hook). This removes a default which ensures that an undo-boundary were inserted in long-running processes periodically, so avoiding the "undo-outer-limit" situation which largely happens in buggy situations (or when a user has done something really big). So, the logic I am trying to implement (or think I have!) is: - record all buffers which have had undo-able changes in them as we go - every ten seconds check the size of the undo list, and iff it is bigger than undo-limit, and has less than 2 boundaries, add one at the start. We need 2 boundaries because the undo-list compact always leaves upto the first boundary. In reality, I have made two optimisations which make life slightly more complex. - The timer actually runs 10 seconds only after the first undoable change in any buffer, since the last time we checked (i.e. it will run once in an idle emacs). - I have not added a "undoable-change-hook" into lisp space because it will get called a lot. Rather, we have "first-undoable-change" which is called only if "undo-buffer-undoably-changed" is nil. The timer resets the buffer-local values of this to nil when it runs. I've pushed some more changes and will test further tomorrow. It's starting to behave as I expected now (my C was broken amoung other things -- initializing local variables! What's that all about?). I need to rename "undo-buffer-undoably-changed" to "-recently-changed" I think. Just to repeat everything that others have said, your patience and kindness at dealing with dumb questions is rather humbling. Good luck to you! Phil ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-22 21:41 ` Phillip Lord @ 2015-09-23 1:23 ` Stefan Monnier 2015-09-23 8:39 ` Phillip Lord 0 siblings, 1 reply; 12+ messages in thread From: Stefan Monnier @ 2015-09-23 1:23 UTC (permalink / raw) To: Phillip Lord; +Cc: emacs-devel > Okay. So, I'll recap, and then explain the logic that I am trying to > implement. So, IIUC this undo-buffer-undoably-changed is meant to distinguish "new change since boundary" from "new change since last timer run"). OK, so we were indeed miscommunicating. But I get the impression that you didn't pay attention to another part of the logic that we need: the part that pushes a boundary at the end of a command. Currently this is done in the C code and is applied only to the current buffer, but we should change this so it is applied to all buffers that were modified during the last command. > - every ten seconds check the size of the undo list, and iff it is > bigger than undo-limit, and has less than 2 boundaries, add one at the > start. Why not just unconditionally add a boundary (i.e. regardless of the undo list size)? That would make it more useful (because more predictable and avoid too large undo steps), and would remove the need for undo-buffer-undoably-changed. Stefan ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-23 1:23 ` Stefan Monnier @ 2015-09-23 8:39 ` Phillip Lord 2015-09-23 13:44 ` Stefan Monnier 0 siblings, 1 reply; 12+ messages in thread From: Phillip Lord @ 2015-09-23 8:39 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> Okay. So, I'll recap, and then explain the logic that I am trying to >> implement. > > So, IIUC this undo-buffer-undoably-changed is meant to distinguish "new > change since boundary" from "new change since last timer run"). Not sure "distinguish" is correct. Yes, it implements the "new change since last timer run" logic. I am not using "new change since boundary" (which as you say can be determined by looking at buffer-undo-list). > OK, so we were indeed miscommunicating. > > But I get the impression that you didn't pay attention to another part > of the logic that we need: the part that pushes a boundary at the end of > a command. Currently this is done in the C code and is applied only to > the current buffer, but we should change this so it is applied to all > buffers that were modified during the last command. Hmmm, indeed, no I have not done that. I can add this. Does this not obviate the need for the timer. A long running process buffer in an otherwise idle emacs would be a counter example, perhaps? >> - every ten seconds check the size of the undo list, and iff it is >> bigger than undo-limit, and has less than 2 boundaries, add one at the >> start. > > Why not just unconditionally add a boundary (i.e. regardless of the undo > list size)? That would make it more useful (because more predictable > and avoid too large undo steps) I am not so sure about predictable. The issue here is that the timer runs 10 seconds after any change at all. So, for a change in a individual buffer, it could be at any time (10 seconds or less) after an undoable-change. But it's easy to make the change. My thought was simply to leave the undo-list as untouched as much as possible. > and would remove the need for undo-buffer-undoably-changed. Unfortunately not! I am using this to enable the "first change" functionality. I have to know which buffers have had a *recent* undoable change *or* I have to signal all undoable changes. I could remove this variable and use a list instead. In fact, that list actually exists (undo-undoably-change-buffers). Equally, I could remove that list, and filter all buffers for those where undo-buffer-undoably-changed is t. Probably I should do at least the latter since it's simpler, and cycling through all buffers at most every 10 seconds is not going to be a high cost operation. Phil ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-23 8:39 ` Phillip Lord @ 2015-09-23 13:44 ` Stefan Monnier 2015-09-28 19:37 ` Phillip Lord 0 siblings, 1 reply; 12+ messages in thread From: Stefan Monnier @ 2015-09-23 13:44 UTC (permalink / raw) To: Phillip Lord; +Cc: emacs-devel >> But I get the impression that you didn't pay attention to another part >> of the logic that we need: the part that pushes a boundary at the end of >> a command. Currently this is done in the C code and is applied only to >> the current buffer, but we should change this so it is applied to all >> buffers that were modified during the last command. > Hmmm, indeed, no I have not done that. I can add this. To me, this is the most important part that relates to your original problem. > Does this not obviate the need for the timer. Not more than the current "push boundary when modifying another buffer". > A long running process buffer in an otherwise idle Emacs would be > a counter example, perhaps? That's right. > But it's easy to make the change. My thought was simply to leave the > undo-list as untouched as much as possible. Since it would only apply to changes made outside of commands, i.e. changes from process filters and timers, I don't think "leave the undo-list as untouched as much as possible" is desirable. The fact that we currently never push a boundary (except when some other buffer happens to be modified) is just an accident. >> and would remove the need for undo-buffer-undoably-changed. > Unfortunately not! I meant in the C code. The C code would only need to trigger the Elisp code when a change is made in a buffer which was previously "at an undo boundary". Of course, the Elisp code will then want to remember those buffers "in need of a boundary" somehow (probably via a list like undo-undoably-change-buffers). Stefan ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries. 2015-09-23 13:44 ` Stefan Monnier @ 2015-09-28 19:37 ` Phillip Lord 0 siblings, 0 replies; 12+ messages in thread From: Phillip Lord @ 2015-09-28 19:37 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >>> But I get the impression that you didn't pay attention to another part >>> of the logic that we need: the part that pushes a boundary at the end of >>> a command. Currently this is done in the C code and is applied only to >>> the current buffer, but we should change this so it is applied to all >>> buffers that were modified during the last command. >> Hmmm, indeed, no I have not done that. I can add this. > > To me, this is the most important part that relates to your original problem. > >> Does this not obviate the need for the timer. > > Not more than the current "push boundary when modifying another buffer". > >> A long running process buffer in an otherwise idle Emacs would be >> a counter example, perhaps? > > That's right. > >> But it's easy to make the change. My thought was simply to leave the >> undo-list as untouched as much as possible. > > Since it would only apply to changes made outside of commands, > i.e. changes from process filters and timers, I don't think "leave the > undo-list as untouched as much as possible" is desirable. The fact that > we currently never push a boundary (except when some other buffer > happens to be modified) is just an accident. > >>> and would remove the need for undo-buffer-undoably-changed. >> Unfortunately not! > > I meant in the C code. The C code would only need to trigger the Elisp > code when a change is made in a buffer which was previously "at an undo > boundary". Of course, the Elisp code will then want to remember those > buffers "in need of a boundary" somehow (probably via a list like > undo-undoably-change-buffers). Okay this is, I believe, done now. It's a good deal simpler than it was, which has to be a positive thing. I am still not entirely convinced -- I think that the "default" undo-boundary behaviour should be to do as little as possible, but the logic is implemented in lisp now, so it can be over-ridden more straight-forwardly if needed. It would also be possible to add a buffer-local variable `undo-no-auto-boundary' to switch this behaviour off, as opposed to changing global state, but adding that seems like overkill at the moment. I've put some ad-hoc logging in; the code runs post-command and on a timer and mostly silently, so it's hard to test it in actual use in any other way. Obviously, I plan to remove that afterwards. Comments welcome. Phil ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2015-09-28 19:37 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <20150915152129.671.61929@vcs.savannah.gnu.org> [not found] ` <E1Zbs2z-0000By-Qe@vcs.savannah.gnu.org> 2015-09-15 16:57 ` [Emacs-diffs] fix/no-undo-boundary-on-secondary-buffer-change c7a6601 1/5: undo-size can count number of boundaries Stefan Monnier 2015-09-17 8:08 ` Phillip Lord 2015-09-17 12:53 ` Stefan Monnier 2015-09-17 15:04 ` Phillip Lord 2015-09-18 20:26 ` Stefan Monnier 2015-09-22 10:45 ` Phillip Lord 2015-09-22 12:49 ` Stefan Monnier 2015-09-22 21:41 ` Phillip Lord 2015-09-23 1:23 ` Stefan Monnier 2015-09-23 8:39 ` Phillip Lord 2015-09-23 13:44 ` Stefan Monnier 2015-09-28 19:37 ` Phillip Lord
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).