'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
'''
import sys as _sys
import re as _re
import json as _json
import yaml as _yaml
import argparse as _argparse
def convey(
x,
fs
):
y = x
for f in fs:
y = f(y)
return y
def string_coin(
template,
arguments,
options = None
):
options = (
{
"character_open": "{{",
"character_close": "}}",
"ignore_whitespaces": True,
}
|
(options or {})
)
result = template
for (key, value, ) in arguments.items():
pattern = (
_re.escape(options["character_open"])
+
("\s*" if options["ignore_whitespaces"] else "")
+
_re.escape(key)
+
("\s*" if options["ignore_whitespaces"] else "")
+
_re.escape(options["character_close"])
)
result = _re.sub(
pattern,
value,
result
)
return result
def file_read(
path
):
handle = open(path, "r")
content = handle.read()
handle.close()
return content
def handle_value(
value,
options = None
):
options = (
{
"indicator": "@",
}
|
(options or {})
)
return (
file_read(value[len(options["indicator"]):])
if value.startswith(options["indicator"]) else
value
)
def data_from_file(
path
):
return (
{}
if
(path is None)
else
(
(
lambda content: (
_json.loads(content)
if path.endswith(".json") else
_yaml.safe_load(content)
)
) (file_read(path))
)
)
def data_from_adhoc_arguments(
arguments
):
return dict(
map(
lambda argument: (
(
lambda parts: (
parts[0],
handle_value(parts[1]),
)
) (argument.split(":", 1))
),
(arguments or {})
)
)
def main(
):
## args
argument_parser = _argparse.ArgumentParser(
prog = "coin",
formatter_class = _argparse.ArgumentDefaultsHelpFormatter,
description = "transforms a template string to its refined version by substituting its placeholders with concrete values; example: »echo '{{flowers}} are {{color}}' | coin -a flowers:roses -a color:red«",
)
argument_parser.add_argument(
"-t",
"--template-path",
dest = "template_path",
type = str,
metavar = "",
default = None,
help = "default: read from stdin",
)
argument_parser.add_argument(
"-d",
"--data-path",
type = str,
default = None,
metavar = "",
help = "path to JSON or YAML file, containing placeholder assignments (e.g. »{\"flowers\": \"roses\", \"color\": \"red\"}«)",
)
argument_parser.add_argument(
"-a",
"--adhoc-argument",
type = str,
dest = "adhoc_arguments",
action = "append",
metavar = ":",
help = "prefixing with '@' causes the value to be interpreted as the path to a text file, whose content shall be used",
)
argument_parser.add_argument(
"-o",
"--character-open",
type = str,
default = "{{",
metavar = "",
help = "placeholder opening character",
)
argument_parser.add_argument(
"-c",
"--character-close",
type = str,
default = "}}",
metavar = "",
help = "placeholder closing character",
)
argument_parser.add_argument(
"-w",
"--heed-whitespaces",
action = "store_true",
help = "whether whitespace characters in the template string shall be heeded, i.e. not be ignored",
)
args = argument_parser.parse_args()
## exec
content_in = (
_sys.stdin.read()
if (args.template_path is None) else
file_read(args.template_path)
)
data = (
data_from_file(args.data_path)
|
data_from_adhoc_arguments(args.adhoc_arguments)
)
content_out = string_coin(
content_in,
data,
{
"character_open": args.character_open,
"character_close": args.character_close,
"ignore_whitespaces": (not args.heed_whitespaces),
}
)
_sys.stdout.write(content_out)
main()