From 1e8fa138696f28cf712d50d85b91afce1faec655 Mon Sep 17 00:00:00 2001 From: Danny van Kooten Date: Fri, 13 Mar 2020 11:26:48 +0100 Subject: add whitespace control for statements --- src/template.c | 44 +++++++++++++++++++++++++++++++++++++++----- tests/test_hashmap.c | 11 +++-------- tests/test_template.c | 10 ++++++++++ 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/template.c b/src/template.c index 51c9a77..56abc6d 100644 --- a/src/template.c +++ b/src/template.c @@ -26,8 +26,35 @@ char *read_file(char *filename) { return input; } +char *trim_trailing_whitespace(char *str) { + for (int i=strlen(str)-1; isspace(str[i]); i--) { + str[i] = '\0'; + } + return str; +} + +char *trim_leading_whitespace(char *str) { + while (isspace(*str)) { + str++; + } + + return str; +} + int eval(char *dest, mpc_ast_t* t, struct hashmap *ctx) { + static int trim_whitespace = 0; + if (strstr(t->tag, "content|var")) { + // maybe eat whitespace going backward + if (strstr(t->children[0]->contents, "{{-")) { + dest = trim_trailing_whitespace(dest); + } + + // set flag for next eval() to trim leading whitespace from text + if (strstr(t->children[2]->contents, "-}}")) { + trim_whitespace = 1; + } + char *value = NULL; char *key = t->children[1]->contents; value = hashmap_resolve(ctx, key); @@ -52,7 +79,13 @@ int eval(char *dest, mpc_ast_t* t, struct hashmap *ctx) { } if (strstr(t->tag, "content|text")) { - strcat(dest, t->contents); + char *str = t->contents; + if (trim_whitespace) { + str = trim_leading_whitespace(str); + trim_whitespace = 0; + } + + strcat(dest, str); return 0; } @@ -65,8 +98,8 @@ int eval(char *dest, mpc_ast_t* t, struct hashmap *ctx) { mpc_parser_t *parser_init() { mpc_parser_t *Symbol = mpc_new("symbol"); - mpc_parser_t *Symbols = mpc_new("symbols"); mpc_parser_t *Text = mpc_new("text"); + mpc_parser_t *Whitespace = mpc_new("whitespace"); mpc_parser_t *Var_Open = mpc_new("var_open"); mpc_parser_t *Var_Close = mpc_new("var_close"); mpc_parser_t *Var = mpc_new("var"); @@ -81,8 +114,9 @@ mpc_parser_t *parser_init() { mpc_parser_t *Template = mpc_new("template"); mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE, " symbol : /[a-zA-Z_.]+/ ;" - " var_open : /\{{2} ?/ ;" - " var_close : / ?}{2}/ ;" + " whitespace: \"-\"; " + " var_open : /\{{2}-? ?/ ;" + " var_close : / ?-?}{2}/ ;" " var : ;" " block_open: /\{\% ?/ ;" " block_close: / ?\%}/ ;" @@ -95,7 +129,7 @@ mpc_parser_t *parser_init() { " body : * ;" " template : /^/ /$/ ;", Symbol, - Symbols, + Whitespace, Var_Open, Var_Close, Var, diff --git a/tests/test_hashmap.c b/tests/test_hashmap.c index d78f768..b9e1cfd 100644 --- a/tests/test_hashmap.c +++ b/tests/test_hashmap.c @@ -6,26 +6,21 @@ START_TESTS TEST(hashmap) { struct hashmap *hm = hashmap_new(); assert(hashmap_get(hm, "foo") == NULL, "expected NULL"); - hashmap_insert(hm, "foo", "bar"); char *value = hashmap_get(hm, "foo"); - assert(value != NULL, "expected value, got NULL"); - assert(strcmp(value, "bar") == 0, "expected %s, got %s", "bar", value); - + assert_str(value, "bar"); hashmap_free(hm); } TEST(dot_notation) { - struct hashmap *user = hashmap_new(); hashmap_insert(user, "name", "Danny"); struct hashmap *hm = hashmap_new(); hashmap_insert(hm, "user", user); + assert(hashmap_resolve(hm, "user") == user, "expected user hashmap, got something else"); char *value = (char *) hashmap_resolve(hm, "user.name"); - assert(value != NULL, "expected value, got NULL"); - assert(strcmp(value, "Danny") == 0, "expected %s, got %s", "Danny", value); - + assert_str(value, "Danny"); hashmap_free(hm); } diff --git a/tests/test_template.c b/tests/test_template.c index d9f74ac..90190cc 100644 --- a/tests/test_template.c +++ b/tests/test_template.c @@ -20,6 +20,16 @@ TEST(var) { free(output); } +TEST(var_whitespace) { + char *input = "Hello \n{{-name -}}\n."; + struct hashmap *ctx = hashmap_new(); + hashmap_insert(ctx, "name", "world"); + char *output = template(input, ctx); + assert_str(output, "Helloworld."); + hashmap_free(ctx); + free(output); +} + TEST(multiline) { char *input = "Hello {{name}}.\nL2"; struct hashmap *ctx = hashmap_new(); -- cgit v1.2.3