1pub mod ansi;
4pub mod fragment;
5pub mod plain;
6
7pub use fragment::FragmentFormatter;
8pub use plain::PlainFormatter;
9
10use crate::Emit;
11use std::io;
12
13pub trait Formatter {
15 fn write(&mut self, sink: &mut dyn io::Write, emit: &Emit) -> io::Result<()>;
16}
17
18#[derive(Debug, Clone)]
20pub struct FormatOpts {
21 pub show_line_numbers: bool,
22 pub show_filename: bool,
23 pub filename: Option<String>,
24 pub color: bool,
25 pub target_marker: bool,
28 pub line_number_width: usize,
29}
30
31impl FormatOpts {
32 pub fn widen_for_line(&mut self, line_no: u64) {
33 self.line_number_width = self.line_number_width.max(digits(line_no));
34 }
35
36 pub fn prefix(&self, line_no: u64) -> String {
37 let mut p = String::new();
38 if self.show_filename
39 && let Some(f) = &self.filename
40 {
41 p.push_str(f);
42 p.push(':');
43 }
44 if self.show_line_numbers {
45 p.push_str(&format!(
46 "{line_no:>width$}: ",
47 width = self.line_number_width
48 ));
49 }
50 p
51 }
52}
53
54pub fn digits(n: u64) -> usize {
55 n.to_string().len()
56}
57
58fn push_lossy(out: &mut String, bytes: &[u8]) {
59 out.push_str(&String::from_utf8_lossy(bytes));
60}