on master help sign in
Add Git support, closes #8
commita979608f37241fbc41c42fe9326d397658b92ffe authorsharkdp <davidpeter@web.de> dateSat 21 Apr 2018, 17:12 (9 years ago) parente6f823c
3 files changed+239−10
Cargo.lock+144 Cargo.toml+1 src/main.rs+94−10
Cargo.lock+144
@@ -46,6 +46,7 @@ dependencies = [
4646 "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
4747 "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
4848 "console 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
49+ "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
4950 "syntect 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
5051]
5152
@@ -141,6 +142,20 @@ dependencies = [
141142 "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
142143]
143144
145+[[package]]
146+name = "curl-sys"
147+version = "0.4.2"
148+source = "registry+https://github.com/rust-lang/crates.io-index"
149+dependencies = [
150+ "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
151+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
152+ "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
153+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
154+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
155+ "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
156+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
157+]
158+
144159[[package]]
145160name = "dtoa"
146161version = "0.4.2"
@@ -185,6 +200,29 @@ name = "fuchsia-zircon-sys"
185200version = "0.3.3"
186201source = "registry+https://github.com/rust-lang/crates.io-index"
187202
203+[[package]]
204+name = "git2"
205+version = "0.6.11"
206+source = "registry+https://github.com/rust-lang/crates.io-index"
207+dependencies = [
208+ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
209+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
210+ "libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
211+ "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
212+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
213+ "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
214+]
215+
216+[[package]]
217+name = "idna"
218+version = "0.1.4"
219+source = "registry+https://github.com/rust-lang/crates.io-index"
220+dependencies = [
221+ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
222+ "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
223+ "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
224+]
225+
188226[[package]]
189227name = "itoa"
190228version = "0.4.1"
@@ -219,11 +257,54 @@ name = "libc"
219257version = "0.2.40"
220258source = "registry+https://github.com/rust-lang/crates.io-index"
221259
260+[[package]]
261+name = "libgit2-sys"
262+version = "0.6.19"
263+source = "registry+https://github.com/rust-lang/crates.io-index"
264+dependencies = [
265+ "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
266+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
267+ "curl-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
268+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
269+ "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
270+ "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
271+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
272+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
273+]
274+
275+[[package]]
276+name = "libssh2-sys"
277+version = "0.2.6"
278+source = "registry+https://github.com/rust-lang/crates.io-index"
279+dependencies = [
280+ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
281+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
282+ "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
283+ "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)",
284+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
285+]
286+
287+[[package]]
288+name = "libz-sys"
289+version = "1.0.18"
290+source = "registry+https://github.com/rust-lang/crates.io-index"
291+dependencies = [
292+ "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
293+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
294+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
295+ "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
296+]
297+
222298[[package]]
223299name = "linked-hash-map"
224300version = "0.5.1"
225301source = "registry+https://github.com/rust-lang/crates.io-index"
226302
303+[[package]]
304+name = "matches"
305+version = "0.1.6"
306+source = "registry+https://github.com/rust-lang/crates.io-index"
307+
227308[[package]]
228309name = "memchr"
229310version = "2.0.1"
@@ -287,6 +368,22 @@ dependencies = [
287368 "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
288369]
289370
371+[[package]]
372+name = "openssl-probe"
373+version = "0.1.2"
374+source = "registry+https://github.com/rust-lang/crates.io-index"
375+
376+[[package]]
377+name = "openssl-sys"
378+version = "0.9.28"
379+source = "registry+https://github.com/rust-lang/crates.io-index"
380+dependencies = [
381+ "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
382+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
383+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
384+ "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
385+]
386+
290387[[package]]
291388name = "os_pipe"
292389version = "0.6.0"
@@ -325,6 +422,11 @@ dependencies = [
325422 "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
326423]
327424
425+[[package]]
426+name = "percent-encoding"
427+version = "1.0.1"
428+source = "registry+https://github.com/rust-lang/crates.io-index"
429+
328430[[package]]
329431name = "pkg-config"
330432version = "0.3.9"
@@ -571,6 +673,19 @@ name = "ucd-util"
571673version = "0.1.1"
572674source = "registry+https://github.com/rust-lang/crates.io-index"
573675
676+[[package]]
677+name = "unicode-bidi"
678+version = "0.3.4"
679+source = "registry+https://github.com/rust-lang/crates.io-index"
680+dependencies = [
681+ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
682+]
683+
684+[[package]]
685+name = "unicode-normalization"
686+version = "0.1.5"
687+source = "registry+https://github.com/rust-lang/crates.io-index"
688+
574689[[package]]
575690name = "unicode-width"
576691version = "0.1.4"
@@ -589,11 +704,26 @@ dependencies = [
589704 "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
590705]
591706
707+[[package]]
708+name = "url"
709+version = "1.7.0"
710+source = "registry+https://github.com/rust-lang/crates.io-index"
711+dependencies = [
712+ "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
713+ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
714+ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
715+]
716+
592717[[package]]
593718name = "utf8-ranges"
594719version = "1.0.0"
595720source = "registry+https://github.com/rust-lang/crates.io-index"
596721
722+[[package]]
723+name = "vcpkg"
724+version = "0.2.3"
725+source = "registry+https://github.com/rust-lang/crates.io-index"
726+
597727[[package]]
598728name = "void"
599729version = "1.0.2"
@@ -670,19 +800,26 @@ dependencies = [
670800"checksum clicolors-control 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f84dec9bc083ce2503908cd305af98bd363da6f54bf8d4bf0ac14ee749ad5d1"
671801"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
672802"checksum console 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7649ca90478264b9686aac8d269fcb014f14c2bed7c79a7e51b9f6afd4d783eb"
803+"checksum curl-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f7738d877ec81040305d5bb91976ac594f564f5e455dc02a29a23c1d00fe6f"
673804"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
674805"checksum duct 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "166298c17c5b4fe5997b962c2f22e887c7c5adc44308eb9103ce5b66af45a423"
675806"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
676807"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
677808"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
678809"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
810+"checksum git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5b4bb7cd2a44e6e5ee3a26ba6a9ca10d4ce2771cdc3839bbc54b47b7d1be84"
811+"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
679812"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682"
680813"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
681814"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
682815"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
683816"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
684817"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b"
818+"checksum libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6eeae66e7b1c995de45cb4e65c5ab438a96a7b4077e448645d4048dc753ad357"
819+"checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
820+"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16"
685821"checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
822+"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
686823"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
687824"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
688825"checksum nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2c5afeb0198ec7be8569d666644b574345aad2e95a53baf3a532da3e0f3fb32"
@@ -690,10 +827,13 @@ dependencies = [
690827"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364"
691828"checksum onig 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be6b3b3411efa38b2cff84a1925df1bb8b048d4c1d60656617ed7aca9a966dd9"
692829"checksum onig_sys 68.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c6be7c4f985508684e54f18dd37f71e66f3e1ad9318336a520d7e42f0d3ea8e"
830+"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
831+"checksum openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)" = "0bbd90640b148b46305c1691eed6039b5c8509bed16991e3562a01eeb76902a3"
693832"checksum os_pipe 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f547689aea1f11fac90333d573854a8e3e52a9160df1c42aefa8cd16734a3c0"
694833"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
695834"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
696835"checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79"
836+"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
697837"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
698838"checksum plist 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c61ac2afed2856590ae79d6f358a24b85ece246d2aa134741a66d589519b7503"
699839"checksum proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "388d7ea47318c5ccdeb9ba6312cee7d3f65dd2804be8580a170fce410d50b786"
@@ -723,10 +863,14 @@ dependencies = [
723863"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
724864"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098"
725865"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
866+"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
867+"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
726868"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
727869"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
728870"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
871+"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7"
729872"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
873+"checksum vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ed0f6789c8a85ca41bbc1c9d175422116a9869bd1cf31bb08e1493ecce60380"
730874"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
731875"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
732876"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
Cargo.toml+1
@@ -13,6 +13,7 @@ atty = "0.2.2"
1313syntect = "2"
1414ansi_term = "0.9"
1515console = "0.6"
16+git2 = "0.6"
1617
1718[dependencies.clap]
1819version = "2"
src/main.rs+94−10
@@ -1,59 +1,143 @@
11extern crate ansi_term;
22extern crate atty;
33extern crate console;
4+extern crate git2;
45extern crate syntect;
56
67#[macro_use]
78extern crate clap;
89
9−use std::io::{BufRead, Result};
10+use std::collections::HashMap;
11+use std::io::{self, BufRead, Result};
1012use std::path::Path;
1113use std::process;
1214
13−use ansi_term::Colour::Fixed;
15+use ansi_term::Colour::{Fixed, Green, Red, Yellow};
1416use atty::Stream;
1517use clap::{App, AppSettings, Arg, ArgMatches};
1618use console::Term;
19+use git2::{DiffOptions, IntoCString, Repository};
1720
1821use syntect::easy::HighlightFile;
1922use syntect::highlighting::ThemeSet;
2023use syntect::parsing::SyntaxSet;
2124use syntect::util::as_24_bit_terminal_escaped;
2225
23−fn print_file<P: AsRef<Path>>(filename: P) -> Result<()> {
26+#[derive(Copy, Clone, Debug)]
27+enum LineChange {
28+ Added,
29+ RemovedAbove,
30+ RemovedBelow,
31+ Modified,
32+}
33+
34+type LineChanges = HashMap<u32, LineChange>;
35+
36+fn print_file<P: AsRef<Path>>(filename: P, line_changes: Option<LineChanges>) -> io::Result<()> {
2437 let ss = SyntaxSet::load_defaults_nonewlines();
2538 let ts = ThemeSet::load_from_folder("/home/shark/Informatik/rust/bat/themes").unwrap();
2639 let theme = &ts.themes["Monokai"];
2740
28− let mut highlighter = HighlightFile::new(filename, &ss, theme).unwrap();
41+ let mut highlighter = HighlightFile::new(filename, &ss, theme)?;
2942
3043 let term = Term::stdout();
3144 let (_height, width) = term.size();
3245
33− println!("{}", width);
34− let prefix = " ┌";
46+ let prefix = "───────┬";
3547 let line = "─".repeat(width as usize - prefix.len());
3648 println!("{}{}", Fixed(238).paint(prefix), Fixed(238).paint(line));
3749
38− for (line_nr, maybe_line) in highlighter.reader.lines().enumerate() {
50+ for (idx, maybe_line) in highlighter.reader.lines().enumerate() {
51+ let line_nr = idx + 1;
3952 let line = maybe_line.unwrap_or("<INVALID UTF-8>".into());
4053 let regions = highlighter.highlight_lines.highlight(&line);
4154
55+ let line_change = if let Some(ref changes) = line_changes {
56+ match changes.get(&(line_nr as u32)) {
57+ Some(&LineChange::Added) => Green.paint("+"),
58+ Some(&LineChange::RemovedAbove) => Red.paint("‾"),
59+ Some(&LineChange::RemovedBelow) => Red.paint("_"),
60+ Some(&LineChange::Modified) => Yellow.paint("~"),
61+ _ => Fixed(1).paint(" "), // TODO
62+ }
63+ } else {
64+ Fixed(1).paint(" ") // TODO
65+ };
66+
4267 println!(
43− "{} {} {}",
68+ "{} {} {} {}",
4469 Fixed(244).paint(format!("{:4}", line_nr)),
70+ line_change,
4571 Fixed(238).paint("│"),
4672 as_24_bit_terminal_escaped(&regions, false)
4773 );
4874 }
4975
76+ let prefix = "───────┴";
77+ let line = "─".repeat(width as usize - prefix.len());
78+ println!("{}{}", Fixed(238).paint(prefix), Fixed(238).paint(line));
79+
5080 Ok(())
5181}
5282
83+fn get_line_changes(filename: String) -> Option<LineChanges> {
84+ let repo = Repository::open_from_env().ok()?;
85+
86+ let mut diff_options = DiffOptions::new();
87+ diff_options.pathspec(filename.into_c_string().unwrap());
88+ diff_options.context_lines(0);
89+
90+ let diff = repo.diff_index_to_workdir(None, Some(&mut diff_options))
91+ .unwrap();
92+
93+ let mut line_changes: LineChanges = HashMap::new();
94+
95+ let mark_section =
96+ |line_changes: &mut LineChanges, start: u32, end: i32, change: LineChange| {
97+ for line in start..(end + 1) as u32 {
98+ line_changes.insert(line, change);
99+ }
100+ };
101+
102+ let _ = diff.foreach(
103+ &mut |_, _| true,
104+ None,
105+ Some(&mut |_, hunk| {
106+ let old_lines = hunk.old_lines();
107+ let new_start = hunk.new_start();
108+ let new_lines = hunk.new_lines();
109+ let new_end = (new_start + new_lines) as i32 - 1;
110+
111+ if old_lines == 0 && new_lines > 0 {
112+ mark_section(&mut line_changes, new_start, new_end, LineChange::Added);
113+ } else if new_lines == 0 && old_lines > 0 {
114+ if new_start <= 0 {
115+ mark_section(&mut line_changes, 1, 1, LineChange::RemovedAbove);
116+ } else {
117+ mark_section(
118+ &mut line_changes,
119+ new_start,
120+ new_start as i32,
121+ LineChange::RemovedBelow,
122+ );
123+ }
124+ } else {
125+ mark_section(&mut line_changes, new_start, new_end, LineChange::Modified);
126+ }
127+
128+ true
129+ }),
130+ None,
131+ );
132+
133+ Some(line_changes)
134+}
135+
53136fn run(matches: &ArgMatches) -> Result<()> {
54137 if let Some(files) = matches.values_of("file") {
55138 for file in files {
56− print_file(file)?;
139+ let line_changes = get_line_changes(file.to_string());
140+ print_file(file, line_changes)?;
57141 }
58142 }
59143
@@ -88,7 +172,7 @@ fn main() {
88172 let result = run(&matches);
89173
90174 if let Err(e) = result {
91− eprintln!("Error: {}", e);
175+ eprintln!("{}: {}", Red.paint("bat error"), e);
92176 process::exit(1);
93177 }
94178}