query_forge/output/formats/
text.rs1use 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}