Skip to main content

query_forge/output/formats/
text.rs

1use std::fmt::Write as _;
2
3use crate::QueryResult;
4use crate::value::display_value;
5
6pub fn render_text(result: &QueryResult) -> String {
7    if result.columns.is_empty() {
8        return String::new();
9    }
10
11    let mut column_widths = result
12        .columns
13        .iter()
14        .map(|column| column.len())
15        .collect::<Vec<_>>();
16    let mut rendered_rows = Vec::with_capacity(result.rows.len());
17
18    for row in &result.rows {
19        let mut rendered_row = Vec::with_capacity(result.columns.len());
20        for index in 0..result.columns.len() {
21            let rendered_value = row.get(index).map(display_value).unwrap_or_default();
22            column_widths[index] = column_widths[index].max(rendered_value.len());
23            rendered_row.push(rendered_value);
24        }
25        rendered_rows.push(rendered_row);
26    }
27
28    let mut output = String::new();
29    write_aligned_row(&mut output, &result.columns, &column_widths);
30    output.push('\n');
31    output.push_str(
32        &column_widths
33            .iter()
34            .map(|width| "-".repeat(*width))
35            .collect::<Vec<_>>()
36            .join("-+-"),
37    );
38
39    for row in rendered_rows {
40        output.push('\n');
41        write_aligned_row(&mut output, &row, &column_widths);
42    }
43
44    output
45}
46
47fn write_aligned_row(output: &mut String, values: &[String], column_widths: &[usize]) {
48    for (index, value) in values.iter().enumerate() {
49        if index > 0 {
50            output.push_str(" | ");
51        }
52
53        let _ = write!(output, "{value:<width$}", width = column_widths[index]);
54    }
55}