#! /usr/bin/env python

# This is a script for generating templated text files using configuration
# variables. It is typically used to generate configuration files using values
# stored as environment variables or passed in the command line, in Docker for
# instance.
#
# This script was written without any external dependency. Also, it is
# compatible both with Python 2 and Python 3, which means that all you need to
# run it is a Python interpreter. This script can be installed with pip:
#
#    pip install ced
#
# or directly downloaded from github:
#
#    curl https://raw.githubusercontent.com/regisb/ced/master/ced/ced > ced
#
# To learn more about ced, check the project on Github: https://github.com/regisb/ced

from __future__ import unicode_literals
import argparse
import os
import string
import sys


def main():
    sys.exit(run())

def run():
    parser = argparse.ArgumentParser(
        description="A lightweight, cross-platform, no-dependency configuration editor."
    )
    parser.add_argument("-o", "--output", help="path to destination file; if unset, print to stdout")
    parser.add_argument("-d", "--delimiter", default='$', help="placeholder delimiter")
    parser.add_argument("-s", "--safe", action='store_true',
                        help="do not raise error on missing placeholder values")
    parser.add_argument("-V", "--value", action="append",
                        help="explicitely set a value: formated as 'var=value'")
    parser.add_argument("src", help="path to source file")
    args = parser.parse_args()

    Template = template_class(args.delimiter)

    # Parse values
    values = os.environ
    if args.value:
        for value in args.value:
            separator = value.index('=')
            if separator < 0:
                sys.stderr.write("Incorrectly formated value: '{}' (missing '=')\n".format(value))
                return 1
            values[value[:separator]] = value[separator+1:]


    # Render template
    with open(args.src) as fi:
        template = Template(fi.read())
        if args.safe:
            substituted = template.safe_substitute(**values)
        else:
            try:
                substituted = template.substitute(**values)
            except KeyError as e:
                sys.stderr.write("Missing placeholder: '{}'\n".format(e.args[0]))
                return 1

    # Save
    if args.output:
        with open(args.output, 'w') as fo:
            fo.write(substituted)
    else:
        print(substituted)

    return 0

def template_class(user_delimiter='$'):
    """
    The default delimiter of the python Template class is '$'. Here, we
    generate a Template class with a custom delimiter. This cannot be done
    after the class creation because the Template metaclass uses the delimiter
    value.
    """
    class Template(string.Template):
        delimiter = user_delimiter
    return Template

if __name__ == "__main__":
    main()
