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:- gccversions- 4.2.1,- 4.6.3and- 4.7.2
- clangversions- 3.0and- 3.3
- msvcversion- 12.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_line
- python
- char_template
- path_template
- stream_template
- string_template
- array- [N](Native static array.)
- [](Native dynamic array.)
- boost::array
 
- bool- bool
 
- complex- std::complex
 
- container- deque- std::deque
 
- list- std::list
 
- map- std::map
- std::multimap
 
- set- std::set
- std::multiset
 
- stack- std::stack
 
- vector- std::vector
 
 
- memory- std::auto_ptr
 
- none- boost::none_t
 
- numeric- char
- char signed
- char unsigned
- short
- short unsigned
- int
- int unsigned
- long
- long unsigned
- wchar_t(When available, unless disabled by- AJG_SYNTH_CONFIG_NO_WCHAR_T)
- long long(When available, unless disabled by- AJG_SYNTH_CONFIG_NO_LONG_LONG)
- long long unsigned(When available, unless disabled by- AJG_SYNTH_CONFIG_NO_LONG_LONG)
- __int64(- msvc-only.)
- __int64 unsigned(- msvc-only.)
- float
- double
- long double
 
- optional- boost::optional
 
- ptime- boost::posix_time::ptime
 
- ptree- boost::property_tree::ptree
 
- pointer- *(Native pointer.)
 
- ref- boost::reference_wrapper
 
- smart_ptr- boost::scoped_array
- boost::scoped_ptr
- boost::shared_array
- boost::shared_ptr
 
- string- std::basic_string
- char*
- char[N]
- wchar_t*(When available, unless disabled by- AJG_SYNTH_CONFIG_NO_WCHAR_T)
- wchar_t[N](When available, unless disabled by- AJG_SYNTH_CONFIG_NO_WCHAR_T)
 
- utility- std::pair
 
- variant- boost::variant
 
- ini
- json
- xml
- base_adapter
- bindings::base_binding
- engines::base_engine
- templates::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_tag
- django::builtin_tags::block_tag
- django::builtin_tags::comment_tag
- django::builtin_tags::csrf_token_tag
- django::builtin_tags::cycle_tag
- django::builtin_tags::cycle_as_tag
- django::builtin_tags::cycle_as_silent_tag
- django::builtin_tags::debug_tag
- django::builtin_tags::extends_tag
- django::builtin_tags::filter_tag
- django::builtin_tags::firstof_tag
- django::builtin_tags::for_tag
- django::builtin_tags::for_empty_tag
- django::builtin_tags::if_tag
- django::builtin_tags::ifchanged_tag
- django::builtin_tags::ifequal_tag
- django::builtin_tags::ifnotequal_tag
- django::builtin_tags::include_tag
- django::builtin_tags::include_with_tag
- django::builtin_tags::include_with_only_tag
- django::builtin_tags::load_tag
- django::builtin_tags::load_from_tag
- django::builtin_tags::now_tag
- django::builtin_tags::regroup_tag
- django::builtin_tags::spaceless_tag
- django::builtin_tags::ssi_tag
- django::builtin_tags::templatetag_tag
- django::builtin_tags::url_tag
- django::builtin_tags::url_as_tag
- django::builtin_tags::variable_tag
- django::builtin_tags::verbatim_tag
- django::builtin_tags::widthratio_tag
- django::builtin_tags::with_tag
- django::builtin_tags::library_tag
- django::builtin_filters::add_filter
- django::builtin_filters::addslashes_filter
- django::builtin_filters::capfirst_filter
- django::builtin_filters::center_filter
- django::builtin_filters::cut_filter
- django::builtin_filters::date_filter
- django::builtin_filters::default_filter
- django::builtin_filters::default_if_none_filter
- django::builtin_filters::dictsort_filter
- django::builtin_filters::dictsortreversed_filter
- django::builtin_filters::divisibleby_filter
- django::builtin_filters::escape_filter
- django::builtin_filters::escapejs_filter
- django::builtin_filters::filesizeformat_filter
- django::builtin_filters::first_filter
- django::builtin_filters::fix_ampersands_filter
- django::builtin_filters::floatformat_filter
- django::builtin_filters::force_escape_filter
- django::builtin_filters::get_digit_filter
- django::builtin_filters::iriencode_filter
- django::builtin_filters::join_filter
- django::builtin_filters::last_filter
- django::builtin_filters::length_filter
- django::builtin_filters::length_is_filter
- django::builtin_filters::linebreaks_filter
- django::builtin_filters::linebreaksbr_filter
- django::builtin_filters::linenumbers_filter
- django::builtin_filters::ljust_filter
- django::builtin_filters::lower_filter
- django::builtin_filters::make_list_filter
- django::builtin_filters::phone2numeric_filter
- django::builtin_filters::pluralize_filter
- django::builtin_filters::pprint_filter
- django::builtin_filters::random_filter
- django::builtin_filters::removetags_filter
- django::builtin_filters::rjust_filter
- django::builtin_filters::safe_filter
- django::builtin_filters::safeseq_filter
- django::builtin_filters::slice_filter
- django::builtin_filters::slugify_filter
- django::builtin_filters::stringformat_filter
- django::builtin_filters::striptags_filter
- django::builtin_filters::time_filter
- django::builtin_filters::timesince_filter
- django::builtin_filters::timeuntil_filter
- django::builtin_filters::title_filter
- django::builtin_filters::truncatechars_filter
- django::builtin_filters::truncatechars_html_filter
- django::builtin_filters::truncatewords_filter
- django::builtin_filters::truncatewords_html_filter
- django::builtin_filters::unordered_list_filter
- django::builtin_filters::upper_filter
- django::builtin_filters::urlencode_filter
- django::builtin_filters::urlize_filter
- django::builtin_filters::urlizetrunc_filter
- django::builtin_filters::wordcount_filter
- django::builtin_filters::wordwrap_filter
- django::builtin_filters::yesno_filter
- django::options::autoescape
- django::options::nonbreaking_space
- django::options::default_value(for- TEMPLATE_STRING_IF_INVALID)
- django::options::formats(for- TIME_FORMAT,- DATE_FORMAT, etc.)
- django::options::debug(for- TEMPLATE_DEBUG)
- django::options::directories(for- TEMPLATE_DIRS)
- django::options::libraries(for external tags & filters)
- django::options::loaders(for dynamically loading libraries)
- ssi::builtin_tags::config_tag
- ssi::builtin_tags::echo_tag
- ssi::builtin_tags::exec_tag
- ssi::builtin_tags::fsize_tag
- ssi::builtin_tags::flastmod_tag
- ssi::builtin_tags::if_tag
- ssi::builtin_tags::include_tag
- ssi::builtin_tags::printenv_tag
- ssi::builtin_tags::set_tag
- ssi::options::echo_message
- ssi::options::directories
- ssi::options::size_format
- ssi::options::time_format
- ssi::options::error_message
- tmpl::builtin_tags::comment_tag(Technically, part of- ctpp)
- tmpl::builtin_tags::if_tag
- tmpl::builtin_tags::include_tag
- tmpl::builtin_tags::loop_tag
- tmpl::builtin_tags::unless_tag
- tmpl::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.
