@@ -11,6 +11,15 @@ let load_file f =
1111 close_in ic;
1212 (Bytes. to_string s)
1313
14+ let locate_template search_path filename =
15+ if Filename. is_relative filename then
16+ search_path
17+ |> List. map (fun path -> Filename. concat path filename)
18+ |> List. find_opt Sys. file_exists
19+ else if Sys. file_exists filename then
20+ Some filename
21+ else None
22+
1423let load_template template_filename =
1524 let template_data = load_file template_filename in
1625 let lexbuf = Lexing. from_string template_data in
@@ -27,14 +36,18 @@ let load_template template_filename =
2736let load_json json_filename =
2837 Ezjsonm. from_string (load_file json_filename)
2938
30- let run json_filename template_filename =
39+ let run search_path json_filename template_filename =
3140 let env = load_json json_filename in
3241 let tmpl = load_template template_filename in
3342 let partials name =
34- let path = Printf. sprintf " %s.mustache" name in
35- if not (Sys. file_exists path) then None
36- else Some (load_template path) in
37- try Mustache. render ~partials tmpl env |> print_endline
43+ let file = Printf. sprintf " %s.mustache" name in
44+ let path = locate_template search_path file in
45+ Option. map load_template path
46+ in
47+ try
48+ let output = Mustache. render ~partials tmpl env in
49+ print_string output;
50+ flush stdout
3851 with Mustache. Render_error err ->
3952 Format. eprintf " Template render error:@\n %a@."
4053 Mustache. pp_render_error err;
@@ -64,6 +77,17 @@ let run_command =
6477 `P " The $(i,ocaml-mustache) implementation is tested against
6578 the Mustache specification testsuite.
6679 All features are supported, except for lambdas and setting delimiter tags." ;
80+ `S Manpage. s_options;
81+ `S " PARTIALS" ;
82+ `P " The $(i,ocaml-mustache) library gives programmatic control over the meaning of partials {{>foo}}.
83+ For the $(tname) tool, partials are interpreted as template file inclusion: '{{>foo}}' includes
84+ the template file 'foo.mustache'." ;
85+ `P " Included files are resolved in a search path, which contains the current working directory
86+ (unless the $(b,--no-working-dir) option is used)
87+ and include directories passed through $(b,-I DIR) options." ;
88+ `P " If a file exists in several directories of the search path, the directory included first
89+ (leftmost $(b,-I) option) has precedence, and the current working directory has precedence
90+ over include directories." ;
6791 `S Manpage. s_examples;
6892 `Pre
6993 {|
@@ -83,6 +107,25 @@ Hello OCaml!
83107Mustache is :
84108- simple
85109- fun
110+
111+
112+ \$ cat page .mustache
113+ <html >
114+ <body >
115+ {{>hello} }
116+ </body >
117+ </html >
118+
119+ \$ $(tname ) data .json page .mustache
120+ <html >
121+ <body >
122+ Hello OCaml!
123+ Mustache is :
124+ - simple
125+ - fun
126+ </body >
127+ </html >
128+
86129|};
87130 `S Manpage. s_bugs ;
88131 `P "Report bugs on https://github.com/rgrinberg/ocaml-mustache/issues" ;
@@ -96,10 +139,25 @@ Mustache is:
96139 let doc = "mustache template" in
97140 Arg. (required & pos 1 (some file ) None & info [] ~docv :"TEMPLATE.mustache" ~doc )
98141 in
99- Term. (const run $ json_file $ template_file ),
142+ let search_path =
143+ let includes =
144+ let doc = "Adds the directory $(docv) to the search path for partials." in
145+ Arg. (value & opt_all dir [] & info ["I" ] ~docv :"DIR" ~doc )
146+ in
147+ let no_working_dir =
148+ let doc = "Disable the implicit inclusion of the working directory
149+ in the search path for partials." in
150+ Arg. (value & flag & info ["no-working-dir" ] ~doc )
151+ in
152+ let search_path includes no_working_dir =
153+ if no_working_dir then includes
154+ else Filename. current_dir_name :: includes
155+ in
156+ Term. (const search_path $ includes $ no_working_dir )
157+ in
158+ Term. (const run $ search_path $ json_file $ template_file ),
100159 Term. info "mustache" ~doc ~man
101160
102-
103161let () =
104162 let open Cmdliner in
105163 Term. exit @@ Term. eval run_command
0 commit comments