display-as 0.1.5

Compile-time templates for displaying data in different markup formats.
Documentation

This template crate uses and defines a DisplayAs trait, which allows a type to be displayed in a particular format.

Overview

This crate defines three things that you need be aware of in order to use it: the Format trait, which defines a markup language or other format, the DisplayAs trait which is implemented for any type that can be converted into some Format, and finally the template language and macros which allow you to conveniently implement DisplayAs for your own types. I will describe each of these concepts in order. (FIXME I should also have a quick-start...)

Format

There are a number of predefined Formats (and I can easily add more if there are user requests), so the focus here will be on using these Formats, rather than on defining your own (which also isn't too hard). A format is a zero-size type that has a rule for escaping strings and an associated MIME type. The builtin formats include HTML, LaTeX, and Math (which is math-mode LaTeX).

DisplayAs<F>

The DisplayAs<F: Format> trait is entirely analogous to the Display trait in the standard library, except that it is parametrized by a Format so you can have different representations for the same type in different formats. This also makes it harder to accidentally include the wrong representation in your output.

Most of the primitive types already have DisplayAs implemented for the included Formats. If you encounter a type that you wish had DisplayAs implemented for a given format, just let me know. You can manually implement DisplayAs for any of your own types (it's not worse than implementing Display) but that isn't how you are intended to do things (except perhaps in very simple cases, like a wrapper around an integer). Instead you will want to use a template to implement DisplayAs for your own types.

Templates!

There are two template macros that you can use. If you just want to get a string out of one or more DisplayAs objects, you will use something like display_as_string!("hello world" value). If you want to implement DisplayAs, you will use the attribute with_template. In these examples I will use display_as_string! because that makes it easy to write testable documentation. But in practice you will most likely primarily use the with_template attribute.

String literals

The first thing you can include in a template is a string literal, which is treated literally.

use display_as::{HTML, display_as_string};
assert_eq!(&display_as_string!(HTML, "Treat this literally <" ),
"Treat this literally <");

Expressions

String literals are essential to representing some other format. To include your data in the output, you can include any expression that yields a type with DisplayAs<F> where F is your format. Each expression is delimited by string literals (or the other options below). Note that since an expression is

use display_as::{HTML, display_as_string};
let s = "This is not a literal: <";
assert_eq!(&display_as_string!(HTML, s ),
"This is not a literal: &lt;");

Blocks and conditionals

You can use braces to enclose any template expression. Any rust code before the braces is treated as literal rust. This enables you to write conditionals, match expressions, and loops.

use display_as::{HTML, display_as_string};
assert_eq!(&display_as_string!(HTML,
for i in 1..4 {
"Counting " i "...\n"
}
"Blast off!"),
"Counting 1...\nCounting 2...\nCounting 3...\nBlast off!");

Semicolons

You may also play any rust statements you wish, if you end them with a semicolon. This enables you to define local variables.

use display_as::{HTML, display_as_string};
assert_eq!(&display_as_string!(HTML, "I am counting " let count = 5;
count " and again " count ),
"I am counting 5 and again 5");

Embedding a different format

You can also embed in one format a representation from another type. This can be helpful, for instance, if you want to use MathJax to handle LaTeX math embedded in an HTML file.

use display_as::{HTML, Math, display_as_string};
assert_eq!(&display_as_string!(HTML, "The number $" 1.2e12 as Math "$"),
r"The number $1.2\times10^{12}$");

Nesting templates?

I want to figure out how to enable you to nest one template in another.

use display_as::{HTML, display_as_string};
assert_eq!(&display_as_string!(HTML, "The number " let x = 5; x ),
"The number 5");

Differences when putting a template in a file

You will most likely always put largish templates in a separate file. This makes editing your template simpler and keeps things in general easier. The template language for templates held in a distinct file has one differnce from those shown above: the file always begins and ends with string literals, but their initial and final quotes respectively are omitted. Furthermore, the first and last string literals must be "raw" literals with a number of # signs equal to the maximum used in the template. I suggest using an equal number of # signs for all string literals in a given template. Thus a template might look like:

<html>
<body>
"## self.title r##"
</body>
</html>

You can see that the quotes appear "inside out." This is intentional, so that for most formats the quotes will appear to enclose the rust code rather than everything else, and as a result editors will hopefully be able to do the "right thing" for the template format (e.g. HTML in this case).