@@ -66,6 +66,7 @@ struct Options<'a> {
6666 style: OptionsStyle,
6767 language: Option<&'a str>,
6868 interactive_terminal: bool,
69+ colored_output: bool,
6970}
7071
7172enum OutputType<'a> {
@@ -115,16 +116,45 @@ type LineChanges = HashMap<u32, LineChange>;
115116
116117const PANEL_WIDTH: usize = 7;
117118const GRID_COLOR: u8 = 238;
119+const LINE_NUMBER_COLOR: u8 = 244;
120+
121+#[derive(Default)]
122+struct Colors {
123+ grid: Style,
124+ filename: Style,
125+ git_added: Style,
126+ git_removed: Style,
127+ git_modified: Style,
128+ line_number: Style,
129+}
130+
131+impl Colors {
132+ fn plain() -> Self {
133+ Colors::default()
134+ }
135+
136+ fn colored() -> Self {
137+ Colors {
138+ grid: Fixed(GRID_COLOR).normal(),
139+ filename: White.bold(),
140+ git_added: Green.normal(),
141+ git_removed: Red.normal(),
142+ git_modified: Yellow.normal(),
143+ line_number: Fixed(LINE_NUMBER_COLOR).normal(),
144+ }
145+ }
146+}
118147
119148fn print_horizontal_line(
120149 handle: &mut Write,
150+ grid_color: &Style,
121151 grid_char: char,
122152 term_width: usize,
123153) -> Result<()> {
124154 let hline = "─".repeat(term_width - (PANEL_WIDTH + 1));
125155 let hline = format!("{}{}{}", "─".repeat(PANEL_WIDTH), grid_char, hline);
126156
127− writeln!(handle, "{}", Fixed(GRID_COLOR).paint(hline))?;
157+ writeln!(handle, "{}", grid_color.paint(hline))?;
128158
129159 Ok(())
130160}
@@ -144,6 +174,7 @@ fn print_file<P: AsRef<Path>>(
144174 .find(|syntax| syntax.name.eq_ignore_ascii_case(language)),
145175 None => syntax_set.find_syntax_for_file(filename.as_ref())?,
146176 };
177+
147178 let syntax = syntax.unwrap_or_else(|| syntax_set.find_syntax_plain_text());
148179 let mut highlighter = HighlightLines::new(syntax, theme);
149180
@@ -156,26 +187,32 @@ fn print_file<P: AsRef<Path>>(
156187 } else {
157188 OutputType::new_stdout(&stdout)
158189 };
159− let mut handle = output_type.stdout()?;
190+ let handle = output_type.stdout()?;
160191
161192 let term = Term::stdout();
162193 let (_, term_width) = term.size();
163194 let term_width = term_width as usize;
164195
196+ let colors = if options.colored_output {
197+ Colors::colored()
198+ } else {
199+ Colors::plain()
200+ };
201+
165202 // Show file name and bars for all but plain style
166203 match options.style {
167204 OptionsStyle::LineNumbers | OptionsStyle::Full => {
168− print_horizontal_line(&mut handle, '┬', term_width)?;
205+ print_horizontal_line(handle, &colors.grid, '┬', term_width)?;
169206
170207 writeln!(
171208 handle,
172209 "{}{} File {}",
173210 " ".repeat(PANEL_WIDTH),
174− Fixed(GRID_COLOR).paint("│"),
175− White.bold().paint(filename.as_ref().to_string_lossy())
211+ colors.grid.paint("│"),
212+ colors.filename.paint(filename.as_ref().to_string_lossy())
176213 )?;
177214
178− print_horizontal_line(handle, '┼', term_width)?;
215+ print_horizontal_line(handle, &colors.grid, '┼', term_width)?;
179216 }
180217 OptionsStyle::Plain => {}
181218 };
@@ -188,10 +225,10 @@ fn print_file<P: AsRef<Path>>(
188225
189226 let line_change = if let Some(ref changes) = *line_changes {
190227 match changes.get(&(line_nr as u32)) {
191− Some(&LineChange::Added) => Green.paint("+"),
192− Some(&LineChange::RemovedAbove) => Red.paint("‾"),
193− Some(&LineChange::RemovedBelow) => Red.paint("_"),
194− Some(&LineChange::Modified) => Yellow.paint("~"),
228+ Some(&LineChange::Added) => colors.git_added.paint("+"),
229+ Some(&LineChange::RemovedAbove) => colors.git_removed.paint("‾"),
230+ Some(&LineChange::RemovedBelow) => colors.git_removed.paint("_"),
231+ Some(&LineChange::Modified) => colors.git_modified.paint("~"),
195232 _ => Style::default().paint(" "),
196233 }
197234 } else {
@@ -202,19 +239,19 @@ fn print_file<P: AsRef<Path>>(
202239 // Show only content for plain style
203240 OptionsStyle::Plain => writeln!(
204241 handle,
205− "{}", as_terminal_escaped(®ions, options.true_color))?,
242+ "{}", as_terminal_escaped(®ions, options.true_color, options.colored_output))?,
206243 _ =>
207244 writeln!(
208245 handle,
209246 "{} {} {} {}",
210− Fixed(244).paint(format!("{:4}", line_nr)),
211− // Show git modificiation markers only for full style
247+ colors.line_number.paint(format!("{:4}", line_nr)),
248+ // Show git modification markers only for full style
212249 match options.style {
213250 OptionsStyle::Full => line_change,
214251 _ => Style::default().paint(" "),
215252 },
216− Fixed(GRID_COLOR).paint("│"),
217− as_terminal_escaped(®ions, options.true_color)
253+ colors.grid.paint("│"),
254+ as_terminal_escaped(®ions, options.true_color, options.colored_output)
218255 )?
219256 }
220257 }
@@ -222,7 +259,7 @@ fn print_file<P: AsRef<Path>>(
222259 // Show bars for all but plain style
223260 match options.style {
224261 OptionsStyle::LineNumbers | OptionsStyle::Full =>
225− print_horizontal_line(handle, '┴', term_width)?,
262+ print_horizontal_line(handle, &colors.grid, '┴', term_width)?,
226263 OptionsStyle::Plain => {}
227264 };
228265
@@ -448,7 +485,16 @@ fn run() -> Result<()> {
448485 .long("style")
449486 .possible_values(&["plain", "line-numbers", "full"])
450487 .default_value("full")
451− .help("Additional info to display alongwith content"),
488+ .help("Additional info to display along with content"),
489+ )
490+ .arg(
491+ Arg::with_name("color")
492+ .short("c")
493+ .long("color")
494+ .takes_value(true)
495+ .possible_values(&["auto", "never", "always"])
496+ .default_value("auto")
497+ .help("When to use colors")
452498 )
453499 .subcommand(
454500 SubCommand::with_name("init-cache")
@@ -473,6 +519,11 @@ fn run() -> Result<()> {
473519 },
474520 language: app_matches.value_of("language"),
475521 interactive_terminal,
522+ colored_output: match app_matches.value_of("color") {
523+ Some("always") => true,
524+ Some("never") => false,
525+ _ => interactive_terminal,
526+ },
476527 };
477528
478529 let assets =