Git · DiffViewer: rows move to their own file; shorter comments
This commit is contained in:
5 files changed
+110
-94
No files matched your search
+2
-2
@@ -152,7 +152,7 @@ pub(crate) fn pair_places(lines: &[DiffLine]) -> Vec<(Option<usize>, Option<usiz
|
||||
out
|
||||
}
|
||||
|
||||
/// A hunk's lines side by side: unchanged lines on both sides, each run of removals beside the additions after it.
|
||||
/// A hunk's lines side by side: removals beside following additions.
|
||||
pub fn pairs(lines: &[DiffLine]) -> Vec<(Option<&DiffLine>, Option<&DiffLine>)> {
|
||||
pair_places(lines)
|
||||
.into_iter()
|
||||
@@ -160,7 +160,7 @@ pub fn pairs(lines: &[DiffLine]) -> Vec<(Option<&DiffLine>, Option<&DiffLine>)>
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Marks the words each removal and the addition beside it changed.
|
||||
/// Marks words changed between each removal and its addition.
|
||||
pub fn mark_words(lines: &mut [DiffLine]) {
|
||||
for (left, right) in pair_places(lines) {
|
||||
let (Some(left), Some(right)) = (left, right) else {
|
||||
|
||||
@@ -9,6 +9,7 @@ mod merge;
|
||||
mod merging;
|
||||
mod refs;
|
||||
mod review;
|
||||
mod rows;
|
||||
mod tags;
|
||||
#[cfg(all(test, feature = "test-support"))]
|
||||
mod tests;
|
||||
@@ -25,5 +26,6 @@ pub use merge::{ConflictResolver, ThreeWayMerge};
|
||||
pub use merging::{Conflict, Region, RegionKind, Take, conflicts, regions, resolve, result};
|
||||
pub use refs::{Branch, BranchList, BranchSelector};
|
||||
pub use review::{PullRequest, PullRequestCard, PullState, ReviewComment, ReviewNote};
|
||||
pub use rows::Place;
|
||||
pub use tags::{GitTag, Stash, StashAction, StashList, TagList};
|
||||
pub use viewer::{DiffLayout, DiffViewer};
|
||||
@@ -0,0 +1,96 @@
|
||||
//! The rows a diff viewer draws, and their colors.
|
||||
|
||||
use std::ops::Range;
|
||||
|
||||
use gpui::{App, HighlightStyle, Hsla, SharedString, StyledText};
|
||||
|
||||
use super::{
|
||||
diff::{DiffLine, LineKind, Stretch, pair_places},
|
||||
viewer::DiffLayout,
|
||||
};
|
||||
use crate::{
|
||||
editor::{code_colors, stack},
|
||||
theme::Palette,
|
||||
};
|
||||
|
||||
/// A line's place: its stretch, then its line there.
|
||||
pub type Place = (usize, usize);
|
||||
|
||||
/// A row as the viewer draws it.
|
||||
#[derive(Clone)]
|
||||
pub(super) enum Shown {
|
||||
/// A hunk's header and its place among the stretches.
|
||||
Header(usize, SharedString),
|
||||
Line(Place, DiffLine),
|
||||
Pair(Option<(Place, DiffLine)>, Option<(Place, DiffLine)>),
|
||||
/// A folded stretch: its place among the stretches and how many lines it hides.
|
||||
Fold(usize, usize),
|
||||
}
|
||||
|
||||
pub(super) fn shown(stretches: &[Stretch], layout: DiffLayout, open: &[usize]) -> Vec<Shown> {
|
||||
let mut rows = Vec::new();
|
||||
for (ix, stretch) in stretches.iter().enumerate() {
|
||||
match stretch {
|
||||
Stretch::Hunk { header, lines } => {
|
||||
rows.push(Shown::Header(ix, header.clone()));
|
||||
let at = |line: usize| ((ix, line), lines[line].clone());
|
||||
match layout {
|
||||
DiffLayout::Unified => rows.extend((0..lines.len()).map(|line| {
|
||||
let (place, line) = at(line);
|
||||
Shown::Line(place, line)
|
||||
})),
|
||||
DiffLayout::Split => rows.extend(
|
||||
pair_places(lines)
|
||||
.into_iter()
|
||||
.map(|(left, right)| Shown::Pair(left.map(at), right.map(at))),
|
||||
),
|
||||
}
|
||||
}
|
||||
Stretch::Folded(lines) if open.contains(&ix) => {
|
||||
rows.extend(lines.iter().enumerate().map(|(at, line)| {
|
||||
let place = (ix, at);
|
||||
match layout {
|
||||
DiffLayout::Unified => Shown::Line(place, line.clone()),
|
||||
DiffLayout::Split => {
|
||||
Shown::Pair(Some((place, line.clone())), Some((place, line.clone())))
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
Stretch::Folded(lines) => rows.push(Shown::Fold(ix, lines.len())),
|
||||
}
|
||||
}
|
||||
rows
|
||||
}
|
||||
|
||||
/// The wash behind a line, and behind its changed words.
|
||||
pub(super) fn washes(kind: LineKind, colors: &Palette) -> (Option<Hsla>, Hsla) {
|
||||
match kind {
|
||||
LineKind::Same => (None, colors.hover),
|
||||
LineKind::Added => (
|
||||
Some(colors.success.opacity(0.08)),
|
||||
colors.success.opacity(0.25),
|
||||
),
|
||||
LineKind::Removed => (
|
||||
Some(colors.danger.opacity(0.08)),
|
||||
colors.danger.opacity(0.25),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// A line's code, colored as code, its changed words washed.
|
||||
pub(super) fn code(line: &DiffLine, colors: &Palette, cx: &App) -> StyledText {
|
||||
let (_, word) = washes(line.kind, colors);
|
||||
let mut styles: Vec<(Range<usize>, HighlightStyle)> = code_colors(&line.text, cx);
|
||||
styles.extend(line.words.iter().map(|range| {
|
||||
(
|
||||
range.clone(),
|
||||
HighlightStyle {
|
||||
background_color: Some(word),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
)
|
||||
}));
|
||||
styles.sort_by_key(|(range, _)| range.start);
|
||||
StyledText::new(line.text.clone()).with_highlights(stack(styles))
|
||||
}
|
||||
+2
-2
@@ -152,7 +152,7 @@ fn changed_lines_and_hunks_answer_presses(cx: &mut TestAppContext) {
|
||||
});
|
||||
settle(cx);
|
||||
};
|
||||
// Past the two layout segments: the hunk's button, then its lines.
|
||||
// Past two layout segments: hunk button, then lines.
|
||||
let next = |cx: &mut VisualTestContext| {
|
||||
cx.update(|window, cx| window.focus_next(cx));
|
||||
settle(cx);
|
||||
@@ -213,7 +213,7 @@ fn a_row_says_which_section_it_is_in(cx: &mut TestAppContext) {
|
||||
cx.update(|window, _| window.activate_window());
|
||||
settle(cx);
|
||||
let mut rows = Vec::new();
|
||||
// Each row is a stop; its icons stay hidden until hover.
|
||||
// Each row is a stop; icons hide until hover.
|
||||
for _ in 0..12 {
|
||||
cx.update(|window, cx| window.focus_next(cx));
|
||||
settle(cx);
|
||||
|
||||
+8
-90
@@ -1,21 +1,21 @@
|
||||
use std::{ops::Range, rc::Rc};
|
||||
use std::rc::Rc;
|
||||
|
||||
use gpui::{
|
||||
AnyElement, App, ElementId, FontWeight, HighlightStyle, Hsla, InteractiveElement, IntoElement,
|
||||
MouseButton, ParentElement, RenderOnce, Role, SharedString, StatefulInteractiveElement, Styled,
|
||||
StyledText, Window, div, prelude::*, relative, transparent_black, uniform_list,
|
||||
AnyElement, App, ElementId, FontWeight, InteractiveElement, IntoElement, MouseButton,
|
||||
ParentElement, RenderOnce, Role, SharedString, StatefulInteractiveElement, Styled, Window, div,
|
||||
prelude::*, relative, transparent_black, uniform_list,
|
||||
};
|
||||
|
||||
use super::{
|
||||
badges::DiffStat,
|
||||
diff::{DiffLine, LineKind, Stretch, diff, pair_places, side_numbers},
|
||||
diff::{DiffLine, LineKind, Stretch, diff, side_numbers},
|
||||
rows::{Place, Shown, code, shown, washes},
|
||||
};
|
||||
use crate::{
|
||||
buttons::{Button, ButtonVariant, SegmentedControl},
|
||||
editor::{code_colors, stack},
|
||||
i18n,
|
||||
primitives::FocusRing,
|
||||
theme::{ActiveTheme, ControlSize, Palette, TextSize},
|
||||
theme::{ActiveTheme, ControlSize, TextSize},
|
||||
typography::LEADING,
|
||||
};
|
||||
|
||||
@@ -29,56 +29,6 @@ pub enum DiffLayout {
|
||||
/// Unchanged lines kept around each change.
|
||||
const CONTEXT: usize = 3;
|
||||
|
||||
/// A line's place: its stretch, then its line there.
|
||||
pub type Place = (usize, usize);
|
||||
|
||||
/// A row as the viewer draws it.
|
||||
#[derive(Clone)]
|
||||
enum Shown {
|
||||
/// A hunk's header and its place among the stretches.
|
||||
Header(usize, SharedString),
|
||||
Line(Place, DiffLine),
|
||||
Pair(Option<(Place, DiffLine)>, Option<(Place, DiffLine)>),
|
||||
/// A folded stretch: its place among the stretches and how many lines it hides.
|
||||
Fold(usize, usize),
|
||||
}
|
||||
|
||||
fn shown(stretches: &[Stretch], layout: DiffLayout, open: &[usize]) -> Vec<Shown> {
|
||||
let mut rows = Vec::new();
|
||||
for (ix, stretch) in stretches.iter().enumerate() {
|
||||
match stretch {
|
||||
Stretch::Hunk { header, lines } => {
|
||||
rows.push(Shown::Header(ix, header.clone()));
|
||||
let at = |line: usize| ((ix, line), lines[line].clone());
|
||||
match layout {
|
||||
DiffLayout::Unified => rows.extend((0..lines.len()).map(|line| {
|
||||
let (place, line) = at(line);
|
||||
Shown::Line(place, line)
|
||||
})),
|
||||
DiffLayout::Split => rows.extend(
|
||||
pair_places(lines)
|
||||
.into_iter()
|
||||
.map(|(left, right)| Shown::Pair(left.map(at), right.map(at))),
|
||||
),
|
||||
}
|
||||
}
|
||||
Stretch::Folded(lines) if open.contains(&ix) => {
|
||||
rows.extend(lines.iter().enumerate().map(|(at, line)| {
|
||||
let place = (ix, at);
|
||||
match layout {
|
||||
DiffLayout::Unified => Shown::Line(place, line.clone()),
|
||||
DiffLayout::Split => {
|
||||
Shown::Pair(Some((place, line.clone())), Some((place, line.clone())))
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
Stretch::Folded(lines) => rows.push(Shown::Fold(ix, lines.len())),
|
||||
}
|
||||
}
|
||||
rows
|
||||
}
|
||||
|
||||
type OnIndex = Rc<dyn Fn(usize, &mut Window, &mut App)>;
|
||||
type OnLayout = Rc<dyn Fn(DiffLayout, &mut Window, &mut App)>;
|
||||
type OnLine = Rc<dyn Fn(Place, bool, &mut Window, &mut App)>;
|
||||
@@ -163,7 +113,7 @@ impl DiffViewer {
|
||||
self
|
||||
}
|
||||
|
||||
/// A button on each hunk's header, given the hunk's place.
|
||||
/// A button on each hunk header, given its place.
|
||||
pub fn hunk_action(
|
||||
mut self,
|
||||
label: impl Into<SharedString>,
|
||||
@@ -204,38 +154,6 @@ impl DiffViewer {
|
||||
}
|
||||
}
|
||||
|
||||
/// The wash behind a line, and behind its changed words.
|
||||
fn washes(kind: LineKind, colors: &Palette) -> (Option<Hsla>, Hsla) {
|
||||
match kind {
|
||||
LineKind::Same => (None, colors.hover),
|
||||
LineKind::Added => (
|
||||
Some(colors.success.opacity(0.08)),
|
||||
colors.success.opacity(0.25),
|
||||
),
|
||||
LineKind::Removed => (
|
||||
Some(colors.danger.opacity(0.08)),
|
||||
colors.danger.opacity(0.25),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// A line's code, colored as code, its changed words washed.
|
||||
fn code(line: &DiffLine, colors: &Palette, cx: &App) -> StyledText {
|
||||
let (_, word) = washes(line.kind, colors);
|
||||
let mut styles: Vec<(Range<usize>, HighlightStyle)> = code_colors(&line.text, cx);
|
||||
styles.extend(line.words.iter().map(|range| {
|
||||
(
|
||||
range.clone(),
|
||||
HighlightStyle {
|
||||
background_color: Some(word),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
)
|
||||
}));
|
||||
styles.sort_by_key(|(range, _)| range.start);
|
||||
StyledText::new(line.text.clone()).with_highlights(stack(styles))
|
||||
}
|
||||
|
||||
impl RenderOnce for DiffViewer {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let theme = cx.theme();
|
||||
|
||||
Reference in new issue
Block a user