Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tried to calculate separate linecount #65

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 59 additions & 23 deletions src/components/diff_view.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
data::{FileDiff, VersionDiff},
data::{ChunkInfo, FileDiff, VersionDiff},
syntax::{highlight_changes, infer_syntax_for_file, syntect_style_to_css},
};
use camino::Utf8PathBuf;
Expand All @@ -15,7 +15,7 @@ struct DiffGroupInfo {
/// The actual changes
group: Vec<(ChangeTag, Vec<(Style, bytes::Bytes)>)>,
/// What range of lines the group covers (used as a Yew list key)
range: std::ops::Range<usize>,
range: ChunkInfo,
/// Whether the group contains an actual diff (and therefore shows some context)
in_context: bool,
}
Expand Down Expand Up @@ -68,31 +68,42 @@ pub fn DiffView(props: &DiffViewProps) -> Html {
// Group contiguous lines by whether they contain an actual diff +/- some context buffer.
let mut cursor = 0;
let mut stack: Vec<DiffGroupInfo> = vec![];

for next_range in ranges {
// out of context lines
if next_range.start != 0 {
if next_range.start() != 0 {
stack.push(DiffGroupInfo {
group: changes.by_ref().take(next_range.start - cursor).collect(),
range: cursor..next_range.start,
group: changes.by_ref().take(next_range.start() - cursor).collect(),
range: ChunkInfo {
range: cursor..next_range.start(),
left_start: (next_range.left_start + cursor).saturating_sub(next_range.start()),
right_start: (next_range.right_start + cursor)
.saturating_sub(next_range.start()),
},
in_context: false,
});
}
// in context lines
stack.push(DiffGroupInfo {
group: changes
.by_ref()
.take(next_range.end - next_range.start)
.take(next_range.end() - next_range.start())
.collect(),
range: next_range.clone(),
in_context: true,
});
cursor = next_range.end;
cursor = next_range.end();
}
if changes.len() > 0 {
// Trailing unchanged lines at the end of a file
stack.push(DiffGroupInfo {
group: changes.by_ref().collect(),
range: cursor..file_diff.changes.len(),
range: ChunkInfo {
range: cursor..file_diff.changes.len(),
left_start: (cursor).saturating_sub(file_diff.summary.added as usize),
right_start: (cursor).saturating_sub(file_diff.summary.removed as usize),
},

// When comparing a version of the crate to itself, this group will
// always contain the full text of the file. Don't collapse it.
in_context: is_identical_version,
Expand Down Expand Up @@ -128,10 +139,10 @@ pub fn UnifiedDiffView(props: &AnyDiffViewProps) -> Html {
.map(|DiffGroupInfo {group, range, in_context}| {
let res = html!{
<DiffLineGroup
key={format!("{:?}", range)}
key={format!("{:?}", range.range)}
group={group.clone()}
{in_context}
group_start_index={overall_index}
group_start_index={(overall_index, range.left_start, range.right_start)}
/>
};
overall_index += group.len();
Expand All @@ -158,7 +169,7 @@ pub fn SplitDiffView(props: &AnyDiffViewProps) -> Html {
key={format!("{:?}", range)}
group={group.clone()}
{in_context}
group_start_index={overall_index}
group_start_index={(overall_index, range.left_start, range.right_start)}
/>
};
overall_index += group.len();
Expand All @@ -184,7 +195,7 @@ fn ExpandIcon() -> Html {
pub struct DiffLineGroupProps {
group: Vec<(ChangeTag, Vec<(Style, bytes::Bytes)>)>,
in_context: bool,
group_start_index: usize,
group_start_index: (usize, usize, usize),
}

#[function_component]
Expand All @@ -194,8 +205,20 @@ pub fn DiffLineGroup(props: &DiffLineGroupProps) -> Html {
let folded = folded.clone();
Callback::from(move |_| folded.set(!*folded))
};
let group_start_index = props.group_start_index + 1;
let end_index = group_start_index + props.group.len() - 1;

// go from 0-indexed to 1-indexed
let start_index = (
props.group_start_index.0 + 1,
props.group_start_index.1 + 1,
props.group_start_index.2 + 1,
);

// use the fact that folded sections never contain changes
let end_index = (
start_index.0 + props.group.len() - 1,
start_index.1 + props.group.len() - 1,
start_index.2 + props.group.len() - 1,
);

if *folded {
html! {
Expand All @@ -204,33 +227,46 @@ pub fn DiffLineGroup(props: &DiffLineGroupProps) -> Html {
<ExpandIcon />
</button>
<button class={classes!("info")} {onclick}>
{format!("Show lines {group_start_index} to {end_index}")}
{
if start_index.1 == start_index.2 {
format!("Show lines {:?} to {:?}", start_index.1, end_index.1)
} else {
format!("Show lines {:?} to {:?}", (start_index.1,start_index.2), (end_index.1,end_index.2))
}
}
</button>
</div>
}
} else {
let (mut left_idx, mut right_idx) = (start_index.1, start_index.2);
html! {
<>
if !props.in_context {
}
{
props.group.iter().enumerate().map(|(index, (tag, change))| {
let overall_index = group_start_index + index;
let (sign, class) = match tag {
ChangeTag::Delete => ("-", "deletion"),
ChangeTag::Insert => ("+", "insertion"),
ChangeTag::Equal => (" ", "unchanged"),
props.group.iter().map(|(tag, change)| {
let (sign, class, left, right) = match tag {
ChangeTag::Delete => ("-", "deletion", left_idx.to_string(), String::new()),
ChangeTag::Insert => ("+", "insertion", String::new(), right_idx.to_string()),
ChangeTag::Equal => (" ", "unchanged", left_idx.to_string(), right_idx.to_string()),
};
(left_idx, right_idx) = match tag {
ChangeTag::Delete => (left_idx + 1, right_idx),
ChangeTag::Insert => (left_idx, right_idx + 1),
ChangeTag::Equal => (left_idx + 1, right_idx + 1),
};

html! {
<div class={classes!("line", class)}>

<div class="line-number">
{
format!("{overall_index}")
format!("{left}")
}
</div>
<div class="line-number">
{
format!("{overall_index}")
format!("{right}")
}
</div>
<div class="change-icon">
Expand Down
67 changes: 54 additions & 13 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,9 @@ pub struct FileDiff {
/// Diff in this file
pub changes: Vec<(ChangeTag, Bytes)>,
/// Ranges of lines to show for each file
pub context_ranges: Vec<Range<usize>>,
pub context_ranges: Vec<ChunkInfo>,
// Redundant - alternativly take from files
pub summary: Changes,
}

/// Precomputed diff data
Expand Down Expand Up @@ -473,37 +475,46 @@ impl VersionDiff {
match tag {
ChangeTag::Equal => {}
ChangeTag::Delete => {
// cnt for determining start idx of hunk, wanna start before this line, so do not count current line
offsets.push((index, insertions, deletions));
deletions += 1;
offsets.push(index);
}
ChangeTag::Insert => {
offsets.push((index, insertions, deletions));
insertions += 1;
offsets.push(index);
}
}
}

// compute ranges to show
let mut ranges = vec![];
let mut last_hunk = 0..0;

for offset in offsets.iter() {
let hunk = offset.saturating_sub(CONTEXT_LINES)..*offset + CONTEXT_LINES + 1;
let mut last_hunk = (0..0, 0, 0);

for (offset, ins, del) in offsets.iter() {
let hunk_start = offset.saturating_sub(CONTEXT_LINES);
let left_start = hunk_start.saturating_sub(*ins);
let right_start = hunk_start.saturating_sub(*del);

let hunk = (
hunk_start..*offset + CONTEXT_LINES + 1,
left_start,
right_start,
);
let overlaps_with_last_hunk =
hunk.start.max(last_hunk.start) <= hunk.end.min(last_hunk.end);
hunk.0.start.max(last_hunk.0.start) <= hunk.0.end.min(last_hunk.0.end);
if overlaps_with_last_hunk {
last_hunk = last_hunk.start..hunk.end;
last_hunk = (last_hunk.0.start..hunk.0.end, last_hunk.1, last_hunk.2);
} else {
if last_hunk.end != 0 {
ranges.push(last_hunk.clone());
if last_hunk.0.end != 0 {
ranges.push(last_hunk.clone().into());
}
last_hunk = hunk;
}
}

// Push the last hunk we've computed if any
if last_hunk.end != 0 {
ranges.push(last_hunk)
if last_hunk.0.end != 0 {
ranges.push(last_hunk.into())
}

// compute additions
Expand All @@ -526,6 +537,10 @@ impl VersionDiff {
FileDiff {
changes,
context_ranges: ranges,
summary: Changes {
added: insertions as u64,
removed: deletions as u64,
},
},
);
}
Expand All @@ -540,6 +555,32 @@ impl VersionDiff {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct ChunkInfo {
pub range: Range<usize>,
pub left_start: usize,
pub right_start: usize,
}

impl From<(Range<usize>, usize, usize)> for ChunkInfo {
fn from((range, left_start, right_start): (Range<usize>, usize, usize)) -> Self {
ChunkInfo {
range,
left_start,
right_start,
}
}
}

impl ChunkInfo {
pub fn start(&self) -> usize {
self.range.start
}
pub fn end(&self) -> usize {
self.range.end
}
}

#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
pub struct Changes {
pub added: u64,
Expand Down