mirror of
https://github.com/zed-industries/zed.git
synced 2024-10-26 00:19:46 +00:00
Improve deleted hunk blocks' behavior (#11340)
* clear their selections on focus lost * allow reverting diff hunks when the caret is inside of the deleted hunk diff editor block Release Notes: - N/A
This commit is contained in:
parent
e69e25c171
commit
cd03e473c8
1 changed files with 70 additions and 73 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::ops::Range;
|
||||
use std::{ops::Range, sync::Arc};
|
||||
|
||||
use collections::{hash_map, HashMap, HashSet};
|
||||
use git::diff::{DiffHunk, DiffHunkStatus};
|
||||
|
@ -14,7 +14,8 @@ use util::{debug_panic, RangeExt};
|
|||
use crate::{
|
||||
git::{diff_hunk_to_display, DisplayDiffHunk},
|
||||
hunks_for_selections, BlockDisposition, BlockId, BlockProperties, BlockStyle, DiffRowHighlight,
|
||||
Editor, ExpandAllHunkDiffs, RangeToAnchorExt, ToDisplayPoint, ToggleHunkDiff,
|
||||
Editor, ExpandAllHunkDiffs, RangeToAnchorExt, RevertSelectedHunks, ToDisplayPoint,
|
||||
ToggleHunkDiff,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -215,35 +216,29 @@ impl Editor {
|
|||
let hunk_end = hunk.multi_buffer_range.end;
|
||||
|
||||
let buffer = self.buffer().clone();
|
||||
let (diff_base_buffer, deleted_text_range, deleted_text_lines) =
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
let snapshot = buffer.snapshot(cx);
|
||||
let hunk = buffer_diff_hunk(&snapshot, multi_buffer_row_range.clone())?;
|
||||
let mut buffer_ranges = buffer.range_to_buffer_ranges(multi_buffer_row_range, cx);
|
||||
if buffer_ranges.len() == 1 {
|
||||
let (buffer, _, _) = buffer_ranges.pop()?;
|
||||
let diff_base_buffer = diff_base_buffer
|
||||
.or_else(|| self.current_diff_base_buffer(&buffer, cx))
|
||||
.or_else(|| create_diff_base_buffer(&buffer, cx));
|
||||
let buffer = buffer.read(cx);
|
||||
let deleted_text_lines = buffer.diff_base().map(|diff_base| {
|
||||
let diff_start_row = diff_base
|
||||
.offset_to_point(hunk.diff_base_byte_range.start)
|
||||
.row;
|
||||
let diff_end_row =
|
||||
diff_base.offset_to_point(hunk.diff_base_byte_range.end).row;
|
||||
let line_count = diff_end_row - diff_start_row;
|
||||
line_count as usize
|
||||
});
|
||||
Some((
|
||||
diff_base_buffer?,
|
||||
hunk.diff_base_byte_range,
|
||||
deleted_text_lines,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})?;
|
||||
let (diff_base_buffer, deleted_text_lines) = buffer.update(cx, |buffer, cx| {
|
||||
let snapshot = buffer.snapshot(cx);
|
||||
let hunk = buffer_diff_hunk(&snapshot, multi_buffer_row_range.clone())?;
|
||||
let mut buffer_ranges = buffer.range_to_buffer_ranges(multi_buffer_row_range, cx);
|
||||
if buffer_ranges.len() == 1 {
|
||||
let (buffer, _, _) = buffer_ranges.pop()?;
|
||||
let diff_base_buffer = diff_base_buffer
|
||||
.or_else(|| self.current_diff_base_buffer(&buffer, cx))
|
||||
.or_else(|| create_diff_base_buffer(&buffer, cx))?;
|
||||
let buffer = buffer.read(cx);
|
||||
let deleted_text_lines = buffer.diff_base().map(|diff_base| {
|
||||
let diff_start_row = diff_base
|
||||
.offset_to_point(hunk.diff_base_byte_range.start)
|
||||
.row;
|
||||
let diff_end_row = diff_base.offset_to_point(hunk.diff_base_byte_range.end).row;
|
||||
let line_count = diff_end_row - diff_start_row;
|
||||
line_count as u8
|
||||
})?;
|
||||
Some((diff_base_buffer, deleted_text_lines))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})?;
|
||||
|
||||
let block_insert_index = match self.expanded_hunks.hunks.binary_search_by(|probe| {
|
||||
probe
|
||||
|
@ -256,13 +251,9 @@ impl Editor {
|
|||
};
|
||||
|
||||
let block = match hunk.status {
|
||||
DiffHunkStatus::Removed => self.add_deleted_lines(
|
||||
deleted_text_lines,
|
||||
hunk_start,
|
||||
diff_base_buffer,
|
||||
deleted_text_range,
|
||||
cx,
|
||||
),
|
||||
DiffHunkStatus::Removed => {
|
||||
self.insert_deleted_text_block(diff_base_buffer, deleted_text_lines, &hunk, cx)
|
||||
}
|
||||
DiffHunkStatus::Added => {
|
||||
self.highlight_rows::<DiffRowHighlight>(
|
||||
hunk_start..hunk_end,
|
||||
|
@ -277,13 +268,7 @@ impl Editor {
|
|||
Some(added_hunk_color(cx)),
|
||||
cx,
|
||||
);
|
||||
self.add_deleted_lines(
|
||||
deleted_text_lines,
|
||||
hunk_start,
|
||||
diff_base_buffer,
|
||||
deleted_text_range,
|
||||
cx,
|
||||
)
|
||||
self.insert_deleted_text_block(diff_base_buffer, deleted_text_lines, &hunk, cx)
|
||||
}
|
||||
};
|
||||
self.expanded_hunks.hunks.insert(
|
||||
|
@ -300,43 +285,20 @@ impl Editor {
|
|||
Some(())
|
||||
}
|
||||
|
||||
fn add_deleted_lines(
|
||||
&mut self,
|
||||
deleted_text_lines: Option<usize>,
|
||||
hunk_start: Anchor,
|
||||
diff_base_buffer: Model<Buffer>,
|
||||
deleted_text_range: Range<usize>,
|
||||
cx: &mut ViewContext<'_, Self>,
|
||||
) -> Option<BlockId> {
|
||||
if let Some(deleted_text_lines) = deleted_text_lines {
|
||||
self.insert_deleted_text_block(
|
||||
hunk_start,
|
||||
diff_base_buffer,
|
||||
deleted_text_range,
|
||||
deleted_text_lines as u8,
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
debug_panic!("Found no deleted text for removed hunk on position {hunk_start:?}");
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_deleted_text_block(
|
||||
&mut self,
|
||||
position: Anchor,
|
||||
diff_base_buffer: Model<Buffer>,
|
||||
deleted_text_range: Range<usize>,
|
||||
deleted_text_height: u8,
|
||||
hunk: &HunkToExpand,
|
||||
cx: &mut ViewContext<'_, Self>,
|
||||
) -> Option<BlockId> {
|
||||
let deleted_hunk_color = deleted_hunk_color(cx);
|
||||
let (editor_height, editor_with_deleted_text) =
|
||||
editor_with_deleted_text(diff_base_buffer, deleted_text_range, deleted_hunk_color, cx);
|
||||
editor_with_deleted_text(diff_base_buffer, deleted_hunk_color, hunk, cx);
|
||||
let parent_gutter_offset = self.gutter_dimensions.width + self.gutter_dimensions.margin;
|
||||
let mut new_block_ids = self.insert_blocks(
|
||||
Some(BlockProperties {
|
||||
position,
|
||||
position: hunk.multi_buffer_range.start,
|
||||
height: editor_height.max(deleted_text_height),
|
||||
style: BlockStyle::Flex,
|
||||
render: Box::new(move |_| {
|
||||
|
@ -571,10 +533,11 @@ fn deleted_hunk_color(cx: &AppContext) -> Hsla {
|
|||
|
||||
fn editor_with_deleted_text(
|
||||
diff_base_buffer: Model<Buffer>,
|
||||
deleted_text_range: Range<usize>,
|
||||
deleted_color: Hsla,
|
||||
hunk: &HunkToExpand,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> (u8, View<Editor>) {
|
||||
let parent_editor = cx.view().downgrade();
|
||||
let editor = cx.new_view(|cx| {
|
||||
let multi_buffer =
|
||||
cx.new_model(|_| MultiBuffer::without_headers(0, language::Capability::ReadOnly));
|
||||
|
@ -582,7 +545,7 @@ fn editor_with_deleted_text(
|
|||
multi_buffer.push_excerpts(
|
||||
diff_base_buffer,
|
||||
Some(ExcerptRange {
|
||||
context: deleted_text_range,
|
||||
context: hunk.diff_base_byte_range.clone(),
|
||||
primary: None,
|
||||
}),
|
||||
cx,
|
||||
|
@ -603,6 +566,40 @@ fn editor_with_deleted_text(
|
|||
.anchor_after(editor.buffer.read(cx).len(cx));
|
||||
|
||||
editor.highlight_rows::<DiffRowHighlight>(start..end, Some(deleted_color), cx);
|
||||
let hunk_related_subscription = cx.on_blur(&editor.focus_handle, |editor, cx| {
|
||||
editor.change_selections(None, cx, |s| {
|
||||
s.try_cancel();
|
||||
});
|
||||
});
|
||||
editor._subscriptions.push(hunk_related_subscription);
|
||||
let original_multi_buffer_range = hunk.multi_buffer_range.clone();
|
||||
let diff_base_range = hunk.diff_base_byte_range.clone();
|
||||
editor.register_action::<RevertSelectedHunks>(move |_, cx| {
|
||||
parent_editor
|
||||
.update(cx, |editor, cx| {
|
||||
let Some((buffer, original_text)) = editor.buffer().update(cx, |buffer, cx| {
|
||||
let (_, buffer, _) =
|
||||
buffer.excerpt_containing(original_multi_buffer_range.start, cx)?;
|
||||
let original_text =
|
||||
buffer.read(cx).diff_base()?.slice(diff_base_range.clone());
|
||||
Some((buffer, Arc::from(original_text.to_string())))
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(
|
||||
Some((
|
||||
original_multi_buffer_range.start.text_anchor
|
||||
..original_multi_buffer_range.end.text_anchor,
|
||||
original_text,
|
||||
)),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
editor
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue