Skip to main content

aagt_core/infra/
format.rs

1//! Tool for formatting structured data into compact, token-efficient formats.
2
3/// Formats a list of records into a Markdown table.
4pub struct MarkdownTable {
5    headers: Vec<String>,
6    rows: Vec<Vec<String>>,
7}
8
9impl MarkdownTable {
10    /// Create a new table with headers
11    pub fn new(headers: Vec<impl Into<String>>) -> Self {
12        Self {
13            headers: headers.into_iter().map(|s| s.into()).collect(),
14            rows: Vec::new(),
15        }
16    }
17
18    /// Add a row to the table
19    pub fn add_row(&mut self, row: Vec<impl Into<String>>) {
20        self.rows.push(row.into_iter().map(|s| s.into()).collect());
21    }
22
23    /// Convert to a Markdown string
24    pub fn render(&self) -> String {
25        if self.headers.is_empty() {
26            return String::new();
27        }
28
29        let mut output = String::new();
30
31        // Headers
32        output.push('|');
33        for header in &self.headers {
34            output.push_str(" ");
35            output.push_str(header);
36            output.push_str(" |");
37        }
38        output.push('\n');
39
40        // Separator
41        output.push('|');
42        for _ in &self.headers {
43            output.push_str(" --- |");
44        }
45        output.push('\n');
46
47        // Rows
48        for row in &self.rows {
49            output.push('|');
50            for (i, cell) in row.iter().enumerate() {
51                if i >= self.headers.len() {
52                    break;
53                }
54                output.push_str(" ");
55                // Escape pipes in content
56                output.push_str(&cell.replace('|', "\\|"));
57                output.push_str(" |");
58            }
59            // Fill missing cells
60            for _ in row.len()..self.headers.len() {
61                output.push_str("  |");
62            }
63            output.push('\n');
64        }
65
66        output
67    }
68}