summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile9
-rw-r--r--README.org44
-rw-r--r--eval.c6
-rw-r--r--lib/pa sta.rcp12
-rw-r--r--lib/pasta red sauce.rcp23
-rw-r--r--lib/pasta-red-sauce.rcp22
-rw-r--r--lib/pasta.rcp12
-rw-r--r--lib/simple_omelette.rcp8
-rw-r--r--main.c115
-rw-r--r--parser.c22
-rw-r--r--types.c50
-rw-r--r--types.h5
12 files changed, 281 insertions, 47 deletions
diff --git a/Makefile b/Makefile
index 99629f0..82c9da1 100644
--- a/Makefile
+++ b/Makefile
@@ -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:
diff --git a/README.org b/README.org
index 04e2c3d..9504c5b 100644
--- a/README.org
+++ b/README.org
@@ -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
diff --git a/eval.c b/eval.c
index 91dddc2..12fe45c 100644
--- a/eval.c
+++ b/eval.c
@@ -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 = *
diff --git a/main.c b/main.c
index 3431ba8..5012bb2 100644
--- a/main.c
+++ b/main.c
@@ -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;
}
+
+
+
+
+
+
diff --git a/parser.c b/parser.c
index c47096c..11e4876 100644
--- a/parser.c
+++ b/parser.c
@@ -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;
}
diff --git a/types.c b/types.c
index 4eb3a1b..091ff8d 100644
--- a/types.c
+++ b/types.c
@@ -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);
+ }
}
}
diff --git a/types.h b/types.h
index 788a767..ea8fa47 100644
--- a/types.h
+++ b/types.h
@@ -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);