Skip to content

martylamb/tictac

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tictac: Template Is Compiled To A Class

Tictac is a super-simple template compiler for Java. It compiles templates to Java source files with static methods that return the generated text as a String. Methods can take whatever parameters you like, so you end up with type-safe compiled Java code generating your text.

If you've ever used Java Server Pages you get the idea, but tictac uses a slightly different syntax and compiles to Java ahead of time.

Tictac has NO RUNTIME DEPENDENCIES WHATSOEVER.

An example is worth a thousand words:

%% package tictac.examples

%% import java.util.Date;

%% template sayHello(String name)
Hello, <% name %>!

It is now <% new Date() %>.

Running tictac against this file (named Example.tic) generates the following Java code:

// Automatically generated - DO NOT EDIT!!!
// Generated by tictac Tue Jun 10 20:03:19 EDT 2014
package tictac.examples  // line 1: 0-26
import java.util.Date;  // line 3: 0-25

public class Example {

	public static String sayHello(String name) {
		StringBuilder _tictacOut = new StringBuilder();
		_tictacOut.append("Hello, "); // line 6: 0-7
		_tictacOut.append(_tictacEscape(name));  // line 6: 7-17
		_tictacOut.append("!"); // line 6: 17-18
		_tictacOut.append("\n"); // line 6: 18-18
		_tictacOut.append("\n"); // line 7: 0-0
		_tictacOut.append("It is now "); // line 8: 0-10
		_tictacOut.append(_tictacEscape(new Date()));  // line 8: 10-26
		_tictacOut.append("."); // line 8: 26-27
		_tictacOut.append("\n"); // line 8: 27-27
		return _tictacOut.toString();
	}
    
    private static String _tictacEscape(Object o) {
    	// omitted for brevity, escapes output for html...
    }

}

The classname Example was taken from the template filename Example.tic.

You can specify whatever package and imports you like. This example defines a single "template method" called sayHello which takes a String as a parameter. The resulting Java method builds and returns a String based upon the contents of he template.

Java values can be inserted via the <% value %> markers. Anything contained within these will be appended to the result after escaping for html safety (so "<" becomes "&lt;", etc.). Escaping can be avoided by using <%! value %>

###Inline Java and Multiple Templates per File

You can use arbitrary Java code in your templates and define multiple templates in a single file. Templates can even call each other:

%% package tictac.examples;
%% import java.util.*;

%% template sayHello(String name)
Hello, <% name %>!

%% template sayHello(Collection<String> names)
%% for (String name: names) sayHello(name);
I just greeted <% names.size() %> people.

This defines two simple templates: one that greets a single person, and another that iterates over a Collection of names and greets them each using the first template. The generated code looks like this:

package tictac.examples;  // line 1: 0-27
import java.util.*;  // line 2: 0-22

public class MultiTemplateExample {

	public static String sayHello(String name) {
		StringBuilder _tictacOut = new StringBuilder();
		_tictacOut.append("Hello, "); // line 6: 0-7
		_tictacOut.append(_tictacEscape(name));  // line 6: 7-17
		_tictacOut.append("!"); // line 6: 17-18
		_tictacOut.append("\n"); // line 6: 18-18
		_tictacOut.append("\n"); // line 7: 0-0
		return _tictacOut.toString();
	}

	public static String sayHello(Collection<String> names) {
		StringBuilder _tictacOut = new StringBuilder();
		 for (String name: names) sayHello(name);  // line 9: 0-43
		_tictacOut.append("I just greeted "); // line 10: 0-15
		_tictacOut.append(_tictacEscape(names.size()));  // line 10: 15-33
		_tictacOut.append(" people."); // line 10: 33-41
		_tictacOut.append("\n"); // line 10: 41-41
		return _tictacOut.toString();
	}
    
    private static String _tictacEscape(Object o) {
    	// omitted for brevity, escapes output for html...
    }

}

Syntax

Tictac uses three special types of blocks in addition to the plain text of the template itself. These are called Java blocks, escaped values, and unescaped values. Each block has a starting delimiter and ending delimiter, but the ending delimiter is optional. If omitted, each block ends at the end of the line. Thus:

%% for (int i = 0; i < 10; ++i) { %%

is equivalent to:

%% for (int i = 0; i < 10; ++i) {

You can mix and match blocks on a single line if you don't find it too cumbersome:

%% for (int i = 0; i < 10; ++i) { %% Item number <% i %> %% } %%

Java Blocks

Java blocks begin and (optionally) end with %%. They are inserted directly in the template method wherever they are defined. No effort is made to validate them; that's your Java compiler's job. Java blocks that begin with "package" and "import" are treated specially applied to the generated class rather than any template methods. Java blocks that begin with "template" are simplistically transformed into static methods that return a String and have the signature that follows the "template" in the block.

Escaped Values

Escaped values begin with <% and (optionally) end with %>. These are treated as Java code that returns an Object, which is passed into an auto-generated method to escape the contents for safe inclusion in html.

Unescaped Values

Unescaped values begin with <%! and (optionally) end with %>. These are treated as Java code that returns an Object, which is NOT escaped for safe inclusion in html. If you have code that generates html you want to use as-is (perhaps another template method?) it should be unescaped.

Invoking the Tictac Compiler

For now, you have to build the jar with Maven and call it via java -jar. I hope to make this simpler in the future (maybe a Maven plugin?)

To compile a single template, use java -jar tictac-1.0-SNAPSHOT.jar TEMPLATEFILE [DESTDIR]. If DESTDIR is omitted, the resulting .java file is placed in the same directory as the template file.

To recursively compile all templates (.tic extension) in a directory, use java -jar tictac-1.0-SNAPSHOT.jar TEMPLATEDIR [DESTDIR]. If DESTDIR is omitted, the resulting .java files are placed in the same directories as the template files.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages