A Powerful Templating Framework in C++, 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.
Version 1 is released and stable.
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.jsonOr on Windows:
echo {"user":"Dolph Lundgren"} > context.json
echo Howdy, {{ user }}! > template.txt
type template.txt | synth -e django -c context.json
import synth, sys
def simple_tmpl_example():
    t = synth.Template('Howdy, <TMPL_VAR user>!', 'tmpl')
    c = {'user': 'Dolph Lundgren'}
    # Render to different destinations:
    t.render_to_path("greeting.txt", c)
    t.render_to_file(sys.stdout, c)
    print(t.render_to_string(c))#include <map>
#include <string>
#include <iostream>
#include <ajg/synth.hpp>
typedef ajg::synth::default_traits<char>                    traits_type;
typedef ajg::synth::engines::ssi::engine<traits_type>       engine_type;
typedef ajg::synth::templates::string_template<engine_type> template_type;
int main() {
    // Parse the template.
    template_type const t(
        "Howdy, <!--#echo var='user' -->! "
        "Your balance is <!--#echo var='points' -->.");
    // Create some data.
    std::map<std::string, engine_type::value_type> m;
    m["user"] = "Dolph Lundgren";
    m["points"] = 42;
    // Render to different destinations:
    t.render_to_stream(std::cout, m);
    t.render_to_path("greeting.txt", m);
    std::cout << t.render_to_string(m);
    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}
  -d path, --directory=path    template location(s)        (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.
Using Chocolatey:
choco install synth
Support for other system package managers like Apt or Yum is welcome.
Note that these will only install the Python module.
Using Pip:
pip install pip --upgrade # Ensure wheel support
pip install synth # Prefix with `sudo` if needed.
Using Easy Install:
easy_install synth # Prefix with `sudo` if needed.
If possible, use Pip instead.
- 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
- buffer_template
- path_template
- stream_template
- string_template
- array- T[N]
- T[]
- 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- void*
- T*
 
- 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
 
- adapters::base_adapter
- bindings::base_binding
- engines::base_engine
- templates::base_template
- engines::context
- engines::options
- engines::state
- engines::value
- templates::cache
- 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)
- ini
- json
- xml
- 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::library_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_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
- context::formats["TEMPLATE_STRING_IF_INVALID"](default:- "")
- context::formats["DATE_FORMAT"](default:- "N j, Y")
- context::formats["DATETIME_FORMAT"](default:- "N j, Y, P")
- context::formats["MONTH_DAY_FORMAT"](default:- "F j")
- context::formats["SHORT_DATE_FORMAT"](default:- "m/d/Y")
- context::formats["SHORT_DATETIME_FORMAT"](default:- "m/d/Y P")
- context::formats["TIME_FORMAT"](default:- "P")
- context::formats["YEAR_MONTH_FORMAT"](default:- "F Y")
(Note: Django's TEMPLATE_DEBUG and TEMPLATE_DIRS are handled through options::debug and options::directories, respectively.)
- 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
- context::formats["echomsg"](default:- "(none)")
- context::formats["errormsg"](default:- "[an error occurred while processing this directive]")
- context::formats["sizefmt"](default:- "bytes")
- context::formats["timefmt"](default:- "%A, %d-%b-%Y %H:%M:%S %Z")
- 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
- options::debug(default:- false)
- options::directories(default:- ".")
- options::libraries(for dynamic tags & filters)
- options::loaders(for dynamic library loading)
- options::resolvers(for dynamic URL resolution and reversal)
- options::caching(a bit mask of caching behavior)- caching_none
- caching_all
- caching_paths
- caching_buffers
- caching_strings
- caching_per_thread
- caching_per_process
 
- 
Build: - Pre-commit script/hook
- GCC:
- [4.9+] Add -fsanitize=undefinedwhen available
 
- [4.9+] Add 
- Visual Studio:
- [2013] Pass /W4 cleanly
- [2013] Pass /Wall cleanly
- [2012] Create 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
- Support is_safe, needs_autoescape, and expects_localtime in custom filters
 
- Other:
 
- Command-line:
- 
Engines: - Django:
- loremtag
- Make markers dynamically configurable
- Native i18nlibrary
- Native l10nlibrary
- Native tzlibrary
- Native staticlibrary
- Native staticfileslibrary
- Native humanizelibrary
- Native webdesignlibrary
 
- 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::tuple
- Adapter for boost::any
- Adapter for boost::function
- 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: - Make documentation comments uniformly ///
- Replace local version of Boost with minimal, shallow submodules once boostorg/boost is ready
- Move render_tagandbuiltin_tags_tobase_engine::kernel
- Move render_blocktobase_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)
- Modernize codebase to with C++11 support:
- Translate macros to variadic templates
- 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
 
- Make documentation comments uniformly 
- 
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 PM> Install-Package boostin the Package Manager Console
 
- Using Homebrew: 
 
- A: Here are some suggestions:
This library is distributed under the Boost LICENSE.
