sql_cli/sql/generators/
ascii_art.rs1use crate::data::datatable::{DataColumn, DataRow, DataTable, DataType, DataValue};
2use crate::sql::generators::TableGenerator;
3use anyhow::{anyhow, Result};
4use figlet_rs::FIGfont;
5use std::collections::HashMap;
6use std::sync::Arc;
7
8pub struct AsciiArt;
10
11impl TableGenerator for AsciiArt {
12 fn name(&self) -> &str {
13 "ASCII_ART"
14 }
15
16 fn columns(&self) -> Vec<DataColumn> {
17 vec![DataColumn {
18 name: "line".to_string(),
19 data_type: DataType::String,
20 nullable: false,
21 unique_values: Some(0),
22 null_count: 0,
23 metadata: HashMap::new(),
24 qualified_name: None,
25 source_table: None,
26 }]
27 }
28
29 fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
30 if args.is_empty() {
31 return Err(anyhow!("ASCII_ART requires at least 1 argument (text)"));
32 }
33
34 let text = match &args[0] {
36 DataValue::String(s) => s.clone(),
37 DataValue::Null => return Err(anyhow!("ASCII_ART text cannot be NULL")),
38 other => other.to_string(),
39 };
40
41 let _font_name = if args.len() > 1 {
43 match &args[1] {
44 DataValue::String(s) => s.clone(),
45 DataValue::Null => "standard".to_string(),
46 _ => "standard".to_string(),
47 }
48 } else {
49 "standard".to_string()
50 };
51
52 let font =
55 FIGfont::standard().map_err(|e| anyhow!("Failed to load standard font: {}", e))?;
56
57 let ascii_art = font
59 .convert(&text)
60 .ok_or_else(|| anyhow!("Failed to convert text to ASCII art"))?;
61
62 let mut table = DataTable::new("ascii_art");
64 table.add_column(DataColumn::new("line"));
65
66 for line in ascii_art.to_string().lines() {
68 table
69 .add_row(DataRow::new(vec![DataValue::String(line.to_string())]))
70 .map_err(|e| anyhow!(e))?;
71 }
72
73 Ok(Arc::new(table))
74 }
75
76 fn description(&self) -> &str {
77 "Generate ASCII art text using FIGlet fonts"
78 }
79
80 fn arg_count(&self) -> usize {
81 1 }
83}
84
85pub struct BigText;
87
88impl TableGenerator for BigText {
89 fn name(&self) -> &str {
90 "BIG_TEXT"
91 }
92
93 fn columns(&self) -> Vec<DataColumn> {
94 AsciiArt.columns()
95 }
96
97 fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
98 AsciiArt.generate(args)
99 }
100
101 fn description(&self) -> &str {
102 "Generate big ASCII text (alias for ASCII_ART)"
103 }
104
105 fn arg_count(&self) -> usize {
106 1
107 }
108}
109
110pub struct Banner;
112
113impl TableGenerator for Banner {
114 fn name(&self) -> &str {
115 "BANNER"
116 }
117
118 fn columns(&self) -> Vec<DataColumn> {
119 vec![DataColumn {
120 name: "line".to_string(),
121 data_type: DataType::String,
122 nullable: false,
123 unique_values: Some(0),
124 null_count: 0,
125 metadata: HashMap::new(),
126 qualified_name: None,
127 source_table: None,
128 }]
129 }
130
131 fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
132 if args.is_empty() {
133 return Err(anyhow!("BANNER requires at least 1 argument (text)"));
134 }
135
136 let text = match &args[0] {
138 DataValue::String(s) => s.clone(),
139 DataValue::Null => return Err(anyhow!("BANNER text cannot be NULL")),
140 other => other.to_string(),
141 };
142
143 let border_char = if args.len() > 1 {
145 match &args[1] {
146 DataValue::String(s) if !s.is_empty() => s.chars().next().unwrap(),
147 _ => '*',
148 }
149 } else {
150 '*'
151 };
152
153 let font =
155 FIGfont::standard().map_err(|e| anyhow!("Failed to load standard font: {}", e))?;
156
157 let ascii_art = font
158 .convert(&text)
159 .ok_or_else(|| anyhow!("Failed to convert text to ASCII art"))?;
160
161 let mut table = DataTable::new("banner");
163 table.add_column(DataColumn::new("line"));
164
165 let lines: Vec<String> = ascii_art
167 .to_string()
168 .lines()
169 .map(|s| s.to_string())
170 .collect();
171 let max_width = lines.iter().map(|l| l.len()).max().unwrap_or(0);
172
173 let border_line = border_char.to_string().repeat(max_width + 4);
175
176 table
178 .add_row(DataRow::new(vec![DataValue::String(border_line.clone())]))
179 .map_err(|e| anyhow!(e))?;
180
181 for line in lines {
183 let padded_line = format!(
184 "{} {:<width$} {}",
185 border_char,
186 line,
187 border_char,
188 width = max_width
189 );
190 table
191 .add_row(DataRow::new(vec![DataValue::String(padded_line)]))
192 .map_err(|e| anyhow!(e))?;
193 }
194
195 table
197 .add_row(DataRow::new(vec![DataValue::String(border_line)]))
198 .map_err(|e| anyhow!(e))?;
199
200 Ok(Arc::new(table))
201 }
202
203 fn description(&self) -> &str {
204 "Generate ASCII art banner with optional border"
205 }
206
207 fn arg_count(&self) -> usize {
208 1 }
210}