Fix Git diff rendering
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
use crate::app::git::{GitChangeKind, GitDiffLine, GitDiffLineKind, GitDiffMode, GitDiffRow};
|
||||
use crate::app::{git_diff_new_scroll_id, git_diff_old_scroll_id};
|
||||
use iced::widget::column;
|
||||
|
||||
impl App {
|
||||
@@ -259,13 +260,7 @@ impl App {
|
||||
} else {
|
||||
split_diff(diff.split_rows())
|
||||
};
|
||||
let diff_scroll = scrollable(content)
|
||||
.direction(scrollable::Direction::Both {
|
||||
vertical: scrollable::Scrollbar::new(),
|
||||
horizontal: scrollable::Scrollbar::new(),
|
||||
})
|
||||
.height(Length::Fill)
|
||||
.width(Length::Fill);
|
||||
let diff_scroll = scrollable(content).height(Length::Fill).width(Length::Fill);
|
||||
let dialog = container(
|
||||
column![
|
||||
row![
|
||||
@@ -342,17 +337,59 @@ fn unified_diff(lines: &[GitDiffLine]) -> Element<'_, Message> {
|
||||
}
|
||||
|
||||
fn split_diff(rows: Vec<GitDiffRow>) -> Element<'static, Message> {
|
||||
let mut content = column![].spacing(0).width(Length::Fill);
|
||||
let width = split_diff_width(&rows);
|
||||
let old = scrollable(split_diff_half(&rows, true, width))
|
||||
.id(git_diff_old_scroll_id())
|
||||
.direction(scrollable::Direction::Horizontal(
|
||||
scrollable::Scrollbar::new(),
|
||||
))
|
||||
.on_scroll(Message::GitDiffScrolled)
|
||||
.width(Length::Fill);
|
||||
let new = scrollable(split_diff_half(&rows, false, width))
|
||||
.id(git_diff_new_scroll_id())
|
||||
.direction(scrollable::Direction::Horizontal(
|
||||
scrollable::Scrollbar::new(),
|
||||
))
|
||||
.on_scroll(Message::GitDiffScrolled)
|
||||
.width(Length::Fill);
|
||||
row![old, rule::vertical(1), new].into()
|
||||
}
|
||||
|
||||
fn split_diff_width(rows: &[GitDiffRow]) -> f32 {
|
||||
rows.iter()
|
||||
.flat_map(|row| match row {
|
||||
GitDiffRow::Header(line) => [Some(line), None],
|
||||
GitDiffRow::Pair { old, new } => [old.as_ref(), new.as_ref()],
|
||||
})
|
||||
.flatten()
|
||||
.map(|line| {
|
||||
line.text
|
||||
.chars()
|
||||
.map(|character| if character == '\t' { 4 } else { 1 })
|
||||
.sum::<usize>()
|
||||
})
|
||||
.max()
|
||||
.unwrap_or_default() as f32
|
||||
* 8.0
|
||||
+ 66.0
|
||||
}
|
||||
|
||||
fn split_diff_half(rows: &[GitDiffRow], old: bool, width: f32) -> Element<'static, Message> {
|
||||
let mut content = column![].spacing(0).width(width);
|
||||
for row in rows {
|
||||
content = content.push(match row {
|
||||
GitDiffRow::Header(line) => diff_line(&line, false),
|
||||
GitDiffRow::Pair { old, new } => row![
|
||||
diff_half(old.as_ref(), true),
|
||||
rule::vertical(1),
|
||||
diff_half(new.as_ref(), false),
|
||||
]
|
||||
.height(24)
|
||||
.into(),
|
||||
GitDiffRow::Header(line) => diff_line(line, old),
|
||||
GitDiffRow::Pair {
|
||||
old: old_line,
|
||||
new: new_line,
|
||||
} => diff_half(
|
||||
if old {
|
||||
old_line.as_ref()
|
||||
} else {
|
||||
new_line.as_ref()
|
||||
},
|
||||
old,
|
||||
),
|
||||
});
|
||||
}
|
||||
content.into()
|
||||
@@ -427,3 +464,28 @@ fn staged_color() -> Color {
|
||||
fn modal_backdrop_style(_: &Theme) -> container::Style {
|
||||
container::Style::default().background(Color::from_rgba8(0, 0, 0, 0.72))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn split_diff_width_covers_the_longest_side_and_tabs() {
|
||||
let rows = [GitDiffRow::Pair {
|
||||
old: Some(GitDiffLine {
|
||||
kind: GitDiffLineKind::Deletion,
|
||||
old_number: Some(1),
|
||||
new_number: None,
|
||||
text: "short".into(),
|
||||
}),
|
||||
new: Some(GitDiffLine {
|
||||
kind: GitDiffLineKind::Addition,
|
||||
old_number: None,
|
||||
new_number: Some(1),
|
||||
text: "\tlong".into(),
|
||||
}),
|
||||
}];
|
||||
|
||||
assert_eq!(split_diff_width(&rows), 130.0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user