1use crate::types::GrepResult;
4use anyhow::Result;
5use std::io::IsTerminal;
6
7pub mod csv;
8pub mod human;
9pub mod json;
10pub mod jsonl;
11pub mod template;
12
13pub use csv::CsvFormatter;
14pub use human::HumanFormatter;
15pub use json::JsonFormatter;
16pub use jsonl::JsonlFormatter;
17pub use template::TemplateFormatter;
18
19pub trait OutputFormatter {
21 fn format_result(&self, result: &GrepResult) -> Result<String>;
23
24 fn format_results(&self, results: &[GrepResult]) -> Result<String>;
26
27 fn print_result(&self, result: &GrepResult) -> Result<()> {
29 print!("{}", self.format_result(result)?);
30 Ok(())
31 }
32
33 fn print_results(&self, results: &[GrepResult]) -> Result<()> {
35 print!("{}", self.format_results(results)?);
36 Ok(())
37 }
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
42pub enum OutputFormat {
43 #[default]
45 Standard,
46 Compact,
48 CompactNoCell,
50 PathsOnly,
52 MatchesOnly,
54 Grouped,
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
60pub enum ColorMode {
61 #[default]
62 Auto,
63 Always,
64 Never,
65}
66
67impl ColorMode {
68 pub fn parse(s: &str) -> Option<Self> {
69 match s.to_lowercase().as_str() {
70 "auto" => Some(ColorMode::Auto),
71 "always" => Some(ColorMode::Always),
72 "never" => Some(ColorMode::Never),
73 _ => None,
74 }
75 }
76
77 pub fn should_use_color(&self) -> bool {
79 match self {
80 ColorMode::Always => true,
81 ColorMode::Never => false,
82 ColorMode::Auto => std::io::stdout().is_terminal(),
83 }
84 }
85}
86
87#[derive(Debug, Clone, Default)]
89pub struct OutputOptions {
90 pub show_filename: bool,
92
93 pub files_with_matches: bool,
95
96 pub count_mode: bool,
98
99 pub context_lines: Option<usize>,
101
102 pub heading_mode: bool,
104
105 pub no_line_number: bool,
107
108 pub format: OutputFormat,
110
111 pub template: Option<String>,
113
114 pub color_mode: ColorMode,
116}