Template strings and macros

# Template strings with macros replacement.

`TemplateString` provides a simple way to customize generic string templates
using macros and replacement.

A macro is represented as a string identifier like `%MACRO%` in the template
string. Using `TemplateString`, macros can be replaced by any `Streamable` data:

    var tpl = new TemplateString("Hello %NAME%!")
    tpl.replace("NAME", "Dave")
    assert tpl.write_to_string == "Hello Dave!"

A macro identifier is valid if:

* starts with an uppercase letter
* contains only numers, uppercase letters or '_'

See `String::is_valid_macro_name` for more details.

## External template files

When using large template files it's recommanded to use external template files.

In external file `example.tpl`:

    <!DOCTYPE html>
    <html lang="en">
     <head>
      <title>%TITLE%</title>
     </head>
     <body>
      <h1>%TITLE%</h1>
      <p>%ARTICLE%</p>
     </body>
    </html>

Loading the template file using `TemplateString`:

    var file = "example.tpl"
    if file.file_exists then
        tpl = new TemplateString.from_file("example.tpl")
        tpl.replace("TITLE", "Home Page")
        tpl.replace("ARTICLE", "Welcome on my site!")
    end

## Outputting

Once macro replacement has been made, the `TemplateString` can be
output like any other `Template` using methods like `write_to`, `write_to_string`
or `write_to_file`.

    tpl = new TemplateString("Hello %NAME%!")
    tpl.replace("NAME", "Dave")
    assert tpl.write_to_string == "Hello Dave!"

## Template correctness

`TemplateString` can be outputed even if all macros were not replaced.
In this case, the name of the macro will be displayed wuthout any replacement.

    tpl = new TemplateString("Hello %NAME%!")
    assert tpl.write_to_string == "Hello %NAME%!"

The `check` method can be used to ensure that all macros were replaced before
performing the output. Warning messages will be stored in `warnings` and can
be used to locate unreplaced macros.

    tpl = new TemplateString("Hello %NAME%!")
    if not tpl.check then
        assert not tpl.warnings.is_empty
        print "Cannot output unfinished template:"
        print tpl.warnings.join("\n")
        exit(0)
    else
        tpl.write_to sys.stdout
    end
    assert tpl.write_to_string == "Hello %NAME%!"

Si si, c'est un template.

En fait, le template se construit en fonction du fichier.

Imaginons qu'on est

    foo
    %MACCRO%
    bar

Ce qu'on fait en fait c'est:

    self.add "foo"
    self.add new TemplateMacro("%MACCRO%")
    self.add "bar"