M README.org +3 -0
@@ 118,6 118,9 @@ My name is Arthur Digby Sellers and I ha
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 ~@!~.
M src/snabela/snabela.ml +13 -0
@@ 225,6 225,10 @@ let rec eval_template buf t kv template
| 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 @@ and eval_list_test_section ln buf t kv t
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
M src/snabela/snabela_lexer.ml +11 -0
@@ 12,6 12,7 @@ module Token = struct
| String of string
| End_section
| Comment
+ | Exists
[@@deriving show,eq]
type t = token list [@@deriving show,eq]
@@ 54,12 55,22 @@ let rec token ln bldr buf =
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
| "@-?" ->
M tests/snabela/test.ml +42 -0
@@ 119,6 119,23 @@ let test_tokenizer8 =
; 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 test_apply12 =
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 @@ let test =
; test_tokenizer6
; test_tokenizer7
; test_tokenizer8
+ ; test_tokenizer9
; test_apply1
; test_apply2
; test_apply3
@@ 495,6 535,8 @@ let test =
; test_apply10
; test_apply11
; test_apply12
+ ; test_apply13
+ ; test_apply14
; test_apply_fail1
; test_apply_fail2
; test_apply_fail3