@@ -1,9 +1,13 @@
11use std::io::{self, Write};
22
33use crate::assets::HighlightingAssets;
4−use crate::config::Config;
4+use crate::config::{Config, VisibleLines};
5+#[cfg(feature = "git")]
6+use crate::diff::{get_git_diff, LineChanges};
57use crate::error::*;
68use crate::input::{Input, InputReader, OpenedInput};
9+#[cfg(feature = "git")]
10+use crate::line_range::LineRange;
711use crate::line_range::{LineRanges, RangeCheckResult};
812use crate::output::OutputType;
913#[cfg(feature = "paging")]
@@ -68,6 +72,32 @@ impl<'b> Controller<'b> {
6872 no_errors = false;
6973 }
7074 Ok(mut opened_input) => {
75+ #[cfg(feature = "git")]
76+ let line_changes = if self.config.visible_lines.diff_context()
77+ || (!self.config.loop_through && self.config.style_components.changes())
78+ {
79+ if let crate::input::OpenedInputKind::OrdinaryFile(ref path) =
80+ opened_input.kind
81+ {
82+ let diff = get_git_diff(path);
83+
84+ if self.config.visible_lines.diff_context()
85+ && diff
86+ .as_ref()
87+ .map(|changes| changes.is_empty())
88+ .unwrap_or(false)
89+ {
90+ continue;
91+ }
92+
93+ diff
94+ } else {
95+ None
96+ }
97+ } else {
98+ None
99+ };
100+
71101 let mut printer: Box<dyn Printer> = if self.config.loop_through {
72102 Box::new(SimplePrinter::new())
73103 } else {
@@ -75,10 +105,18 @@ impl<'b> Controller<'b> {
75105 &self.config,
76106 &self.assets,
77107 &mut opened_input,
108+ #[cfg(feature = "git")]
109+ &line_changes,
78110 ))
79111 };
80112
81− let result = self.print_file(&mut *printer, writer, &mut opened_input);
113+ let result = self.print_file(
114+ &mut *printer,
115+ writer,
116+ &mut opened_input,
117+ #[cfg(feature = "git")]
118+ &line_changes,
119+ );
82120
83121 if let Err(error) = result {
84122 handle_error(&error);
@@ -96,13 +134,31 @@ impl<'b> Controller<'b> {
96134 printer: &mut dyn Printer,
97135 writer: &mut dyn Write,
98136 input: &mut OpenedInput,
137+ #[cfg(feature = "git")] line_changes: &Option<LineChanges>,
99138 ) -> Result<()> {
100139 if !input.reader.first_line.is_empty() || self.config.style_components.header() {
101140 printer.print_header(writer, input)?;
102141 }
103142
104143 if !input.reader.first_line.is_empty() {
105− self.print_file_ranges(printer, writer, &mut input.reader, &self.config.line_ranges)?;
144+ let line_ranges = match self.config.visible_lines {
145+ VisibleLines::Ranges(ref line_ranges) => line_ranges.clone(),
146+ #[cfg(feature = "git")]
147+ VisibleLines::DiffContext(context) => {
148+ let mut line_ranges: Vec<LineRange> = vec![];
149+
150+ if let Some(line_changes) = line_changes {
151+ for line in line_changes.keys() {
152+ let line = *line as usize;
153+ line_ranges.push(LineRange::new(line - context, line + context));
154+ }
155+ }
156+
157+ LineRanges::from(line_ranges)
158+ }
159+ };
160+
161+ self.print_file_ranges(printer, writer, &mut input.reader, &line_ranges)?;
106162 }
107163 printer.print_footer(writer, input)?;
108164