1
1
//! Facilities to produce git-formatted diffs.
2
2
3
3
use std:: cmp:: Ordering ;
4
- use std:: fmt:: Display ;
5
4
use std:: ops:: Range ;
6
5
6
+ use crate :: blob:: GitDiff ;
7
7
use imara_diff:: intern:: { InternedInput , Interner , Token } ;
8
8
use imara_diff:: Sink ;
9
9
@@ -25,6 +25,20 @@ const RELATIVE_OUTDENT_WITH_BLANK_PENALTY: i16 = 17;
25
25
const RELATIVE_DEDENT_PENALTY : i16 = 23 ;
26
26
const RELATIVE_DEDENT_WITH_BLANK_PENALTY : i16 = 17 ;
27
27
28
+ pub ( super ) mod types {
29
+ use crate :: blob:: git_diff:: ChangeGroup ;
30
+
31
+ /// A [`Sink`](imara_diff::Sink) that creates a diff like git would.
32
+ pub struct GitDiff < ' a , T >
33
+ where
34
+ T : std:: fmt:: Display ,
35
+ {
36
+ pub ( crate ) after : & ' a [ imara_diff:: intern:: Token ] ,
37
+ pub ( crate ) interner : & ' a imara_diff:: intern:: Interner < T > ,
38
+ pub ( crate ) changes : Vec < ChangeGroup > ,
39
+ }
40
+ }
41
+
28
42
/// An enum indicating the kind of change that occurred.
29
43
#[ derive( PartialEq , Debug ) ]
30
44
pub enum ChangeKind {
@@ -63,22 +77,13 @@ pub struct ChangeGroup {
63
77
/// Range indicating the lines of the previous block.
64
78
/// To actually see how the previous block looked like, you need to combine this range with
65
79
/// the [`InternedInput`].
66
- before : Range < usize > ,
80
+ pub before : Range < usize > ,
67
81
/// Range indicating the lines of the new block
68
82
/// To actually see how the current block looks like, you need to combine this range with
69
83
/// the [`InternedInput`].
70
- after : Range < usize > ,
71
- change_kind : ChangeKind ,
72
- }
73
-
74
- /// A [`Sink`] that creates a diff like git would.
75
- pub struct GitDiff < ' a , T >
76
- where
77
- T : Display ,
78
- {
79
- after : & ' a [ Token ] ,
80
- interner : & ' a Interner < T > ,
81
- changes : Vec < ChangeGroup > ,
84
+ pub after : Range < usize > ,
85
+ /// Further specify what kind of change is denoted by the ranges above.
86
+ pub change_kind : ChangeKind ,
82
87
}
83
88
84
89
// Calculate the indentation of a single line
@@ -102,7 +107,12 @@ fn get_indent(s: String) -> Option<u8> {
102
107
None
103
108
}
104
109
105
- fn measure_and_score_change < T : Display > ( lines : & [ Token ] , split : usize , interner : & Interner < T > , score : & mut Score ) {
110
+ fn measure_and_score_change < T : std:: fmt:: Display > (
111
+ lines : & [ Token ] ,
112
+ split : usize ,
113
+ interner : & Interner < T > ,
114
+ score : & mut Score ,
115
+ ) {
106
116
// Gather information about the surroundings of the change
107
117
let end_of_file = split >= lines. len ( ) ;
108
118
let mut indent: Option < u8 > = if split >= lines. len ( ) {
@@ -181,7 +191,7 @@ fn measure_and_score_change<T: Display>(lines: &[Token], split: usize, interner:
181
191
182
192
impl < ' a , T > GitDiff < ' a , T >
183
193
where
184
- T : Display ,
194
+ T : std :: fmt :: Display ,
185
195
{
186
196
/// Create a new instance of [`GitDiff`] that can then be passed to [`imara_diff::diff`]
187
197
/// and generate a more human-readable diff.
@@ -196,48 +206,37 @@ where
196
206
197
207
impl < T > Sink for GitDiff < ' _ , T >
198
208
where
199
- T : Display ,
209
+ T : std :: fmt :: Display ,
200
210
{
201
211
type Out = Vec < ChangeGroup > ;
202
212
203
213
fn process_change ( & mut self , before : Range < u32 > , after : Range < u32 > ) {
204
- if before. is_empty ( ) && !after. is_empty ( ) {
205
- self . changes . push ( ChangeGroup {
206
- before : before. start as usize ..before. end as usize ,
207
- after : after. start as usize ..after. end as usize ,
208
- change_kind : ChangeKind :: Added ,
209
- } ) ;
210
- } else if after. is_empty ( ) && !before. is_empty ( ) {
211
- if after. start == 0 {
212
- self . changes . push ( ChangeGroup {
213
- before : before. start as usize ..before. end as usize ,
214
- after : after. start as usize ..after. end as usize ,
215
- change_kind : ChangeKind :: RemovedAbove ,
216
- } ) ;
217
- } else {
218
- self . changes . push ( ChangeGroup {
219
- before : before. start as usize ..before. end as usize ,
220
- after : after. start as usize ..after. end as usize ,
221
- change_kind : ChangeKind :: RemovedBelow ,
222
- } ) ;
214
+ let change_kind = match ( before. is_empty ( ) , after. is_empty ( ) ) {
215
+ ( true , false ) => ChangeKind :: Added ,
216
+ ( false , true ) => {
217
+ if after. start == 0 {
218
+ ChangeKind :: RemovedAbove
219
+ } else {
220
+ ChangeKind :: RemovedBelow
221
+ }
223
222
}
224
- } else {
225
- self . changes . push ( ChangeGroup {
226
- before : before . start as usize ..before . end as usize ,
227
- after : after . start as usize ..after . end as usize ,
228
- change_kind : ChangeKind :: Modified ,
229
- } ) ;
230
- }
223
+ _ => ChangeKind :: Modified ,
224
+ } ;
225
+ self . changes . push ( ChangeGroup {
226
+ before : before . start as usize ..before . end as usize ,
227
+ after : after . start as usize ..after . end as usize ,
228
+ change_kind ,
229
+ } ) ;
231
230
}
232
231
233
232
fn finish ( mut self ) -> Self :: Out {
234
233
if self . changes . is_empty ( ) {
235
234
return self . changes ;
236
235
}
237
- let mut shift: usize ;
238
236
239
- for change in self . changes . iter_mut ( ) {
240
- // Skip one liner changes
237
+ let mut shift: usize ;
238
+ for change in & mut self . changes {
239
+ // Skip one-liner changes
241
240
if change. after . is_empty ( ) {
242
241
continue ;
243
242
}
@@ -316,85 +315,3 @@ where
316
315
self . changes
317
316
}
318
317
}
319
-
320
- #[ test]
321
- fn git_diff_test ( ) {
322
- let before = r#"struct SomeStruct {
323
- field1: f64,
324
- field2: f64,
325
- }
326
-
327
- fn main() {
328
- // Some comment
329
- let c = SomeStruct { field1: 10.0, field2: 10.0 };
330
-
331
- println!(
332
- "Print field1 from SomeStruct {}",
333
- get_field1(&c)
334
- );
335
- }
336
-
337
- fn get_field1(c: &SomeStruct) -> f64 {
338
- c.field1
339
- }
340
- "# ;
341
-
342
- let after = r#"/// This is a struct
343
- struct SomeStruct {
344
- field1: f64,
345
- field2: f64,
346
- }
347
-
348
- fn main() {
349
- let c = SomeStruct { field1: 10.0, field2: 10.0 };
350
-
351
- println!(
352
- "Print field1 and field2 from SomeStruct {} {}",
353
- get_field1(&c), get_field2(&c)
354
- );
355
- println!("Print another line");
356
- }
357
-
358
- fn get_field1(c: &SomeStruct) -> f64 {
359
- c.field1
360
- }
361
-
362
- fn get_field2(c: &SomeStruct) -> f64 {
363
- c.field2
364
- }
365
- "# ;
366
- use crate :: blob:: git_diff:: ChangeKind ;
367
-
368
- let input = InternedInput :: new ( before, after) ;
369
- let diff = imara_diff:: diff ( imara_diff:: Algorithm :: Histogram , & input, GitDiff :: new ( & input) ) ;
370
- assert_eq ! (
371
- diff,
372
- vec![
373
- ChangeGroup {
374
- before: 0 ..0 ,
375
- after: 0 ..1 ,
376
- change_kind: ChangeKind :: Added
377
- } ,
378
- ChangeGroup {
379
- before: 6 ..7 ,
380
- after: 7 ..7 ,
381
- change_kind: ChangeKind :: RemovedBelow
382
- } ,
383
- ChangeGroup {
384
- before: 10 ..12 ,
385
- after: 10 ..12 ,
386
- change_kind: ChangeKind :: Modified
387
- } ,
388
- ChangeGroup {
389
- before: 13 ..13 ,
390
- after: 13 ..14 ,
391
- change_kind: ChangeKind :: Added
392
- } ,
393
- ChangeGroup {
394
- before: 17 ..17 ,
395
- after: 19 ..23 ,
396
- change_kind: ChangeKind :: Added
397
- }
398
- ]
399
- ) ;
400
- }
0 commit comments