1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(* src/package_manager/template_engine.ml *)
(* Simple {{variable}} template substitution engine *)
(** A substitution context: list of (key, value) pairs *)
type context = (string * string) list
(** Replace all occurrences of {{key}} with the corresponding value from context.
Unknown variables are left as-is. *)
let substitute (ctx : context) (template : string) : string =
let buf = Buffer.create (String.length template) in
let len = String.length template in
let i = ref 0 in
while !i < len do
if !i + 1 < len && template.[!i] = '{' && template.[!i + 1] = '{' then begin
(* Found opening {{ — look for closing }} *)
let start = !i + 2 in
let j = ref start in
let found = ref false in
while !j + 1 < len && not !found do
if template.[!j] = '}' && template.[!j + 1] = '}' then
found := true
else
incr j
done;
if !found then begin
let key = String.trim (String.sub template start (!j - start)) in
(match List.assoc_opt key ctx with
| Some value -> Buffer.add_string buf value
| None ->
(* Leave unknown variables as-is *)
Buffer.add_string buf "{{";
Buffer.add_string buf key;
Buffer.add_string buf "}}");
i := !j + 2
end else begin
(* No closing }} found — emit literal {{ *)
Buffer.add_string buf "{{";
i := start
end
end else begin
Buffer.add_char buf template.[!i];
incr i
end
done;
Buffer.contents buf
(** Build a template context from scaffold options *)
let context_of_options (opts : Package_types.scaffold_options) : context =
let today =
let t = Unix.gmtime (Unix.gettimeofday ()) in
Printf.sprintf "%04d-%02d-%02d" (1900 + t.Unix.tm_year) (t.Unix.tm_mon + 1) t.Unix.tm_mday
in
[
("name", opts.target_name);
("author", opts.author);
("license", opts.license);
("date", today);
("t_version", "0.51.0");
("nixpkgs_date", opts.nixpkgs_date);
]