on master help sign in
Refactoring, introduce Printer trait
commitea955c734dd9c2796c7e8c49f6054bd045be910d authorsharkdp <davidpeter@web.de> dateThu 23 Aug 2018, 19:43 (8 years ago) parent6223ad6
5 files changed+77−51
src/app.rs+4−2 src/decorations.rs+10−6 src/features.rs+18−14 src/main.rs+6−1 src/printer.rs+39−28
src/app.rs+4−2
@@ -32,8 +32,8 @@ pub struct Config<'a> {
3232 /// The character width of the terminal
3333 pub term_width: usize,
3434
35− /// Whether or not the terminal is interactive
36− pub interactive_output: bool,
35+ /// Whether or not to simply loop through all input (`cat` mode)
36+ pub loop_through: bool,
3737
3838 /// Whether or not the output should be colorized
3939 pub colored_output: bool,
@@ -336,6 +336,8 @@ impl App {
336336 },
337337 },
338338 term_width: Term::stdout().size().1 as usize,
339+ loop_through: self.interactive_output
340+ && self.matches.value_of("color") != Some("always"),
339341 files,
340342 theme: self
341343 .matches
src/decorations.rs+10−6
@@ -1,6 +1,6 @@
11use ansi_term::Style;
22use diff::LineChange;
3−use printer::{Colors, Printer};
3+use printer::{Colors, InteractivePrinter};
44
55#[derive(Clone)]
66pub struct DecorationText {
@@ -9,8 +9,12 @@ pub struct DecorationText {
99}
1010
1111pub trait Decoration {
12− fn generate(&self, line_number: usize, continuation: bool, printer: &Printer)
13− -> DecorationText;
12+ fn generate(
13+ &self,
14+ line_number: usize,
15+ continuation: bool,
16+ printer: &InteractivePrinter,
17+ ) -> DecorationText;
1418 fn width(&self) -> usize;
1519}
1620
@@ -38,7 +42,7 @@ impl Decoration for LineNumberDecoration {
3842 &self,
3943 line_number: usize,
4044 continuation: bool,
41− _printer: &Printer,
45+ _printer: &InteractivePrinter,
4246 ) -> DecorationText {
4347 if continuation {
4448 if line_number > self.cached_wrap_invalid_at {
@@ -97,7 +101,7 @@ impl Decoration for LineChangesDecoration {
97101 &self,
98102 line_number: usize,
99103 continuation: bool,
100− printer: &Printer,
104+ printer: &InteractivePrinter,
101105 ) -> DecorationText {
102106 if !continuation {
103107 if let Some(ref changes) = printer.line_changes {
@@ -139,7 +143,7 @@ impl Decoration for GridBorderDecoration {
139143 &self,
140144 _line_number: usize,
141145 _continuation: bool,
142− _printer: &Printer,
146+ _printer: &InteractivePrinter,
143147 ) -> DecorationText {
144148 self.cached.clone()
145149 }
src/features.rs+18−14
@@ -13,7 +13,7 @@ use diff::get_git_diff;
1313use errors::*;
1414use line_range::LineRange;
1515use output::OutputType;
16−use printer::Printer;
16+use printer::{InteractivePrinter, Printer};
1717
1818pub fn list_languages(assets: &HighlightingAssets, term_width: usize) {
1919 let mut languages = assets
@@ -72,7 +72,7 @@ pub fn print_files(assets: &HighlightingAssets, config: &Config) -> Result<bool>
7272
7373 let mut output_type = OutputType::from_mode(config.paging_mode);
7474 let handle = output_type.handle()?;
75− let mut printer = Printer::new(handle, &config, &theme);
75+ let mut printer = InteractivePrinter::new(handle, &config, &theme);
7676 let mut no_errors: bool = true;
7777
7878 for file in &config.files {
@@ -80,7 +80,7 @@ pub fn print_files(assets: &HighlightingAssets, config: &Config) -> Result<bool>
8080 printer.line_changes = file.and_then(|filename| get_git_diff(filename));
8181 let syntax = assets.get_syntax(config.language, *file);
8282
83− let result = print_file(theme, &syntax, &mut printer, *file);
83+ let result = print_file(config, theme, &syntax, &mut printer, *file);
8484
8585 if let Err(error) = result {
8686 handle_error(&error);
@@ -91,13 +91,14 @@ pub fn print_files(assets: &HighlightingAssets, config: &Config) -> Result<bool>
9191 Ok(no_errors)
9292}
9393
94−fn print_file(
94+fn print_file<P: Printer>(
95+ config: &Config,
9596 theme: &Theme,
9697 syntax: &SyntaxDefinition,
97− printer: &mut Printer,
98+ printer: &mut P,
9899 filename: Option<&str>,
99100) -> Result<()> {
100− let stdin = io::stdin(); // TODO: this variable is not always needed
101+ let stdin = io::stdin();
101102 {
102103 let reader: Box<BufRead> = match filename {
103104 None => Box::new(stdin.lock()),
@@ -107,20 +108,22 @@ fn print_file(
107108 let highlighter = HighlightLines::new(syntax, theme);
108109
109110 printer.print_header(filename)?;
110− print_file_ranges(printer, reader, highlighter, &printer.config.line_range)?;
111+ print_file_ranges(printer, reader, highlighter, &config.line_range)?;
111112 printer.print_footer()?;
112113 }
113114 Ok(())
114115}
115116
116−fn print_file_ranges<'a>(
117− printer: &mut Printer,
117+fn print_file_ranges<'a, P: Printer>(
118+ printer: &mut P,
118119 mut reader: Box<BufRead + 'a>,
119120 mut highlighter: HighlightLines,
120121 line_ranges: &Option<LineRange>,
121122) -> Result<()> {
122123 let mut buffer = Vec::new();
123124
125+ let mut line_number: usize = 1;
126+
124127 while reader.read_until(b'\n', &mut buffer)? > 0 {
125128 {
126129 let line = String::from_utf8_lossy(&buffer);
@@ -128,20 +131,21 @@ fn print_file_ranges<'a>(
128131
129132 match line_ranges {
130133 &Some(ref range) => {
131− if printer.line_number + 1 < range.lower {
134+ if line_number < range.lower {
132135 // skip line
133− printer.line_number += 1;
134− } else if printer.line_number >= range.upper {
136+ } else if line_number > range.upper {
135137 // no more lines in range
136138 break;
137139 } else {
138− printer.print_line(&regions)?;
140+ printer.print_line(line_number, &regions)?;
139141 }
140142 }
141143 &None => {
142− printer.print_line(&regions)?;
144+ printer.print_line(line_number, &regions)?;
143145 }
144146 }
147+
148+ line_number += 1;
145149 }
146150 buffer.clear();
147151 }
src/main.rs+6−1
@@ -104,7 +104,12 @@ fn run() -> Result<bool> {
104104
105105 Ok(true)
106106 } else {
107− print_files(&assets, &config)
107+ if config.loop_through {
108+ // TODO
109+ print_files(&assets, &config)
110+ } else {
111+ print_files(&assets, &config)
112+ }
108113 }
109114 }
110115 }
src/printer.rs+39−28
@@ -16,18 +16,27 @@ use errors::*;
1616use style::OutputWrap;
1717use terminal::{as_terminal_escaped, to_ansi_color};
1818
19−pub struct Printer<'a> {
19+pub trait Printer {
20+ fn print_header(&mut self, filename: Option<&str>) -> Result<()>;
21+ fn print_footer(&mut self) -> Result<()>;
22+ fn print_line(
23+ &mut self,
24+ line_number: usize,
25+ regions: &[(highlighting::Style, &str)],
26+ ) -> Result<()>;
27+}
28+
29+pub struct InteractivePrinter<'a> {
2030 handle: &'a mut Write,
2131 colors: Colors,
2232 pub config: &'a Config<'a>,
2333 decorations: Vec<Box<Decoration>>,
2434 panel_width: usize,
2535 pub ansi_prefix_sgr: String,
26− pub line_number: usize,
2736 pub line_changes: Option<LineChanges>,
2837}
2938
30−impl<'a> Printer<'a> {
39+impl<'a> InteractivePrinter<'a> {
3140 pub fn new(handle: &'a mut Write, config: &'a Config, theme: &Theme) -> Self {
3241 let colors = if config.colored_output {
3342 Colors::colored(theme, config.true_color)
@@ -66,21 +75,36 @@ impl<'a> Printer<'a> {
6675 }
6776
6877 // Create printer.
69− Printer {
78+ InteractivePrinter {
7079 panel_width,
7180 handle,
7281 colors,
7382 config,
7483 decorations,
7584 ansi_prefix_sgr: String::new(),
76− line_number: 0,
7785 line_changes: None,
7886 }
7987 }
8088
81− pub fn print_header(&mut self, filename: Option<&str>) -> Result<()> {
82− self.line_number = 0;
89+ fn print_horizontal_line(&mut self, grid_char: char) -> Result<()> {
90+ if self.panel_width == 0 {
91+ writeln!(
92+ self.handle,
93+ "{}",
94+ self.colors.grid.paint("─".repeat(self.config.term_width))
95+ )?;
96+ } else {
97+ let hline = "─".repeat(self.config.term_width - (self.panel_width + 1));
98+ let hline = format!("{}{}{}", "─".repeat(self.panel_width), grid_char, hline);
99+ writeln!(self.handle, "{}", self.colors.grid.paint(hline))?;
100+ }
101+
102+ Ok(())
103+ }
104+}
83105
106+impl<'a> Printer for InteractivePrinter<'a> {
107+ fn print_header(&mut self, filename: Option<&str>) -> Result<()> {
84108 if !self.config.output_components.header() {
85109 return Ok(());
86110 }
@@ -114,7 +138,7 @@ impl<'a> Printer<'a> {
114138 Ok(())
115139 }
116140
117− pub fn print_footer(&mut self) -> Result<()> {
141+ fn print_footer(&mut self) -> Result<()> {
118142 if self.config.output_components.grid() {
119143 self.print_horizontal_line('┴')
120144 } else {
@@ -122,8 +146,11 @@ impl<'a> Printer<'a> {
122146 }
123147 }
124148
125− pub fn print_line(&mut self, regions: &[(highlighting::Style, &str)]) -> Result<()> {
126− self.line_number += 1;
149+ fn print_line(
150+ &mut self,
151+ line_number: usize,
152+ regions: &[(highlighting::Style, &str)],
153+ ) -> Result<()> {
127154 let mut cursor: usize = 0;
128155 let mut cursor_max: usize = self.config.term_width;
129156 let mut panel_wrap: Option<String> = None;
@@ -133,7 +160,7 @@ impl<'a> Printer<'a> {
133160 let decorations = self
134161 .decorations
135162 .iter()
136− .map(|ref d| d.generate(self.line_number, false, self))
163+ .map(|ref d| d.generate(line_number, false, self))
137164 .collect::<Vec<_>>();
138165
139166 for deco in decorations {
@@ -218,7 +245,7 @@ impl<'a> Printer<'a> {
218245 self.decorations
219246 .iter()
220247 .map(|ref d| d
221− .generate(self.line_number, true, self)
248+ .generate(line_number, true, self)
222249 .text).collect::<Vec<String>>()
223250 .join(" ")
224251 ))
@@ -260,22 +287,6 @@ impl<'a> Printer<'a> {
260287
261288 Ok(())
262289 }
263−
264− fn print_horizontal_line(&mut self, grid_char: char) -> Result<()> {
265− if self.panel_width == 0 {
266− writeln!(
267− self.handle,
268− "{}",
269− self.colors.grid.paint("─".repeat(self.config.term_width))
270− )?;
271− } else {
272− let hline = "─".repeat(self.config.term_width - (self.panel_width + 1));
273− let hline = format!("{}{}{}", "─".repeat(self.panel_width), grid_char, hline);
274− writeln!(self.handle, "{}", self.colors.grid.paint(hline))?;
275− }
276−
277− Ok(())
278− }
279290}
280291
281292const DEFAULT_GUTTER_COLOR: u8 = 238;