standout_input/questionnaire/
render.rs1use std::fmt::Write as _;
2
3use super::definition::{Item, Questionnaire};
4
5pub(crate) const FORMAT_LINE: &str = "#! standout-answers 1";
6pub(crate) const QUESTIONNAIRE_PREFIX: &str = "#! questionnaire:";
7pub(crate) const FINGERPRINT_PREFIX: &str = "#! fingerprint:";
8pub(crate) const TAG_OPEN: &str = "<id:";
9
10const REPEAT_GUIDANCE: &str =
11 "(Add an item by copying one complete block - its heading line and its questions - below the last block, then answering the copy.)";
12
13fn tag(id: &str) -> String {
14 format!("{TAG_OPEN}{id}>")
15}
16
17impl Questionnaire {
18 pub fn render_answer_sheet(&self) -> String {
19 let mut out = String::new();
20 out.push_str(FORMAT_LINE);
21 out.push('\n');
22 let _ = writeln!(out, "{QUESTIONNAIRE_PREFIX} {}", self.id());
23 let _ = writeln!(out, "{FINGERPRINT_PREFIX} {}", self.fingerprint());
24 render_items(self.items(), "", &mut out);
25 out
26 }
27}
28
29fn render_items(items: &[Item], number_prefix: &str, out: &mut String) {
30 for (index, item) in items.iter().enumerate() {
31 let number = display_number(number_prefix, index + 1);
32 match item {
33 Item::Field(field) => {
34 out.push('\n');
35 let _ = writeln!(
36 out,
37 "{number} {} ({}) {}",
38 field.prompt(),
39 field.type_hint(),
40 tag(field.id())
41 );
42 if let Some(default) = field.default() {
43 let _ = writeln!(out, "{default}");
44 }
45 }
46 Item::Group(group) => {
47 let occurrences = group.repeat().map_or(1, |repeat| repeat.min());
48 for occurrence in 0..occurrences {
49 out.push('\n');
50 let _ = writeln!(
51 out,
52 "{number} {} ({}) {}",
53 group.prompt(),
54 group.type_hint(),
55 tag(group.id())
56 );
57 if group.repeat().is_some() && occurrence == 0 {
58 out.push_str(REPEAT_GUIDANCE);
59 out.push('\n');
60 }
61 render_items(group.children(), number.trim_end_matches('.'), out);
62 }
63 }
64 }
65 }
66}
67
68fn display_number(prefix: &str, ordinal: usize) -> String {
69 if prefix.is_empty() {
70 format!("{ordinal}.")
71 } else {
72 format!("{prefix}.{ordinal}")
73 }
74}