diff options
Diffstat (limited to 'helix-vcs/src/diff.rs')
-rw-r--r-- | helix-vcs/src/diff.rs | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/helix-vcs/src/diff.rs b/helix-vcs/src/diff.rs index 9c6a362f..ca33dda4 100644 --- a/helix-vcs/src/diff.rs +++ b/helix-vcs/src/diff.rs @@ -28,11 +28,18 @@ struct Event { render_lock: Option<RenderLock>, } +#[derive(Clone, Debug, Default)] +struct DiffInner { + diff_base: Rope, + doc: Rope, + hunks: Vec<Hunk>, +} + #[derive(Clone, Debug)] pub struct DiffHandle { channel: UnboundedSender<Event>, render_lock: Arc<RwLock<()>>, - hunks: Arc<Mutex<Vec<Hunk>>>, + diff: Arc<Mutex<DiffInner>>, inverted: bool, } @@ -47,10 +54,10 @@ impl DiffHandle { redraw_handle: RedrawHandle, ) -> (DiffHandle, JoinHandle<()>) { let (sender, receiver) = unbounded_channel(); - let hunks: Arc<Mutex<Vec<Hunk>>> = Arc::default(); + let diff: Arc<Mutex<DiffInner>> = Arc::default(); let worker = DiffWorker { channel: receiver, - hunks: hunks.clone(), + diff: diff.clone(), new_hunks: Vec::default(), redraw_notify: redraw_handle.0, diff_finished_notify: Arc::default(), @@ -58,7 +65,7 @@ impl DiffHandle { let handle = tokio::spawn(worker.run(diff_base, doc)); let differ = DiffHandle { channel: sender, - hunks, + diff, inverted: false, render_lock: redraw_handle.1, }; @@ -69,9 +76,9 @@ impl DiffHandle { self.inverted = !self.inverted; } - pub fn hunks(&self) -> FileHunks { - FileHunks { - hunks: self.hunks.lock(), + pub fn load(&self) -> Diff { + Diff { + diff: self.diff.lock(), inverted: self.inverted, } } @@ -168,12 +175,28 @@ impl Hunk { /// A list of changes in a file sorted in ascending /// non-overlapping order #[derive(Debug)] -pub struct FileHunks<'a> { - hunks: MutexGuard<'a, Vec<Hunk>>, +pub struct Diff<'a> { + diff: MutexGuard<'a, DiffInner>, inverted: bool, } -impl FileHunks<'_> { +impl Diff<'_> { + pub fn diff_base(&self) -> &Rope { + if self.inverted { + &self.diff.doc + } else { + &self.diff.diff_base + } + } + + pub fn doc(&self) -> &Rope { + if self.inverted { + &self.diff.diff_base + } else { + &self.diff.doc + } + } + pub fn is_inverted(&self) -> bool { self.inverted } @@ -181,7 +204,7 @@ impl FileHunks<'_> { /// Returns the `Hunk` for the `n`th change in this file. /// if there is no `n`th change `Hunk::NONE` is returned instead. pub fn nth_hunk(&self, n: u32) -> Hunk { - match self.hunks.get(n as usize) { + match self.diff.hunks.get(n as usize) { Some(hunk) if self.inverted => hunk.invert(), Some(hunk) => hunk.clone(), None => Hunk::NONE, @@ -189,7 +212,7 @@ impl FileHunks<'_> { } pub fn len(&self) -> u32 { - self.hunks.len() as u32 + self.diff.hunks.len() as u32 } pub fn is_empty(&self) -> bool { @@ -204,19 +227,20 @@ impl FileHunks<'_> { }; let res = self + .diff .hunks .binary_search_by_key(&line, |hunk| hunk_range(hunk).start); match res { // Search found a hunk that starts exactly at this line, return the next hunk if it exists. - Ok(pos) if pos + 1 == self.hunks.len() => None, + Ok(pos) if pos + 1 == self.diff.hunks.len() => None, Ok(pos) => Some(pos as u32 + 1), // No hunk starts exactly at this line, so the search returns // the position where a hunk starting at this line should be inserted. // That position is exactly the position of the next hunk or the end // of the list if no such hunk exists - Err(pos) if pos == self.hunks.len() => None, + Err(pos) if pos == self.diff.hunks.len() => None, Err(pos) => Some(pos as u32), } } @@ -228,6 +252,7 @@ impl FileHunks<'_> { |hunk: &Hunk| hunk.after.clone() }; let res = self + .diff .hunks .binary_search_by_key(&line, |hunk| hunk_range(hunk).end); @@ -237,7 +262,7 @@ impl FileHunks<'_> { // which represents a pure removal. // Removals are technically empty but are still shown as single line hunks // and as such we must jump to the previous hunk (if it exists) if we are already inside the removal - Ok(pos) if !hunk_range(&self.hunks[pos]).is_empty() => Some(pos as u32), + Ok(pos) if !hunk_range(&self.diff.hunks[pos]).is_empty() => Some(pos as u32), // No hunk ends exactly at this line, so the search returns // the position where a hunk ending at this line should be inserted. @@ -255,6 +280,7 @@ impl FileHunks<'_> { }; let res = self + .diff .hunks .binary_search_by_key(&line, |hunk| hunk_range(hunk).start); @@ -267,7 +293,7 @@ impl FileHunks<'_> { // The previous hunk contains this hunk if it exists and doesn't end before this line Err(0) => None, Err(pos) => { - let hunk = hunk_range(&self.hunks[pos - 1]); + let hunk = hunk_range(&self.diff.hunks[pos - 1]); if hunk.end > line || include_removal && hunk.start == line && hunk.is_empty() { Some(pos as u32 - 1) } else { |