@@ -28,11 +28,18 @@ struct Event {
2828 render_lock: Option<RenderLock>,
2929}
3030
31+#[derive(Clone, Debug, Default)]
32+struct DiffInner {
33+ diff_base: Rope,
34+ doc: Rope,
35+ hunks: Vec<Hunk>,
36+}
37+
3138#[derive(Clone, Debug)]
3239pub struct DiffHandle {
3340 channel: UnboundedSender<Event>,
3441 render_lock: Arc<RwLock<()>>,
35− hunks: Arc<Mutex<Vec<Hunk>>>,
42+ diff: Arc<Mutex<DiffInner>>,
3643 inverted: bool,
3744}
3845
@@ -47,10 +54,10 @@ impl DiffHandle {
4754 redraw_handle: RedrawHandle,
4855 ) -> (DiffHandle, JoinHandle<()>) {
4956 let (sender, receiver) = unbounded_channel();
50− let hunks: Arc<Mutex<Vec<Hunk>>> = Arc::default();
57+ let diff: Arc<Mutex<DiffInner>> = Arc::default();
5158 let worker = DiffWorker {
5259 channel: receiver,
53− hunks: hunks.clone(),
60+ diff: diff.clone(),
5461 new_hunks: Vec::default(),
5562 redraw_notify: redraw_handle.0,
5663 diff_finished_notify: Arc::default(),
@@ -58,7 +65,7 @@ impl DiffHandle {
5865 let handle = tokio::spawn(worker.run(diff_base, doc));
5966 let differ = DiffHandle {
6067 channel: sender,
61− hunks,
68+ diff,
6269 inverted: false,
6370 render_lock: redraw_handle.1,
6471 };
@@ -69,9 +76,9 @@ impl DiffHandle {
6976 self.inverted = !self.inverted;
7077 }
7178
72− pub fn hunks(&self) -> FileHunks {
73− FileHunks {
74− hunks: self.hunks.lock(),
79+ pub fn load(&self) -> Diff {
80+ Diff {
81+ diff: self.diff.lock(),
7582 inverted: self.inverted,
7683 }
7784 }
@@ -168,12 +175,28 @@ impl Hunk {
168175/// A list of changes in a file sorted in ascending
169176/// non-overlapping order
170177#[derive(Debug)]
171−pub struct FileHunks<'a> {
172− hunks: MutexGuard<'a, Vec<Hunk>>,
178+pub struct Diff<'a> {
179+ diff: MutexGuard<'a, DiffInner>,
173180 inverted: bool,
174181}
175182
176−impl FileHunks<'_> {
183+impl Diff<'_> {
184+ pub fn diff_base(&self) -> &Rope {
185+ if self.inverted {
186+ &self.diff.doc
187+ } else {
188+ &self.diff.diff_base
189+ }
190+ }
191+
192+ pub fn doc(&self) -> &Rope {
193+ if self.inverted {
194+ &self.diff.diff_base
195+ } else {
196+ &self.diff.doc
197+ }
198+ }
199+
177200 pub fn is_inverted(&self) -> bool {
178201 self.inverted
179202 }
@@ -181,7 +204,7 @@ impl FileHunks<'_> {
181204 /// Returns the `Hunk` for the `n`th change in this file.
182205 /// if there is no `n`th change `Hunk::NONE` is returned instead.
183206 pub fn nth_hunk(&self, n: u32) -> Hunk {
184− match self.hunks.get(n as usize) {
207+ match self.diff.hunks.get(n as usize) {
185208 Some(hunk) if self.inverted => hunk.invert(),
186209 Some(hunk) => hunk.clone(),
187210 None => Hunk::NONE,
@@ -189,7 +212,7 @@ impl FileHunks<'_> {
189212 }
190213
191214 pub fn len(&self) -> u32 {
192− self.hunks.len() as u32
215+ self.diff.hunks.len() as u32
193216 }
194217
195218 pub fn is_empty(&self) -> bool {
@@ -204,19 +227,20 @@ impl FileHunks<'_> {
204227 };
205228
206229 let res = self
230+ .diff
207231 .hunks
208232 .binary_search_by_key(&line, |hunk| hunk_range(hunk).start);
209233
210234 match res {
211235 // Search found a hunk that starts exactly at this line, return the next hunk if it exists.
212− Ok(pos) if pos + 1 == self.hunks.len() => None,
236+ Ok(pos) if pos + 1 == self.diff.hunks.len() => None,
213237 Ok(pos) => Some(pos as u32 + 1),
214238
215239 // No hunk starts exactly at this line, so the search returns
216240 // the position where a hunk starting at this line should be inserted.
217241 // That position is exactly the position of the next hunk or the end
218242 // of the list if no such hunk exists
219− Err(pos) if pos == self.hunks.len() => None,
243+ Err(pos) if pos == self.diff.hunks.len() => None,
220244 Err(pos) => Some(pos as u32),
221245 }
222246 }
@@ -228,6 +252,7 @@ impl FileHunks<'_> {
228252 |hunk: &Hunk| hunk.after.clone()
229253 };
230254 let res = self
255+ .diff
231256 .hunks
232257 .binary_search_by_key(&line, |hunk| hunk_range(hunk).end);
233258
@@ -237,7 +262,7 @@ impl FileHunks<'_> {
237262 // which represents a pure removal.
238263 // Removals are technically empty but are still shown as single line hunks
239264 // and as such we must jump to the previous hunk (if it exists) if we are already inside the removal
240− Ok(pos) if !hunk_range(&self.hunks[pos]).is_empty() => Some(pos as u32),
265+ Ok(pos) if !hunk_range(&self.diff.hunks[pos]).is_empty() => Some(pos as u32),
241266
242267 // No hunk ends exactly at this line, so the search returns
243268 // the position where a hunk ending at this line should be inserted.
@@ -255,6 +280,7 @@ impl FileHunks<'_> {
255280 };
256281
257282 let res = self
283+ .diff
258284 .hunks
259285 .binary_search_by_key(&line, |hunk| hunk_range(hunk).start);
260286
@@ -267,7 +293,7 @@ impl FileHunks<'_> {
267293 // The previous hunk contains this hunk if it exists and doesn't end before this line
268294 Err(0) => None,
269295 Err(pos) => {
270− let hunk = hunk_range(&self.hunks[pos - 1]);
296+ let hunk = hunk_range(&self.diff.hunks[pos - 1]);
271297 if hunk.end > line || include_removal && hunk.start == line && hunk.is_empty() {
272298 Some(pos as u32 - 1)
273299 } else {