# HG changeset patch # User Malcolm Matalka # Date 1555177739 -7200 # Sat Apr 13 19:48:59 2019 +0200 # Node ID c23be0cafc1594224af72f5278653d9e0ef9216e # Parent 77627181c128e7a941f6f880d69d13c543d38dbd ADD Ability to test if key exists diff --git a/README.org b/README.org --- a/README.org +++ b/README.org @@ -118,6 +118,9 @@ Like Mustache, Snabela has sections. The identifier to enter a section depends on the type of section however each section is exited with ~@/~. +*** Testing for existence of a key +Testing for the existence of a key is done with ~@^~ and ~@^!~ if the key does +not exist. *** Boolean testing A boolean value in the template can be tested for ~true~ with ~@?~ and ~false~ with ~@!~. diff --git a/src/snabela/snabela.ml b/src/snabela/snabela.ml --- a/src/snabela/snabela.ml +++ b/src/snabela/snabela.ml @@ -225,6 +225,10 @@ | At ln::List::Neg_test::Key k::At _::ts -> (* @#!key@ ... @/key@ *) eval_list_test_section ln buf t kv ts section k `Empty + | At ln::Exists::Test::Key k::At _::ts -> + eval_exists_test_section ln buf t kv ts section k `Exists + | At ln::Exists::Neg_test::Key k::At _::ts -> + eval_exists_test_section ln buf t kv ts section k `Not_exists | At _::End_section::Key k::At _::ts when k = section -> (* @/key@ *) ts @@ -279,6 +283,15 @@ raise (Apply_error (`Expected_list (key, ln))) | None -> raise (Apply_error (`Missing_key (key, ln))) +and eval_exists_test_section ln buf t kv ts section key exists = + match (Kv.Map.get key kv, exists) with + | (Some _, `Exists) + | (None, `Not_exists) -> + let ts = eval_template buf t kv ts key in + eval_template buf t kv ts section + | _ -> + let ts = skip_section key ts in + eval_template buf t kv ts section let apply t kv = let buf = Buffer.create 100 in diff --git a/src/snabela/snabela_lexer.ml b/src/snabela/snabela_lexer.ml --- a/src/snabela/snabela_lexer.ml +++ b/src/snabela/snabela_lexer.ml @@ -12,6 +12,7 @@ | String of string | End_section | Comment + | Exists [@@deriving show,eq] type t = token list [@@deriving show,eq] @@ -54,12 +55,22 @@ comment ln (Tb.add_l [At ln; Comment] bldr) buf | "@-#?" -> replacement ln (Tb.add_l [At ln; Left_trim; List; Test] bldr) buf + | "@-#!" -> + replacement ln (Tb.add_l [At ln; Left_trim; List; Neg_test] bldr) buf | "@-#" -> replacement ln (Tb.add_l [At ln; Left_trim; List] bldr) buf + | "@-^!" -> + replacement ln (Tb.add_l [At ln; Left_trim; Exists; Neg_test] bldr) buf + | "@-^" -> + replacement ln (Tb.add_l [At ln; Left_trim; Exists; Test] bldr) buf | "@#?" -> replacement ln (Tb.add_l [At ln; List; Test] bldr) buf | "@#!" -> replacement ln (Tb.add_l [At ln; List; Neg_test] bldr) buf + | "@^!" -> + replacement ln (Tb.add_l [At ln; Exists; Neg_test] bldr) buf + | "@^" -> + replacement ln (Tb.add_l [At ln; Exists; Test] bldr) buf | "@#" -> replacement ln (Tb.add_l [At ln; List] bldr) buf | "@-?" -> diff --git a/tests/snabela/test.ml b/tests/snabela/test.ml --- a/tests/snabela/test.ml +++ b/tests/snabela/test.ml @@ -119,6 +119,23 @@ ; At 12; End_section; Key "parties"; Right_trim; At 12 ])) +let test_tokenizer9 = + Oth.test + ~name:"Tokenizer: Key test" + (fun _ -> + let template = "Hello, @^name@@name@@/name@" in + let lexbuf = Sedlexing.Utf8.from_string template in + let tokens = CCResult.get_exn (Snabela_lexer.tokenize lexbuf) in + assert + Snabela_lexer.Token.( + equal + tokens + [ String "Hello, " + ; At 1; Exists; Test; Key "name"; At 1 + ; At 1; Key "name"; At 1 + ; At 1; End_section; Key "name"; At 1 + ])) + let test_apply1 = Oth.test ~name:"Apply: Simple" @@ -319,6 +336,28 @@ let applied = CCResult.get_exn (Snabela.apply compile kv) in assert ("Hello, foo" = applied)) +let test_apply13 = + Oth.test + ~name:"Apply: Key test" + (fun _ -> + let template = "Hello, @^name@@name@@/name@" in + let kv = Snabela.Kv.(Map.of_list [("name", string "foo")]) in + let t = CCResult.get_exn (Snabela.Template.of_utf8_string template) in + let compile = Snabela.of_template t [] in + let applied = CCResult.get_exn (Snabela.apply compile kv) in + assert ("Hello, foo" = applied)) + +let test_apply14 = + Oth.test + ~name:"Apply: Neg key test" + (fun _ -> + let template = "Hello, @^!name@bar@/name@" in + let kv = Snabela.Kv.(Map.of_list []) in + let t = CCResult.get_exn (Snabela.Template.of_utf8_string template) in + let compile = Snabela.of_template t [] in + let applied = CCResult.get_exn (Snabela.apply compile kv) in + assert ("Hello, bar" = applied)) + let test_apply_fail1 = Oth.test ~name:"Apply Fail: Missing key" @@ -483,6 +522,7 @@ ; test_tokenizer6 ; test_tokenizer7 ; test_tokenizer8 + ; test_tokenizer9 ; test_apply1 ; test_apply2 ; test_apply3 @@ -495,6 +535,8 @@ ; test_apply10 ; test_apply11 ; test_apply12 + ; test_apply13 + ; test_apply14 ; test_apply_fail1 ; test_apply_fail2 ; test_apply_fail3