gitfetch_rs/display/
text_patterns.rs

1use std::collections::HashMap;
2
3pub type Pattern = Vec<Vec<u8>>;
4
5pub fn get_patterns() -> HashMap<String, Pattern> {
6  let mut patterns = HashMap::new();
7
8  // A-Z alphabet patterns
9  patterns.insert(
10    "A".to_string(),
11    vec![
12      vec![0, 3, 3, 3, 3, 3, 0],
13      vec![3, 0, 0, 0, 0, 0, 3],
14      vec![3, 0, 0, 0, 0, 0, 3],
15      vec![3, 3, 3, 3, 3, 3, 3],
16      vec![3, 0, 0, 0, 0, 0, 3],
17      vec![3, 0, 0, 0, 0, 0, 3],
18      vec![3, 0, 0, 0, 0, 0, 3],
19    ],
20  );
21
22  patterns.insert(
23    "B".to_string(),
24    vec![
25      vec![3, 3, 3, 3, 3, 3, 0],
26      vec![3, 0, 0, 0, 0, 0, 3],
27      vec![3, 0, 0, 0, 0, 0, 3],
28      vec![3, 3, 3, 3, 3, 3, 0],
29      vec![3, 0, 0, 0, 0, 0, 3],
30      vec![3, 0, 0, 0, 0, 0, 3],
31      vec![3, 3, 3, 3, 3, 3, 0],
32    ],
33  );
34
35  patterns.insert(
36    "C".to_string(),
37    vec![
38      vec![0, 3, 3, 3, 3, 3, 0],
39      vec![3, 0, 0, 0, 0, 0, 3],
40      vec![3, 0, 0, 0, 0, 0, 0],
41      vec![3, 0, 0, 0, 0, 0, 0],
42      vec![3, 0, 0, 0, 0, 0, 0],
43      vec![3, 0, 0, 0, 0, 0, 3],
44      vec![0, 3, 3, 3, 3, 3, 0],
45    ],
46  );
47
48  patterns.insert(
49    "D".to_string(),
50    vec![
51      vec![3, 3, 3, 3, 3, 3, 0],
52      vec![3, 0, 0, 0, 0, 0, 3],
53      vec![3, 0, 0, 0, 0, 0, 3],
54      vec![3, 0, 0, 0, 0, 0, 3],
55      vec![3, 0, 0, 0, 0, 0, 3],
56      vec![3, 0, 0, 0, 0, 0, 3],
57      vec![3, 3, 3, 3, 3, 3, 0],
58    ],
59  );
60
61  patterns.insert(
62    "E".to_string(),
63    vec![
64      vec![3, 3, 3, 3, 3, 3, 3],
65      vec![3, 0, 0, 0, 0, 0, 0],
66      vec![3, 0, 0, 0, 0, 0, 0],
67      vec![3, 3, 3, 3, 3, 3, 0],
68      vec![3, 0, 0, 0, 0, 0, 0],
69      vec![3, 0, 0, 0, 0, 0, 0],
70      vec![3, 3, 3, 3, 3, 3, 3],
71    ],
72  );
73
74  patterns.insert(
75    "F".to_string(),
76    vec![
77      vec![3, 3, 3, 3, 3, 3, 3],
78      vec![3, 0, 0, 0, 0, 0, 0],
79      vec![3, 0, 0, 0, 0, 0, 0],
80      vec![3, 3, 3, 3, 3, 3, 0],
81      vec![3, 0, 0, 0, 0, 0, 0],
82      vec![3, 0, 0, 0, 0, 0, 0],
83      vec![3, 0, 0, 0, 0, 0, 0],
84    ],
85  );
86
87  patterns.insert(
88    "G".to_string(),
89    vec![
90      vec![0, 3, 3, 3, 3, 3, 0],
91      vec![3, 0, 0, 0, 0, 0, 3],
92      vec![3, 0, 0, 0, 0, 0, 0],
93      vec![3, 0, 3, 3, 3, 3, 3],
94      vec![3, 0, 0, 0, 0, 0, 3],
95      vec![3, 0, 0, 0, 0, 0, 3],
96      vec![0, 3, 3, 3, 3, 3, 0],
97    ],
98  );
99
100  patterns.insert(
101    "H".to_string(),
102    vec![
103      vec![3, 0, 0, 0, 0, 0, 3],
104      vec![3, 0, 0, 0, 0, 0, 3],
105      vec![3, 0, 0, 0, 0, 0, 3],
106      vec![3, 3, 3, 3, 3, 3, 3],
107      vec![3, 0, 0, 0, 0, 0, 3],
108      vec![3, 0, 0, 0, 0, 0, 3],
109      vec![3, 0, 0, 0, 0, 0, 3],
110    ],
111  );
112
113  patterns.insert(
114    "I".to_string(),
115    vec![
116      vec![3, 3, 3, 3, 3, 3, 3],
117      vec![0, 0, 0, 3, 0, 0, 0],
118      vec![0, 0, 0, 3, 0, 0, 0],
119      vec![0, 0, 0, 3, 0, 0, 0],
120      vec![0, 0, 0, 3, 0, 0, 0],
121      vec![0, 0, 0, 3, 0, 0, 0],
122      vec![3, 3, 3, 3, 3, 3, 3],
123    ],
124  );
125
126  patterns.insert(
127    "J".to_string(),
128    vec![
129      vec![3, 3, 3, 3, 3, 3, 3],
130      vec![0, 0, 0, 0, 0, 3, 0],
131      vec![0, 0, 0, 0, 0, 3, 0],
132      vec![0, 0, 0, 0, 0, 3, 0],
133      vec![0, 0, 0, 0, 0, 3, 0],
134      vec![3, 0, 0, 0, 0, 3, 0],
135      vec![0, 3, 3, 3, 3, 0, 0],
136    ],
137  );
138
139  patterns.insert(
140    "K".to_string(),
141    vec![
142      vec![3, 0, 0, 0, 0, 3, 0],
143      vec![3, 0, 0, 0, 3, 0, 0],
144      vec![3, 0, 0, 3, 0, 0, 0],
145      vec![3, 3, 3, 0, 0, 0, 0],
146      vec![3, 0, 0, 3, 0, 0, 0],
147      vec![3, 0, 0, 0, 3, 0, 0],
148      vec![3, 0, 0, 0, 0, 3, 0],
149    ],
150  );
151
152  patterns.insert(
153    "L".to_string(),
154    vec![
155      vec![3, 0, 0, 0, 0, 0, 0],
156      vec![3, 0, 0, 0, 0, 0, 0],
157      vec![3, 0, 0, 0, 0, 0, 0],
158      vec![3, 0, 0, 0, 0, 0, 0],
159      vec![3, 0, 0, 0, 0, 0, 0],
160      vec![3, 0, 0, 0, 0, 0, 0],
161      vec![3, 3, 3, 3, 3, 3, 3],
162    ],
163  );
164
165  patterns.insert(
166    "M".to_string(),
167    vec![
168      vec![3, 0, 0, 0, 0, 0, 3],
169      vec![3, 3, 0, 0, 0, 3, 3],
170      vec![3, 0, 3, 0, 3, 0, 3],
171      vec![3, 0, 0, 3, 0, 0, 3],
172      vec![3, 0, 0, 0, 0, 0, 3],
173      vec![3, 0, 0, 0, 0, 0, 3],
174      vec![3, 0, 0, 0, 0, 0, 3],
175    ],
176  );
177
178  patterns.insert(
179    "N".to_string(),
180    vec![
181      vec![3, 0, 0, 0, 0, 0, 3],
182      vec![3, 3, 0, 0, 0, 0, 3],
183      vec![3, 0, 3, 0, 0, 0, 3],
184      vec![3, 0, 0, 3, 0, 0, 3],
185      vec![3, 0, 0, 0, 3, 0, 3],
186      vec![3, 0, 0, 0, 0, 3, 3],
187      vec![3, 0, 0, 0, 0, 0, 3],
188    ],
189  );
190
191  patterns.insert(
192    "O".to_string(),
193    vec![
194      vec![0, 3, 3, 3, 3, 3, 0],
195      vec![3, 0, 0, 0, 0, 0, 3],
196      vec![3, 0, 0, 0, 0, 0, 3],
197      vec![3, 0, 0, 0, 0, 0, 3],
198      vec![3, 0, 0, 0, 0, 0, 3],
199      vec![3, 0, 0, 0, 0, 0, 3],
200      vec![0, 3, 3, 3, 3, 3, 0],
201    ],
202  );
203
204  patterns.insert(
205    "P".to_string(),
206    vec![
207      vec![3, 3, 3, 3, 3, 3, 0],
208      vec![3, 0, 0, 0, 0, 0, 3],
209      vec![3, 0, 0, 0, 0, 0, 3],
210      vec![3, 3, 3, 3, 3, 3, 0],
211      vec![3, 0, 0, 0, 0, 0, 0],
212      vec![3, 0, 0, 0, 0, 0, 0],
213      vec![3, 0, 0, 0, 0, 0, 0],
214    ],
215  );
216
217  patterns.insert(
218    "Q".to_string(),
219    vec![
220      vec![0, 3, 3, 3, 3, 3, 0],
221      vec![3, 0, 0, 0, 0, 0, 3],
222      vec![3, 0, 0, 0, 0, 0, 3],
223      vec![3, 0, 0, 0, 0, 0, 3],
224      vec![3, 0, 0, 0, 3, 0, 3],
225      vec![3, 0, 0, 0, 0, 3, 0],
226      vec![0, 3, 3, 3, 3, 0, 3],
227    ],
228  );
229
230  patterns.insert(
231    "R".to_string(),
232    vec![
233      vec![3, 3, 3, 3, 3, 3, 0],
234      vec![3, 0, 0, 0, 0, 0, 3],
235      vec![3, 0, 0, 0, 0, 0, 3],
236      vec![3, 3, 3, 3, 3, 3, 0],
237      vec![3, 0, 0, 3, 0, 0, 0],
238      vec![3, 0, 0, 0, 3, 0, 0],
239      vec![3, 0, 0, 0, 0, 3, 0],
240    ],
241  );
242
243  patterns.insert(
244    "S".to_string(),
245    vec![
246      vec![0, 3, 3, 3, 3, 3, 3],
247      vec![3, 0, 0, 0, 0, 0, 0],
248      vec![3, 0, 0, 0, 0, 0, 0],
249      vec![0, 3, 3, 3, 3, 3, 0],
250      vec![0, 0, 0, 0, 0, 0, 3],
251      vec![0, 0, 0, 0, 0, 0, 3],
252      vec![3, 3, 3, 3, 3, 3, 0],
253    ],
254  );
255
256  patterns.insert(
257    "T".to_string(),
258    vec![
259      vec![3, 3, 3, 3, 3, 3, 3],
260      vec![0, 0, 0, 3, 0, 0, 0],
261      vec![0, 0, 0, 3, 0, 0, 0],
262      vec![0, 0, 0, 3, 0, 0, 0],
263      vec![0, 0, 0, 3, 0, 0, 0],
264      vec![0, 0, 0, 3, 0, 0, 0],
265      vec![0, 0, 0, 3, 0, 0, 0],
266    ],
267  );
268
269  patterns.insert(
270    "U".to_string(),
271    vec![
272      vec![3, 0, 0, 0, 0, 0, 3],
273      vec![3, 0, 0, 0, 0, 0, 3],
274      vec![3, 0, 0, 0, 0, 0, 3],
275      vec![3, 0, 0, 0, 0, 0, 3],
276      vec![3, 0, 0, 0, 0, 0, 3],
277      vec![3, 0, 0, 0, 0, 0, 3],
278      vec![0, 3, 3, 3, 3, 3, 0],
279    ],
280  );
281
282  patterns.insert(
283    "V".to_string(),
284    vec![
285      vec![3, 0, 0, 0, 0, 0, 3],
286      vec![3, 0, 0, 0, 0, 0, 3],
287      vec![3, 0, 0, 0, 0, 0, 3],
288      vec![3, 0, 0, 0, 0, 0, 3],
289      vec![3, 0, 0, 0, 0, 0, 3],
290      vec![0, 3, 0, 0, 0, 3, 0],
291      vec![0, 0, 3, 3, 3, 0, 0],
292    ],
293  );
294
295  patterns.insert(
296    "W".to_string(),
297    vec![
298      vec![3, 0, 0, 0, 0, 0, 3],
299      vec![3, 0, 0, 0, 0, 0, 3],
300      vec![3, 0, 0, 0, 0, 0, 3],
301      vec![3, 0, 0, 3, 0, 0, 3],
302      vec![3, 0, 3, 0, 3, 0, 3],
303      vec![3, 3, 0, 0, 0, 3, 3],
304      vec![3, 0, 0, 0, 0, 0, 3],
305    ],
306  );
307
308  patterns.insert(
309    "X".to_string(),
310    vec![
311      vec![3, 0, 0, 0, 0, 0, 3],
312      vec![0, 3, 0, 0, 0, 3, 0],
313      vec![0, 0, 3, 0, 3, 0, 0],
314      vec![0, 0, 0, 3, 0, 0, 0],
315      vec![0, 0, 3, 0, 3, 0, 0],
316      vec![0, 3, 0, 0, 0, 3, 0],
317      vec![3, 0, 0, 0, 0, 0, 3],
318    ],
319  );
320
321  patterns.insert(
322    "Y".to_string(),
323    vec![
324      vec![3, 0, 0, 0, 0, 0, 3],
325      vec![0, 3, 0, 0, 0, 3, 0],
326      vec![0, 0, 3, 0, 3, 0, 0],
327      vec![0, 0, 0, 3, 0, 0, 0],
328      vec![0, 0, 0, 3, 0, 0, 0],
329      vec![0, 0, 0, 3, 0, 0, 0],
330      vec![0, 0, 0, 3, 0, 0, 0],
331    ],
332  );
333
334  patterns.insert(
335    "Z".to_string(),
336    vec![
337      vec![3, 3, 3, 3, 3, 3, 3],
338      vec![0, 0, 0, 0, 0, 3, 0],
339      vec![0, 0, 0, 0, 3, 0, 0],
340      vec![0, 0, 0, 3, 0, 0, 0],
341      vec![0, 0, 3, 0, 0, 0, 0],
342      vec![0, 3, 0, 0, 0, 0, 0],
343      vec![3, 3, 3, 3, 3, 3, 3],
344    ],
345  );
346
347  patterns.insert(
348    " ".to_string(),
349    vec![
350      vec![0, 0, 0, 0, 0, 0, 0],
351      vec![0, 0, 0, 0, 0, 0, 0],
352      vec![0, 0, 0, 0, 0, 0, 0],
353      vec![0, 0, 0, 0, 0, 0, 0],
354      vec![0, 0, 0, 0, 0, 0, 0],
355      vec![0, 0, 0, 0, 0, 0, 0],
356      vec![0, 0, 0, 0, 0, 0, 0],
357    ],
358  );
359
360  // Shape patterns
361  patterns.insert(
362    "heart".to_string(),
363    vec![
364      vec![0, 4, 4, 0, 4, 4, 0],
365      vec![4, 2, 2, 4, 2, 2, 4],
366      vec![4, 2, 2, 2, 2, 2, 4],
367      vec![4, 2, 2, 2, 2, 2, 4],
368      vec![0, 4, 2, 2, 2, 4, 0],
369      vec![0, 0, 4, 2, 4, 0, 0],
370      vec![0, 0, 0, 4, 0, 0, 0],
371    ],
372  );
373
374  patterns.insert(
375    "octocat".to_string(),
376    vec![
377      vec![0, 0, 0, 4, 0, 0, 0, 4, 0],
378      vec![0, 0, 4, 4, 4, 4, 4, 4, 4],
379      vec![0, 0, 4, 1, 3, 3, 3, 1, 4],
380      vec![0, 0, 4, 3, 3, 3, 3, 3, 4],
381      vec![4, 0, 3, 4, 3, 3, 3, 4, 3],
382      vec![0, 4, 0, 0, 4, 4, 4, 0, 0],
383      vec![0, 0, 4, 4, 4, 4, 4, 4, 4],
384    ],
385  );
386
387  patterns
388}
389
390pub fn text_to_grid(text: &str) -> Result<Vec<Vec<u8>>, String> {
391  if text.is_empty() {
392    return Ok(Vec::new());
393  }
394
395  let patterns = get_patterns();
396  let mut grid: Vec<Vec<u8>> = Vec::new();
397
398  for ch in text.to_uppercase().chars() {
399    if !ch.is_ascii_alphabetic() && ch != ' ' {
400      return Err(format!(
401        "Text mode only supports A-Z and space. Use --shape for predefined shapes. Got: '{}'",
402        ch
403      ));
404    }
405
406    let pattern = patterns
407      .get(&ch.to_string())
408      .or_else(|| patterns.get(" "))
409      .ok_or_else(|| format!("Pattern not found for '{}'", ch))?;
410
411    if grid.is_empty() {
412      grid = pattern.clone();
413    } else {
414      for (i, row) in pattern.iter().enumerate() {
415        grid[i].extend(row);
416      }
417    }
418
419    // Add one-column spacer after each character
420    for row in grid.iter_mut() {
421      row.push(0);
422    }
423  }
424
425  Ok(grid)
426}
427
428pub fn shape_to_grid(shapes: &[String]) -> Result<Vec<Vec<u8>>, String> {
429  if shapes.is_empty() {
430    return Ok(Vec::new());
431  }
432
433  let patterns = get_patterns();
434  let mut grid: Vec<Vec<u8>> = Vec::new();
435
436  for shape_name in shapes {
437    let pattern = patterns
438      .get(shape_name)
439      .ok_or_else(|| format!("Unknown shape: {}", shape_name))?;
440
441    if grid.is_empty() {
442      grid = pattern.clone();
443    } else {
444      // Add spacer column
445      for row in grid.iter_mut() {
446        row.push(0);
447      }
448
449      // Append shape
450      for (i, row) in pattern.iter().enumerate() {
451        grid[i].extend(row);
452      }
453    }
454  }
455
456  Ok(grid)
457}