diff options
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | README.org | 44 | ||||
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | lib/pa sta.rcp | 12 | ||||
-rw-r--r-- | lib/pasta red sauce.rcp | 23 | ||||
-rw-r--r-- | lib/pasta-red-sauce.rcp | 22 | ||||
-rw-r--r-- | lib/pasta.rcp | 12 | ||||
-rw-r--r-- | lib/simple_omelette.rcp | 8 | ||||
-rw-r--r-- | main.c | 115 | ||||
-rw-r--r-- | parser.c | 22 | ||||
-rw-r--r-- | types.c | 50 | ||||
-rw-r--r-- | types.h | 5 |
12 files changed, 281 insertions, 47 deletions
@@ -1,10 +1,9 @@ -TARGET=c.out +TARGET=food SRC=*.c CC=gcc CFLAGS=-D_GNU_SOURCE -std=c99 -pedantic REL_FLAGS=-O3 DBG_FLAGS=-Wall -g3 -# LIBS=-l X11 make: $(SRC) $(CC) $(REL_FLAGS) $(CFLAGS) -o $(TARGET) $^ $(LIBS) @@ -15,6 +14,12 @@ debug: $(SRC) noasan: $(SRC) $(CC) $(DBG_FLAGS) $(CFLAGS) -o $(TARGET) $^ $(LIBS) +tests: + $(MAKE) -C test + +clean-tests: + $(MAKE) clean -C test + .PHONY: clean clean: @@ -1,16 +1,25 @@ #+begin_src conf - # fried onion - - # `-` means preping step - # `>` means cooking step - # in a step you can add a time range in `[]` - # each step might produce some new ingredients `=>` + # title + @ fried onion + ## INGREDIENTS + # `!/path/to/rcp` to include it <TODO: add number> + # `a = b` set ingredient a to quantity b onion = 2 salt = 1tsp sugar = 1/2tsp butter = 3tbsp + # sep + --- + + ## STEPS + # `-` means preping step + # `>` means cooking step + # `+` means serving step + # in a step you can add a time range in `[]` + # each step might produce some new ingredients `=>` + - chop $onion to thin stripes => sliced onion > melt $butter in pan > add ${sliced onion} and $salt @@ -19,27 +28,6 @@ > continue cooking [until onion caramelises] #+end_src -#+begin_src fundamental - # basic seasoning - - salt = * - pepper = * -#+end_src -#+begin_src conf - # egg omellete with fried onions - - egg = 3 - !basic_seasoning - garlic paste = 1tsp - spring onion = 1 - !fried_onion - butter = 1tbsp - - - beat the ${egg}s and add the ${seasoning} - > melt $butter in pan - > cook ${egg}s [until they start to set] -#+end_src - * cmd cmd [-switches] path/to/file ... @@ -51,7 +39,7 @@ - should accept multiple keys and a switch for AND or OR between them + or a custom syntax like =cmd -s"eggs & (tomatoes | potatoes)" lib/*.rcp= + or =cmd -[A|O] -stomatoes -stomatoes -seggs lib/*rcp= (And/Or) - - *ls* + - *ls* ??? + list recipies with path + or with title + or both @@ -16,11 +16,11 @@ recipe * eval(recipe * r) { if (!r) return NULL; - /* recipe * eve = new_recipe(); */ + recipe * eve = new_recipe(); /* /\* Copy filename, title, etc *\/ */ /* copy_metadata(eve, r); */ - /* /\* attempt to merge items (adding qtys) *\/ */ - /* merge_items(eve, r); */ + /* attempt to merge items (adding qtys) */ + merge_items(eve, r); /* /\* Resolve step type, variables, duration and step output (if any) *\/ */ /* finalize_steps(eve, r); */ diff --git a/lib/pa sta.rcp b/lib/pa sta.rcp new file mode 100644 index 0000000..da71596 --- /dev/null +++ b/lib/pa sta.rcp @@ -0,0 +1,12 @@ +@pasta + +pasta = 240g +salt = * +olive oil = 1tblsp + +--- + +> boil 2 liters of water in a pot +> add the $salt and the ${olive oil} +> add the pasta and cook according to the \ +instructions in the box
\ No newline at end of file diff --git a/lib/pasta red sauce.rcp b/lib/pasta red sauce.rcp new file mode 100644 index 0000000..b0bc460 --- /dev/null +++ b/lib/pasta red sauce.rcp @@ -0,0 +1,23 @@ +@pasta with red sauce
+
+!~/code/food_compiler/lib/pasta.rcp
+salt = *
+sugar = 1 teaspoon
+onion = 1
+garlic = 1 clove
+oregano = 1tbsp
+tomato sauce = 1 can
+wine = 100ml
+olive oil = *
+
+---
+
+- prepare $pasta
+> heat some ${olive oil} in the pan
+> fry $garlic [until light brown]
+> add $onion and some $salt, fry [until \
+onion is translucent]
+> deglaze with the $wine and cook [until it reduces in half]
+> add the ${tomato sauce}, and some warm water to rinse the can
+> add $pasta to the sauce, turn the heat off, and cook [for 1-2 minutes]
++ serve on a big bowl
diff --git a/lib/pasta-red-sauce.rcp b/lib/pasta-red-sauce.rcp new file mode 100644 index 0000000..e870358 --- /dev/null +++ b/lib/pasta-red-sauce.rcp @@ -0,0 +1,22 @@ +@pasta with red sauce
+
+!lib/pa sta.rcp
+salt = *
+sugar = 1 teaspoon
+onion, garlic = 1
+oregano = 1tbsp
+tomato sauce = 1 can
+wine = 100ml
+olive oil = *
+
+---
+
+- prepare $pasta
+> heat some ${olive oil} in the pan
+> fry $garlic [until light brown]
+> add $onion and some $salt, fry [until \
+onion is translucent]
+> deglaze with the $wine and cook [until it reduces in half]
+> add the ${tomato sauce}, and some warm water to rinse the can
+> add $pasta to the sauce, turn the heat off, and cook [for 1-2 minutes]
++ serve on a big bowl
diff --git a/lib/pasta.rcp b/lib/pasta.rcp new file mode 100644 index 0000000..da71596 --- /dev/null +++ b/lib/pasta.rcp @@ -0,0 +1,12 @@ +@pasta + +pasta = 240g +salt = * +olive oil = 1tblsp + +--- + +> boil 2 liters of water in a pot +> add the $salt and the ${olive oil} +> add the pasta and cook according to the \ +instructions in the box
\ No newline at end of file diff --git a/lib/simple_omelette.rcp b/lib/simple_omelette.rcp index 37a0cb8..c867e47 100644 --- a/lib/simple_omelette.rcp +++ b/lib/simple_omelette.rcp @@ -1,7 +1,13 @@ # -*- mode: fundamental -*- @title -!/home/gramanas/code/food_compiler/lib/include.rcp +# default lib search path FOOD_LIB=/var/lib/food +# order: +# 1a. full path if s[0] = / or ~ +# 1b. local path +# 2. default library path +# !pasta.rcp = 3 +!~/code/food_compiler/lib/include.rcp eggs = 3 milk = 2tbsp salt, pepper = * @@ -1,14 +1,123 @@ +#include "getopt.h" + #include "util.h" #include "parser.h" recipe ** cookbook; +static struct opts { + int json; + int html; + int rcp; + char *query; + int help; +} opt = { + .json = 0, + .html = 0, + .rcp = 0, + .query = NULL, + .help = 0, +}; + +void +print_help() { + printf("Help!\n"); + +} + int main(int argc, char * argv[]) { fdebug("--- Debug mode is on ---\n"); - recipe * r = parse(argv[1], NULL); - if (r) tojson(r); - free_recipe(r); + + int c; + + while (1) { + static struct option long_options[] = + { + /* <span class="roman">These options set a flag.</span> */ + // {"verbose", no_argument, &verbose_flag, 1}, + // {"brief", no_argument, &verbose_flag, 0}, + {"help", no_argument, 0, 'h'}, + {"to-json", no_argument, 0, 'j'}, + {"to-html", no_argument, 0, 'w'}, + {"to-rcp", no_argument, 0, 'r'}, + {"format", required_argument, 0, 'f'}, + // {"to-rcp", required_argument, 0, 'r'}, + {0, 0, 0, 0} + }; + + int option_index = 0; + + c = getopt_long (argc, argv, "jhrwf:", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 0: + if (long_options[option_index].flag != 0) + break; + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + case 'f': + if (!strcmp(optarg, "json")) + opt.json = 1; + else if (!strcmp(optarg, "rcp")) + opt.rcp = 1; + else if (!strcmp(optarg, "html")) + opt.html = 1; + else + fprintf(stderr, "invalid format: %s\n", optarg); + break; + case 'j': + opt.json = 1; + break; + case 'w': + opt.html = 1; + break; + case 'r': + opt.rcp = 1; + break; + case 'h': + opt.help = 1; + break; + case '?': + return -1; + break; + default: + abort (); + } + } + + if (opt.help) { + print_help(); + return 0; + } + + if (optind < argc) { + while (optind < argc) { + recipe * r = parse(argv[optind++], NULL); + if (r) { + if (opt.json) tojson(r); + if (opt.html) tohtml(r); + if (opt.rcp) torcp(r); + } + free_recipe(r); + } + } else { + fprintf(stderr, "Specify filenames\n"); + } + return 0; } + + + + + + @@ -47,7 +47,7 @@ parse_item(const char * s, recipe * r, pt * type, char * error) return 1; } - if (tmp[0] == '/') { + if (tmp[0] == '/' || tmp[0] == '~') { strcpy(path, tmp); } else { strcpy(path, r->path); @@ -60,8 +60,9 @@ parse_item(const char * s, recipe * r, pt * type, char * error) sprintf(error, "Couldn't include %s", path); return 1; } - copy_items(r, rr); - free_recipe(rr); + //copy_items(r, rr); + new_subrecipe(r, rr); + //free_recipe(rr); return 0; } @@ -115,9 +116,11 @@ parse_step(const char * s, recipe * r, char * error) { fdebug("^ step\n"); - if ((s[0] == '>' || s[0] == '-') && strlen(s+1)) { + if ((s[0] == '>' || + s[0] == '-' || + s[0] == '+') && strlen(s+1)) { new_step(r); - r->s[r->sn - 1]->type = s[0] == '>' ? COOK : PREP; + r->s[r->sn - 1]->type = s[0] == '>' ? COOK : s[0] == '-' ? PREP : SERVE; char *tmp = strdup(s+1); trim(tmp); r->s[r->sn - 1]->inst = tmp; @@ -201,7 +204,14 @@ parse(char * path, const char * prev) if (!strcmp(path, "-")) { f = stdin; } else { - f = fopen(path, "r"); + char tmp[LINE_SIZE] = ""; + if (path[0] == '~') { + strcpy(tmp, getenv("HOME")); + strcat(tmp, path + 1); + } else { + strcpy(tmp, path); + } + f = fopen(tmp, "r"); if (!f) return NULL; } @@ -11,10 +11,13 @@ new_recipe() if (!r) die("Couldn't allocate memory for recipe"); + r->n = 1; r->i = NULL; r->in = 0; r->s = NULL; r->sn = 0; + r->r = NULL; + r->rn = 0; r->filename = NULL; r->path = NULL; r->title = NULL; @@ -22,6 +25,17 @@ new_recipe() } void +new_subrecipe(recipe * r, recipe * src) +{ + r->r = (recipe **)realloc(r->r, (r->rn + 1) * sizeof(recipe *)); + if (!r->r) + die("Couldn't allocate memory for subricepie"); + + r->r[r->rn] = src; + r->rn++; +} + +void new_item(recipe * r) { r->i = (item **)realloc(r->i, (r->in + 1) * sizeof(item *)); @@ -97,6 +111,12 @@ free_recipe(recipe * r) free(r->s); } + if (r->r) { + for (int i = 0; i < r->rn; i++) + free_recipe(r->r[i]); + free(r->r); + } + if (r->filename) free(r->filename); if (r->path) @@ -128,7 +148,18 @@ tojson(recipe * r) { printf("{\"filename\":\"%s\",", r->filename); printf("\"dirname\":\"%s\",", r->path); - printf("\"title\":\"%s\"", r->title); + printf("\"title\":\"%s\",", r->title); + printf("\"n\":\"%d\"", r->n); + if (r->rn) { + printf(",\"subrecipes\":["); + int i = 0; + for (; i < r->rn - 1; i++) { + tojson(r->r[i]); + printf(","); + } + tojson(r->r[i]); + printf("]"); + } if (r->in) { printf(",\"ingredients\":{"); int i = 0; @@ -143,7 +174,7 @@ tojson(recipe * r) printf("\"%s\",", r->s[i]->inst); printf("\"%s\"]", r->s[i]->inst); } - printf("}\n"); + printf("}"); } void @@ -157,12 +188,23 @@ torcp(recipe * r) { printf("# %s/%s\n\n", r->path, r->filename); printf("@%s\n\n", r->title); + for (int i = 0; i < r->rn; i++) { + printf("!%s/%s\n", r->r[i]->path, r->r[i]->filename); + } for (int i = 0; i < r->in; i++) printf("%s = %s\n", r->i[i]->name, r->i[i]->qty); if (r->sn) { printf("\n---\n\n"); - for (int i = 0; i < r->sn; i++) - printf("%s %s\n", r->s[i]->type == PREP ? "-" : ">", r->s[i]->inst); + for (int i = 0; i < r->sn; i++) { + char c; + if (r->s[i]->type == PREP) + c = '-'; + else if (r->s[i]->type == COOK) + c = '>'; + else + c = '+'; + printf("%c %s\n", c, r->s[i]->inst); + } } } @@ -9,6 +9,7 @@ typedef struct item_t { enum step_type { PREP = 0, COOK, + SERVE, }; typedef struct step_t { @@ -22,13 +23,17 @@ typedef struct recipe_t { char * filename; char * path; char * title; + int n; item **i; int in; step **s; int sn; + struct recipe_t **r; + int rn; } recipe; recipe * new_recipe(); +void new_subrecipe(recipe * r, recipe * src); void new_item(recipe * r); void new_step(recipe * r); |