Programming a Cookbook

As my girlfriend Rima and I were cooking dinner we read over the recipe we'd made before. Soon we would struggle to recall if it was the lemon juice or the salt that we wanted to reduce or omit this second time around.  Or was that an increase we had wanted? This was turning out to be the usual guessing game.

I also lamented the fact that my favorite meal recipes live exclusively in said girlfriends head. With this in mind, we came to the natural conclusion that we should write a cookbook; something for our own use. i.e. an aggregation of recipes we like from books, family, the internet, and even the ones that we've made up ourselves.

As I began mulling over cookbook writing options, it occurred to me to use LaTeX. LaTeX is a document typesetting system that is used primarily in the scientific field of document and book publishing. It is a very powerful tool to programmatically generate very clean documents. I have used it on many occasions when writing notes for various math classes, airplane checklists, reports, and more.

The decision to use LaTeX really came together when I discovered that someone has already written a LaTeX package for typesetting recipes. The package is called Cuisine and you can read more about that in the link.  Below is a screen cap of some LaTeX to generate a recipe using the Cuisine package followed by the typeset output in the finished PDF book.

You can see from the image above that the recipes follow a format where a group of ingredients and an action to perform on the ingredients are linked. This is continued in chronological order with 1 or more ingredients listed and an associated action to perform with those ingredients.

I really like this order of listing ingredients. It succinctly communicates and compartmentalizes each step of the recipe thereby reducing confusion, errors, and even fatigue. It is tiresome to read a recipe that says "Add the cumin" and then you have to hunt thru the ingredient list to find how much cumin you need. 

The first task was to design the LaTeX document. This entails setting margins, paper size, fonts, preparing a table of contents, a title page, etc. With the rough template sorted out, I turned my attention to entering recipes. 

I got about 2 recipes deep before I realized a better way to enter recipes was needed. As you can see in the syntax above, there are a lot of brackets and braces and duplicate typing. It was clear that typing up a multitude of recipes in LaTeX was going to be a tedious adventure. This is where Perl comes in.

The idea was to casually type up a recipe as a text file that could be parsed and let Perl do all of the tedious and repetitive typing. This way, we can just type up a new recipe text file at any time, take a picture, and rerun the scripts to output a new copy of our nicely formatted cookbook. After all, who knows how many recipes we may come up with! 

Below you can see an example of one of these user typed recipe.txt files. This file was used to generate the LaTeX that output the hummus recipe above. As you can see, the format is quite simplified when compared to the LaTeX. Write a line that starts with 't' for title, 'p' for picture filename, 's' for setup, 'i' for ingredient, 'a' for action - a cooking step, and 'n' for any note. These line type identifiers are separated by the '>' symbol for parsing.

The first three lines must be in all recipe text files. i.e. Title, Picture, and Setup. If no picture is wanted for a particular recipe, simply set the filename as "none". e.g. "p > none". This will omit the picture and placeholder image for a given recipe. If a picture is desired, then the filename should be entered on this line and the image file stored in the ./Latex/Images directory.

The subsequent Ingredient and Action lines must be in the order you wish them to appear in the recipe. When creating the recipe text file, write 1 or more Ingredient lines followed by an Action line that describes an action to perform with the previously listed ingredients. Continue the recipe by listing the next set of ingredients and an action to perform with them.

The Note designator must only come at the very end of the file, although if no note is required, simply omit the line and line type designator entirely. i.e. have no line that reads "n > ".

So, the Perl script can now parse these files and generate the LaTeX, but this alone does not a cookbook make. We need chapters, but which ones? What if a friend or family member wants to make a book, but doesn't want a desert chapter? Will we have enough soup recipes to warrant their own chapter or should we fold those in with the main courses?  The penultimate scenario is strange to be sure, but clearly chapters must not be hard coded in LaTeX or Perl; we want all that code to remain unchanged even as the contents of the cookbook change.

To handle the changing needs of chapter definitions I went with a directory structure scheme. The directory "Chapters" is scanned for directories who's name should follow the convention "x-ChapterName" where x is any letter used to force an alphabetic order to the directories. The order that the chapters appear in the book is set alphabetically by the left "x-" portion of the directory name which is then discarded. The chapter names are generated by the Perl script using the right portion after the hyphen only. In the screencap below then it is clear to see that there will be 4 chapters in book order "Snacks", "Side Dishes", "Soups", and "Main Course". In this method chapters can be added, deleted, and renamed without the need to change any code.

From the above image you have probably already guessed that there are two recipes that will be included in the "Snacks" chapter. However, the only thing you can discern from this is the alphabetical order in which the recipes appear within the chapter. i.e. the filename is not used to title the recipe, however naming the files something descriptive is recommended. It might be hard to go back to edit your recipe for fig jam if the filename is 123.txt. The title of the recipe used in the cookbook is contained within the recipe text file itself on the line "t > 'Recipe Title'".

Toward the beginning of the book goes the front matter. This contains the author name, book title, and a preface. This front matter gets placed before the table of contents, and is generated from a user editable text file at ./latex/frontMatter.txt. It is parsed similarly to the files described above where the lines "a >" is for the author, "t >" is for the cookbook title, and "p >" is for the preface.

To make your own cookbook in this manner you will need Perl and LaTeX. Additionally, a sample cookbook structure is included in this Google Drive shared folder. It should just be a matter of downloading a copy the directory, editing your own frontMatter.txt, and recipe cards. Oh, and be sure to add some pictures of your tasty foods. With all of the edits in place, run the perl script then typeset the LaTeX and out comes your cookbook.pdf. If you are interested in taking a peek at our latest cookbook you can download  it separately.

Well, I think that is about it. With only a couple evenings work we have a sustainable method of maintaining our own cookbook. Now, I am off to the kitchen to make a pizza. If it turns out well, it might make it into our recipes.