Snippetory uses a simple syntax — and syntax fitting the host format allows for intact templates.

Syntax

A syntax should be very simple and, fit to the people who deal with as well as the output generated. In addition, the output data may even consist of different formats. Therefore Snippetory is designed independent from its syntax. So it's easy to switch the syntax, even dynamically within the file.

Intact templates

As Snippetory is a small project it can't generate perfect tool support for every supported output language. It goes another way: Make the syntax simple and create several of them. As every syntax is very simple and follows commons rules one can keep them in mind. For instance the tags of FLUYT_X work great within the html part of a file, while causing errors in the javaScript part. As javaScript requires me to think in a completely different way it is no additional problem to switch over to FLUYT_CC that allows me to coat my Snippetory expressions in comments, giving them a highlighting color, as well as avoiding syntactical errors created by them.

How to implement a syntax

Additional syntaxes can be created by implementing the interface org.jproggy.snippetory.spi.Syntax. A good starting point to do so is RegExSyntax. It just needs a bunch of regular expressions to work and provides some snippets to create syntaxes consistent with the core syntaxes. Once your syntax is ready the interface provides a registry to register it. The harder part is to document the syntax. ;->

Anatomy

As the syntax can be replaced easily, it's not that simple to describe. However there is a number of elements each concrete syntax may provide and some rules a syntax can't control. The main elements are

Names
Names should be valid java field names with one addition: '-'. The minus sign is allowed to support typical XML naming schemes. Like in java names are case-sensitive.
Location mark
A location mark is simply a point, where data can be bound to. It can be annotated, how this binding should happen, by meta data. The same data may be bound to different locations with different meta data each. I.e. there may be several locations with same name in one region. All locations are accessed with a single set or append method call. But the results may be different depending on the meta data.
Region
Syntactically a region consists of a start and an end. The content between start and end can be used as an independent template. As a region can be retrieved, its name has to be unique for the regions within the parent region.
Each region serves as location mark, as well. Therefore it can be configured by meta data.
Meta Data
Allows fine grained control over the Snippetory abstraction layer by several attributes.
Syntax selector
The syntax selector allows to switch the syntax at any point of parsing. To be able to use templates like output files in order to validate them, it's mandatory to use a syntax the fits its environment.
Template Data
The portion of the template file, that is not considered to be mark up and therefore is copied verbatim to the output, if used. Of course, there might be some regions, that are not always used.
Comment
The comment is an optional element and not yet supported by all of the core syntaxes.

Syntactical Elements

Names

Snippetory supports the full Java naming scheme with, in addition, allowing the minus sign '-' at any position of the name, to support typical XML naming strategies. The characters sharp '#' and period '.' will work but are reserved for future use. While the standard syntaxes enforce this naming scheme, there's no check in Snippetory whether other syntaxes enforce this too, or allow other names. But this might change in the future.

Names are always case-sensitive.

Location mark

A location mark has a name and may be configured by meta data. However there's a special variant without a name and at least one attribute. This is useful with so-called void formats, as such a location mark can't be accessed from java, so no data can be bound.
For more information on formatting see the formats documentation and Formats in java doc

$value $value(msg="cart_no_data") $(msg="cart_no_data")

Region

Like a location mark it can be replaced entirely by actual data. Even though this string typically consists of one or more parameterized copies of itself, this might be any data appropriate. However replaced isn't that correct, as of it's not replaced it's not rendered anyway. In fact an inner template is absolutely independent of it's parent. It's just stored there for better understanding of the context and simpler access. But technically it could be taken from anywhere and used everywhere one likes.

A region is marked by a start and an end element. In some syntaxes the name of region can be repeated in the end element. If it repeated it will be checked. That's recommended for longer regions, because it makes it easier to get what ends there. The start element may be configured by meta data. (In fact the syntax defines where meta data can be placed...)

A region can contain any number of complete regions with distinct names. I.e. there mustn't be more than one region with the same name directly embedded into one region, but any of these child regions provides its own, distinct name space.

A region may contain any number of location marks, without any limitations to naming. I.e. a single write operation can target several location marks and one region. These location marks are all direct children of one region. Location marks within child regions are out of scope anyway.

The start and end elements are provided in two variants each.

  • In the inline variant only the element itself is considered to be part of the markup and is therefore omitted from output. All white-space before and after is normal part of the template.
  • If the element is found in its 'own' line with only white space and a single region start or end element the entire line including the line break is considered to be markup, and therefore not part of the template. Let's call this the block variant.
The gray part is to be removed. $inline-region{ Containing some text }$$block-region{ Also with text contained }block-region$

Conditional regions

Starting with Snippetory 0.9.5 there is an addition type of region: Conditional regions have no name, and so they can't be controlled by java logic. Instead their contained locations control them. This makes it easy to implement cases where the absence of data removes some infrastructre as well.

Optional attribute:

${title="$title"}$

If there are no rows the entire table will be omitted.

<t:> <table> <tr> <th>Heading1</th><th>Heading2</th> </tr> <t:row> <tr> <td>$data1</td><td>$data2</td> </tr> </t:row> </table> </t:>

Meta Data

For the core syntaxes the syntax of attributes is similar to XML (Other definitions may overwrite this, of course):

<name>=<quoted_value>

Where name consists on alphanumeric chars plus '.-_'. The quoted_value may be quoted either in single or double quotes. Again similar to XML. However, in contrast to XML the escaping of special characters works, similar to Strings in many programming languages, with the backslash character:

\\
backslash
\'
single quote (In double quoted values the backslash is optional)
\"
double quote (In single quoted values the backslash is optional)
\n
new line
\r
carriage return
\b
bell
\t
tabulator
\f
form feed

A single backslash might cause the piece of markup being considered to be template code.

Meta data consists of a bunch of attributes. Some of these attributes are implemented directly:

enc
Valid values are the name of all registered encodings. The encodings shipped with Snippetory are documented in org.jproggy.snippetory.Encodings.
delimiter
Is rendered only in case the values gets appended data more than once between the final content created by two subsequent calls to the append method. I.e. it's prepended any but the first call to the append method. The value will be neither formatted nor escaped. Note: Calls to some render-methods will cause calls to the append method, too.
prefix
is only prepended if the region or location mark got data by appending or setting.
However, the prefix attribute will prevent the rendering of markup if no value is bound on a location mark. Deprecated: Consider use of conditional regions instead
suffix
same as prefix but behind. Deprecated: Consider use of conditional regions instead
backward
This is a very advanced technique that allows 'touch-less' value binding. In some case it's very useful to keep the template syntactically intact. However, this makes it impossible to bind data to some places, where the syntax of the output format is too strict. In those cases it's possible to place the insert location behind the real target.
resultset.getInt(i); // $types(backward='Int')
But Snippetory will fail, if the regular expression matches not exactly once within the region until next markup. If a simple expression is not specific enough, you can have a single sub-expression, that will actually replaced, and use the main expression to describe the surroundings:
var langdesc = $.datepicker.regional["de"]; // {v:lang backward='\"(de)\"'}

Formats

... are created by registration of a Format. There's an example how to do that. And some come predefined with Snippetory to convert, like those to convert data types or manipulate character data like crop or pad.

Annotations

... can be read while dealing with the template. They allow the template author to place some additional information that's handled by some generic program code. Similar to annotations in Java. Annotation attributes can be registered via the Metadata interface

Syntax selector

The syntax selector allows to change the syntax on the fly. It can be placed inside a region. This might lead to regions with start and end element defined in different syntaxes. The only data of a syntax selector is the selected syntax. I.e. no name, hence a syntax selector can't be accessed from java.

A syntax selector generally needs to be the only content of a line. This line is considered markup and thus not part of the output.

It can be either expressed as empty tag in name-space s with no attributes. The tag name is the name of the syntax: <s:FLUYT_X />

Or it can be expressed as a comment containing 'Syntax:<Syntax_Name>' with no white space within the expression. Surrounding white space is allowed. There are a number of commenting schemes implemented.
Region: /* .. */ <!-- .. --> Full line: // or # or ' or rem or -- Start and end can be mixed or even omitted:

# Syntax:FLUYT Syntax:MyCoolSyntax */ Syntax:YetAnotherSyntax

Syntax Variants

The syntaxes shipped with Snippetory are documented in org.jproggy.snippetory.Syntaxes.

FLUYT

FLUYT is the main syntax of Snippetory and the root of an entire syntax family. It's designed to be concise and unified. Following this concept locations and regions are integrated into one syntactical concept where about every part is optional. In fact this perfectly shows that regions are location with an additional template part. There are 3 segments. Each segment is optional, but there has to be at least one. The segments are:

  • Name
  • Attribute brackets (i.e. Meta data surrounded by round brackets)
  • The template region (Surrounded by curly brackets and finalized by a dollar sign. Repeating the name is optional even if there is one). If there's no template region, the final $ is optional
$[<name>][(<attribute>='value'...)][{<content_area>}[<name>]$]|[$]

In addition there is a 3-slash comment and the normal syntax selector.

Example:

$item(delimiter=","){   {     id: $id /// You can terminate locations with a $ to explicitly mark the end of the name.     image: 'details_$id$_small.jpg'     name: '$name(enc="string")'     values: [$values(delimiter=","){$value}$]   } }item$

Usage

The vanilla FLUYT syntax is most likely to be used in add hoc formatting, or when generating natural text, like a plain text e-mail, as there is no integration needed.

FLUYT_X

FLUYT_X adds an alternative region mark-up to the FLUYT syntax scheme, looking like XML tags in name space 't'. Those tags are very convenient for XML or HTML integration. Many editors support one by closing the tags consistently and by this it's easy to build valid output. Typical tools recognize them as part of the document structure and display them nicely.

Example:

<t:cart> <table> <tr><th colspan="2">Product</th><th>Quantity</th><th>Price</th></tr> <t:entry> <tr> <td><img src="imgs/icon_$imgId$.jpg" ${title="$desc"}$ /></td> <td>$prodName</td><td>$quantity</td><td>$price(number="currency")</td> </tr> <t:><tr><td colspan="4">$longDescription</td></tr></t:> </t:entry> </table> </t:cart>

Usage

FLUYT_X is designed for integration with HTML and XML. But FLUYT_X is no XML. Empty tags with the slash at the end aren't supported and there is no entity support. The escaping within attribute values works like described above.

FLUYT_CC

FLUYT_CC allows the FLUYT syntax to be coated with comments. Those comments will be considered to be part of the respective expression and removed together with the expression itself. To achieve this each token can be prefixed with either '//' or '/*' and can be suffixed with '*/'. In addition there is an optional mock part before the closing attribute bracket. This is a portion of free text prefixed with '*/' and suffixed with '/*'. If used within an comment region this will make the free text visible for a tool handling it:

/* $name(default="" */<mock>/*)*/

Example:

package /*$package(*/org.jproggy.examples/*)*/; // $imports{ import /*$type(*/org.jproggy.snippetory.Template/*)*/; // }$ public class /*$name(*/TemplateName/*)*//*${ implements $interfaces(delimiter=", ")}$*/ { /*$body*/ }

Usage

FLUYT_CC integrates nicely with languages like java, javaScript, C, C++, or CSS.

XML_ALIKE

The regions of this syntax look almost like XML within the name space t. If the name-space identifier 't' is already used for some reason, it's easy to create a similar syntax better supporting your needs. However there are some differences to XML. The empty tag variant with the slash at the end is not allowed. And there's no entity support. But the rules for attribute definition are similar. However, the values are defined the programming way with backslashes as described above.

Location marks are limited by curly braces. The content start with v: immediately followed by the name.

Example:

<t:region-one>inline variant</t:region-one> {v:location default="xyz"} <t:region-two> produces only a single line of output, whenever rendered. </t:region-two>

Usage

XML_ALIKE provides a rather robust syntax scheme so it might be used where conflicts with the template code are likely.

HIDDEN_BLOCKS

This syntax is quite similar to xml_alike. Just the start and end sequences of the region elements are modified to let it look like comments in a number of environments.

start element

Start sequence may be either
/*t: or <!--t:
and the end sequence may be
*/ or -->

End element

The start sequences are
/*!t: or <!--!t:
and the end sequence are also
*/ or -->

In either case it is allowed to mix the variants as needed.

<!--Syntax:HIDDEN_BLOCKS--> <script> /*t:region-one-->code might be hidden from javaScript<t:!--!t:region-one*/ /*t:region-two*/or visible, just as needed /*!t:region-two*/ </script> <!--t:region-three*/same works in HTML, too, of course/*!t:region-three--> <!--t:region-four--> The markup lines work here, too. <!--!t:region-four-->
Bernd Ebertz Head, Founder and chief technology evangelist of
jproggy.org