[][src]Crate tracery

Rust port of tracery

This library is a port of https://github.com/galaxykate/tracery, which implements Generative grammars. Given a set of rules, written in a specific syntax, it will generate strings of text.

Example:

let source = r##"
{
    "origin": ["foo #bar#", "#baz# quux #qux#"],
    "bar": ["bar", "BAR"],
    "baz": ["baz", "BaZ", "bAZ"],
    "qux": ["qux", "QUX"]
}
"##;

let grammar = tracery::from_json(source).unwrap();
// Starting from the "origin" rule, which is selected by default, fills in
// random entries from the "bar", "baz", and "qux" rules, where called for
// in the "origin" text:
let flattened = grammar.flatten(&grammar, &mut BTreeMap::new())?;
let matches = flattened.eq_ignore_ascii_case("foo bar") || flattened.eq_ignore_ascii_case("baz quux qux");
assert!(matches);

or, even shorter:

let source = r##"
{
    "origin": ["foo #bar#", "#baz# quux #qux#"],
    "bar": ["bar", "BAR"],
    "baz": ["baz", "BaZ", "bAZ"],
    "qux": ["qux", "QUX"]
}
"##;
let flattened = tracery::flatten(source)?;
let matches = flattened.eq_ignore_ascii_case("foo bar") || flattened.eq_ignore_ascii_case("baz quux qux");
assert!(matches);

So, in the example above, we might end up with "foo bar" or "BaZ quux lazy dog", etc

API

In the example above, we used Grammar.flatten, but that is a convenience function that does the following:

let grammar = tracery::from_json(r##"{
  "origin": [ "#foo# is #bar#" ],
  "foo": [ "tracery" ],
  "bar": [ "fun" ]
}"##)?;
let flattened = grammar.flatten(&grammar, &mut BTreeMap::new())?;
assert_eq!(flattened, "tracery is fun");

.from_json will parse the rule set out into a tree-like structure, and .flatten collapses that tree-like structure into a single string.

More tracery syntax

Tracery allows for more than just word replacement. You can attach "actions" and "modifiers" to rules as well. There are quite a few modifiers built-in to this library. Here is one:

let source = r##"
{
    "origin": ["this word is in plural form: #noun.s#"],
    "noun": ["apple"]
}"##;

let grammar = tracery::from_json(source)?;
let flattened = grammar.flatten(&grammar, &mut BTreeMap::new())?;
assert_eq!("this word is in plural form: apples", flattened);

Actions allow you to, for example, lock in a specific value for a #tag#, so that you can refer to it multiple times in your story. Here is an example (modified from @galaxykate's official tutorial http://www.crystalcodepalace.com/traceryTut.html)

let source = r##"{
    "name": ["Arjun","Yuuma","Darcy","Mia","Chiaki","Izzi","Azra","Lina"],
    "animal": ["unicorn","raven","sparrow","scorpion","coyote","eagle","owl","lizard","zebra","duck","kitten"],
    "mood": ["vexed","indignant","impassioned","wistful","astute","courteous"],
    "story": ["#hero# traveled with her pet #heroPet#.  #hero# was never #mood#, for the #heroPet# was always too #mood#."],
    "origin": ["#[hero:#name#][heroPet:#animal#]story#"]
}"##;
println!("{}", tracery::flatten(source)?);

We see, in the "origin" rule, the use of actions to lock-in the value of #hero# and #heroPet#, so that we can use those tags in the "story" rule, and know that the same generated value will be used in all cases.

Structs

Grammar

Represents a single grammar

Rule

Represents a single expansion that tracery can select for a key.

Tag

Structure representing a #tag# in a tracery rule

Enums

Error

The tracery error type

Node

Represents a part of a single expandable string

Traits

Flatten

A trait for types that can be flattened into an output string

Functions

flatten

Creates a new grammar from a JSON grammar string, then uses it to create a random output string

from_json

Creates a new grammar from a JSON grammar string

Type Definitions

Result

A convenience type for a Result of T or Error