Test page 01

Skip to end of sidebar
Go to start of sidebar
Skip to end of metadata
Go to start of metadata

Does toc plugin pick up headings from included pages?

Why indeed it does! Very good. But is that really the right thing if one wants to interleave some hierarchy above the individual pages?   This could probably be kludged by wedging in H1 headings, as the detail pages look to be using H2 as top level headings.

Sorta works, but presence of any h1 forces included pages to level 2 of tree, even if they should not be subsidiary.  Arrg.

OK, so hierarchy can only be automatically picked up in TOC or page listings if:

  • Using parent "grouping" pages plus children macro  for a group of topic subpages, even if there's no point to the grouping page. Also this makes ordering of children pages very fragile... set via drag-and-drop in pages treeview, where it's susceptible to getting alphabetized.
  • Alphabetize the page titles:  Eg Page 100: Working with blah, Page 200: Accessing blah... etc.  Or Page 1.1, Page 1.2 etc. Then alpha order of children macro would be OK. (Still requires superfluous grouping page). However this requires title changes to change order, which changes page URLs and breaks links between pages.
  • Using toc macro on a page including all other pages in desired order. We insert H1 group titles, but then there's not way to have non-sub-pages appear in level 1 of tree.

This is just a test

Let's see if we can include other pages, and what that looks like...

Manually maintained TOC

Auto-indentation

StringTemplate has auto-indentation on by default. To turn it off, use NoIndentWriter rather than (the default) AutoIndentWriter.

At the simplest level, the indentation looks like a simple column count:

will yield output like:

where the last line gets "unindented" after displaying the list. StringTemplate tracks the characters to the left of the $ or < rather than the column number so that if you indent with tabs versus spaces, you'll get the same indentation in the output.

When there are nested templates, StringTemplate tracks the combined indentation:

In this case, you would get output like:

where the combined indentation is tab plus space for the attribute references in template quote. Expression $user$ is indented by 1 tab and hence any attribute generated from it (in this case the $attr$ of quote()) must have
at least the tab.

Consider generating nested statement lists as in C. Any statements inside must be nested 4 spaces. Here are two templates that could take care of this:

Your code would create a function template instance and an slist instance, which gets passed to the function template as attribute body. The following code:

Java
C#
Python

should generate something like:

Indentation can only occur at the start of a line so indentation is only tracked in front of attribute expressions following a newline.

The one exception to indentation is that naturally, $if$ actions do not cause indentation as they do not result in any output. However, the subtemplates (THEN and ELSE clauses) will see indentations. For example, in the following template, the two subtemplates are indented by exactly 1 space each:

Templates

Defining Templates

Creating Templates With Code

Here is a simple example that creates and uses a template on the fly:

Java
C#
Python

where StringTemplate considers anything in $...$ to be something it needs to pay attention to. By setting attributes, you are "pushing" values into the template for use when the template is printed out. The attribute values are set by referencing their names. Invoking toString() on query would yield

You can set an attribute multiple times, which simply means that the attribute is multi-valued. For example, adding another value to the attribute named column as shown below makes the attribute multi-valued:

Java
C#
Python

Invoking toString() on query would now yield

Ooops...there is no separator between the multiple values. If you want a comma, say, between the column names, then change the template to record that formatting information:

Java
C#
Python

Note that the right-hand-side of the separator specification in this case is a string literal; therefore, we have escaped the double-quotes as the template is specified in a string. In general, the right-hand-side can be any attribute expression. Invoking toString() on query would now yield

Attributes can be any object at all. StringTemplate calls toString() on each object as it writes the template out. The separator is not used unless the attribute is multi-valued.

Loading Templates From Files

The rest of this article discusses StringTemplateGroups, but only covers the case of groups of individual template files. You may also be interested in string template group files (xxx.stg) which provide more functionality for many scenarios. See separate Group Files article.

To load a template from the disk you must use a StringTemplateGroup that will manage all the templates you load, caching them so you do not waste time talking to the disk for each template fetch request (you can change it to not cache; see below). You may have multiple template groups. Here is a simple example that loads the previous SQL template from a file /tmp/theQuery.st:

The code below creates a StringTemplateGroup called myGroup rooted at /tmp so that requests for template theQuery forces a load of file /tmp/theQuery.st.

Java
C#
Python

If you have a directory hierarchy of templates such as file /tmp/jguru/bullet.st, you would reference them relative to the root; in this case, you would ask for template jguru/bullet().

Note
StringTemplate strips whitespace from the front and back of all loaded template files. You can add, for example, <\n> at the end of the file to get an extra carriage return.

Loading Templates relative to an implementation specific location

Java
Loading Templates from CLASSPATH

When deploying applications or providing a library for use by other programmers, you will not know where your templates files live specifically on the disk. You will, however, know relative to the classpath where your templates reside. For example, if your code is in package com.mycompany.server you might put your templates in a templates subdirectory of server. If you do not specify an absolute directory with the StringTemplateGroup constructor, future loads via that group will happen relative to the CLASSPATH. For example, to load template file page.st you would do the following:


C#
Loading Templates relative to the Assembly's Location

When deploying applications or providing a library for use by other programmers, you will not know in advance where your templates files will be located live in the file system. You will, however, often know the location of your templates relative to the where the application assembly is deployed. For example, if your code is in the an assembly named com.mycompany.server.exe you might put your templates in a templates subdirectory of the directory containing com.mycompany.server.exe. If you do not specify an absolute directory with the StringTemplateGroup constructor, future loads via that group will happen relative to the location of com.mycompany.server.exe. For example, to load template file page.st you would do the following:


Python
Loading Templates from sys.path

FIXME: there was an implementation, test&document it!

If page.st references, say, searchbox template, it must be fully qualified as:
<font size=2>SEARCH</font>: $com/mycompany/server/templates/page/searchbox()$

This is inconvenient and ST may add the invoking template's path prefix automatically in the future.

Caching

By default templates are loaded from disk just once. During development, however, it is convenient to turn caching off. Also, you may want to turn off caching so that you can quickly update a running site. You can set a simple refresh interval using StringTemplateGroup.setRefreshInterval(...). When the interval is reached, all templates are thrown out. Set interval to 0 to refresh constantly (no caching). Set the interval to a huge number like Integer.MAX_INT or Int32.MaxValue to have no refreshing at all.

Java
C#
The C# version of StringTemplate does not implement the StringGroup.setRefreshInterval() method. Template files that have been successfully opened are monitored using FileSystemWatcher.
Python

There are many situations when you want to conditionally include some text or another template. StringTemplate provides simple IF-statements to let you specify conditional includes. For example, in a dynamic web page you usually want a slightly different look depending on whether or not the viewer is "logged in" or not. Without a conditional include, you would need two templates: page_logged_in and page_logged_out. You can use a single page definition with if(expr) attribute actions instead:

where template top_gutter_logged_in is located in the gutter subdirectory of my StringTemplateGroup.

IF actions test the presence or absence of an attribute unless the object is a Boolean/bool, in which case it tests the attribute for true/false. The only operator allowed is "not" and means either "not present" or "not true". For example, "$if(!member)$...$endif$".

You can also use elseif to make a chain of tests:

$if(x)$
...
$elseif(y)$
...
$elseif(z)$
...
$else$
...
$endif$

The first true expression "wins".

Whitespace in conditionals issue

There is a simple, but not perfect rule: kill a single newline after <if>, <<, <else>, and <endif> (but for <endif> only if it's on a line by itself) . Kill newlines before <else> and <endif> and >>. For example,

is identical to:

It is very difficult to get the newline rule to work "properly" because sometimes you want newlines and sometimes you don't. I
decided to chew up as many as is reasonable and then let you explicitly say <\n> when you need to.

Acknowledgements

Please see http://www.antlr.org/credits.html

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.