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