Skip to content

Fix jump_backwards behaviour when jumplist is at capacity - #10968

Merged
pascalkuthe merged 9 commits into
helix-editor:masterfrom
thomasschafer:tschafer-fix-jump_backward
Jun 18, 2024
Merged

Fix jump_backwards behaviour when jumplist is at capacity#10968
pascalkuthe merged 9 commits into
helix-editor:masterfrom
thomasschafer:tschafer-fix-jump_backward

Conversation

@thomasschafer

@thomasschafer thomasschafer commented Jun 15, 2024

Copy link
Copy Markdown
Contributor

This PR resolves some issues with the jumplist when the capacity is reached. In particular:

  • Decrements the current position in the jumplist if elements are removed from the front: if an element in the jumplist shifts backwards then the index pointing to that element should shift backwards with it.
  • Checks whether the previous position in the jumplist is the position that the cursor is currently on: if so, move another step back in the jumplist, as otherwise the cursor stays in the same place and nothing happens.

Fixes #10967.

@thomasschafer
thomasschafer force-pushed the tschafer-fix-jump_backward branch from 2285936 to 12f8df1 Compare June 15, 2024 15:42
@thomasschafer

Copy link
Copy Markdown
Contributor Author

Realised that tests are failing - away from my laptop but will fix when I can

@the-mikedavis the-mikedavis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for opening this up! I've seen this bug before but couldn't figure out how to reproduce the behavior.

As you note in a comment in backwards, the issue is that we're using current as a sort of pointer and when we pop items from the front, the index of our "current" item changes. The fix for this I believe is smaller than what you have at the moment here: in backward we can make current mut and subtract the number of items we will remove in push (self.jumps.len() - JUMP_LIST_CAPACITY + 1) in the if self.current == self.jumps.len() block.

@the-mikedavis the-mikedavis added C-bug Category: This is a bug A-command Area: Commands labels Jun 15, 2024
@thomasschafer

thomasschafer commented Jun 15, 2024

Copy link
Copy Markdown
Contributor Author

Thanks for opening this up! I've seen this bug before but couldn't figure out how to reproduce the behavior.

As you note in a comment in backwards, the issue is that we're using current as a sort of pointer and when we pop items from the front, the index of our "current" item changes. The fix for this I believe is smaller than what you have at the moment here: in backward we can make current mut and subtract the number of items we will remove in push (self.jumps.len() - JUMP_LIST_CAPACITY + 1) in the if self.current == self.jumps.len() block.

Thank you for taking a look!

Is it not preferable to update current in push, rather than backwards, as that ensures that any other uses of push also ensure that current is valid? I can't see why we'd want to use push while allowing elements to be popped from the front of the jump list and not also keep current in sync.

Also, I know that the prev_jump == &cur_jump is a slightly different issue, but I still think it's worth fixing in this PR for the rare occasion where the cursor is already on the last jump position, to avoid jump_backward doing nothing in that case - unless you disagree?

@thomasschafer
thomasschafer force-pushed the tschafer-fix-jump_backward branch from 8f57e9c to 381660c Compare June 15, 2024 17:57
@the-mikedavis

Copy link
Copy Markdown
Member

push can modify self.current as it currently does on master but it can't automatically adjust the current binding in backward. I mean the current binding in the if let Some here:

if let Some(current) = self.current.checked_sub(count) {

The current changes to push actually do not change the behavior. Decrementing self.current while popping elements isn't necessary because self.current isn't read anywhere between the popping and assignment of self.current = self.jumps.len(). And moving that assignment to the end of the block also doesn't have an effect because self.jumps.truncate(self.current) implies that self.current then equals self.jumps.len()

@thomasschafer

Copy link
Copy Markdown
Contributor Author

push can modify self.current as it currently does on master but it can't automatically adjust the current binding in backward. I mean the current binding in the if let Some here:

if let Some(current) = self.current.checked_sub(count) {

The current changes to push actually do not change the behavior. Decrementing self.current while popping elements isn't necessary because self.current isn't read anywhere between the popping and assignment of self.current = self.jumps.len(). And moving that assignment to the end of the block also doesn't have an effect because self.jumps.truncate(self.current) implies that self.current then equals self.jumps.len()

Ah I see, you're right - thanks for explaining. I've removed the changes from push. I've also updated backward in line with your comment here with a slight modification: I felt uneasy about performing the subtraction in backward to try and determine how many elements had been popped from the front in push, so I've updated push to return the number of elements removed from the front and backward now subtracts those from current, as per your comment. Hopefully this is okay but happy to make changes if not!

@thomasschafer
thomasschafer force-pushed the tschafer-fix-jump_backward branch from 1fe288e to f2721f2 Compare June 15, 2024 19:19
@thomasschafer
thomasschafer force-pushed the tschafer-fix-jump_backward branch from f2721f2 to e3b9c1f Compare June 15, 2024 20:28
Comment thread helix-view/src/view.rs Outdated
Comment thread helix-view/src/view.rs Outdated
Comment thread helix-view/src/view.rs Outdated
@pascalkuthe
pascalkuthe merged commit 668f123 into helix-editor:master Jun 18, 2024
smortime pushed a commit to smortime/helix that referenced this pull request Jul 10, 2024
…or#10968)

* Fix jump_backwards behaviour when jumplist is at capacity

* Decrement self.current while popping from front

* Fix issue with conflicting updates to self.current

* Realised that truncate is intentional

* Use saturating_sub when decrementing current

* Fix naming of previous jump, and remove unneeded comment change

* Remove unnecessary changes in push

* Return num elements removed from front, and use in backward method

* Hide num_removed from public interface and tidy up jump location check
mxxntype pushed a commit to mxxntype/helix that referenced this pull request Aug 14, 2024
…or#10968)

* Fix jump_backwards behaviour when jumplist is at capacity

* Decrement self.current while popping from front

* Fix issue with conflicting updates to self.current

* Realised that truncate is intentional

* Use saturating_sub when decrementing current

* Fix naming of previous jump, and remove unneeded comment change

* Remove unnecessary changes in push

* Return num elements removed from front, and use in backward method

* Hide num_removed from public interface and tidy up jump location check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-command Area: Commands C-bug Category: This is a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

jump_backward requires two presses when capacity is reached

3 participants