Skip to content
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

[undo-] prevent undo of command that created sheet #2244

Merged
merged 4 commits into from
Feb 13, 2024

Conversation

midichef
Copy link
Contributor

The undo command currently incorrectly attempts to undo the command that created the sheet.

To reproduce:
vd sample_data/sample.tsv then g" and undo-last. This will empty the sheet out.

The cause is an assumption in the undo code, that the first line of the command log is for the command that created the sheet:

# don't allow undo of first command on a sheet, which is always the command that created the sheet.

Because set-option commands are carried into new sheets, that assumption is no longer true. (since 1925808)

This PR skips over the first sequence of command log rows for the global sheet, where cmdlogrow.sheet == 'global'. I think these commands are all for set-option, so we could instead match longname: cmdlogrow.longname == "set-option". But I think excluding the first commands from the global sheet, is more robust to future changes.

visidata/undo.py Outdated
@@ -37,14 +37,23 @@ def undo(vd, sheet):
if not vd.options.undo:
vd.fail("options.undo not enabled")

# don't allow undo of first command on a sheet, which is always the command that created the sheet.
for i, cmdlogrow in enumerate(sheet.cmdlog_sheet.rows[:0:-1]):
cmdlogrows = sheet.cmdlog_sheet.rows
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

cmdlogrows = itertools.filterfalse(lambda r: r.longname == 'set-option')
for i, cmdlogrow in enumerate(reversed(cmdlogrows[1:])):

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I've incorporated this change.
Right now cmdlog.py only adds 'set-option' commands before the sheet creation command, but never after it. So filterfalse() is fine as long as that is true.
Is there any situation where user-created code might cause the insertion of 'set-option' after sheet creation? If that ever happens, row_idx will not be correct and the undo log would be corrupted.

row_idx = len(sheet.cmdlog_sheet.rows)-1 - i

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If an option gets set by the user, it should be added as a set-option command on the source sheet cmdlog. (I think this doesn't happen currently, which would mean that in-session option changes aren't recorded properly for replay.) So your original code might have been better, though I can't see it after the force push. Sorry to make an incorrect suggestion if that's the case!

Also what's the difference between this islice and [1:]?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I shouldn't have force pushed to overwrite the original code, then! That code skipped just the first sequential set-option commands. But it did it by calculating indices. It is shorter and cleaner to translate it to iterators as you suggested. So I've done that now with 43ad4ae.

As for the islice, it was needed because the generator from filterfalse didn't allow subscripts. But next() is all we actually need, so I got rid of the islice.

@anjakefala anjakefala added this to the 3.0.1 milestone Jan 13, 2024
@anjakefala
Copy link
Collaborator

@midichef If you get the modification in by tomorrow, this can be part of v3.0.2 =)

@anjakefala anjakefala modified the milestones: 3.0.1, 3.0.2 Jan 14, 2024
@midichef
Copy link
Contributor Author

midichef commented Feb 5, 2024

@anjakefala okay this is ready to go, if it gets approved. Can you squash it into 1 commit before doing the final merge? Or I can do this myself. I don't quite know the usual protocol, but I do like to keep the commit history clean.

visidata/undo.py Outdated Show resolved Hide resolved
@anjakefala
Copy link
Collaborator

okay this is ready to go, if it gets approved. Can you squash it into 1 commit before doing the final merge? Or I can do this myself. I don't quite know the usual protocol, but I do like to keep the commit history clean.

For sure! I can make a habit of cleaning your commits before merging.

@anjakefala anjakefala merged commit 9a41b26 into saulpw:develop Feb 13, 2024
13 checks passed
@midichef midichef deleted the undo_sheet_creation branch March 23, 2024 01:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants