arborist_cli/output/
table.rs1use std::io::{self, IsTerminal, Write};
2
3use arborist::FileReport;
4use comfy_table::{ContentArrangement, Table};
5
6use crate::analysis::FlatFunction;
7use crate::cli::AnalyzeArgs;
8use crate::error::ArboristError;
9
10pub fn write_reports(reports: &[FileReport], args: &AnalyzeArgs) -> Result<(), ArboristError> {
11 let stdout = io::stdout();
12 let mut out = stdout.lock();
13 let is_tty = stdout.is_terminal();
14
15 for (i, report) in reports.iter().enumerate() {
16 if i > 0 {
17 writeln!(out)?;
18 }
19
20 writeln!(
21 out,
22 "{} ({}) \u{2014} {} function{}, {} SLOC",
23 report.path,
24 report.language,
25 report.functions.len(),
26 if report.functions.len() == 1 { "" } else { "s" },
27 report.file_sloc,
28 )?;
29
30 if report.functions.is_empty() {
31 writeln!(out)?;
32 continue;
33 }
34
35 let mut table = Table::new();
36 table.set_content_arrangement(ContentArrangement::Dynamic);
37
38 if !is_tty {
39 table.load_preset(comfy_table::presets::NOTHING);
40 }
41
42 table.set_header(vec!["Function", "Lines", "Cognitive", "Cyclomatic", "SLOC"]);
43
44 for func in &report.functions {
45 let cognitive_str = if let Some(threshold) = args.threshold {
46 if func.cognitive > threshold {
47 if is_tty {
48 format!("{} \u{26a0}", func.cognitive)
49 } else {
50 format!("{} !", func.cognitive)
51 }
52 } else {
53 func.cognitive.to_string()
54 }
55 } else {
56 func.cognitive.to_string()
57 };
58
59 table.add_row(vec![
60 func.name.clone(),
61 format!("{}-{}", func.start_line, func.end_line),
62 cognitive_str,
63 func.cyclomatic.to_string(),
64 func.sloc.to_string(),
65 ]);
66 }
67
68 writeln!(out, "{table}")?;
69 }
70
71 Ok(())
72}
73
74pub fn write_flat(flat: &[FlatFunction], args: &AnalyzeArgs) -> Result<(), ArboristError> {
75 let stdout = io::stdout();
76 let mut out = stdout.lock();
77 let is_tty = stdout.is_terminal();
78
79 let mut table = Table::new();
80 table.set_content_arrangement(ContentArrangement::Dynamic);
81
82 if !is_tty {
83 table.load_preset(comfy_table::presets::NOTHING);
84 }
85
86 table.set_header(vec!["Function", "File", "Cognitive", "Cyclomatic", "SLOC"]);
87
88 for func in flat {
89 let cognitive_str = if let Some(threshold) = args.threshold {
90 if func.cognitive > threshold {
91 if is_tty {
92 format!("{} \u{26a0}", func.cognitive)
93 } else {
94 format!("{} !", func.cognitive)
95 }
96 } else {
97 func.cognitive.to_string()
98 }
99 } else {
100 func.cognitive.to_string()
101 };
102
103 table.add_row(vec![
104 func.name.clone(),
105 func.file_path.clone(),
106 cognitive_str,
107 func.cyclomatic.to_string(),
108 func.sloc.to_string(),
109 ]);
110 }
111
112 writeln!(out, "{table}")?;
113
114 Ok(())
115}