tweep

Tweep is a parser for the Twee 3 interactive fiction format

What is Twee?

Twee is "a text format for marking up the source code of Twine stories." It is an alternate way to produce interactive fiction stories for the [Twine 2] platform, using plain text files instead of a graphical environment. The specification for Twee 3, supported by tweep, can be found [here]

Goals

The goal of tweep is to provide a fully standards-compliant Twee 3 parser that provides helpful warning and error messages for bad practices and common mistakes, which can be used as a backend for a compiler as well as other novel applications of the Twee 3 format.

What it's not

Getting started

To use tweep in your Rust project, simply add the following to your Cargo.toml:

toml [dependencies] tweep = "0.2"

For basic parsing, the main entry point into tweep is through the [Story] struct, which provides utility methods for parsing out a complete story from a String or a Path representing a file or directory. When given a directory, tweep will parse all files ending in .tw or .twee and merge them into a single output story. For more advanced parsing, such as if the tags or metadata attached to a special passage is needed, [StoryPassages] provides the same interface, but provides [Passage] objects in places where usually unnecessary information is stripped out.

Examples

```rust use tweep::Story; let input = r#":: StoryTitle RustDoc Sample Story

:: StoryData { "ifid": "D674C58C-DEFA-4F70-B7A2-27742230C0FC", "format": "SugarCube", "format-version": "2.28.2", "start": "My Starting Passage", "tag-colors": { "tag1": "green", "tag2": "red", "tag3": "blue" }, "zoom": 0.25 }

:: My Starting Passage [ tag1 tag2 ] This is the starting passage, specified by the start attribute of StoryData. Alternately, we could remove that attribute and rename the passage to Start.

It has tags and links to: [[Another passage]] [[Here too!|Another passage]] [[A third passage<-And a different passage]]

:: Another passage {"position":"600,400","size":"100,200"} This passage has some metadata attached to it

:: A third passage [tag3] { "position": "400,600" } This passage has both tags and metadata. The size attribute of the metadata isn't overridden, so it will be set to the default value. "#.to_string();

// Parse the input into an Output> let out = Story::fromstring(input); assert!(!out.haswarnings());

// Move the Result out of the Output let (res, ) = out.take(); assert!(res.isok());

// Get the Story object let story = res.ok().unwrap();

// StoryTitle and StoryData contents are parsed into special fields asserteq!(story.title.unwrap(), "RustDoc Sample Story"); asserteq!(story.data.unwrap().ifid, "D674C58C-DEFA-4F70-B7A2-27742230C0FC");

// Other passages are parsed into a map, keyed by the passage name asserteq!(story.passages["My Starting Passage"].tags(), &vec!["tag1", "tag2"]); let metadata = story.passages["A third passage"].metadata(); asserteq!(metadata["size"], "100,100"); assert_eq!(metadata["position"], "400,600"); ```

License: MIT