@@ -3,7 +3,7 @@ use std::{
33 env:: ArgsOs ,
44 ffi:: OsString ,
55 fs,
6- io:: { stdin, Read , Write } ,
6+ io:: { self , stdin, Read , StdoutLock , Write } ,
77 iter:: Peekable ,
88 process:: ExitCode ,
99 vec,
@@ -45,59 +45,56 @@ pub fn main(opts: Peekable<ArgsOs>) -> ExitCode {
4545 // first we need to get the properly files
4646 let file1 = read_file_contents ( & params. file1 ) ;
4747 let file2 = read_file_contents ( & params. file2 ) ;
48-
49- // now we get the lines from the files as bytes, cuz the sdiff
48+
49+ // now we get the lines from the files as bytes, cuz the sdiff
5050 // must be compatible with ut8, ascii etc.
5151 let mut lines_left: Vec < & [ u8 ] > = file1. split ( |& c| c == b'\n' ) . collect ( ) ;
52- let mut lines_rght : Vec < & [ u8 ] > = file2. split ( |& c| c == b'\n' ) . collect ( ) ;
52+ let mut lines_right : Vec < & [ u8 ] > = file2. split ( |& c| c == b'\n' ) . collect ( ) ;
5353
54- // for some reason, the original file appends a empty line at
54+ // for some reason, the original file appends a empty line at
5555 // the end of file. I did not search for it, but my guess is
5656 // that this is EOL or an zeroed terminated file. Just remove it
5757 if lines_left. last ( ) == Some ( & & b"" [ ..] ) {
5858 lines_left. pop ( ) ;
5959 }
6060
61- if lines_rght . last ( ) == Some ( & & b"" [ ..] ) {
62- lines_rght . pop ( ) ;
61+ if lines_right . last ( ) == Some ( & & b"" [ ..] ) {
62+ lines_right . pop ( ) ;
6363 }
6464
65- let mut output: Vec < u8 > = Vec :: new ( ) ;
6665 let width = 60 ;
67- let max_lines = lines_left. len ( ) . max ( lines_rght. len ( ) ) ;
68-
69- // ok, now we start running over the lines and get the lines right
70- // and left file
71- for i in 0 ..max_lines {
72- // now we convert the bytes to utf8. May the file is encoded with invalid chars,
73- // so it can result in a line with �.
74- let left = lines_left. get ( i) . map ( |l| String :: from_utf8_lossy ( l) ) ;
75- let right = lines_rght. get ( i) . map ( |r| String :: from_utf8_lossy ( r) ) ;
76-
77- match ( left, right) {
78- ( Some ( l) , Some ( r) ) if l == r => {
79- // this is nice, cuz if the line is empty we stiill can print it, cause it equal : )
80- writeln ! ( output, "{:<width$} {}" , l, r, width = width) . unwrap ( ) ;
81- }
82- ( Some ( l) , Some ( r) ) => {
83- // if both lines are present but not equal, they are different, just print with |
84- writeln ! ( output, "{:<width$} | {}" , l, r, width = width) . unwrap ( ) ;
66+ let max_lines = lines_left. len ( ) . max ( lines_right. len ( ) ) ;
67+
68+ fn write_line (
69+ out : & mut StdoutLock ,
70+ left : & [ u8 ] ,
71+ right : & [ u8 ] ,
72+ middle : & [ u8 ] ,
73+ width : usize ,
74+ ) -> io:: Result < ( ) > {
75+ let count = out. write ( left. get ( ..width) . unwrap_or ( left) ) ?;
76+ write ! ( out, "{}" , " " . repeat( width - count) ) ?;
77+ out. write ( middle) ?;
78+ out. write ( right. get ( ..width) . unwrap_or ( right) ) ?;
79+ Ok ( ( ) )
80+ }
81+
82+ let mut out = io:: stdout ( ) . lock ( ) ;
83+ for result in diff:: slice ( & lines_left, & lines_right) {
84+ match result {
85+ diff:: Result :: Left ( str) => {
86+ write_line ( & mut out, str, & [ ] , b" < " , width) . unwrap ( ) ;
8587 }
86- ( Some ( l) , None ) => {
87- // we have only left val, so print it with <
88- writeln ! ( output, "{:<width$} <" , l, width = width) . unwrap ( ) ;
88+ diff:: Result :: Right ( str) => {
89+ write_line ( & mut out, & [ ] , & str, b" > " , width) . unwrap ( ) ;
8990 }
90- ( None , Some ( r) ) => {
91- // we have only the ...
92- writeln ! ( output, "{:<width$} > {}" , "" , r, width = width) . unwrap ( ) ;
91+ diff:: Result :: Both ( str_l, str_r) => {
92+ write_line ( & mut out, str_l, str_r, b" " , width) . unwrap ( ) ;
9393 }
94- _ => { }
9594 }
95+ writeln ! ( & mut out) . unwrap ( ) ;
9696 }
9797
98- // now print the line at stdout
99- println ! ( "{}" , String :: from_utf8( output) . unwrap( ) ) ;
100-
10198 ExitCode :: SUCCESS
10299}
103100
0 commit comments