158 lines
4.2 KiB
Python
158 lines
4.2 KiB
Python
"""
|
|
Copyright (C) 2022 Daniel Mowitz
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
import sys, os, cooklang
|
|
|
|
def parse_recipe(cooklang_source, title=""):
|
|
"""
|
|
Takes: string cooklang_source
|
|
Returns: [ string ] tex
|
|
|
|
Takes the recipes source as an argument and returns the cuisine recipe block.
|
|
One element per line.
|
|
"""
|
|
|
|
recipe = cooklang.parseRecipe(cooklang_source)
|
|
|
|
if title:
|
|
title = get_metadata_value(["title"], recipe, title)
|
|
else:
|
|
title = get_metadata_value(["title"], recipe)
|
|
|
|
servings = get_metadata_value(time_keys, recipe)
|
|
time = get_metadata_value(serving_keys, recipe)
|
|
|
|
tex = []
|
|
|
|
tex.append("\\begin{recipe}{" +
|
|
title + "}{" +
|
|
servings + "}{" +
|
|
time + "}")
|
|
|
|
for step in recipe["steps"]:
|
|
ingredients = get_step_ingredients(step)
|
|
|
|
if ingredients:
|
|
tex += texify_ingredients(ingredients)
|
|
else:
|
|
tex.append("\\newstep")
|
|
|
|
step_text = ""
|
|
for part in step:
|
|
if "value" in part.keys():
|
|
step_text += part["value"]
|
|
elif "name" in part.keys():
|
|
# Remove whitespaces from ingredient names
|
|
step_text += part["name"].strip()
|
|
tex.append(step_text)
|
|
|
|
tex.append("\\end{recipe}")
|
|
|
|
return tex
|
|
|
|
|
|
def parse_recipe_from_file(path):
|
|
"""
|
|
Takes: string path
|
|
Returns: [ string ] tex
|
|
|
|
Takes a recipe path as an argument and returns the cuisine recipe block.
|
|
One element per line.
|
|
"""
|
|
if not os.path.exists(path):
|
|
raise ArgumentError
|
|
|
|
name = os.path.basename(path)
|
|
split_name = os.path.splitext(name)
|
|
title = split_name[0]
|
|
|
|
with open(path) as file:
|
|
return parse_recipe(file.read(), title)
|
|
|
|
|
|
serving_keys = ["servings", "serves"]
|
|
time_keys = ["time", "total time", "total-time"]
|
|
|
|
def get_metadata_value(keys, recipe, substitute="N/A"):
|
|
|
|
# Sometimes people use too many >s for their metadata…
|
|
meta_data = { rem_beginning_duplicate(key, ">").strip(): recipe["metadata"][key] for key in recipe["metadata"].keys() }
|
|
|
|
for key in keys:
|
|
if key in meta_data.keys():
|
|
return meta_data[key]
|
|
|
|
return substitute
|
|
|
|
|
|
def rem_beginning_duplicate(in_str, rem_char):
|
|
while in_str and in_str[0] == rem_char:
|
|
in_str = in_str[1:]
|
|
|
|
return in_str
|
|
|
|
|
|
def get_step_ingredients(step):
|
|
ingredients = []
|
|
|
|
for part in step:
|
|
if part["type"] == "ingredient":
|
|
ingredients.append(part)
|
|
|
|
return ingredients
|
|
|
|
|
|
def texify_ingredients(ingredients):
|
|
tex = []
|
|
|
|
for ing in ingredients:
|
|
if ing["units"]:
|
|
|
|
try:
|
|
quantity = float(ing["quantity"])
|
|
if quantity % 1 == 0:
|
|
quantity = int(quantity)
|
|
except ValueError:
|
|
quantity = ing["units"]
|
|
|
|
tex.append("\\ingredient[" +
|
|
str(quantity) + "]{" +
|
|
ing["units"] + "}{" +
|
|
ing["name"] + "}")
|
|
else:
|
|
tex.append("\\ingredient{" +
|
|
ing["units"] + "}{" +
|
|
ing["name"] + "}")
|
|
|
|
return tex
|
|
|
|
|
|
class ArgumentError(Exception):
|
|
def __init__(self):
|
|
self.message = "Please supply the path to a cooklang file as an argument."
|
|
super().__init__(self.message)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
if sys.argv[1] == "--":
|
|
tex = parse_recipe(sys.stdin.read())
|
|
else:
|
|
tex = parse_recipe_from_file(sys.argv[1])
|
|
|
|
for line in tex:
|
|
print(line)
|