Skip to content

Conversation

@siame
Copy link

@siame siame commented Nov 4, 2025

Addressing #22546, we want git permalinks to be aware of the current changes within the buffer.

This change calculates how many lines have been added/deleted between the start and end of the selection and uses those values to offset the selection.

This is done within Editor::get_permalink_to_line so that it can be passed to any git_store.

Example:

image

Where this selections permalink would previously return L3-L9, it now returns L2-L7.

Release Notes:

  • git: make permalinks aware of current diffs

Closes #22546


This is my first PR into the zed repository so very happy for any feedback on how I've implemented this. Thanks!

Addressing zed-industries#22546, we want git permalinks to be aware of the current
changes within the buffer.

This change calculates how many lines have been added/deleted between the
start and end of the selection and uses those values to offset the
selection.

This is done within Editor::get_permalink_to_line so that it can be
passed to any git_store.
@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Nov 4, 2025
@maxdeviant maxdeviant changed the title git: make permalinks aware of current diffs git: Make permalinks aware of current diffs Nov 4, 2025
@cole-miller
Copy link
Member

Thanks for tackling this! From reading the code, there are a couple of things that need to change:

  • copy permalink to line supports multibuffers, but right now the code to adjust the line range for diff hunks won't work in that situation--it'll iterate over diff hunks in the multibuffer, which may come from buffers unrelated to the one where the selection is.
  • The handling of deleted and modified hunks is not right. For these hunks, the adjustment to make depends on whether the hunks are expanded or not (because expanding and collapsing hunks affects the row_range of MultiBufferDiffHunk, but it shouldn't affect the line range we use for the permalink)

Here is an approach to this feature that I think should avoid these problems:

  • We can still call range_to_buffer_ranges and take the first/last range. This gives us a selection in terms of usize offsets in a single BufferSnapshot, and from here on we shouldn't need to use the original MultiBufferSnapshot at all.
  • Then we need to perform the diff hunk adjustment on that usize buffer range. I think we can do this efficiently (i.e. without iterating over all the diff hunks before the selection) by making some minor changes to the code in the buffer_diff crate and using a sum tree Cursor.

This is probably easier to work through live, would you like to pair on it? Link to book a time (I'll be covering the time slots on this Friday): https://cal.com/esther-trapadoux-zed/30min

@siame
Copy link
Author

siame commented Nov 5, 2025

Thanks for the comments @cole-miller, I've booked in some time to pair on this, looking forward to it.

@siame
Copy link
Author

siame commented Nov 10, 2025

@cole-miller I've pushed up changes to recalculate this using offsets rather than with row ranges.

I've not got to the buffer_diff Cursor changes yet, but I'm currently having an issue with these calculations which are causing the end_row_in_base_buffer to be off by one. I'm able to fix by changing the calculation to:

let end_row_in_base_buffer = buffer_diff_snapshot
    .base_text()
    // off by one
    .offset_to_point((range.end as isize + delta.end - 1) as usize) // additional -1 here
    .row;

I thought this was to do with the range.end maybe being a Bias::Right Anchor grabbing one too many characters in the selection, but it's an Offset, so that's not quite it.

Would appreciate any insight into any issues you can see here.

Thanks!

@siame siame force-pushed the git-permalink-hunk-aware branch from b8ae95d to 33dc85c Compare November 11, 2025 13:26
@cole-miller
Copy link
Member

@siame Thanks for the progress report! I haven't had the chance to run the code and investigate, but if the start value is what you expect and the end value isn't, and you're testing this a selection that covers entire lines, it might just be that the selection includes the trailing newline of the last line? You could confirm by looking at whether the end of the selection looks like Point::new(row + 1, 0) where row is the row you're expecting to see.

@siame siame force-pushed the git-permalink-hunk-aware branch from 33dc85c to d0ecdd1 Compare November 12, 2025 14:31
@siame
Copy link
Author

siame commented Nov 15, 2025

Thanks for the input @cole-miller, the ranges of the selection are as expected, but I think I've got to the bottom of the issue.

In calculating the delta, we're adding the initial size and subtracting the changed size. I added a cmp::min to cap the changed_size to the end of the selection:

let changed_size =
    (cmp::min(buffer_range.end, range.end) as isize) - buffer_range.start as isize;

This is so that we only consider the diff until the end of the selection, as any more than that would be unnecessary.

However, we're not doing the same for the initial_size, as this is a Range<Offset>, and doesn't map to the current BufferSnapshot the same way:

let initial_size = hunk.diff_base_byte_range.end as isize
    - hunk.diff_base_byte_range.start as isize;

There is the function hunk.diff_base_byte_range.to_anchors, however this takes a MultiBufferSnapshot, so I'm not sure if these Anchors will be comparable to the current Selection's.

Without scaling the diff_base_byte_range the same way we're scaling the buffer_range, I'm unable to get an accurate line count when calculating the delta. Is there any way to map the initial size to anchors for the BufferSnapshot we're using? Then we can should be able to calculate the delta accordingly. Thanks!

@cole-miller
Copy link
Member

Hey @siame--thanks for the update. It seems like it might be a bit more natural to do this using a SumTree cursor like we talked about--would you like to pair on that sometime this week? https://cal.com/cole-miller-zed/30min

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copy Permalink (GitHub, etc) should better handle modified code

2 participants