mirror of
				https://github.com/sharkdp/bat.git
				synced 2025-11-04 00:51:56 +00:00 
			
		
		
		
	Refactoring, introduce Printer trait
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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<bool>
 | 
			
		||||
 | 
			
		||||
    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<bool>
 | 
			
		||||
        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<bool>
 | 
			
		||||
    Ok(no_errors)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn print_file(
 | 
			
		||||
fn print_file<P: Printer>(
 | 
			
		||||
    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<BufRead> = 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<BufRead + 'a>,
 | 
			
		||||
    mut highlighter: HighlightLines,
 | 
			
		||||
    line_ranges: &Option<LineRange>,
 | 
			
		||||
) -> 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();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -104,7 +104,12 @@ fn run() -> Result<bool> {
 | 
			
		||||
 | 
			
		||||
                Ok(true)
 | 
			
		||||
            } else {
 | 
			
		||||
                print_files(&assets, &config)
 | 
			
		||||
                if config.loop_through {
 | 
			
		||||
                    // TODO
 | 
			
		||||
                    print_files(&assets, &config)
 | 
			
		||||
                } else {
 | 
			
		||||
                    print_files(&assets, &config)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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<Box<Decoration>>,
 | 
			
		||||
    panel_width: usize,
 | 
			
		||||
    pub ansi_prefix_sgr: String,
 | 
			
		||||
    pub line_number: usize,
 | 
			
		||||
    pub line_changes: Option<LineChanges>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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<String> = 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::<Vec<_>>();
 | 
			
		||||
 | 
			
		||||
            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::<Vec<String>>()
 | 
			
		||||
                                                .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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user