-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
vundo saved status: add highlights for saved buffer states #62
Conversation
Looks cool! While I read your PR, have you signed the copyright assignment for Emacs? Because this package is on ELPA and ELPA is part of Emacs, technically you are contributing to Emacs. So you need to sign the assignment which essentially shares your copyright on all of your Emacs contribution with FSF. If you haven't, you can send an email to [email protected] asking for it. Someone will send you the assignment. |
Yes I have, long ago. I added a couple small cleanup tweaks. |
Fantastic! |
I've looked at the code, it's pretty clever! I made some minor stylistic changes to your first commit, and added a commit to fix one corner case I encountered. You can see the commits on branch last-saved-working. The corner case happens when the saved node is on the tip of a branch, try this:
You can read more in the commit message, fortunately the fix is pretty simple. If you are fine with it, I'll merge my minor fix into your first commit and add some commit messages, and push it with my fix commit. (Plus some documentation.) OTOH, I'm hesitant about the "most recently saved" feature. I don't know what many users would feel about vundo quietly adding a hook to after-save-hook and never removing it; plus the "most recently saved" wouldn't be correct before user invoked vundo for the first time in a buffer (adding to a hook globally at load time is way beyond the line IMO); plus it doesn't feel as essential: one can easily tell that the most recently saved state is the saved node that's closes to the current state, or the current state itself. IOW, if it works perfectly and cleanly without adding hooks, I'd happily add it; but in it's current state I'm hesitant. |
Thanks for taking a look. That's a good find RE child vs. "next node" in the mod-list; makes sense in hindsight. Of course it still doesn't fix the problem of "no additional mods" leaving a saved node unmarked.
I figured this might be a bit more to consider ;), which is why I kept the commits separate. I do worry that not marking the last save will lead to non-intuitive results, when you save a state and make no further changes, either at the top of a branch, or having moved "back in time". For example, the recent rebinding of
Right. In that case you get no filled green circle, so it's not misleading at least. I do agree about not adding an after save hook en masse in every buffer, and I can see how some may not like any save-hook at all.
I had one other thought to try; give me a bit to explore it and I'll update this branch incorporating your tweaks. |
OK I merged in your last-saved-working branch, and rolled back the after-save-hook. Instead, as a compromise position, this now saves the timestamp itself (not just a flag) in each node with a So this solves 1/2 of the problem: that the "rightmost" saved state is not always the most recent. You can now clearly see which save is the latest. It also eliminates the after-save-hook entirely. Then I suppose all that's needed is some documentation to make clear that green nodes are those which are "saved and then modified". Nodes which are "saved but never modified" are simply not indicated. Let me know what you think. Feel free to push changes directly to this PR. |
Should we also consider new key binding(s)?
|
I think binding Could you introduce a defcustom that toggle display for saved nodes, and use bold face instead of a solid circle for the latest saved node? Could you track timestamps in More over, is comparing timestamp necessary? The last mode in the mod list which is saved should naturally be the latest save node, right? |
The reason I had compared TS and not index is |
vundo.el
Outdated
(setf (vundo-m-prev-saved-ts (car new-mlist)) mod-timestamp) | ||
(when (time-less-p vundo--latest-saved-ts mod-timestamp) | ||
(setq vundo--latest-saved-ts mod-timestamp)))))) | ||
(when (and mod-timestamp (not pos-only) vundo-highlight-saved-nodes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should check for vundo-highlight-saved-nodes
here. Checking this doesn't bring any advantage. If we don't check it, a) the prev-node-saved-ts
would be always correct, and b) if there user changes vundo-highlight-saved-nodes, we don't need to regenerate the mod list. Also the field can be changed back to a boolean now, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
the field can be changed back to a boolean
I store the TS despite using it as a boolean so we can report on the change time (see changes below to i
). I would personally enjoy seeing a little message like "Saved 32min ago" when I move over a saved node.
Thanks, I added some comments. Also, could you squash all the commits into one and force push it? And for the case when there isn't any modification after the last saved node, you can check whether the original buffer is saved ( |
OK this is a good thought. It's not the last, but the current node that has this logic. For the last node it's probably fine just to mark it last-saved, even though no timestamp has been seen. But an intermediate node will be "ephemeral". But... this spurred a new discovery: Conclusion: checking that the undo-list pointer matches again some prior value (via the mod-hash) doesn't really tell the whole story; the buffer-undo-list must be getting insertions not just pushes to head. So this inserted data is being lost. Any ideas on how to save it? |
This ALSO explain one small issue I have long noticed with vundo: when you navigate to and then save an older buffer state, and then undo/redo away from and back to it, the buffer is no longer marked "unmodified". But if you do the exact same operations with with plain undo/redo, the buffer is marked unmodified. This is in fact the main use of the timestamps:
I had the vague sense that the file was being modified somehow, but I now understand the real reason: vundo has trimmed away and tossed those "loopback timestamps". I think we should figure out how to preserve them. |
One maybe dumb idea: save the timestamp on the node itself, not the next node where it actually occurred. When trimming the useless tail, first process any timestamps among the to-be-trimmed records, and update the TS of the lowest index equivalent node (No. 1 in the image above). I get fuzzy when it comes to efficiency impact, GC issues, etc. This would also (if it worked) make vundo happy, but not plain undo itself, as plain undo expects those "save amidst a series of undos" to be tagged so it can set buffer-modified-p accordingly. |
..this isn't a fix for the lost timestamps issue, just a hack to highlight current node as last-saved if buffer is unmodified. As soon as you visit another node, it loses its "last saved" status. |
a20f57a
to
263b985
Compare
I squashed this PR as-is, with the quasi-fix (mark current node saved if buffer is unmodified). I have what may be a solution, but I think it would be too much for this PR. I'll open a separate issue with my idea (see #66). |
You mean the last-saved highlight is removed as soon as we move to another node? Why? Could you write Why do we need to change Also, please, fix indentation and trailing whitespace before committing. And I'll be happier if all the comments starts with a capital and ends with a period. |
Also, why highlight the late saved node in |
Mostly for symmetry with the highlighting of the current node, and because we are (for now) special casing the current node when it is unmodified. I could make a helper function |
Sorry, missed this.
No, but when you hit return on a different node, then re-enter vundo, the node you navigated to and saved is no longer recognizable as saved, because vundo has trimmed off the timestamp that undo added to indicate this. There is a potential solution though: see #66. This will also help undo correctly mark a saved buffer state as unmodified (no
Sure, done.
Technically we don't; it works identically. I had re-written earlier when it also highlighted the current node with an overlay, and on stripping that part out my version looked cleaner/clearer for the reader. Let me know your preference.
My indentation is always good on this end (lispy enforces that). Do you perhaps use |
I found one other little wibble. I should highlight last saved only once, when drawing. Otherwise you can end up with two different "last saved" highlights as you mouse around. |
I took a break too :-) And please allow me to focus on this PR before dealing with the other ones, this is the most important one, and the other PR's seem to warrant complexity not worth the outcome. Anyway, let's first get this done, and we can look at the rest one-by-one.
I agree that we should fix it, but if the solution is too complex or require some hack, it might not worth it. Let's finish this PR and then look at #66.
Your version is probably cleaner. Still, I'd prefer we don't make stylistic change that doesn't relate to the main change.
Yeah that must be it. I always set
IMO, last saved node is conceptually the same as other saved nodes and should be highlighted in |
No rush at all. I had time to add/fix a few things over the course of last week, so I submitted them together, but did not expect a parallel review. vundo is such a clean and performant tool, the main criteria as bugs are addressed and features considered is keeping it so. Please take your time to get this right.
Understood; reversed.
If we don't implement a fix like #66, this isn't strictly true, since last-saved is a special-casing for But I do take your point. I have moved the latest-saved highlighting to BTW, I'll be traveling and in more sporadic contact over the next couple of weeks, so please don't take slower response as a sign of waning interest. |
One other small point to consider: I find the default last-saved-node=bold face to be insufficiently distinct for my font/size. I am using |
Gah, that's true. My suggestion is to create a new function
I'd prefer we keep it simple by default. If someone comes to complain (I doubt it), we can think of making it more distinct. |
OK done. I used an overlay instead of searching for and moving the text property. The one peculiarity is that saved nodes, unless they were already recognized as saved when the tree was drawn, do not retain their saved status; they go back to being regular nodes. This is "fair" in the sense that (without something like #66) they will never be recognized as having been saved. If we do something to correct that, we could consider "updating" the saved status of a node while the drawn tree is live. |
Thanks! Now, could you squash and force push again, so I can have a look at the patch as a whole? |
We track the index of the last node with a timestamp record in buffer-local variable `vundo--last-saved-idx'. The node prior to the latest timestamp-laden modification is marked specially.
18db1b0
to
4054627
Compare
Anything else in need of attention? |
My bad! I didn't see that you pushed. I'll check it out tomorrow! |
Merged! I made some minor edits here and there (can't resist the urge...). Thanks for your patience. |
This seems to be working fine. Are you planning a new release, or to wait for other feature development? |
Yeah I'll make a release soon. |
I often find myself hitting return to check the "saved" status of a given state along vundo's history. This PR adds highlights to indicate which buffer states have been saved, including a special mark for the most recent.
Details
buffer-undo-list
includes timestamp records like(t 25613 2538 435008 282000)
whenever a given modification alters a buffer which has been created or saved to file. This PR adds a (green) highlight face to those buffer states which were saved, and a solid green overlay for the most recent.Note that the "saved" status inferred from the undo-list timestamps is only visible after that buffer is further modified. So if you go back to some state, save it, and then immediately leave it via vundo navigation, that save is simply not recorded on undo-list. We therefore also save and mark the "most recent saved state" specially. This also has the nice additional benefit of indicating which is the most recent save when you've saved states along several branches in the tree (rightmost is not always most recent!).
This is achieved by saving the (
nil
-trimmed)buffer-undo-list
via anafter-save-hook
in the original buffer. We can then use vundo's nice hash table to map it back to the node [1].One thing to consider is that the
after-save-hook
is only setup aftervundo
is invoked the first time. So the solid green indicator will only show thereafter. I think this isn't such a problem, but the trivialafter-save-hook
could be setup on vundo load or init time instead, so that the last save prior to invoking vundo the first time in a buffer will be correctly indicated.[1] It's slightly more complicated: due to vundo's clever "trimming" of the excess state repetitions from looping undo-lists, we must update the saved
vundo--undo-list-at-last-save
using the master equivalent node'sundo-list
value.