201 lines
3.6 KiB
Python
201 lines
3.6 KiB
Python
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 = "<template-path>",
|
|
default = None,
|
|
help = "default: read from stdin",
|
|
)
|
|
argument_parser.add_argument(
|
|
"-d",
|
|
"--data-path",
|
|
type = str,
|
|
default = None,
|
|
metavar = "<data-path>",
|
|
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 = "<adhoc-argument-key>:<adhoc-argument-value>",
|
|
help = "prefixing <value> 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 = "<character-open>",
|
|
help = "placeholder opening character",
|
|
)
|
|
argument_parser.add_argument(
|
|
"-c",
|
|
"--character-close",
|
|
type = str,
|
|
default = "}}",
|
|
metavar = "<character-close>",
|
|
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()
|
|
|