Using Emacs Org for grocery lists and batch cooking
Posted: - Modified: | cooking, emacs, orgWe like preparing our meals in bulk. Buying groceries and cooking up a storm on the weekends means that we can grab quick and healthy lunches from the fridge or freezer, enjoy a variety of dinners during the week, and focus on other things that we want to do in the evenings.
I was looking for a menu planner and grocery list maker to help us plan and execute these batch cooking sessions more efficiently. In particular, I wanted something that could sort the ingredients for preparation, too. I like preparing ingredients for all the different recipes before I start cooking. If several recipes call for garlic, I might as well chop a lot of garlic in one session instead of breaking out the chopping board for each recipe.
I tried several menu planning and grocery list apps, but I wasn’t happy with any of the ones I came across. I like using Emacs for as much as possible, so I figured that I should give it a try. Here’s what I did and how it worked out.
I created an Org file for my recipes. In this plain-text outline, I created sections for my plan, shopping list, preparation tasks, and recipes. Under recipes, I created TODO items and scheduled them. Here’s an example entry:
** TODO Colorful bulgur salad SCHEDULED: <2012-06-19 Tue> http://allrecipes.com/recipe/colorful-bulgur-salad/ | 1/2 cup | bulgur wheat | | [[Colorful bulgur salad]] | | 1/2 cup | chicken broth | | [[Colorful bulgur salad]] | | 1 small | cucumber | seeded and chopped | [[Colorful bulgur salad]] | | 1 | tomato | chopped | [[Colorful bulgur salad]] | | 1 | carrot | shredded | [[Colorful bulgur salad]] | | 3 | green onions | thinly sliced | [[Colorful bulgur salad]] | | 3 tablespoons | fresh lime juice | | [[Colorful bulgur salad]] | | 3/4 tablespoon | chili powder | | [[Colorful bulgur salad]] | | 1 pinch | garlic powder | | [[Colorful bulgur salad]] |
I reformatted each recipe to fit this format, with columns for quantity, type, preparation, and recipe link. After I chose several recipes, I copied the ingredient lists into my preparation section and my shopping section. In the shopping section, I deleted the lines for ingredients I already had or could skip. I used org-table-sort-lines
to sort the table by the second column, which gave me this list:
| 1 bag | chicken legs and thighs | | [[Arroz caldo]] | | 2 small or 1 large | cucumber | chopped | [[Gazpacho]] | | 1 small | cucumber | seeded and chopped | [[Colorful bulgur salad]] | | 3 | green onions | thinly sliced | [[Colorful bulgur salad]] | | 1 | red onion | cut into 1" pieces | [[Shrimp kebabs]] | | 1 pound | shrimp | peeled and deveined | [[Shrimp kebabs]] | | 6 - 8 | tomatoes | chopped (Roma or plum are best; Don't lose the juice!) | [[Gazpacho]] | | 1 | zucchini | seeded and cut into 1" pieces | [[Shrimp kebabs]] |
It wasn’t sorted by aisle, but that was easy to do when I copied the list onto a recycled envelope. If I find myself using this a lot, I might write an Emacs Lisp function to gather the tables and sort the rows by aisle.
Anyway, shopping list in hand, we picked up our groceries in about ten minutes last Saturday. The next day, I looked at my prep list:
| | basil | chopped | [[Gazpacho]] | | 1/2 cup | bulgur wheat | | [[Colorful bulgur salad]] | | 1 tbsp | butter | | [[Bubble and squeak]] | | 2 tbsp | canola or peanut oil | | [[Teriyaki tofu]] | | 1 | carrot | shredded | [[Colorful bulgur salad]] | | 1/2 cup | chicken broth | | [[Colorful bulgur salad]] | | 1 bag | chicken legs and thighs | separated | [[Arroz caldo]] | | 3/4 tablespoon | chili powder | | [[Colorful bulgur salad]] | | 1/4 cup | cider vinegar | | [[Teriyaki tofu]] | | 1 can | corned beef | | [[Bubble and squeak]] | | 3 tbsp | cornstarch | | [[Teriyaki tofu]] | | 1 tbsp | cornstarch | | [[Teriyaki tofu]] | | 1 small | cucumber | seeded and chopped | [[Colorful bulgur salad]] | | 2 small or 1 large | cucumber | chopped | [[Gazpacho]] | | 1 lb | firm tofu | drained | [[Teriyaki tofu]] | | | fresh ground black pepper | | [[Gazpacho]] | | 3 tablespoons | fresh lime juice | | [[Colorful bulgur salad]] | | 3 cloves | garlic | chopped | [[Arroz caldo]] | | 1 clove | garlic | minced | [[Teriyaki tofu]] | | 2 cloves | garlic | diced | [[Gazpacho]] | | 1 tablespoon | garlic | minced | [[Shrimp kebabs]] | | 1 pinch | garlic powder | | [[Colorful bulgur salad]] | | | glutinous rice | | [[Arroz caldo]] | | 1 tsp ginger | grated or minced | | [[Teriyaki tofu]] | | | green onions | chopped | [[Arroz caldo]] | | 3 | green onions | thinly sliced | [[Colorful bulgur salad]] | | | leftover vegetables (cabbage, carrots) | | [[Bubble and squeak]] | | 1 | lemon | juice of | [[Gazpacho]] | | 2 teaspoons | lemon juice | | [[Shrimp kebabs]] | | 1/4 cup | olive oil | | [[Shrimp kebabs]] | | 1 | onion | thinly sliced | [[Bubble and squeak]] | | 1/2 large | onion | chopped finely (red is a nice alternative) | [[Gazpacho]] | | 1/2 large | onion | chopped in 1/4 inch chunks | [[Gazpacho]] | | pinch | parsley | finely chopped | [[Shrimp kebabs]] | | 1/4 tsp | pepper | | [[Teriyaki tofu]] | | 1/4 teaspoon | pepper | | [[Shrimp kebabs]] | | 3 cups | potatoes | mashed | [[Bubble and squeak]] | | 1 | red onion | cut into 1" pieces | [[Shrimp kebabs]] | | | salt (preferably sea salt) | | [[Gazpacho]] | | 1 tsp | sesame oil | | [[Teriyaki tofu]] | | 1 pound | shrimp | peeled and deveined | [[Shrimp kebabs]] | | | soy sauce | | [[Arroz caldo]] | | 1/2 cup | soy sauce | | [[Teriyaki tofu]] | | 1 | tomato | chopped | [[Colorful bulgur salad]] | | 6 - 8 | tomatoes | chopped (Roma or plum are best; Don't lose the juice!) | [[Gazpacho]] | | | virgin olive oil | | [[Gazpacho]] | | 1/2 cup | white sugar | | [[Teriyaki tofu]] | | 1 | zucchini | seeded and cut into 1" pieces | [[Shrimp kebabs]] |
Sorting the list by ingredient made it easy to go through the groups of ingredients and prepare them all, and the links to the recipes made it easy to look up next steps. I planned the order of doing them. First, I prepared the bulgur wheat because that needed an hour to soak. I saved the chicken legs for the end because they were messy, and I saved the onions for later as well because they always make me cry. I cut and chopped and food-processed my way through stacks of vegetables, covering the kitchen table with bowls.
With all the ingredients prepared, I washed the utensils and put things away. That freed up counter space for cooking. I reordered the recipes so that it was easy to see what to work on next, and I started cooking.
The entire cooking sprint took me 5 hours and 42 minutes, which was a lot of cooking but well worth it. With that and the meals we’d prepared over the past few weeks, our freezer’s stuffed to capacity. Four tidy stacks of identical food containers, then odds and ends crammed into the spaces! By golly.
I really liked planning this batch cooking session in Emacs. Org tables made things easy to sort, and the hyperlinks let me look up recipes and notes quickly.
I could probably make this even better by:
- rigging up my foot pedal to scroll up and down through food.org
- copying in the recipe steps so that I can take advantage of that scrolling
- figuring out how to use Org Babel to automatically compile the ingredient tables for the named recipes
Now if only someone would write M-x wash-dishes
…
14 comments
Raymond Zeitler
2012-06-19T18:11:06ZThat's neat! Our 14yo daughter is starting a vegan bakery as a hobby, so I thought it would be good to have the recipes in a database in order to come up with that same sort of shopping list. But I'd want to include prices so that we'd be able to determine the cost of each batch of product.
And we'd also want to do reverse queries, so that, given a glut of one or more ingredients, it would offer recipes to best utilize those ingredients. For example, when blueberries become abundant, you could do a search and have it tell you to make blueberry pie, blueberry muffins, etc.
Hmmm, I'm trying to imagine our daughter trying to figure out Emacs. LOL
Benton
2012-06-29T23:37:55ZLow-tech solution for sorting the grocery shopping list --
Prefix the item type with a department code; when you sort they'll be grouped together. fv for 'fruits-n-veggies', mt for meat, bk for the baking aisle, da for dairy. rx maybe for the medicines. na for all the other stuff that doesn't fit the broad categories.
fv:cucumber
fv:zucchini
fv:onion
mt:shirmp
bk:salt
da:milk
da:eggs
da:cheese
na:lottoTickets
Sacha Chua
2012-06-30T04:59:24ZA high-tech solution would be to code a VLOOKUP equivalent for org tables, which would likely be useful for lots of other situations as well. =) Thanks for the suggestion!
Fredrik
2013-08-25T00:49:27ZI just stumbled on to this when looking for how to handle recipes with org mode maybe it can help : https://gitorious.org/org-c...
Sacha Chua
2013-08-25T05:46:53ZHmm, maybe the parsing and conversion will make it easier to combine ingredients from different recipes... Interesting!
cehter
2013-12-12T10:31:58ZThanks for the inspiration! :) Here is how I plan and organize my cooking with org mode: http://lebensverrueckt.hakt...
Emmanuel Goldstein
2017-05-01T22:55:49ZAwesome! Can you tell me how to make the main shopping table to gather all the recipes you want? Thanks. (Im a newbie).
Davor
2015-01-03T10:42:52ZI just started doing this after I read your post, and it's freaking genius.
sachac
2015-01-07T22:55:10ZCome to think of it, one can probably write an Emacs Lisp snippet to collect all the ingredient tables from anything with the :current: tag (or maybe a COOKING todo-state)...
Emmanuel Goldstein
2017-05-01T22:48:12ZAny possibility to get your org file? Please!! Desperate here!
sachac
2017-05-02T04:47:36ZI'm not sure how useful you'll find this, but here's the gist: https://gist.githubusercont...
I haven't updated it in a while as we've settled into a comfortable rhythm of cooking (life with a baby!), but I scheduled two items so you might be able to see how the code picks stuff up.
sachac
2017-05-02T06:56:45ZI realized that my cooking Org file has fallen into disuse because:
- I've been making small, frequent grocery trips instead of large ones (I can only carry so much while also carrying a baby =) )
- we plan for a few meals at a time using mostly pantry ingredients plus a few fresh things
- we use an Android app to synchronize grocery lists (OurGroceries)
- we focus on recipes we're both comfortable with, and tend to repeat them to practise techniques or minimize effort. A-'s late afternoon nap is unpredictable, so W- often cooks dinner, but if we're both in the kitchen, she prefers to hang out with him. We swap as needed.
- I switched from my Org file to a kanban ( http://sachachua.com/blog/2... ) using index cards on the fridge door, although that's out of commission now that A- tends to pull cards off when she gets carried within range. In the meantime, we try to keep things simple and prioritize leftovers.
Someday I might be able to get back to more batch cooking! =)
Emmanuel Goldstein
2017-05-02T09:49:38ZOMG, this is so complex and detailed! Thank you so much. I hope I can navigate it. Could I ask you more questions later on when I have had a look at it? There are some things I don't seem to understand (as I am new in emacs), like the check-grocery-list code and how to execute it within the orgfile.
P.S.: I noticed it needs the org-summarize-scheduled-recipes function. Would you share that too?
sachac
2017-05-03T05:03:57ZSure, although it might take me some time to answer. :) (Life with a baby!)
You can execute the code by going to the #+CALL: line and pressing C-c C-c. I haven't tested it to see if it assumes anything about my config, though...
If all else fails, you can make your own tables and then use org-sort to sort the lines. Hope that helps!