aimx/values/
format.rs

1//! Format value support for AIMX.
2//!
3//! Provides the `Format` struct, parsing helpers, and trait implementations
4//! used to represent formatting instructions as `Value::Format`.
5
6use nom::{
7    IResult, Parser,
8    character::complete::{char, multispace0},
9    combinator::map,
10    multi::separated_list0,
11    sequence::preceded,
12};
13use std::{
14    fmt,
15    sync::Arc,
16};
17
18use crate::{
19    aim::{WriterLike, Writer},
20    literals::{parse_tag, parse_text},
21    values::Value,
22};
23
24/// Formatting instruction stored as `Value::Format`.
25///
26/// Parsed from `"Instruction" <template> "Example1", ...` and rendered by
27/// `Writer` helpers for prompts or output schemas.
28#[derive(Debug, Clone, PartialEq)]
29pub struct Format {
30    instruction: Arc<str>,
31    template: Arc<str>,
32    examples: Arc<Vec<Arc<str>>>,
33}
34
35impl Format {
36    /// Constructs a new `Value::Format` from components.
37    pub fn as_value(instruction: Arc<str>, template: Arc<str>, examples: Arc<Vec<Arc<str>>>) -> Value {
38        Value::Format(Format {
39            instruction: instruction,
40            template: template,
41            examples: examples,
42        })
43    }
44
45    /// Instruction text.
46    pub fn instruction(&self) -> Arc<str> {
47        self.instruction.clone()
48    }
49
50    /// Template string.
51    pub fn template(&self) -> Arc<str> {
52        self.template.clone()
53    }
54
55    /// Example values.
56    pub fn examples(&self) -> Arc<Vec<Arc<str>>> {
57        self.examples.clone()
58    }
59
60    /// Print format.
61    pub fn print(&self, writer: &mut Writer) {
62        writer.print(&self.instruction);
63        writer.write_str(" <");
64        writer.print(&self.template);
65        writer.write_str("> ");
66        for (index, text) in self.examples.iter().enumerate() {
67            if index > 0 {
68                writer.write_str(", ");
69            }
70            writer.print(text);
71        }
72    }
73
74    /// Return the formula-string representation (round-trippable by the parser).
75    pub fn to_formula(&self) -> String {
76        let mut writer = Writer::formulizer();
77        self.print(&mut writer);
78        writer.finish()
79    }
80}
81
82impl WriterLike for Format {
83    fn write(&self, writer: &mut Writer) {
84        self.print(writer);
85    }
86}
87
88impl fmt::Display for Format {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        write!(f, "{}", self.to_stringized())
91    }
92}
93
94/// Parse a `Value::Format` from `"Instruction" <template> "Example1", ...`.
95pub fn parse_format(input: &str) -> IResult<&str, Format> {
96    map(
97        (
98            multispace0,
99            parse_text,
100            multispace0,
101            parse_tag,
102            multispace0,
103            parse_string_array,
104        ),
105        |(_, instruction, _, template, _, examples)| {
106            Format {
107                instruction,
108                template,
109                examples: Arc::new(examples),
110            }
111        },
112    )
113    .parse(input)
114}
115
116/// Parse comma-separated quoted strings used by `parse_format`.
117pub fn parse_string_array(input: &str) -> IResult<&str, Vec<Arc<str>>> {
118    separated_list0(
119        preceded(multispace0, char(',')),
120        preceded(multispace0, parse_text),
121    )
122    .parse(input)
123}