mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-26 10:40:54 +00:00
Something's happening, nothing correct, but something
This commit is contained in:
parent
7528bf8f32
commit
a6910584b6
1 changed files with 93 additions and 42 deletions
|
@ -48,6 +48,11 @@ use std::{
|
|||
};
|
||||
use theme::DiffStyle;
|
||||
|
||||
struct DiffHunkLayout {
|
||||
visual_range: Range<u32>,
|
||||
status: DiffHunkStatus,
|
||||
}
|
||||
|
||||
struct SelectionLayout {
|
||||
head: DisplayPoint,
|
||||
range: Range<DisplayPoint>,
|
||||
|
@ -539,17 +544,17 @@ impl EditorElement {
|
|||
}
|
||||
|
||||
fn diff_quad(
|
||||
hunk: &DiffHunk<u32>,
|
||||
hunk: &DiffHunkLayout,
|
||||
gutter_layout: &GutterLayout,
|
||||
diff_style: &DiffStyle,
|
||||
) -> Quad {
|
||||
let color = match hunk.status() {
|
||||
let color = match hunk.status {
|
||||
DiffHunkStatus::Added => diff_style.inserted,
|
||||
DiffHunkStatus::Modified => diff_style.modified,
|
||||
|
||||
//TODO: This rendering is entirely a horrible hack
|
||||
DiffHunkStatus::Removed => {
|
||||
let row = hunk.buffer_range.start;
|
||||
let row = hunk.visual_range.start;
|
||||
|
||||
let offset = gutter_layout.line_height / 2.;
|
||||
let start_y =
|
||||
|
@ -570,8 +575,8 @@ impl EditorElement {
|
|||
}
|
||||
};
|
||||
|
||||
let start_row = hunk.buffer_range.start;
|
||||
let end_row = hunk.buffer_range.end;
|
||||
let start_row = hunk.visual_range.start;
|
||||
let end_row = hunk.visual_range.end;
|
||||
|
||||
let start_y = start_row as f32 * gutter_layout.line_height - gutter_layout.scroll_top;
|
||||
let end_y = end_row as f32 * gutter_layout.line_height - gutter_layout.scroll_top;
|
||||
|
@ -613,7 +618,13 @@ impl EditorElement {
|
|||
GitGutter::TrackedFiles
|
||||
);
|
||||
|
||||
// line is `None` when there's a line wrap
|
||||
if show_gutter {
|
||||
for hunk in &layout.hunk_layouts {
|
||||
let quad = diff_quad(hunk, &gutter_layout, diff_style);
|
||||
cx.scene.push_quad(quad);
|
||||
}
|
||||
}
|
||||
|
||||
for (ix, line) in layout.line_number_layouts.iter().enumerate() {
|
||||
if let Some(line) = line {
|
||||
let line_origin = bounds.origin()
|
||||
|
@ -624,38 +635,9 @@ impl EditorElement {
|
|||
);
|
||||
|
||||
line.paint(line_origin, visible_bounds, gutter_layout.line_height, cx);
|
||||
|
||||
if show_gutter {
|
||||
//This line starts a buffer line, so let's do the diff calculation
|
||||
let new_hunk = get_hunk(diff_layout.buffer_row, &layout.diff_hunks);
|
||||
|
||||
let (is_ending, is_starting) = match (diff_layout.last_diff, new_hunk) {
|
||||
(Some(old_hunk), Some(new_hunk)) if new_hunk == old_hunk => (false, false),
|
||||
(a, b) => (a.is_some(), b.is_some()),
|
||||
};
|
||||
|
||||
if is_ending {
|
||||
let last_hunk = diff_layout.last_diff.take().unwrap();
|
||||
cx.scene
|
||||
.push_quad(diff_quad(last_hunk, &gutter_layout, diff_style));
|
||||
}
|
||||
|
||||
if is_starting {
|
||||
let new_hunk = new_hunk.unwrap();
|
||||
diff_layout.last_diff = Some(new_hunk);
|
||||
};
|
||||
|
||||
diff_layout.buffer_row += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we ran out with a diff hunk still being prepped, paint it now
|
||||
if let Some(last_hunk) = diff_layout.last_diff {
|
||||
cx.scene
|
||||
.push_quad(diff_quad(last_hunk, &gutter_layout, diff_style))
|
||||
}
|
||||
|
||||
if let Some((row, indicator)) = layout.code_actions_indicator.as_mut() {
|
||||
let mut x = bounds.width() - layout.gutter_padding;
|
||||
let mut y = *row as f32 * gutter_layout.line_height - gutter_layout.scroll_top;
|
||||
|
@ -1013,6 +995,78 @@ impl EditorElement {
|
|||
.width()
|
||||
}
|
||||
|
||||
fn layout_diff_hunk(
|
||||
hunk: &DiffHunk<u32>,
|
||||
buffer_rows: &mut std::iter::Peekable<impl Iterator<Item = Option<u32>>>,
|
||||
) -> DiffHunkLayout {
|
||||
//This should start with a row which is contained in the hunk's buffer range
|
||||
let visual_start = buffer_rows.peek().unwrap().unwrap();
|
||||
|
||||
let mut visual_count = 0;
|
||||
while let Some(&buffer_row) = buffer_rows.peek() {
|
||||
if let Some(buffer_row) = buffer_row {
|
||||
if buffer_row == hunk.buffer_range.end {
|
||||
visual_count += 1;
|
||||
break;
|
||||
} else if buffer_row > hunk.buffer_range.end {
|
||||
break;
|
||||
}
|
||||
visual_count += 1;
|
||||
buffer_rows.next();
|
||||
}
|
||||
}
|
||||
|
||||
DiffHunkLayout {
|
||||
visual_range: visual_start..visual_start + visual_count,
|
||||
status: hunk.status(),
|
||||
}
|
||||
}
|
||||
|
||||
//Folds contained in a hunk are ignored apart from shrinking visual size
|
||||
//If a fold contains any hunks then that fold line is marked as modified
|
||||
fn layout_git_gutters(
|
||||
&self,
|
||||
rows: Range<u32>,
|
||||
snapshot: &EditorSnapshot,
|
||||
) -> Vec<DiffHunkLayout> {
|
||||
let mut diff_hunks = snapshot
|
||||
.buffer_snapshot
|
||||
.git_diff_hunks_in_range(rows.clone())
|
||||
.peekable();
|
||||
|
||||
//Some number followed by Nones for wrapped lines
|
||||
//Jump in number for folded lines
|
||||
let mut buffer_rows = snapshot
|
||||
.buffer_rows(rows.start)
|
||||
.take((rows.end - rows.start) as usize)
|
||||
.peekable();
|
||||
|
||||
let mut layouts = Vec::new();
|
||||
|
||||
while let Some(buffer_row) = buffer_rows.next() {
|
||||
let buffer_row = buffer_row.unwrap();
|
||||
|
||||
if let Some(hunk) = diff_hunks.peek() {
|
||||
if hunk.buffer_range.contains(&buffer_row) {
|
||||
layouts.push(Self::layout_diff_hunk(hunk, &mut buffer_rows));
|
||||
diff_hunks.next();
|
||||
} else if hunk.buffer_range.end < buffer_row {
|
||||
//A hunk that was missed due to being entirely contained in a fold
|
||||
//We can safely assume that the previous visual row is the fold
|
||||
//TODO: If there is another hunk that ends inside the fold then
|
||||
//this will overlay over, but right now that seems fine
|
||||
layouts.push(DiffHunkLayout {
|
||||
visual_range: buffer_row - 1..buffer_row,
|
||||
status: DiffHunkStatus::Modified,
|
||||
});
|
||||
diff_hunks.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layouts
|
||||
}
|
||||
|
||||
fn layout_line_numbers(
|
||||
&self,
|
||||
rows: Range<u32>,
|
||||
|
@ -1367,7 +1421,7 @@ impl EditorElement {
|
|||
|
||||
/// Get the hunk that contains buffer_line, starting from start_idx
|
||||
/// Returns none if there is none found, and
|
||||
fn get_hunk(buffer_line: u32, hunks: &[DiffHunk<u32>]) -> Option<&DiffHunk<u32>> {
|
||||
fn get_hunk(hunks: &[DiffHunk<u32>], buffer_line: u32) -> Option<&DiffHunk<u32>> {
|
||||
for i in 0..hunks.len() {
|
||||
// Safety: Index out of bounds is handled by the check above
|
||||
let hunk = hunks.get(i).unwrap();
|
||||
|
@ -1561,10 +1615,7 @@ impl Element for EditorElement {
|
|||
let line_number_layouts =
|
||||
self.layout_line_numbers(start_row..end_row, &active_rows, &snapshot, cx);
|
||||
|
||||
let diff_hunks = snapshot
|
||||
.buffer_snapshot
|
||||
.git_diff_hunks_in_range(start_row..end_row)
|
||||
.collect();
|
||||
let hunk_layouts = self.layout_git_gutters(start_row..end_row, &snapshot);
|
||||
|
||||
let mut max_visible_line_width = 0.0;
|
||||
let line_layouts = self.layout_lines(start_row..end_row, &snapshot, cx);
|
||||
|
@ -1714,7 +1765,7 @@ impl Element for EditorElement {
|
|||
highlighted_rows,
|
||||
highlighted_ranges,
|
||||
line_number_layouts,
|
||||
diff_hunks,
|
||||
hunk_layouts,
|
||||
blocks,
|
||||
selections,
|
||||
context_menu,
|
||||
|
@ -1848,11 +1899,11 @@ pub struct LayoutState {
|
|||
active_rows: BTreeMap<u32, bool>,
|
||||
highlighted_rows: Option<Range<u32>>,
|
||||
line_number_layouts: Vec<Option<text_layout::Line>>,
|
||||
hunk_layouts: Vec<DiffHunkLayout>,
|
||||
blocks: Vec<BlockLayout>,
|
||||
highlighted_ranges: Vec<(Range<DisplayPoint>, Color)>,
|
||||
selections: Vec<(ReplicaId, Vec<SelectionLayout>)>,
|
||||
context_menu: Option<(DisplayPoint, ElementBox)>,
|
||||
diff_hunks: Vec<DiffHunk<u32>>,
|
||||
code_actions_indicator: Option<(u32, ElementBox)>,
|
||||
hover_popovers: Option<(DisplayPoint, Vec<ElementBox>)>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue