1 (**************************************************************************)
2 (* *)
3 (* OCaml *)
4 (* *)
5 (* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
6 (* *)
7 (* Copyright 2010 Institut National de Recherche en Informatique et *)
8 (* en Automatique. *)
9 (* *)
10 (* All rights reserved. This file is distributed under the terms of *)
11 (* the GNU Lesser General Public License version 2.1, with the *)
12 (* special exception on linking described in the file LICENSE. *)
13 (* *)
14 (**************************************************************************)
15
16 (** An OCamldoc generator to retrieve information in "todo" tags and
17 generate an html page with all todo items. *)
18
19 open Odoc_info
20 module Naming = Odoc_html.Naming
21 open Odoc_info.Value
22 open Odoc_info.Module
23 open Odoc_info.Type
24 open Odoc_info.Extension
25 open Odoc_info.Exception
26 open Odoc_info.Class
27
28 let p = Printf.bprintf
29
30 module Html =
31 (val
32 (
33 match !Odoc_args.current_generator with
34 None -> (module Odoc_html.Generator : Odoc_html.Html_generator)
35 | Some (Odoc_gen.Html m) -> m
36 | _ ->
37 failwith
38 "A non-html generator is already set. Cannot install the Todo-list html generator"
39 ) : Odoc_html.Html_generator)
40 ;;
41
42 module Generator =
43 struct
44 class scanner html =
45 object (self)
46 inherit Odoc_info.Scan.scanner
47
48 val b = Buffer.create 256
49 method buffer = b
50
51 method private gen_if_tag name target info_opt =
52 match info_opt with
53 None -> ()
54 | Some i ->
55 let l =
56 List.fold_left
57 (fun acc (t, text) ->
58 match t with
59 "todo" ->
60 begin
61 match text with
62 (Odoc_info.Code s) :: q ->
63 (
64 try
65 let n = int_of_string s in
66 let head =
67 Odoc_info.Code (Printf.sprintf "[%d] " n)
68 in
69 (Some n, head::q) :: acc
70 with _ -> (None, text) :: acc
71 )
72 | _ -> (None, text) :: acc
73
74 end
75 | _ -> acc
76 )
77 []
78 i.i_custom
79 in
80 match l with
81 [] -> ()
82 | _ ->
83 let l = List.sort
84 (fun a b ->
85 match a, b with
86 (None, _), _ -> -1
87 | _, (None, _) -> 1
88 | (Some n1, _), (Some n2, _) -> compare n1 n2
89 )
90 l
91 in
92 p b "<pre><a href=\"%s\">%s</a></pre><div class=\"info\">"
93 target name;
94 let col = function
95 None -> "#000000"
96 | Some 1 -> "#FF0000"
97 | Some 2 -> "#AA5555"
98 | Some 3 -> "#44BB00"
99 | Some n -> Printf.sprintf "#%2x0000" (0xAA - (n * 0x10))
100 in
101 List.iter
102 (fun (n, e) ->
103 Printf.bprintf b "<span style=\"color: %s\">" (col n);
104 html#html_of_text ?with_p:(Some false) b e;
105 p b "</span><br/>\n";
106 )
107 l;
108 p b "</div>"
109
110 method! scan_value v =
111 self#gen_if_tag
112 v.val_name
113 (Odoc_html.Naming.complete_value_target v)
114 v.val_info
115
116 method! scan_type t =
117 self#gen_if_tag
118 t.ty_name
119 (Odoc_html.Naming.complete_type_target t)
120 t.ty_info
121
122 method! scan_extension_constructor x =
123 self#gen_if_tag
124 x.xt_name
125 (Odoc_html.Naming.complete_extension_target x)
126 x.xt_type_extension.te_info
127
128 method! scan_exception e =
129 self#gen_if_tag
130 e.ex_name
131 (Odoc_html.Naming.complete_exception_target e)
132 e.ex_info
133
134 method! scan_attribute a =
135 self#gen_if_tag
136 a.att_value.val_name
137 (Odoc_html.Naming.complete_attribute_target a)
138 a.att_value.val_info
139
140 method! scan_method m =
141 self#gen_if_tag
142 m.met_value.val_name
143 (Odoc_html.Naming.complete_method_target m)
144 m.met_value.val_info
145
146 (** This method scans the elements of the given module. *)
147 method! scan_module_elements m =
148 List.iter
149 (fun ele ->
150 match ele with
151 Odoc_module.Element_module m -> self#scan_module m
152 | Odoc_module.Element_module_type mt -> self#scan_module_type mt
153 | Odoc_module.Element_included_module im -> self#scan_included_module im
154 | Odoc_module.Element_class c -> self#scan_class c
155 | Odoc_module.Element_class_type ct -> self#scan_class_type ct
156 | Odoc_module.Element_value v -> self#scan_value v
157 | Odoc_module.Element_type_extension te -> self#scan_type_extension te
158 | Odoc_module.Element_exception e -> self#scan_exception e
159 | Odoc_module.Element_type t -> self#scan_type t
160 | Odoc_module.Element_module_comment t -> self#scan_module_comment t
161 )
162 (Odoc_module.module_elements ~trans: false m)
163
164 method! scan_included_module _ = ()
165
166 method! scan_class_pre c =
167 self#gen_if_tag
168 c.cl_name
169 (fst (Odoc_html.Naming.html_files c.cl_name))
170 c.cl_info;
171 true
172
173 method! scan_class_type_pre ct =
174 self#gen_if_tag
175 ct.clt_name
176 (fst (Odoc_html.Naming.html_files ct.clt_name))
177 ct.clt_info;
178 true
179
180 method! scan_module_pre m =
181 self#gen_if_tag
182 m.m_name
183 (fst (Odoc_html.Naming.html_files m.m_name))
184 m.m_info;
185 true
186
187 method! scan_module_type_pre mt =
188 self#gen_if_tag
189 mt.mt_name
190 (fst (Odoc_html.Naming.html_files mt.mt_name))
191 mt.mt_info;
192 true
193 end
194
195 class html : Html.html =
196 object (self)
197 inherit Html.html as html
198
199 (** we have to hack a little because we cannot inherit from
200 scanner, since public method cannot be hidden and
201 our html class must respect the type of the default
202 html generator class *)
203 val mutable scanner = new scanner (new Html.html )
204
205 method! generate modules =
206 (* prevent having the 'todo' tag signaled as not handled *)
207 tag_functions <- ("todo", (fun _ -> "")) :: tag_functions;
208 (* generate doc as usual *)
209 html#generate modules;
210 (* then retrieve the todo tags and generate the todo.html page *)
211 let title =
212 match !Odoc_info.Global.title with
213 None -> ""
214 | Some s -> s
215 in
216 let b = Buffer.create 512 in
217 p b "<html>";
218 self#print_header b title ;
219 p b "<body><h1>%s</h1>" title;
220 scanner#scan_module_list modules;
221 Buffer.add_buffer b scanner#buffer;
222 let oc = open_out
223 (Filename.concat !Odoc_info.Global.target_dir "todo.html")
224 in
225 Buffer.output_buffer oc b;
226 close_out oc
227
228 initializer
229 scanner <- new scanner self
230 end
231 end
232
233 let _ = Odoc_args.set_generator
234 (Odoc_gen.Html (module Generator : Odoc_html.Html_generator))
235 ;;
236