A Powerful C++ Templating Framework with a command-line tool and Python module, written by Alvaro J. Genial.
Synth is a template framework—a set of components that can be mixed and matched to build the right functionality; furthermore, components are loosely-coupled, designed to be both extensible and replaceable.
Beta, approaching a first full release.
Synth blurs the line between compile-time and runtime, and it does so by blending three worlds: (a) the static C++ type system; (b) the dynamic values that need to be manipulated and formatted, including those from other languages; and (c) the templates to do so. The name is an allusion to this synthesis process, which combines values to generate new ones (streams, files, strings, numbers, etc.)
echo '{"user": "Dolph Lundgren"}' > 'context.json'
echo 'Howdy, {{ user }}!' > 'template.txt'
cat template.txt | ./synth -e django -c context.jsonimport synth, sys
def simple_tmpl_example():
    t = synth.Template('Howdy, <TMPL_VAR user>!', 'tmpl')
    c = {'user': 'Dolph Lundgren'}
    t.render_to_path("greeting.txt", c) # or, e.g.:
    t.render_to_file(sys.stdout, c) # or, e.g.:
    print t.render_to_string(c)#include <iostream>
#include <ajg/synth.hpp>
namespace synth = ajg::synth;
typedef synth::default_traits<char>                         traits_type;
typedef synth::engines::ssi::engine<traits_type>            engine_type;
typedef synth::templates::string_template<engine_type>      template_type;
int main() {
    template_type const t("Howdy, <!--#echo var=\"user\" -->!");
    template_type::context_type c;
    c["user"] = "Dolph Lundgren";
    // Render to different destinations:
    t.render_to_stream(std::cout);
    t.render_to_path("greeting.txt", c);
    std::cout << t.render_to_string(c);
    return 0;
}USAGE: synth [OPTIONS...]
Options:
  -h,      --help              print help message
  -v,      --version           print library version
  -c file, --context=file      contextual data             *.{ini,json,xml}
  -e name, --engine=name       template engine             {django,ssi,tmpl}
  -a,      --autoescape[=bool] automatically escape values (default: 'true')
  -d path, --directory=path    template location(s)        (default: '.')
  -r text, --replacement=text  replaces missing values     (default: '')
Using Homebrew:
brew install https://raw.github.com/ajg/synth/master/synth.rb
# Note that you must append `--with-python` to install the Python module.
(Support for other system package managers like Apt or Yum is welcome.)
Using Pip:
pip install synth # Prefix with `sudo` if needed.
Using Easy Install:
easy_install synth # Prefix with `sudo` if needed.
(Pre-built binary releases for common platforms are welcome.)
- Ensure you have the following:
 
- A tool to get the source (
git,curl, a browser, etc.) - A system to build it with (SCons or Visual Studio)
 - A C++ compiler (
clang,gcc,msvc, etc.) In particular, Synth is known to compile with:gccversions4.2.1,4.6.3and4.7.2clangversions3.0and3.3msvcversion12.0(VS2013)
 
- 
Get the source (e.g. the latest, as shown here):
git clone --depth 1 --recursive https://github.com/ajg/synth.git && cd synth - 
Optionally, build the command-line tool:
scons synth # Add debug=1 to generate debugging symbols & disable optimizations.(Note that if you are hell bent on it, you can use a different version of Boost; see Infrequently Asked Questions.)
 - 
Optionally, build (and install) the Python module:
python setup.py install # Prefix with `sudo` if needed. 
django: An implementation of Django Templates.ssi: An implementation of Server Side Includes.tmpl: An implementation of Perl's HTML::Template.null: A minimal implementation that does nothing (i.e. a no-op.)
command_linepython
char_templatepath_templatestream_templatestring_template
array[N](Native static array.)[](Native dynamic array.)boost::array
boolbool
complexstd::complex
containerdequestd::deque
liststd::list
mapstd::mapstd::multimap
setstd::setstd::multiset
stackstd::stack
vectorstd::vector
memorystd::auto_ptr
noneboost::none_t
numericcharchar signedchar unsignedshortshort unsignedintint unsignedlonglong unsignedwchar_t(When available, unless disabled byAJG_SYNTH_CONFIG_NO_WCHAR_T)long long(When available, unless disabled byAJG_SYNTH_CONFIG_NO_LONG_LONG)long long unsigned(When available, unless disabled byAJG_SYNTH_CONFIG_NO_LONG_LONG)__int64(msvc-only.)__int64 unsigned(msvc-only.)floatdoublelong double
optionalboost::optional
ptimeboost::posix_time::ptime
ptreeboost::property_tree::ptree
pointer*(Native pointer.)
refboost::reference_wrapper
smart_ptrboost::scoped_arrayboost::scoped_ptrboost::shared_arrayboost::shared_ptr
stringstd::basic_stringchar*char[N]wchar_t*(When available, unless disabled byAJG_SYNTH_CONFIG_NO_WCHAR_T)wchar_t[N](When available, unless disabled byAJG_SYNTH_CONFIG_NO_WCHAR_T)
utilitystd::pair
variantboost::variant
inijsonxml
base_adapterbindings::base_bindingengines::base_enginetemplates::base_template
value_facade
AJG_SYNTH_VERSION(e.g.1.2.3)AJG_SYNTH_VERSION_MAJOR(e.g.1)AJG_SYNTH_VERSION_MINOR(e.g.2)AJG_SYNTH_VERSION_PATCH(e.g.3)AJG_SYNTH_VERSION_SEQ(e.g.(1)(2)(3))AJG_SYNTH_VERSION_TUPLE(e.g.(1, 2, 3))AJG_SYNTH_VERSION_ARRAY(e.g.(3, (1, 2, 3)))AJG_SYNTH_VERSION_STRING(e.g."1.2.3")
AJG_SYNTH_CONFIG_NO_WCHAR_T(default: automatically determined)AJG_SYNTH_CONFIG_NO_LONG_LONG(default: automatically determined)AJG_SYNTH_CONFIG_NO_DEBUG(default: automatically determined)AJG_SYNTH_CONFIG_NO_WINDOWS_H(default: not defined)AJG_SYNTH_CONFIG_DEFAULT_CHAR_TYPE(default:char)AJG_SYNTH_CONFIG_MAX_FRAMES(default:1024)AJG_SYNTH_CONFIG_HANDLE_ASSERT(default:BOOST_ASSERT)AJG_SYNTH_CONFIG_HANDLE_EXCEPTION(default:boost::throw_exception)
django::builtin_tags::autoescape_tagdjango::builtin_tags::block_tagdjango::builtin_tags::comment_tagdjango::builtin_tags::csrf_token_tagdjango::builtin_tags::cycle_tagdjango::builtin_tags::cycle_as_tagdjango::builtin_tags::cycle_as_silent_tagdjango::builtin_tags::debug_tagdjango::builtin_tags::extends_tagdjango::builtin_tags::filter_tagdjango::builtin_tags::firstof_tagdjango::builtin_tags::for_tagdjango::builtin_tags::for_empty_tagdjango::builtin_tags::if_tagdjango::builtin_tags::ifchanged_tagdjango::builtin_tags::ifequal_tagdjango::builtin_tags::ifnotequal_tagdjango::builtin_tags::include_tagdjango::builtin_tags::include_with_tagdjango::builtin_tags::include_with_only_tagdjango::builtin_tags::load_tagdjango::builtin_tags::load_from_tagdjango::builtin_tags::now_tagdjango::builtin_tags::regroup_tagdjango::builtin_tags::spaceless_tagdjango::builtin_tags::ssi_tagdjango::builtin_tags::templatetag_tagdjango::builtin_tags::url_tagdjango::builtin_tags::url_as_tagdjango::builtin_tags::variable_tagdjango::builtin_tags::verbatim_tagdjango::builtin_tags::widthratio_tagdjango::builtin_tags::with_tagdjango::builtin_tags::library_tag
django::builtin_filters::add_filterdjango::builtin_filters::addslashes_filterdjango::builtin_filters::capfirst_filterdjango::builtin_filters::center_filterdjango::builtin_filters::cut_filterdjango::builtin_filters::date_filterdjango::builtin_filters::default_filterdjango::builtin_filters::default_if_none_filterdjango::builtin_filters::dictsort_filterdjango::builtin_filters::dictsortreversed_filterdjango::builtin_filters::divisibleby_filterdjango::builtin_filters::escape_filterdjango::builtin_filters::escapejs_filterdjango::builtin_filters::filesizeformat_filterdjango::builtin_filters::first_filterdjango::builtin_filters::fix_ampersands_filterdjango::builtin_filters::floatformat_filterdjango::builtin_filters::force_escape_filterdjango::builtin_filters::get_digit_filterdjango::builtin_filters::iriencode_filterdjango::builtin_filters::join_filterdjango::builtin_filters::last_filterdjango::builtin_filters::length_filterdjango::builtin_filters::length_is_filterdjango::builtin_filters::linebreaks_filterdjango::builtin_filters::linebreaksbr_filterdjango::builtin_filters::linenumbers_filterdjango::builtin_filters::ljust_filterdjango::builtin_filters::lower_filterdjango::builtin_filters::make_list_filterdjango::builtin_filters::phone2numeric_filterdjango::builtin_filters::pluralize_filterdjango::builtin_filters::pprint_filterdjango::builtin_filters::random_filterdjango::builtin_filters::removetags_filterdjango::builtin_filters::rjust_filterdjango::builtin_filters::safe_filterdjango::builtin_filters::safeseq_filterdjango::builtin_filters::slice_filterdjango::builtin_filters::slugify_filterdjango::builtin_filters::stringformat_filterdjango::builtin_filters::striptags_filterdjango::builtin_filters::time_filterdjango::builtin_filters::timesince_filterdjango::builtin_filters::timeuntil_filterdjango::builtin_filters::title_filterdjango::builtin_filters::truncatechars_filterdjango::builtin_filters::truncatechars_html_filterdjango::builtin_filters::truncatewords_filterdjango::builtin_filters::truncatewords_html_filterdjango::builtin_filters::unordered_list_filterdjango::builtin_filters::upper_filterdjango::builtin_filters::urlencode_filterdjango::builtin_filters::urlize_filterdjango::builtin_filters::urlizetrunc_filterdjango::builtin_filters::wordcount_filterdjango::builtin_filters::wordwrap_filterdjango::builtin_filters::yesno_filter
django::options::autoescapedjango::options::nonbreaking_spacedjango::options::default_value(forTEMPLATE_STRING_IF_INVALID)django::options::formats(forTIME_FORMAT,DATE_FORMAT, etc.)django::options::debug(forTEMPLATE_DEBUG)django::options::directories(forTEMPLATE_DIRS)django::options::libraries(for external tags & filters)django::options::loaders(for dynamically loading libraries)
ssi::builtin_tags::config_tagssi::builtin_tags::echo_tagssi::builtin_tags::exec_tagssi::builtin_tags::fsize_tagssi::builtin_tags::flastmod_tagssi::builtin_tags::if_tagssi::builtin_tags::include_tagssi::builtin_tags::printenv_tagssi::builtin_tags::set_tag
ssi::options::echo_messagessi::options::directoriesssi::options::size_formatssi::options::time_formatssi::options::error_message
tmpl::builtin_tags::comment_tag(Technically, part ofctpp)tmpl::builtin_tags::if_tagtmpl::builtin_tags::include_tagtmpl::builtin_tags::loop_tagtmpl::builtin_tags::unless_tagtmpl::builtin_tags::variable_tag
- 
Build:
- Pre-commit script/hook
 - Add 
-fsanitize=undefinedwhen available (GCC 4.9+ so far) - Visual Studio 2013:
- Add project for command-line tool
 - Pass /W4 cleanly
 - Pass /Wall cleanly
 
 - Create Visual Studio 2012 solution & projects
 
 - 
Distribution:
- RPM package
 - Apt package
 - Yum package
 - MacPort support
 - Standalone pre-built Darwin binaries
 - Standalone pre-built Windows binaries
 - MSI installer
 
 - 
Documentation:
- Produce Boost-compatible documentation
 - Create 
conf.py(et al.) to enable ReadTheDocs 
 - 
Testing:
- Rewrite the majority of unit tests as a set of 
.in/.outfiles - Add exhaustive date/time formatting tests
 - Add way to specify expected failures; re-enable commented out tests
 
 - Rewrite the majority of unit tests as a set of 
 - 
Optimization:
- Compare benefit/cost of 
-O,-O2,-O3and-Ofast - Investigate using thread locals instead of statics for medium-expense objects
 - Investigate 
-fvisibility-inlines-hidden - Replace 
ostream << string(a, b)constructs withstd::ostream_iterator+std::copy 
 - Compare benefit/cost of 
 - 
Bindings:
- Command-line:
- Allow specifying formats option
 - Allow specifying debug option
 - Allow named input files
 - Allow named output files
 - [v1+] Allow using arbitrary programs as tags
 - [v1+] Allow using arbitrary programs as filters
 
 - Python:
- [v1] Set docstrings where appropriate
 - [v1] Turn optional arguments to synth.Template into kwargs
 - [v1+] Support for Python 3
 - Support is_safe, needs_autoescape, and expects_localtime in custom filters
 - Support for non-simple custom tags via token and parser objects
- Custom inclusion tags
 - Custom assignment tags
 - Custom tags with arbitrary blocks
 
 
 - Other:
 
 - Command-line:
 - 
Engines:
- Django:
- Implement multi-level inheritance
 - Option to pre-load libraries, tags and filters
 - Make markers dynamically configurable
 - Consider using hex character entities (vs. named) to match Django's engine
 - Native 
i18nlibrary - Native 
l10nlibrary - Native 
tzlibrary - Native 
staticlibrary 
 - SSI:
- Implement additional tags from Jigsaw
 
 - TMPL:
- Consider renaming 
html 
 - Consider renaming 
 - Other:
- Create 
ctppengine - [v1+] Create 
jinja2engine - [v1+] Create 
cheetahengine - [v1+] Create 
xsltengine 
 - Create 
 
 - Django:
 - 
Adapters:
- Adapter for 
boost::tribool - Adapters for 
boost::fusionsequences - Adapters for 
boost::local_timetypes - Adapter for 
boost::intrusive_ptr - Support for 
boost::enable_shared_from_this - [v2] Adapters for 
c++11types - [v2] Adapters for 
c++14types 
 - Adapter for 
 - 
Templates:
- Create new 
file_template(usingFILE* file)- Add 
render_to_fileto base_template - Add 
render_fileto engines 
 - Add 
 - Create 
descriptor_template(usingint descriptor)- Add 
render_to_descriptorto base_template - Add 
render_descriptorto engines 
 - Add 
 
 - Create new 
 - 
Refactoring:
- Rename value_facade to base_value
 - Make documentation comments uniformly 
/// - Replace catching 
invalid_methodwith dedicated attribute methods - Replace 
BOOST_ASSERTwithAJG_SYNTH_ASSERT - Remove as much dead weight from local Boost copy as possible; and/or
 - Replace local version of Boost with minimal, shallow submodules once boostorg/boost is ready
 - Move 
render_tagandbuiltin_tags_tobase_engine::kernel - Remove all no-op tags (e.g. 
cycle_as_silent_tag) - Fold all variant tags into their main version (e.g. 
load_from_tag) - [v2] Create 
c++11/c++14branch- Translate macros to variadic templates
 - Replace 
BOOST_FOREACHwith newforloop - Replace 
BOOST_STATIC_CONSTANTwithstatic const - Replace 
BOOST_STATIC_ASSERTwithstatic_assert - Replace 
boost::assignuse with aggregate initializers - Remove complex redundant 
typedefs in favor ofauto - Replace 
<boost/cstdint.hpp>with<cstdint> - Replace Boost.Random with 
<random> - Replace Boost.Atomic with 
<atomic> - Consider switching to unordered_map/unordered_set where possible
 
 - [v1+] Add 
AJG_SYNTH_PRAGMAmacro that invokes_Pragmaor__pragma(MSVC) as needed- Add 
AJG_SYNTH_PRAGMA(once)to all header files and see if it speeds up compilations 
 - Add 
 - [v1+] Sort 
#includes alphabetically - [v1+] Run entire C++ codebase through clang-format
 - Change 
classin template signatures totypename - [v1] Reformat all 
operator _()'s tooperator_() - [v1+] Remove header guard closing comments
 - [v1+] Remove namespace closing comments
 - [v2+] Factor out values & adapters into separate library for generic language interop
 
 
- 
Q: Can I use a version of Boost other than the one bundled?
- A: Yes, you can, though note that unless you're already using Boost in your project, there is usually no good reason to; anyway:
- On most systems, you can build Synth with the system's Boost by passing 
boost=systemtoscons. - On Windows, you'll need to edit the project file(s) in Visual Studio and set the include and library directories to point to the existing Boost installation.
 - The Python module does not support this option yet.
 
 - On most systems, you can build Synth with the system's Boost by passing 
 
 - A: Yes, you can, though note that unless you're already using Boost in your project, there is usually no good reason to; anyway:
 - 
Q: How can I install a system-wide version of Boost?
- A: Here are some suggestions:
- Using Homebrew: 
brew install boost(Append--with-pythonfor Boost.Python support.) - Using Apt: 
sudo apt-get install libboost-all-dev - Using Yum: 
sudo yum install boost-devel - On Windows, try http://sourceforge.net/projects/boost/files/boost-binaries/
 
 - Using Homebrew: 
 
 - A: Here are some suggestions:
 
This library is distributed under the Boost LICENSE.
