From ea955c734dd9c2796c7e8c49f6054bd045be910d Mon Sep 17 00:00:00 2001 From: sharkdp Date: Thu, 23 Aug 2018 19:43:10 +0200 Subject: [PATCH] Refactoring, introduce Printer trait --- src/app.rs | 6 +++-- src/decorations.rs | 16 ++++++----- src/features.rs | 32 ++++++++++++---------- src/main.rs | 7 ++++- src/printer.rs | 67 +++++++++++++++++++++++++++------------------- 5 files changed, 77 insertions(+), 51 deletions(-) diff --git a/src/app.rs b/src/app.rs index 1a5c973c..0f9c0714 100644 --- a/src/app.rs +++ b/src/app.rs @@ -32,8 +32,8 @@ pub struct Config<'a> { /// The character width of the terminal pub term_width: usize, - /// Whether or not the terminal is interactive - pub interactive_output: bool, + /// Whether or not to simply loop through all input (`cat` mode) + pub loop_through: bool, /// Whether or not the output should be colorized pub colored_output: bool, @@ -336,6 +336,8 @@ impl App { }, }, term_width: Term::stdout().size().1 as usize, + loop_through: self.interactive_output + && self.matches.value_of("color") != Some("always"), files, theme: self .matches diff --git a/src/decorations.rs b/src/decorations.rs index 9d779438..7eceb280 100644 --- a/src/decorations.rs +++ b/src/decorations.rs @@ -1,6 +1,6 @@ use ansi_term::Style; use diff::LineChange; -use printer::{Colors, Printer}; +use printer::{Colors, InteractivePrinter}; #[derive(Clone)] pub struct DecorationText { @@ -9,8 +9,12 @@ pub struct DecorationText { } pub trait Decoration { - fn generate(&self, line_number: usize, continuation: bool, printer: &Printer) - -> DecorationText; + fn generate( + &self, + line_number: usize, + continuation: bool, + printer: &InteractivePrinter, + ) -> DecorationText; fn width(&self) -> usize; } @@ -38,7 +42,7 @@ impl Decoration for LineNumberDecoration { &self, line_number: usize, continuation: bool, - _printer: &Printer, + _printer: &InteractivePrinter, ) -> DecorationText { if continuation { if line_number > self.cached_wrap_invalid_at { @@ -97,7 +101,7 @@ impl Decoration for LineChangesDecoration { &self, line_number: usize, continuation: bool, - printer: &Printer, + printer: &InteractivePrinter, ) -> DecorationText { if !continuation { if let Some(ref changes) = printer.line_changes { @@ -139,7 +143,7 @@ impl Decoration for GridBorderDecoration { &self, _line_number: usize, _continuation: bool, - _printer: &Printer, + _printer: &InteractivePrinter, ) -> DecorationText { self.cached.clone() } diff --git a/src/features.rs b/src/features.rs index ff293fdb..5d20c929 100644 --- a/src/features.rs +++ b/src/features.rs @@ -13,7 +13,7 @@ use diff::get_git_diff; use errors::*; use line_range::LineRange; use output::OutputType; -use printer::Printer; +use printer::{InteractivePrinter, Printer}; pub fn list_languages(assets: &HighlightingAssets, term_width: usize) { let mut languages = assets @@ -72,7 +72,7 @@ pub fn print_files(assets: &HighlightingAssets, config: &Config) -> Result let mut output_type = OutputType::from_mode(config.paging_mode); let handle = output_type.handle()?; - let mut printer = Printer::new(handle, &config, &theme); + let mut printer = InteractivePrinter::new(handle, &config, &theme); let mut no_errors: bool = true; for file in &config.files { @@ -80,7 +80,7 @@ pub fn print_files(assets: &HighlightingAssets, config: &Config) -> Result printer.line_changes = file.and_then(|filename| get_git_diff(filename)); let syntax = assets.get_syntax(config.language, *file); - let result = print_file(theme, &syntax, &mut printer, *file); + let result = print_file(config, theme, &syntax, &mut printer, *file); if let Err(error) = result { handle_error(&error); @@ -91,13 +91,14 @@ pub fn print_files(assets: &HighlightingAssets, config: &Config) -> Result Ok(no_errors) } -fn print_file( +fn print_file( + config: &Config, theme: &Theme, syntax: &SyntaxDefinition, - printer: &mut Printer, + printer: &mut P, filename: Option<&str>, ) -> Result<()> { - let stdin = io::stdin(); // TODO: this variable is not always needed + let stdin = io::stdin(); { let reader: Box = match filename { None => Box::new(stdin.lock()), @@ -107,20 +108,22 @@ fn print_file( let highlighter = HighlightLines::new(syntax, theme); printer.print_header(filename)?; - print_file_ranges(printer, reader, highlighter, &printer.config.line_range)?; + print_file_ranges(printer, reader, highlighter, &config.line_range)?; printer.print_footer()?; } Ok(()) } -fn print_file_ranges<'a>( - printer: &mut Printer, +fn print_file_ranges<'a, P: Printer>( + printer: &mut P, mut reader: Box, mut highlighter: HighlightLines, line_ranges: &Option, ) -> Result<()> { let mut buffer = Vec::new(); + let mut line_number: usize = 1; + while reader.read_until(b'\n', &mut buffer)? > 0 { { let line = String::from_utf8_lossy(&buffer); @@ -128,20 +131,21 @@ fn print_file_ranges<'a>( match line_ranges { &Some(ref range) => { - if printer.line_number + 1 < range.lower { + if line_number < range.lower { // skip line - printer.line_number += 1; - } else if printer.line_number >= range.upper { + } else if line_number > range.upper { // no more lines in range break; } else { - printer.print_line(®ions)?; + printer.print_line(line_number, ®ions)?; } } &None => { - printer.print_line(®ions)?; + printer.print_line(line_number, ®ions)?; } } + + line_number += 1; } buffer.clear(); } diff --git a/src/main.rs b/src/main.rs index 80e772b8..098f597e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -104,7 +104,12 @@ fn run() -> Result { Ok(true) } else { - print_files(&assets, &config) + if config.loop_through { + // TODO + print_files(&assets, &config) + } else { + print_files(&assets, &config) + } } } } diff --git a/src/printer.rs b/src/printer.rs index 2d156806..3ab75089 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -16,18 +16,27 @@ use errors::*; use style::OutputWrap; use terminal::{as_terminal_escaped, to_ansi_color}; -pub struct Printer<'a> { +pub trait Printer { + fn print_header(&mut self, filename: Option<&str>) -> Result<()>; + fn print_footer(&mut self) -> Result<()>; + fn print_line( + &mut self, + line_number: usize, + regions: &[(highlighting::Style, &str)], + ) -> Result<()>; +} + +pub struct InteractivePrinter<'a> { handle: &'a mut Write, colors: Colors, pub config: &'a Config<'a>, decorations: Vec>, panel_width: usize, pub ansi_prefix_sgr: String, - pub line_number: usize, pub line_changes: Option, } -impl<'a> Printer<'a> { +impl<'a> InteractivePrinter<'a> { pub fn new(handle: &'a mut Write, config: &'a Config, theme: &Theme) -> Self { let colors = if config.colored_output { Colors::colored(theme, config.true_color) @@ -66,21 +75,36 @@ impl<'a> Printer<'a> { } // Create printer. - Printer { + InteractivePrinter { panel_width, handle, colors, config, decorations, ansi_prefix_sgr: String::new(), - line_number: 0, line_changes: None, } } - pub fn print_header(&mut self, filename: Option<&str>) -> Result<()> { - self.line_number = 0; + fn print_horizontal_line(&mut self, grid_char: char) -> Result<()> { + if self.panel_width == 0 { + writeln!( + self.handle, + "{}", + self.colors.grid.paint("─".repeat(self.config.term_width)) + )?; + } else { + let hline = "─".repeat(self.config.term_width - (self.panel_width + 1)); + let hline = format!("{}{}{}", "─".repeat(self.panel_width), grid_char, hline); + writeln!(self.handle, "{}", self.colors.grid.paint(hline))?; + } + Ok(()) + } +} + +impl<'a> Printer for InteractivePrinter<'a> { + fn print_header(&mut self, filename: Option<&str>) -> Result<()> { if !self.config.output_components.header() { return Ok(()); } @@ -114,7 +138,7 @@ impl<'a> Printer<'a> { Ok(()) } - pub fn print_footer(&mut self) -> Result<()> { + fn print_footer(&mut self) -> Result<()> { if self.config.output_components.grid() { self.print_horizontal_line('┴') } else { @@ -122,8 +146,11 @@ impl<'a> Printer<'a> { } } - pub fn print_line(&mut self, regions: &[(highlighting::Style, &str)]) -> Result<()> { - self.line_number += 1; + fn print_line( + &mut self, + line_number: usize, + regions: &[(highlighting::Style, &str)], + ) -> Result<()> { let mut cursor: usize = 0; let mut cursor_max: usize = self.config.term_width; let mut panel_wrap: Option = None; @@ -133,7 +160,7 @@ impl<'a> Printer<'a> { let decorations = self .decorations .iter() - .map(|ref d| d.generate(self.line_number, false, self)) + .map(|ref d| d.generate(line_number, false, self)) .collect::>(); for deco in decorations { @@ -218,7 +245,7 @@ impl<'a> Printer<'a> { self.decorations .iter() .map(|ref d| d - .generate(self.line_number, true, self) + .generate(line_number, true, self) .text).collect::>() .join(" ") )) @@ -260,22 +287,6 @@ impl<'a> Printer<'a> { Ok(()) } - - fn print_horizontal_line(&mut self, grid_char: char) -> Result<()> { - if self.panel_width == 0 { - writeln!( - self.handle, - "{}", - self.colors.grid.paint("─".repeat(self.config.term_width)) - )?; - } else { - let hline = "─".repeat(self.config.term_width - (self.panel_width + 1)); - let hline = format!("{}{}{}", "─".repeat(self.panel_width), grid_char, hline); - writeln!(self.handle, "{}", self.colors.grid.paint(hline))?; - } - - Ok(()) - } } const DEFAULT_GUTTER_COLOR: u8 = 238;