const DEFINITION: &str = include_str!("../docs/definition.md");
const DRIVING: &str = include_str!("../docs/driving.md");
const TOPICS: &[(&str, &str, &str)] = &[
(
"definition",
"the YAML definition format, authoring patterns, and anti-patterns",
DEFINITION,
),
(
"driving",
"a short primer on driving any machine one transition at a time",
DRIVING,
),
];
pub fn topic_text(topic: &str) -> Option<&'static str> {
TOPICS
.iter()
.find(|(name, _, _)| *name == topic)
.map(|(_, _, text)| *text)
}
pub fn topic_names() -> String {
TOPICS
.iter()
.map(|(name, _, _)| *name)
.collect::<Vec<_>>()
.join(", ")
}
pub fn list_topics() -> String {
let mut out = String::from("fsmp guide — authoring and driving reference\n\nTopics:\n");
for (name, blurb, _) in TOPICS {
out.push_str(&format!(" {name:<12} {blurb}\n"));
}
out.push_str("\nRun `fsmp guide <topic>` to print one.\n");
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_topics_return_their_docs() {
assert!(topic_text("definition")
.unwrap()
.contains("Authoring fsmp definitions"));
assert!(topic_text("driving")
.unwrap()
.contains("Driving an fsmp machine"));
}
#[test]
fn unknown_topic_returns_none() {
assert!(topic_text("nonsense").is_none());
}
#[test]
fn topic_names_lists_every_topic() {
let names = topic_names();
assert!(names.contains("definition"));
assert!(names.contains("driving"));
}
#[test]
fn listing_names_every_topic_with_a_blurb() {
let listing = list_topics();
assert!(listing.contains("definition"));
assert!(listing.contains("driving"));
assert!(listing.contains("anti-patterns"));
assert!(listing.contains("primer"));
}
}