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

git-changebar: Add the possibility to undo hunk at cursor position #531

Merged
merged 8 commits into from Aug 19, 2017

Conversation

techee
Copy link
Member

@techee techee commented Feb 19, 2017

The patch adds a new keybinding action for undoing hunks. When cursor is
placed at a line with a diff and the keybinding is invoked, the
corresponding hunk is undone.

To get the previous contents at the given position, a temporary Scintilla
instance is used into which the previous state of the document is loaded
and the corresponding text from the previous state of the document is
extracted. This temporary Scintilla object is then destroyed.

@techee techee requested a review from b4n February 19, 2017 17:01
@techee
Copy link
Member Author

techee commented Feb 19, 2017

This is something I wanted for a long time so here's an attempt to implement it.

Note that I based the patch mostly on what I have seen in git-changebar (basically combined the "goto next hunk" code and get_widget_for_buf_range()) without knowing libgit or the majority of the plugin code. So if anyone asks why I did something certain way, the answer is "because I didn't know what I was doing" :-).

@techee
Copy link
Member Author

techee commented Feb 23, 2017

I've added a fix for #532.

@frlan frlan added this to the 1.31.0 milestone Mar 5, 2017
@frlan
Copy link
Member

frlan commented May 1, 2017

I've got it inside local branch and it seems to work fine. But did not some kind of extended code review or something.

Copy link
Member

@b4n b4n left a comment

Choose a reason for hiding this comment

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

I didn't yet do any kind of proper review (not even tested it yet), but sounds reasonable and the feature seems great :)

I'll try and make a proper review in the upcoming days if I can get enough Internet (yeah, not sure I'll make it through without any, crossing fingers :]).

@@ -1044,13 +1053,13 @@ goto_next_hunk_diff_hunk_cb (const git_diff_delta *delta,
if (data->next_line >= 0) {
return 1;
} else if (data->line < hunk->new_start - 1) {
data->next_line = hunk->new_start - 1;
data->next_line = (hunk->new_start == 0) ? 0 : hunk->new_start - 1;
Copy link
Member

Choose a reason for hiding this comment

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

maybe it'd be worth creating a function/macro for that, as it's repeated 3 times? Not sure of a name for it yet though :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe something like

data->next_line = REMOVED_MARKER_POS (hunk->new_start);

?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah OK sounds good

old_pos_end = sci_get_position_from_line (old_sci, old_start + old_lines);
old_range = sci_get_contents_range (old_sci, old_pos_start, old_pos_end);

sci_insert_text(doc->editor->sci, pos, old_range);
Copy link
Member

Choose a reason for hiding this comment

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

style: space before the open parenthesis

@techee
Copy link
Member Author

techee commented May 10, 2017

@b4n Thanks for having a look at this (I want this feature badly!!!). Please let me know if you have some other suggestions, I'll address them together with your above comments.

Copy link
Member

@b4n b4n left a comment

Choose a reason for hiding this comment

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

Looks mostly good, but I'd rather not rely on where the caret is. Not relying on it makes it fairly easy to add a right-click version of the feature (I have an unpolished version locally that work just fine, yay :)).

Otherwise, it seems to work great 👍

}

if (data->old_lines > 0) {
gint line = sci_get_current_line (sci);
Copy link
Member

Choose a reason for hiding this comment

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

Why current line? couldn't it be gint pos = sci_get_position_from_line (sci, data->new_start - 1); instead? I don't get exactly how you can be sure it's the current line, and not relying on that would allow for that to be used on non-current lines too (like adding an entry to the editor menu).

And I don't get why caring about position of the delete marker as we don't use them here, do we?

Copy link
Member

Choose a reason for hiding this comment

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

hum, OK, the marker comment is a bit misleading, but indeed there's the same problem here, so we indeed need a similar fix, sorry. But still not relying on the current line should be easy enough and better IMO.

Copy link
Member Author

Choose a reason for hiding this comment

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

gint pos = sci_get_position_from_line (sci, data->new_start - 1); returns the pos on the previous line which is wrong when undoing deleted-only diff - I need to advance it to the next line if new_lines == 0 (see a few lines below). I could probably get the length of the line and add it to pos in this case.

Just to understand - what does scintilla return from sci_get_current_line() when you right-click somewhere - I'd expect it doesn't change the current line, does it?

Copy link
Member

Choose a reason for hiding this comment

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

gint pos = sci_get_position_from_line (sci, data->new_start - 1); returns the pos on the previous line which is wrong when undoing deleted-only diff - I need to advance it to the next line if new_lines == 0 (see a few lines below).

Indeed, I was confused at first. I suggest 00e3745

Just to understand - what does scintilla return from sci_get_current_line() when you right-click somewhere - I'd expect it doesn't change the current line, does it?

No it doesn't, but Geany gives us the position of the right click, and other features in the menu work at the click position, not the caret position. So for the feature I want to do the same: propose undoing the diff at the right click position, not at the caret one. See 0c4415d for a proposal.

data->old_lines);
}

sci_scroll_caret(sci);
Copy link
Member

Choose a reason for hiding this comment

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

Similarly, what about

      scintilla_send_message (sci, SCI_SCROLLRANGE,
                              sci_get_position_from_line (sci, data->new_start + data->old_lines - 1),
                              sci_get_position_from_line (sci, data->new_start - 1));

Copy link
Member

Choose a reason for hiding this comment

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

It's actually similarly wrong, but there's a fixed version in 00e3745

@techee
Copy link
Member Author

techee commented May 13, 2017

Looks mostly good, but I'd rather not rely on where the caret is. Not relying on it makes it fairly easy to add a right-click version of the feature

Maybe I misunderstand how you meant it but how does the right-click version know at which position to undo when it don't use the caret position? I'd expect the caret is somewhere where you want to undo, you right-click (at which point I expect Scintilla still preserves the caret position but I may be wrong) and select undo from the menu. But you still need the caret position, not?

@b4n
Copy link
Member

b4n commented May 14, 2017

Maybe I misunderstand how you meant it but how does the right-click version know at which position to undo when it don't use the caret position? I'd expect the caret is somewhere where you want to undo, you right-click (at which point I expect Scintilla still preserves the caret position but I may be wrong) and select undo from the menu. But you still need the caret position, not?

As said above, no: the right click undo would undo at the position of the click, which indeed doesn't move the caret, which means we need be able to undo arbitrary hunks regardless of the caret position.

@b4n
Copy link
Member

b4n commented May 14, 2017

A series of proposed fixes and changes: https://github.com/b4n/geany-plugins/commits/git-changebar/techee/sidebar_undo/review
Feel free to reuse, squash, comment on, bash, nitpick, throw away or anything else you could thunk of :)

@b4n
Copy link
Member

b4n commented May 16, 2017

BTW, you maybe could add a line to the README about the new feature :)

techee and others added 8 commits May 22, 2017 15:06
The patch adds a new keybinding action for undoing hunks. When cursor is
placed at a line with a diff and the keybinding is invoked, the
corresponding hunk is undone.

To get the previous contents at the given position, a temporary Scintilla
instance is used into which the previous state of the document is loaded
and the corresponding text from the previous state of the document is
extracted. This temporary Scintilla object is then destroyed.
Diffs for removed lines are shown on previous line - this works well except
the first line where there's no previous line so nothing is displayed.

This patch adds corresponding tests to the code and shows diffs for the
first line on the first line. It also fixes related problems with going
to previous/next hunk and undoing hunks.
Don't rely on the caret position when altering the document to undo a
hunk, and use the hunk position itself instead.

This allows to use the same mechanism anywhere in the document
regardless of the caret position, making the code more easily reusable.
…eted hunk

For deleted hunk, move cursor at the end of the undone text. This
behavior corresponds to what normal undo does - when undoing deletion,
cursor is also placed at the end of the newly inserted text.

Also change primary position for SCI_SCROLLRANGE in this case so it becomes
the cursor position.
@techee
Copy link
Member Author

techee commented May 22, 2017

Thanks @b4n - I've finally had time to have a look at it. Your patches look good (I reviewed only the patches dealing with the undo stuff and didn't spend much time looking at the menu feature but it seems to work fine). I've just squashed your whitespace fix to the original commit and left the rest as separate commits. I've also updated README and added the REMOVED_MARKER_POS() macro.

The last patch is one more minor modification - it updates the cursor position when undoing deleted hunk - originally the cursor was placed at the position where the hunk started but I think it should be placed at the end of the undone deletion which corresponds more closely to what normal undo does. The question is what to do with modified hunks (i.e. those with both old lines and new lines). I still find it more natural to place the cursor behind them so it behaves the same way as delete-only hunk.

@frlan
Copy link
Member

frlan commented Jun 22, 2017

@b4n @techee Merging it for 1.31?

@techee
Copy link
Member Author

techee commented Jun 23, 2017

@b4n @techee Merging it for 1.31?

I'm fine with it, depends on Colomban.

@frlan frlan added this to the 1.32.0 milestone Jun 25, 2017
@frlan frlan removed this from the 1.31.0 milestone Jun 25, 2017
@frlan
Copy link
Member

frlan commented Jun 25, 2017

postponed to 1.32

@vfaronov
Copy link
Contributor

I have been running with this change for some time. Very useful, thank you @techee and @b4n. No problems so far (I have only a few small repos though).

@frlan
Copy link
Member

frlan commented Aug 19, 2017

As I'm also running this patchset for some time now I'm going to merge it. Let us more beta test it on master.

@frlan frlan merged commit 59118d8 into geany:master Aug 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants