@@ -3,24 +3,58 @@ use diff::{chars, lines, Result, Result::*};
3
3
4
4
#[ derive( Default ) ]
5
5
struct DiffState < ' a > {
6
- skipped_lines : usize ,
7
- /// When we skip a line, remember it, in case
8
- /// we end up only skipping one line. In that case we just
9
- /// print the line instead of `... skipped one line ...`
10
- last_skipped_line : Option < & ' a str > ,
6
+ /// Whether we've already printed something, so we should print starting context, too.
7
+ print_start_context : bool ,
8
+ /// When we skip lines, remember the last `CONTEXT` ones to
9
+ /// display after the " skipped N lines" message
10
+ skipped_lines : Vec < & ' a str > ,
11
11
/// When we see a removed line, we don't print it, we
12
12
/// keep it around to compare it with the next added line.
13
13
prev_left : Option < & ' a str > ,
14
14
}
15
15
16
+ /// How many lines of context are displayed around the actual diffs
17
+ const CONTEXT : usize = 2 ;
18
+
16
19
impl < ' a > DiffState < ' a > {
17
- fn print_skip ( & mut self ) {
18
- match self . skipped_lines {
20
+ /// Print `... n lines skipped ...` followed by the last `CONTEXT` lines.
21
+ fn print_end_skip ( & self , skipped : usize ) {
22
+ self . print_skipped_msg ( skipped) ;
23
+ for line in self . skipped_lines . iter ( ) . rev ( ) . take ( CONTEXT ) . rev ( ) {
24
+ eprintln ! ( " {line}" ) ;
25
+ }
26
+ }
27
+ fn print_skipped_msg ( & self , skipped : usize ) {
28
+ match skipped {
19
29
0 => { }
20
- 1 => eprintln ! ( " {}" , self . last_skipped_line. unwrap( ) ) ,
21
- _ => eprintln ! ( "... {} lines skipped ..." , self . skipped_lines) ,
30
+ 1 => eprintln ! ( " {}" , self . skipped_lines[ CONTEXT ] ) ,
31
+ _ => eprintln ! ( "... {skipped} lines skipped ..." ) ,
32
+ }
33
+ }
34
+ fn print_start_skip ( & self ) {
35
+ for line in self . skipped_lines . iter ( ) . take ( CONTEXT ) {
36
+ eprintln ! ( " {line}" ) ;
22
37
}
23
- self . skipped_lines = 0 ;
38
+ }
39
+ fn print_skip ( & mut self ) {
40
+ let half = self . skipped_lines . len ( ) / 2 ;
41
+ if !self . print_start_context {
42
+ self . print_start_context = true ;
43
+ self . print_end_skip ( self . skipped_lines . len ( ) . saturating_sub ( CONTEXT ) ) ;
44
+ } else if half < CONTEXT {
45
+ for line in self . skipped_lines . drain ( ..) {
46
+ eprintln ! ( " {line}" ) ;
47
+ }
48
+ } else {
49
+ self . print_start_skip ( ) ;
50
+ let skipped = self . skipped_lines . len ( ) - CONTEXT * 2 ;
51
+ self . print_end_skip ( skipped) ;
52
+ }
53
+ self . skipped_lines . clear ( ) ;
54
+ }
55
+
56
+ fn skip ( & mut self , line : & ' a str ) {
57
+ self . skipped_lines . push ( line) ;
24
58
}
25
59
26
60
fn print_prev ( & mut self ) {
@@ -46,8 +80,7 @@ impl<'a> DiffState<'a> {
46
80
}
47
81
Both ( l, _) => {
48
82
self . print_prev ( ) ;
49
- self . last_skipped_line = Some ( l) ;
50
- self . skipped_lines += 1
83
+ self . skip ( l) ;
51
84
}
52
85
Right ( r) => {
53
86
if let Some ( l) = self . prev_left . take ( ) {
@@ -101,8 +134,9 @@ impl<'a> DiffState<'a> {
101
134
}
102
135
}
103
136
104
- fn finish ( mut self ) {
105
- self . print_skip ( ) ;
137
+ fn finish ( self ) {
138
+ self . print_start_skip ( ) ;
139
+ self . print_skipped_msg ( self . skipped_lines . len ( ) . saturating_sub ( CONTEXT ) ) ;
106
140
eprintln ! ( )
107
141
}
108
142
}
0 commit comments