suiron/
built_in_print.rs

1//! Support for built-in predicate print().
2
3use std::rc::Rc;
4
5use super::substitution_set::*;
6use super::built_in_predicates::*;
7
8static FORMAT_SPECIFIER: &str = "%s";
9
10/// Prints out terms for the built-in print() predicate.
11///
12/// This function is called by
13/// [next_solution_bip()](../built_in_predicates/fn.next_solution_bip.html)
14/// in built_in_predicates.rs.
15///
16/// It converts the predicate's operands (Unifiable terms) into strings,
17/// formats them for output, and prints out the result.
18///
19/// # Arguments
20/// * [BuiltInPredicate](../built_in_predicates/struct.BuiltInPredicate.html)
21/// * [SubstitutionSet](../substitution_set/type.SubstitutionSet.html)
22/// # Usage
23/// ```
24/// use std::rc::Rc;
25/// use suiron::*;
26///
27/// // Make a print() predicate.
28/// let functor = "print".to_string();
29/// let v = vec![atom!("A"), SInteger(7), atom!("\n")];
30/// let print_pred = BuiltInPredicate::new(functor, Some(v));
31///
32/// // Call function with print predicate and substitution set.
33/// let ss = empty_ss!();
34/// next_solution_print(print_pred, &ss);
35/// // Prints: A7
36/// ```
37pub fn next_solution_print<'a>(bip: BuiltInPredicate,
38                               ss: &'a Rc<SubstitutionSet<'a>>) {
39    let mut v: Vec<String> = vec![];
40    if let Some(terms) = bip.terms {
41        // Collect ground terms into v.
42        for term in terms {
43            match get_ground_term(&term, &ss) {
44                Some(ground_term) => { v.push(format!("{}", ground_term)); },
45                None              => { v.push(format!("{}", term)); },
46            }
47        }
48        print!("{}", format_for_print_pred(&v));
49    }
50} // next_solution_print()
51
52/// Formats a list of strings for the built-in predicate print().
53///
54/// If the first string contains format specifiers (%s), the function
55/// uses them as place-holders for the following strings.
56///
57/// For example, if the first string is "I'm sorry %s, I'm afraid I can't
58/// do that.", and the second string is "Dave", the function will output
59/// "I'm sorry Dave, I'm afraid I can't do that."
60///
61/// Otherwise, if there are no format specifiers, the function simply
62/// concatenates the strings.
63///
64/// This function is called by
65/// [next_solution_print()](../built_in_print/fn.next_solution_print.html).
66///
67/// # Arguments
68/// * vector of Strings
69/// # Return
70/// * a String
71/// # Usage
72/// ```
73/// use suiron::*;
74///
75/// let s1 = "Hello, %s. You're looking well today.".to_string();
76/// let s2 = "Dave".to_string();
77/// let v = vec![s1, s2];
78///
79/// let s = format_for_print_pred(&v);
80/// println!("{}", s);
81/// // Prints: Hello, Dave. You're looking well today.
82/// ```
83pub fn format_for_print_pred(the_strings: &Vec<String>) -> String {
84    if the_strings.len() == 0 {
85        panic!("format_for_print_pred() - No strings to format.");
86    }
87    let format_string = the_strings[0].to_string();
88    let split: Vec<_> = format_string.split(FORMAT_SPECIFIER).collect();
89    let mut out: String = split[0].to_string();
90    let mut i = 1;
91    let mut j = 1;
92    let split_length = split.len();
93    let num_of_strings = the_strings.len();
94    loop {
95        if j < num_of_strings { out += &the_strings[j]; j += 1; }
96        if i < split_length { out += split[i]; i += 1; }
97        if i >= split_length && j >= num_of_strings { break; }
98    }
99    out
100} // format_for_print_pred()
101
102#[cfg(test)]
103mod test {
104
105    use super::*;
106
107    // Test formatting with a format specifier: %s
108    #[test]
109    fn test_format_for_print_pred() {
110        let s1 = "Hello, %s. ".to_string();
111        let s2 = "Dave".to_string();
112        let s3 = "You're looking well today.".to_string();
113        let v = vec![s1, s2, s3];
114        let s = format_for_print_pred(&v);
115        assert_eq!("Hello, Dave. You're looking well today.", s);
116    }
117
118} // test