Extended Mako Templates for Python
Links
Programming Interface
Command Line
makolator has two sub-commands gen and inplace:
usage: makolator [-h] {gen,inplace} ...
Mako Templates (https://www.makotemplates.org/) extended.
positional arguments:
{gen,inplace}
gen Generate File
inplace Update File Inplace
optional arguments:
-h, --help show this help message and exit
Generate
usage: makolator gen [-h] [--verbose] [--show-diff]
[--existing {error,keep,overwrite,keep_timestamp}]
[--template-path TEMPLATE_PATH]
[--marker-fill MARKER_FILL]
[--marker-linelength MARKER_LINELENGTH]
templates [templates ...] output
positional arguments:
templates Template Files. At least one must exist
output Output File
optional arguments:
-h, --help show this help message and exit
--verbose, -v Tell what happens to the file.
--show-diff, -s Show what lines changed.
--existing {error,keep,overwrite,keep_timestamp}, -e {error,keep,overwrite,keep_timestamp}
What if the file exists. Default is 'keep_timestamp'
--template-path TEMPLATE_PATH, -T TEMPLATE_PATH
Directories with templates referred by include/inherit/...
--marker-fill MARKER_FILL
Static Code, Inplace and Template Marker are filled with this given value until reaching line length of --marker-linelength.
--marker-linelength MARKER_LINELENGTH
Static Code, Inplace and Template Marker are filled until --marker-linelength.
Generate a file from a template:
makolator gen test.txt.mako test.txt
Generate a file from a template and fallback to 'default.txt.mako' if 'test.txt.mako' is missing:
makolator gen test.txt.mako default.txt.mako test.txt
Inplace
usage: makolator inplace [-h] [--ignore-unknown] [--eol EOL] [--verbose]
[--show-diff]
[--existing {error,keep,overwrite,keep_timestamp}]
[--template-path TEMPLATE_PATH]
[--marker-fill MARKER_FILL]
[--marker-linelength MARKER_LINELENGTH]
[templates ...] inplace
positional arguments:
templates Optional Template Files
inplace Updated File
optional arguments:
-h, --help show this help message and exit
--ignore-unknown, -i Ignore unknown template function calls.
--eol EOL, -E EOL EOL comment on generated lines
--verbose, -v Tell what happens to the file.
--show-diff, -s Show what lines changed.
--existing {error,keep,overwrite,keep_timestamp}, -e {error,keep,overwrite,keep_timestamp}
What if the file exists. Default is 'keep_timestamp'
--template-path TEMPLATE_PATH, -T TEMPLATE_PATH
Directories with templates referred by include/inherit/...
--marker-fill MARKER_FILL
Static Code, Inplace and Template Marker are filled with this given value until reaching line length of --marker-linelength.
--marker-linelength MARKER_LINELENGTH
Static Code, Inplace and Template Marker are filled until --marker-linelength.
Update with inplace template only:
makolator inplace test.txt
Update a file from a template:
makolator inplace test.txt.mako test.txt
Update a file from a template and fallback to 'default.txt.mako' if 'test.txt.mako' is missing:
makolator inplace test.txt.mako default.txt.mako test.txt
Template Writing
https://www.makotemplates.org/ documents the template language. Within the template the following symbols are available
Symbol |
Description |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Examples:
The variable |
|
Indent single line or multiple lines by two spaces:
|
|
Indent single line or multiple lines by given number of spaces:
|
|
Prefix single line or multiple lines by given text:
|
|
Escape latex special characters:
|
File Generation
The template test.txt.mako
:
<%def name="afunc(pos, opt=None)">\
${output_filepath.name}
pos=${pos}
% if opt:
options: ${opt}
% endif
</%def>
# ${makolator.info.genwarning}
# This file is updated by '${makolator.info.cli}'
Text
${afunc('abc')}
${afunc('def', opt=5)}
A generate (makolator gen test.txt.mako test.txt
) will result in:
# THIS FILE IS GENERATED!!! DO NOT EDIT MANUALLY. CHANGES ARE LOST.
# This file is updated by 'makolator gen test.txt.mako test.txt'
Text
test.txt
pos=abc
test.txt
pos=def
options: 5
Inplace Code Generation
Assume the following file:
This is just some handwritten text.
GENERATE INPLACE BEGIN afunc("foo")
obsolete
GENERATE INPLACE END afunc
This is also something inbetween.
// ==== GENERATE INPLACE BEGIN afunc("foo", "bar") ====
will be updated
// ==== GENERATE INPLACE END afunc ====
The lines between GENERATE INPLACE BEGIN
and GENERATE INPLACE END
can be
filled via a template like:
<%def name="afunc(pos, opt=None)">\
${output_filepath.name}
pos=${pos}
% if opt:
options: ${opt}
% endif
</%def>
An inplace update (makolator inplace test.txt.mako file.txt
) will result in:
This is just some handwritten text.
GENERATE INPLACE BEGIN afunc("foo")
inplace.txt
pos=foo
GENERATE INPLACE END afunc
This is also something inbetween.
// ==== GENERATE INPLACE BEGIN afunc("foo", "bar") ====
inplace.txt
pos=foo
options: bar
// ==== GENERATE INPLACE END afunc ====
Inplace Template
The file can contain templates too:
You can define your own template in the source code
// MAKO TEMPLATE BEGIN
// <%def name="repeat(num)">\
// # ${makolator.info.inplacewarning}
// # This section is updated via '${makolator.info.cli}'
// ${output_filepath.name}
// % for idx in range(num):
// item${idx}
// % endfor
// </%def>
// MAKO TEMPLATE END
GENERATE INPLACE BEGIN repeat(2)
obsolete
GENERATE INPLACE END repeat
GENERATE INPLACE BEGIN repeat(5)
obsolete
GENERATE INPLACE END repeat
The inplace update (makolator inplace file.txt
) will result in:
You can define your own template in the source code
// MAKO TEMPLATE BEGIN
// <%def name="repeat(num)">\
// # ${makolator.info.inplacewarning}
// # This section is updated via '${makolator.info.cli}'
// ${output_filepath.name}
// % for idx in range(num):
// item${idx}
// % endfor
// </%def>
// MAKO TEMPLATE END
GENERATE INPLACE BEGIN repeat(2)
# THIS SECTION IS GENERATED!!! DO NOT EDIT MANUALLY. CHANGES ARE LOST.
# This section is updated via 'makolator inplace inplace-mako.txt'
inplace-mako.txt
item0
item1
GENERATE INPLACE END repeat
GENERATE INPLACE BEGIN repeat(5)
# THIS SECTION IS GENERATED!!! DO NOT EDIT MANUALLY. CHANGES ARE LOST.
# This section is updated via 'makolator inplace inplace-mako.txt'
inplace-mako.txt
item0
item1
item2
item3
item4
GENERATE INPLACE END repeat
Static Code
Fully and inplace generated files might want to leave space
for user manipulation, which is kept even on update.
These locations need to be prepared by ${staticcode('name')}
, where
name
is a unique identifier within the target file.
Assume the following template:
<%def name="example(greet='Hello')">\
${greet} before
${staticcode('a', default='obsolete a')}
${greet} middle
${staticcode('b')}
${greet} after
</%def>
${example()}
and an outdated generated file:
Outdated before
// STATIC BEGIN a
kept a
// STATIC END a
Outdated middle
// STATIC BEGIN b ignored
kept b
// STATIC END b
Outdated after
An update (makolator gen file.txt.mako file.txt
) will result in:
Hello before
// STATIC BEGIN a
kept a
// STATIC END a
Hello middle
// STATIC BEGIN b
kept b
// STATIC END b
Hello after