-
Notifications
You must be signed in to change notification settings - Fork 86
/
latex.ml
94 lines (79 loc) · 3.32 KB
/
latex.ml
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
open StdLabels
open Or_error
open Odoc_document
let document_of_page ~syntax v =
match syntax with
| Renderer.Reason -> Odoc_document.Reason.page v
| Renderer.OCaml -> Odoc_document.ML.page v
let document_of_compilation_unit ~syntax v =
match syntax with
| Renderer.Reason -> Odoc_document.Reason.compilation_unit v
| Renderer.OCaml -> Odoc_document.ML.compilation_unit v
let mk_page ~syntax v =
Odoc_latex.Generator.render @@
document_of_page ~syntax v
let mk_compilation_unit ~syntax v =
Odoc_latex.Generator.render @@
document_of_compilation_unit ~syntax v
let with_tex_file ~pkg_dir ~page_name f =
let oc =
let f = Fs.File.create ~directory:pkg_dir ~name:(page_name ^ ".tex") in
open_out (Fs.File.to_string f)
in
let fmt = Format.formatter_of_out_channel oc in
Format.fprintf fmt "%t@?" f;
close_out oc
(* See comment in compile for explanation regarding the env duplication. *)
let resolve env unit =
let resolve_env = Env.build env (`Unit unit) in
Odoc_xref.resolve (Env.resolver resolve_env) unit >>= fun resolved ->
let expand_env = Env.build env (`Unit resolved) in
Odoc_xref.expand (Env.expander expand_env) resolved >>= fun expanded ->
Odoc_xref.Lookup.lookup expanded
|> Odoc_xref.resolve (Env.resolver expand_env) (* Yes, again. *)
let mk_pkg_dir root_dir pkg_name =
let pkg_dir = Fs.Directory.reach_from ~dir:root_dir pkg_name in
Fs.Directory.mkdir_p pkg_dir;
pkg_dir
let link_children pkgdir parents self children ppf =
let page_input ppf name =
let child_fullname = String.concat ~sep:"." (List.rev (name :: self :: parents)) ^ ".tex" in
let loc = Fs.File.( to_string @@ create ~directory:pkgdir ~name:child_fullname) in
Format.fprintf ppf {|@[<v>\input{%s}@,@]|} loc in
List.iter ~f:(page_input ppf) children
(* We need to take care of linking children ourselves *)
let traverse ~f t =
let rec aux parents (node:Renderer.page) =
let children_names = List.map ~f:(fun (x:Renderer.page) -> x.filename) node.children in
f ~parents ~children_names node.filename node.content;
List.iter ~f:(aux (node.filename :: parents)) node.children
in
aux [] t
let from_odoc ~env ?(syntax=Renderer.OCaml) ?(with_children=true) ~output:root_dir input =
Root.read input >>= fun root ->
match root.file with
| Page page_name ->
Page.load input >>= fun page ->
let resolve_env = Env.build env (`Page page) in
Odoc_xref.resolve_page (Env.resolver resolve_env) page >>= fun odoctree ->
let pkg_name = root.package in
let pkg_dir = mk_pkg_dir root_dir pkg_name in
let pages = mk_page ~syntax odoctree in
Renderer.traverse pages ~f:(fun ~parents _pkg_name content ->
assert (parents = []); with_tex_file ~pkg_dir ~page_name content
);
Ok ()
| Compilation_unit {hidden = _; _} ->
Compilation_unit.load input >>= fun unit ->
let unit = Odoc_xref.Lookup.lookup unit in
resolve env unit >>= fun odoctree ->
let pkg_dir = mk_pkg_dir root_dir root.package in
let pages = mk_compilation_unit ~syntax odoctree in
traverse pages ~f:(fun ~parents ~children_names name content ->
let page_name = String.concat ~sep:"." (List.rev @@ name :: parents) in
with_tex_file ~pkg_dir ~page_name (fun ppf ->
content ppf;
if with_children then link_children pkg_dir parents name children_names ppf
)
);
Ok ()