1use std::io::Write;
2use topo_core::ScoredFile;
3
4pub struct CompactWriter;
9
10impl CompactWriter {
11 pub fn new() -> Self {
12 Self
13 }
14
15 pub fn render(&self, files: &[ScoredFile]) -> String {
17 let mut buf = Vec::new();
18 self.write_to(&mut buf, files).expect("write to Vec failed");
19 String::from_utf8(buf).expect("compact output is valid UTF-8")
20 }
21
22 pub fn write_to(&self, writer: &mut dyn Write, files: &[ScoredFile]) -> std::io::Result<()> {
24 for file in files {
25 writeln!(
26 writer,
27 "{} ({}, {}tok, {:.2})",
28 file.path,
29 file.role.as_str(),
30 file.tokens,
31 file.score,
32 )?;
33 }
34 Ok(())
35 }
36}
37
38impl Default for CompactWriter {
39 fn default() -> Self {
40 Self::new()
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use topo_core::{FileRole, Language, ScoredFile, SignalBreakdown};
48
49 fn sample_files() -> Vec<ScoredFile> {
50 vec![
51 ScoredFile {
52 path: "src/auth.rs".to_string(),
53 score: 7.01,
54 signals: SignalBreakdown::default(),
55 tokens: 2494,
56 language: Language::Rust,
57 role: FileRole::Implementation,
58 },
59 ScoredFile {
60 path: "src/commands/init.rs".to_string(),
61 score: 6.92,
62 signals: SignalBreakdown::default(),
63 tokens: 2635,
64 language: Language::Rust,
65 role: FileRole::Implementation,
66 },
67 ScoredFile {
68 path: "README.md".to_string(),
69 score: 6.54,
70 signals: SignalBreakdown::default(),
71 tokens: 128,
72 language: Language::Markdown,
73 role: FileRole::Documentation,
74 },
75 ]
76 }
77
78 #[test]
79 fn compact_output_one_line_per_file() {
80 let writer = CompactWriter::new();
81 let output = writer.render(&sample_files());
82 let lines: Vec<&str> = output.trim().lines().collect();
83 assert_eq!(lines.len(), 3);
84 }
85
86 #[test]
87 fn compact_output_format() {
88 let writer = CompactWriter::new();
89 let output = writer.render(&sample_files());
90 let first_line = output.lines().next().unwrap();
91 assert_eq!(first_line, "src/auth.rs (impl, 2494tok, 7.01)");
92 }
93
94 #[test]
95 fn compact_output_includes_role() {
96 let writer = CompactWriter::new();
97 let output = writer.render(&sample_files());
98 assert!(output.contains("(docs,"));
99 assert!(output.contains("(impl,"));
100 }
101
102 #[test]
103 fn compact_empty_files() {
104 let writer = CompactWriter::new();
105 let output = writer.render(&[]);
106 assert!(output.is_empty());
107 }
108}