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 collections::{hash_map, HashMap, HashSet};
|
||||||
use git::diff::{DiffHunk, DiffHunkStatus};
|
use git::diff::{DiffHunk, DiffHunkStatus};
|
||||||
|
@ -14,7 +14,8 @@ use util::{debug_panic, RangeExt};
|
||||||
use crate::{
|
use crate::{
|
||||||
git::{diff_hunk_to_display, DisplayDiffHunk},
|
git::{diff_hunk_to_display, DisplayDiffHunk},
|
||||||
hunks_for_selections, BlockDisposition, BlockId, BlockProperties, BlockStyle, DiffRowHighlight,
|
hunks_for_selections, BlockDisposition, BlockId, BlockProperties, BlockStyle, DiffRowHighlight,
|
||||||
Editor, ExpandAllHunkDiffs, RangeToAnchorExt, ToDisplayPoint, ToggleHunkDiff,
|
Editor, ExpandAllHunkDiffs, RangeToAnchorExt, RevertSelectedHunks, ToDisplayPoint,
|
||||||
|
ToggleHunkDiff,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -215,35 +216,29 @@ impl Editor {
|
||||||
let hunk_end = hunk.multi_buffer_range.end;
|
let hunk_end = hunk.multi_buffer_range.end;
|
||||||
|
|
||||||
let buffer = self.buffer().clone();
|
let buffer = self.buffer().clone();
|
||||||
let (diff_base_buffer, deleted_text_range, deleted_text_lines) =
|
let (diff_base_buffer, deleted_text_lines) = buffer.update(cx, |buffer, cx| {
|
||||||
buffer.update(cx, |buffer, cx| {
|
let snapshot = buffer.snapshot(cx);
|
||||||
let snapshot = buffer.snapshot(cx);
|
let hunk = buffer_diff_hunk(&snapshot, multi_buffer_row_range.clone())?;
|
||||||
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);
|
||||||
let mut buffer_ranges = buffer.range_to_buffer_ranges(multi_buffer_row_range, cx);
|
if buffer_ranges.len() == 1 {
|
||||||
if buffer_ranges.len() == 1 {
|
let (buffer, _, _) = buffer_ranges.pop()?;
|
||||||
let (buffer, _, _) = buffer_ranges.pop()?;
|
let diff_base_buffer = diff_base_buffer
|
||||||
let diff_base_buffer = diff_base_buffer
|
.or_else(|| self.current_diff_base_buffer(&buffer, cx))
|
||||||
.or_else(|| self.current_diff_base_buffer(&buffer, cx))
|
.or_else(|| create_diff_base_buffer(&buffer, cx))?;
|
||||||
.or_else(|| create_diff_base_buffer(&buffer, cx));
|
let buffer = buffer.read(cx);
|
||||||
let buffer = buffer.read(cx);
|
let deleted_text_lines = buffer.diff_base().map(|diff_base| {
|
||||||
let deleted_text_lines = buffer.diff_base().map(|diff_base| {
|
let diff_start_row = diff_base
|
||||||
let diff_start_row = diff_base
|
.offset_to_point(hunk.diff_base_byte_range.start)
|
||||||
.offset_to_point(hunk.diff_base_byte_range.start)
|
.row;
|
||||||
.row;
|
let diff_end_row = diff_base.offset_to_point(hunk.diff_base_byte_range.end).row;
|
||||||
let diff_end_row =
|
let line_count = diff_end_row - diff_start_row;
|
||||||
diff_base.offset_to_point(hunk.diff_base_byte_range.end).row;
|
line_count as u8
|
||||||
let line_count = diff_end_row - diff_start_row;
|
})?;
|
||||||
line_count as usize
|
Some((diff_base_buffer, deleted_text_lines))
|
||||||
});
|
} else {
|
||||||
Some((
|
None
|
||||||
diff_base_buffer?,
|
}
|
||||||
hunk.diff_base_byte_range,
|
})?;
|
||||||
deleted_text_lines,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let block_insert_index = match self.expanded_hunks.hunks.binary_search_by(|probe| {
|
let block_insert_index = match self.expanded_hunks.hunks.binary_search_by(|probe| {
|
||||||
probe
|
probe
|
||||||
|
@ -256,13 +251,9 @@ impl Editor {
|
||||||
};
|
};
|
||||||
|
|
||||||
let block = match hunk.status {
|
let block = match hunk.status {
|
||||||
DiffHunkStatus::Removed => self.add_deleted_lines(
|
DiffHunkStatus::Removed => {
|
||||||
deleted_text_lines,
|
self.insert_deleted_text_block(diff_base_buffer, deleted_text_lines, &hunk, cx)
|
||||||
hunk_start,
|
}
|
||||||
diff_base_buffer,
|
|
||||||
deleted_text_range,
|
|
||||||
cx,
|
|
||||||
),
|
|
||||||
DiffHunkStatus::Added => {
|
DiffHunkStatus::Added => {
|
||||||
self.highlight_rows::<DiffRowHighlight>(
|
self.highlight_rows::<DiffRowHighlight>(
|
||||||
hunk_start..hunk_end,
|
hunk_start..hunk_end,
|
||||||
|
@ -277,13 +268,7 @@ impl Editor {
|
||||||
Some(added_hunk_color(cx)),
|
Some(added_hunk_color(cx)),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
self.add_deleted_lines(
|
self.insert_deleted_text_block(diff_base_buffer, deleted_text_lines, &hunk, cx)
|
||||||
deleted_text_lines,
|
|
||||||
hunk_start,
|
|
||||||
diff_base_buffer,
|
|
||||||
deleted_text_range,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.expanded_hunks.hunks.insert(
|
self.expanded_hunks.hunks.insert(
|
||||||
|
@ -300,43 +285,20 @@ impl Editor {
|
||||||
Some(())
|
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(
|
fn insert_deleted_text_block(
|
||||||
&mut self,
|
&mut self,
|
||||||
position: Anchor,
|
|
||||||
diff_base_buffer: Model<Buffer>,
|
diff_base_buffer: Model<Buffer>,
|
||||||
deleted_text_range: Range<usize>,
|
|
||||||
deleted_text_height: u8,
|
deleted_text_height: u8,
|
||||||
|
hunk: &HunkToExpand,
|
||||||
cx: &mut ViewContext<'_, Self>,
|
cx: &mut ViewContext<'_, Self>,
|
||||||
) -> Option<BlockId> {
|
) -> Option<BlockId> {
|
||||||
let deleted_hunk_color = deleted_hunk_color(cx);
|
let deleted_hunk_color = deleted_hunk_color(cx);
|
||||||
let (editor_height, editor_with_deleted_text) =
|
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 parent_gutter_offset = self.gutter_dimensions.width + self.gutter_dimensions.margin;
|
||||||
let mut new_block_ids = self.insert_blocks(
|
let mut new_block_ids = self.insert_blocks(
|
||||||
Some(BlockProperties {
|
Some(BlockProperties {
|
||||||
position,
|
position: hunk.multi_buffer_range.start,
|
||||||
height: editor_height.max(deleted_text_height),
|
height: editor_height.max(deleted_text_height),
|
||||||
style: BlockStyle::Flex,
|
style: BlockStyle::Flex,
|
||||||
render: Box::new(move |_| {
|
render: Box::new(move |_| {
|
||||||
|
@ -571,10 +533,11 @@ fn deleted_hunk_color(cx: &AppContext) -> Hsla {
|
||||||
|
|
||||||
fn editor_with_deleted_text(
|
fn editor_with_deleted_text(
|
||||||
diff_base_buffer: Model<Buffer>,
|
diff_base_buffer: Model<Buffer>,
|
||||||
deleted_text_range: Range<usize>,
|
|
||||||
deleted_color: Hsla,
|
deleted_color: Hsla,
|
||||||
|
hunk: &HunkToExpand,
|
||||||
cx: &mut ViewContext<'_, Editor>,
|
cx: &mut ViewContext<'_, Editor>,
|
||||||
) -> (u8, View<Editor>) {
|
) -> (u8, View<Editor>) {
|
||||||
|
let parent_editor = cx.view().downgrade();
|
||||||
let editor = cx.new_view(|cx| {
|
let editor = cx.new_view(|cx| {
|
||||||
let multi_buffer =
|
let multi_buffer =
|
||||||
cx.new_model(|_| MultiBuffer::without_headers(0, language::Capability::ReadOnly));
|
cx.new_model(|_| MultiBuffer::without_headers(0, language::Capability::ReadOnly));
|
||||||
|
@ -582,7 +545,7 @@ fn editor_with_deleted_text(
|
||||||
multi_buffer.push_excerpts(
|
multi_buffer.push_excerpts(
|
||||||
diff_base_buffer,
|
diff_base_buffer,
|
||||||
Some(ExcerptRange {
|
Some(ExcerptRange {
|
||||||
context: deleted_text_range,
|
context: hunk.diff_base_byte_range.clone(),
|
||||||
primary: None,
|
primary: None,
|
||||||
}),
|
}),
|
||||||
cx,
|
cx,
|
||||||
|
@ -603,6 +566,40 @@ fn editor_with_deleted_text(
|
||||||
.anchor_after(editor.buffer.read(cx).len(cx));
|
.anchor_after(editor.buffer.read(cx).len(cx));
|
||||||
|
|
||||||
editor.highlight_rows::<DiffRowHighlight>(start..end, Some(deleted_color), 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
|
editor
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue