on 53eb9c5 help sign in
bat/src/printer.rs
160 lines 4.6 kB history raw
1use ansi_term::Style;
2use app::Config;
3use diff::{LineChange, LineChanges};
4use errors::*;
5use std::io::Write;
6use syntect::highlighting;
7use terminal::as_terminal_escaped;
8use Colors;
10const PANEL_WIDTH: usize = 7;
12pub struct Printer<'a> {
13 handle: &'a mut Write,
14 colors: Colors,
15 config: &'a Config<'a>,
16 pub line_changes: Option<LineChanges>,
19impl<'a> Printer<'a> {
20 pub fn new(handle: &'a mut Write, config: &'a Config) -> Self {
21 let colors = if config.colored_output {
22 Colors::colored()
23 } else {
24 Colors::plain()
25 };
27 Printer {
28 handle,
29 colors,
30 config,
31 line_changes: None,
32 }
33 }
35 pub fn print_header(&mut self, filename: Option<&str>) -> Result<()> {
36 if !self.config.output_components.header() {
37 return Ok(());
38 }
40 if self.config.output_components.grid() {
41 self.print_horizontal_line('┬')?;
43 write!(
44 self.handle,
45 "{}{} ",
46 " ".repeat(PANEL_WIDTH),
47 self.colors.grid.paint("│"),
48 )?;
49 }
51 writeln!(
52 self.handle,
53 "{}{}",
54 filename.map_or("", |_| "File: "),
55 self.colors.filename.paint(filename.unwrap_or("STDIN"))
56 )?;
58 if self.config.output_components.grid() {
59 self.print_horizontal_line('┼')?;
60 }
62 Ok(())
63 }
65 pub fn print_footer(&mut self) -> Result<()> {
66 if self.config.output_components.grid() {
67 self.print_horizontal_line('┴')
68 } else {
69 Ok(())
70 }
71 }
73 pub fn print_line(
74 &mut self,
75 line_number: usize,
76 regions: &[(highlighting::Style, &str)],
77 ) -> Result<()> {
78 let decorations = vec![
79 self.print_line_number(line_number),
80 self.print_git_marker(line_number),
81 self.print_line_border(),
82 Some(as_terminal_escaped(
83 &regions,
84 self.config.true_color,
85 self.config.colored_output,
86 )),
87 ];
89 let grid_requested = self.config.output_components.grid();
90 write!(
91 self.handle,
92 "{}",
93 decorations
94 .into_iter()
95 .filter_map(|dec| if grid_requested {
96 Some(dec.unwrap_or_else(|| " ".to_owned()))
97 } else {
98 dec
99 })
100 .collect::<Vec<_>>()
101 .join(" ")
102 )?;
104 Ok(())
105 }
107 fn print_line_number(&self, line_number: usize) -> Option<String> {
108 if self.config.output_components.numbers() {
109 Some(
110 self.colors
111 .line_number
112 .paint(format!("{:4}", line_number))
113 .to_string(),
114 )
115 } else if self.config.output_components.grid() {
116 Some(" ".to_owned())
117 } else {
118 None
119 }
120 }
122 fn print_git_marker(&self, line_number: usize) -> Option<String> {
123 if self.config.output_components.changes() {
124 Some(
125 if let Some(ref changes) = self.line_changes {
126 match changes.get(&(line_number as u32)) {
127 Some(&LineChange::Added) => self.colors.git_added.paint("+"),
128 Some(&LineChange::RemovedAbove) => self.colors.git_removed.paint("‾"),
129 Some(&LineChange::RemovedBelow) => self.colors.git_removed.paint("_"),
130 Some(&LineChange::Modified) => self.colors.git_modified.paint("~"),
131 _ => Style::default().paint(" "),
132 }
133 } else {
134 Style::default().paint(" ")
135 }.to_string(),
136 )
137 } else if self.config.output_components.grid() {
138 Some(" ".to_owned())
139 } else {
140 None
141 }
142 }
144 fn print_line_border(&self) -> Option<String> {
145 if self.config.output_components.grid() {
146 Some(self.colors.grid.paint("│").to_string())
147 } else {
148 None
149 }
150 }
152 fn print_horizontal_line(&mut self, grid_char: char) -> Result<()> {
153 let hline = "─".repeat(self.config.term_width - (PANEL_WIDTH + 1));
154 let hline = format!("{}{}{}", "─".repeat(PANEL_WIDTH), grid_char, hline);
156 writeln!(self.handle, "{}", self.colors.grid.paint(hline))?;
158 Ok(())
159 }