(***********************************************************************)
(* OCamldoc *)
(* *)
(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 2001 Institut National de Recherche en Informatique et *)
(* en Automatique. All rights reserved. This file is distributed *)
(* under the terms of the Q Public License version 1.0. *)
(* *)
(***********************************************************************)
(** Generation of html documentation. *)
let print_DEBUG s = print_string s ; print_newline ()
open Odoc_info
open Parameter
open Value
open Type
open Exception
open Class
open Module
(** The functions used for naming files and html marks.*)
module Naming =
struct
(** The prefix for types marks. *)
let mark_type = "TYPE"
(** The prefix for functions marks. *)
let mark_function = "FUN"
(** The prefix for exceptions marks. *)
let mark_exception = "EXCEPTION"
(** The prefix for values marks. *)
let mark_value = "VAL"
(** The prefix for attributes marks. *)
let mark_attribute = "ATT"
(** The prefix for methods marks. *)
let mark_method = "METHOD"
(** The prefix for code files.. *)
let code_prefix = "code_"
(** The prefix for type files.. *)
let type_prefix = "type_"
(** Return the two html files names for the given module or class name.*)
let html_files name =
let html_file = name^".html" in
let html_frame_file = name^"-frame.html" in
(html_file, html_frame_file)
(** Return the target for the given prefix and simple name. *)
let target pref simple_name = pref^simple_name
(** Return the complete link target (file#target) for the given prefix string and complete name.*)
let complete_target pref complete_name =
let simple_name = Name.simple complete_name in
let module_name =
let s = Name.father complete_name in
if s = "" then simple_name else s
in
let (html_file, _) = html_files module_name in
html_file^"#"^(target pref simple_name)
(** Return the link target for the given type. *)
let type_target t = target mark_type (Name.simple t.ty_name)
(** Return the complete link target for the given type. *)
let complete_type_target t = complete_target mark_type t.ty_name
(** Return the link target for the given exception. *)
let exception_target e = target mark_exception (Name.simple e.ex_name)
(** Return the complete link target for the given exception. *)
let complete_exception_target e = complete_target mark_exception e.ex_name
(** Return the link target for the given value. *)
let value_target v = target mark_value (Name.simple v.val_name)
(** Return the complete link target for the given value. *)
let complete_value_target v = complete_target mark_value v.val_name
(** Return the complete filename for the code of the given value. *)
let file_code_value_complete_target v =
let f = code_prefix^mark_value^v.val_name^".html" in
f
(** Return the link target for the given attribute. *)
let attribute_target a = target mark_attribute (Name.simple a.att_value.val_name)
(** Return the complete link target for the given attribute. *)
let complete_attribute_target a = complete_target mark_attribute a.att_value.val_name
(** Return the complete filename for the code of the given attribute. *)
let file_code_attribute_complete_target a =
let f = code_prefix^mark_attribute^a.att_value.val_name^".html" in
f
(** Return the link target for the given method. *)
let method_target m = target mark_method (Name.simple m.met_value.val_name)
(** Return the complete link target for the given method. *)
let complete_method_target m = complete_target mark_method m.met_value.val_name
(** Return the complete filename for the code of the given method. *)
let file_code_method_complete_target m =
let f = code_prefix^mark_method^m.met_value.val_name^".html" in
f
(** Return the link target for the given label section. *)
let label_target l = target "" l
(** Return the complete link target for the given section label. *)
let complete_label_target l = complete_target "" l
(** Return the complete filename for the code of the type of the
given module or module type name. *)
let file_type_module_complete_target name =
let f = type_prefix^name^".html" in
f
(** Return the complete filename for the code of the type of the
given class or class type name. *)
let file_type_class_complete_target name =
let f = type_prefix^name^".html" in
f
end
(** A class with a method to colorize a string which represents OCaml code. *)
class ocaml_code =
object(self)
method html_of_code fmt ?(with_pre=true) code =
Odoc_ocamlhtml.html_of_code fmt ~with_pre: with_pre code
end
(** Generation of html code from text structures. *)
class text =
object (self)
(** We want to display colorized code. *)
inherit ocaml_code
(** Escape the strings which would clash with html syntax, and
make some replacements (double newlines replaced by ). *)
method escape s = Odoc_ocamlhtml.escape_base s
(** Print the html code corresponding to the [text] parameter. *)
method html_of_text fmt t = List.iter (self#html_of_text_element fmt) t
(** Print the html code for the [text_element] in parameter. *)
method html_of_text_element fmt te =
print_DEBUG "text::html_of_text_element";
match te with
| Odoc_info.Raw s -> self#html_of_Raw fmt s
| Odoc_info.Code s -> self#html_of_Code fmt s
| Odoc_info.CodePre s -> self#html_of_CodePre fmt s
| Odoc_info.Verbatim s -> self#html_of_Verbatim fmt s
| Odoc_info.Bold t -> self#html_of_Bold fmt t
| Odoc_info.Italic t -> self#html_of_Italic fmt t
| Odoc_info.Emphasize t -> self#html_of_Emphasize fmt t
| Odoc_info.Center t -> self#html_of_Center fmt t
| Odoc_info.Left t -> self#html_of_Left fmt t
| Odoc_info.Right t -> self#html_of_Right fmt t
| Odoc_info.List tl -> self#html_of_List fmt tl
| Odoc_info.Enum tl -> self#html_of_Enum fmt tl
| Odoc_info.Newline -> self#html_of_Newline fmt
| Odoc_info.Block t -> self#html_of_Block fmt t
| Odoc_info.Title (n, l_opt, t) -> self#html_of_Title fmt n l_opt t
| Odoc_info.Latex s -> self#html_of_Latex fmt s
| Odoc_info.Link (s, t) -> self#html_of_Link fmt s t
| Odoc_info.Ref (name, ref_opt) -> self#html_of_Ref fmt name ref_opt
| Odoc_info.Superscript t -> self#html_of_Superscript fmt t
| Odoc_info.Subscript t -> self#html_of_Subscript fmt t
method html_of_Raw fmt s =
Format.pp_print_string fmt (self#escape s)
method html_of_Code fmt s =
if !Odoc_args.colorize_code then
self#html_of_code fmt ~with_pre: false s
else
Format.fprintf fmt "@{%s@}" Odoc_ocamlhtml.code_class (self#escape s)
method html_of_CodePre fmt s =
Format.fprintf fmt "@{
";
if !Odoc_args.colorize_code then
(
Format.fprintf fmt "@}";
self#html_of_code fmt s;
Format.fprintf fmt "@{
\n"
method html_of_Block fmt t =
Format.fprintf fmt "@{
";
self#html_of_text fmt t;
Format.fprintf fmt "@}"
method html_of_Title fmt n label_opt t =
let css_class = "title"^(string_of_int n) in
Format.pp_print_string fmt " \n";
(
match label_opt with
None -> ()
| Some l -> Format.fprintf fmt "@{@}" (Naming.label_target l)
);
Format.fprintf fmt "@{
";
Format.fprintf fmt "@{
@{
@{
" css_class;
Format.fprintf fmt "@{
@{
\n" css_class;
Format.fprintf fmt "@{
";
Format.fprintf fmt "@{" css_class;
self#html_of_text fmt t;
Format.fprintf fmt "@}@}@}@}@}@}@}@}"
method html_of_Latex fmt _ = ()
(* don't care about LaTeX stuff in HTML. *)
method html_of_Link fmt s t =
Format.fprintf fmt "@{" s;
self#html_of_text fmt t;
Format.fprintf fmt "@}"
method html_of_Ref fmt name ref_opt =
match ref_opt with
None ->
self#html_of_text_element fmt (Odoc_info.Code name)
| Some kind ->
let target =
match kind with
Odoc_info.RK_module
| Odoc_info.RK_module_type
| Odoc_info.RK_class
| Odoc_info.RK_class_type ->
let (html_file, _) = Naming.html_files name in
html_file
| Odoc_info.RK_value -> Naming.complete_target Naming.mark_value name
| Odoc_info.RK_type -> Naming.complete_target Naming.mark_type name
| Odoc_info.RK_exception -> Naming.complete_target Naming.mark_exception name
| Odoc_info.RK_attribute -> Naming.complete_target Naming.mark_attribute name
| Odoc_info.RK_method -> Naming.complete_target Naming.mark_method name
| Odoc_info.RK_section -> Naming.complete_label_target name
in
Format.fprintf fmt "@{" target;
self#html_of_text_element fmt (Odoc_info.Code (Odoc_info.use_hidden_modules name));
Format.fprintf fmt "@}"
method html_of_Superscript fmt t =
Format.fprintf fmt "@{";
self#html_of_text fmt t;
Format.fprintf fmt "@}"
method html_of_Subscript fmt t =
Format.fprintf fmt "@{";
self#html_of_text fmt t;
Format.fprintf fmt "@}"
end
(** A class used to generate html code for info structures. *)
class virtual info =
object (self)
(** The list of pairs [(tag, f)] where [f] is a function taking
the [text] associated to [tag] and returning html code.
Add a pair here to handle a tag.*)
val mutable tag_functions = ([] : (string * (Format.formatter -> Odoc_info.text -> unit)) list)
(** The method used to get html code from a [text]. *)
method virtual html_of_text : Format.formatter -> Odoc_info.text -> unit
(** Print html for an author list. *)
method html_of_author_list fmt l =
match l with
[] -> ()
| _ -> Format.fprintf fmt "@{%s: @}%s \n"
Odoc_messages.authors (String.concat ", " l)
(** Print html code for the given optional version information.*)
method html_of_version_opt fmt v_opt =
match v_opt with
None -> ()
| Some v -> Format.fprintf fmt "@{%s: @}%s \n" Odoc_messages.version v
(** Print html code for the given optional since information.*)
method html_of_since_opt fmt s_opt =
match s_opt with
None -> ()
| Some s -> Format.fprintf fmt "@{%s :@}%s \n" Odoc_messages.since s
(** Print html code for the given list of raised exceptions.*)
method html_of_raised_exceptions fmt l =
match l with
[] -> ()
| (s, t) :: [] ->
Format.fprintf fmt "@{%s@} @{%s@} " Odoc_messages.raises s;
self#html_of_text fmt t;
Format.pp_print_string fmt " \n"
| _ ->
Format.fprintf fmt "@{%s@}@{
@{%s@} " ex;
self#html_of_text fmt desc;
Format.fprintf fmt "@}"
)
l;
Format.fprintf fmt "@}"
(** Print html code for the given "see also" reference. *)
method html_of_see fmt (see_ref, t) =
let t_ref =
match see_ref with
Odoc_info.See_url s -> [ Odoc_info.Link (s, t) ]
| Odoc_info.See_file s -> (Odoc_info.Code s) :: (Odoc_info.Raw " ") :: t
| Odoc_info.See_doc s -> (Odoc_info.Italic [Odoc_info.Raw s]) :: (Odoc_info.Raw " ") :: t
in
self#html_of_text fmt t_ref
(** Print html code for the given list of "see also" references.*)
method html_of_sees fmt l =
match l with
[] -> ()
| see :: [] ->
Format.fprintf fmt "@{%s@} " Odoc_messages.see_also;
self#html_of_see fmt see;
Format.pp_print_string fmt " \n"
| _ ->
Format.fprintf fmt "@{%s@}@{
" Odoc_messages.see_also;
List.iter
(fun see ->
Format.fprintf fmt "@{
";
self#html_of_see fmt see;
Format.fprintf fmt "@}"
)
l;
Format.fprintf fmt "@}"
(** Print html code for the given optional return information.*)
method html_of_return_opt fmt return_opt =
match return_opt with
None -> ()
| Some s ->
Format.fprintf fmt "@{%s@} " Odoc_messages.returns;
self#html_of_text fmt s;
Format.pp_print_string fmt " \n"
(** Print html code for the given list of custom tagged texts. *)
method html_of_custom fmt l =
let buf = Buffer.create 50 in
List.iter
(fun (tag, text) ->
try
let f = List.assoc tag tag_functions in
f fmt text
with
Not_found ->
Odoc_info.warning (Odoc_messages.tag_not_handled tag)
)
l
(** Print html code for a description, except for the [i_params] field. *)
method html_of_info fmt info_opt =
match info_opt with
None -> ()
| Some info ->
let module M = Odoc_info in
Format.fprintf fmt "@{
\n";
(match info.M.i_deprecated with
None -> ()
| Some d ->
Format.fprintf fmt "@{%s@} " Odoc_messages.deprecated;
self#html_of_text fmt d;
Format.pp_print_string fmt " \n"
);
(match info.M.i_desc with
None -> ()
| Some d when d = [Odoc_info.Raw ""] -> ()
| Some d -> self#html_of_text fmt d; Format.pp_print_string fmt " \n"
);
self#html_of_author_list fmt info.M.i_authors;
self#html_of_version_opt fmt info.M.i_version;
self#html_of_since_opt fmt info.M.i_since;
self#html_of_raised_exceptions fmt info.M.i_raised_exceptions;
self#html_of_return_opt fmt info.M.i_return_value;
self#html_of_sees fmt info.M.i_sees;
self#html_of_custom fmt info.M.i_custom;
Format.fprintf fmt "@}\n"
(** Print html code for the first sentence of a description. *)
method html_of_info_first_sentence fmt info_opt =
match info_opt with
None -> ()
| Some info ->
let module M = Odoc_info in
let dep = info.M.i_deprecated <> None in
Format.fprintf fmt "@{
";
if dep then Format.fprintf fmt "@{";
(match info.M.i_desc with
None -> ()
| Some d when d = [Odoc_info.Raw ""] -> ()
| Some d ->
self#html_of_text fmt (Odoc_info.first_sentence_of_text d)
);
if dep then Format.fprintf fmt "@}";
Format.fprintf fmt "@}"
end
let opt = Odoc_info.apply_opt
(** This class is used to create objects which can generate a simple html documentation. *)
class html =
object (self)
inherit text
inherit info
(** The default style options. *)
val mutable default_style_options =
["a:visited {color : #416DFF; text-decoration : none; }" ;
"a:link {color : #416DFF; text-decoration : none;}" ;
"a:hover {color : Red; text-decoration : none; background-color: #5FFF88}" ;
"a:active {color : Red; text-decoration : underline; }" ;
".keyword { font-weight : bold ; color : Red }" ;
".keywordsign { color : #C04600 }" ;
".superscript { font-size : 4 }" ;
".subscript { font-size : 4 }" ;
".comment { color : Green }" ;
".constructor { color : Blue }" ;
".type { color : DarkSlateBlue }" ;
".string { color : Maroon }" ;
".warning { color : Red ; font-weight : bold }" ;
".info { margin-left : 3em; margin-right : 3em }" ;
".code { color : #465F91 ; }" ;
".title1 { font-size : 20pt ; background-color : #416DFF }" ;
".title2 { font-size : 20pt ; background-color : #418DFF }" ;
".title3 { font-size : 20pt ; background-color : #41ADFF }" ;
".title4 { font-size : 20pt ; background-color : #41CDFF }" ;
".title5 { font-size : 20pt ; background-color : #41EDFF }" ;
".title6 { font-size : 20pt ; background-color : #41FFFF }" ;
"body { background-color : White }" ;
"tr { background-color : White }" ;
]
(** The style file for all pages. *)
val mutable style_file = "style.css"
(** The code to import the style. Initialized in [init_style]. *)
val mutable style = ""
(** The known types names.
Used to know if we must create a link to a type
when printing a type. *)
val mutable known_types_names = []
(** The known class and class type names.
Used to know if we must create a link to a class
or class type or not when printing a type. *)
val mutable known_classes_names = []
(** The known modules and module types names.
Used to know if we must create a link to a type or not
when printing a module type. *)
val mutable known_modules_names = []
(** The main file. *)
val mutable index = "index.html"
(** The file for the index of values. *)
val mutable index_values = "index_values.html"
(** The file for the index of types. *)
val mutable index_types = "index_types.html"
(** The file for the index of exceptions. *)
val mutable index_exceptions = "index_exceptions.html"
(** The file for the index of attributes. *)
val mutable index_attributes = "index_attributes.html"
(** The file for the index of methods. *)
val mutable index_methods = "index_methods.html"
(** The file for the index of classes. *)
val mutable index_classes = "index_classes.html"
(** The file for the index of class types. *)
val mutable index_class_types = "index_class_types.html"
(** The file for the index of modules. *)
val mutable index_modules = "index_modules.html"
(** The file for the index of module types. *)
val mutable index_module_types = "index_module_types.html"
(** The list of attributes. Filled in the [generate] method. *)
val mutable list_attributes = []
(** The list of methods. Filled in the [generate] method. *)
val mutable list_methods = []
(** The list of values. Filled in the [generate] method. *)
val mutable list_values = []
(** The list of exceptions. Filled in the [generate] method. *)
val mutable list_exceptions = []
(** The list of types. Filled in the [generate] method. *)
val mutable list_types = []
(** The list of modules. Filled in the [generate] method. *)
val mutable list_modules = []
(** The list of module types. Filled in the [generate] method. *)
val mutable list_module_types = []
(** The list of classes. Filled in the [generate] method. *)
val mutable list_classes = []
(** The list of class types. Filled in the [generate] method. *)
val mutable list_class_types = []
(** The header of pages. Must be prepared by the [prepare_header] method.*)
val mutable header = fun fmt -> fun ?(nav=None) -> fun _ -> ()
(** Init the style. *)
method init_style =
(match !Odoc_args.css_style with
None ->
let default_style = String.concat "\n" default_style_options in
(
try
let chanout = open_out (Filename.concat !Odoc_args.target_dir style_file) in
output_string chanout default_style ;
flush chanout ;
close_out chanout
with
Sys_error s ->
prerr_endline s ;
incr Odoc_info.errors ;
)
| Some f ->
style_file <- f
);
style <- ""
(** Get the title given by the user *)
method title = match !Odoc_args.title with None -> "" | Some t -> self#escape t
(** Get the title given by the user completed with the given subtitle. *)
method inner_title s =
(match self#title with "" -> "" | t -> t^" : ")^
(self#escape s)
(** Get the page header. *)
method header fmt ?nav title = header fmt ?nav title
(** A function to build the header of pages. *)
method prepare_header module_list =
let f fmt ?(nav=None) t =
let link_if_not_empty l m url =
match l with
[] -> ()
| _ -> Format.fprintf fmt "\n" m url
in
Format.fprintf fmt "@{%s\n" style;
Format.fprintf fmt "\n" index;
(
match nav with
None -> ()
| Some (pre_opt, post_opt, name) ->
(match pre_opt with
None -> ()
| Some name ->
Format.fprintf fmt "\n"
(fst (Naming.html_files name))
);
(match post_opt with
None -> ()
| Some name ->
Format.fprintf fmt "\n"
(fst (Naming.html_files name))
);
let father = Name.father name in
let href = if father = "" then index else fst (Naming.html_files father) in
Format.fprintf fmt "\n" href
);
link_if_not_empty list_types Odoc_messages.index_of_types index_types;
link_if_not_empty list_exceptions Odoc_messages.index_of_exceptions index_exceptions;
link_if_not_empty list_values Odoc_messages.index_of_values index_values;
link_if_not_empty list_attributes Odoc_messages.index_of_attributes index_attributes;
link_if_not_empty list_methods Odoc_messages.index_of_methods index_methods;
link_if_not_empty list_classes Odoc_messages.index_of_classes index_classes;
link_if_not_empty list_class_types Odoc_messages.index_of_class_types index_class_types;
link_if_not_empty list_modules Odoc_messages.index_of_modules index_modules;
link_if_not_empty list_module_types Odoc_messages.index_of_module_types index_module_types;
List.iter
(fun m ->
let html_file = fst (Naming.html_files m.m_name) in
Format.fprintf fmt
"\n"
m.m_name html_file
)
module_list;
Format.fprintf fmt "@{%s@}@}" t
in
header <- f
(** Print HTML code for navigation bar.
@param pre optional name for optional previous module/class
@param post optional name for optional next module/class
@param name name of current module/class *)
method navbar fmt pre post name =
Format.fprintf fmt "@{
";
(match pre with
None -> ()
| Some name ->
Format.fprintf fmt "@{%s@}\n"
(fst (Naming.html_files name))
Odoc_messages.previous
);
let father = Name.father name in
let href = if father = "" then index else fst (Naming.html_files father) in
Format.fprintf fmt " @{%s@}\n " href Odoc_messages.up;
(match post with
None -> ()
| Some name -> Format.fprintf fmt "@{%s@}\n"
(fst (Naming.html_files name)) Odoc_messages.next
);
Format.fprintf fmt "@}"
(** Print html code with the given string in the keyword style.*)
method keyword fmt s =
Format.fprintf fmt "@{%s@}" s
(** Print html code with the given string in the constructor style. *)
method constructor fmt s =
Format.fprintf fmt "@{%s@}" s
(** Output the given ocaml code to the given file name. *)
method private output_code in_title file code =
try
let (fmt, chanout) = self#formatter_of_file file in
Format.fprintf fmt "@{";
self#header fmt (self#inner_title in_title);
Format.fprintf fmt "@{";
self#html_of_code fmt code;
Format.fprintf fmt "@}@}";
Format.pp_print_flush fmt ();
close_out chanout
with
Sys_error s ->
incr Odoc_info.errors ;
prerr_endline s
(** Take a string and return the string where fully qualified
type (or class or class type) idents
have been replaced by links to the type referenced by the ident.*)
method create_fully_qualified_idents_links m_name s =
let f str_t =
let match_s = Str.matched_string str_t in
let rel = Name.get_relative m_name match_s in
let s_final = Odoc_info.apply_if_equal
Odoc_info.use_hidden_modules
match_s
rel
in
if List.mem match_s known_types_names then
""^
s_final^
""
else
if List.mem match_s known_classes_names then
let (html_file, _) = Naming.html_files match_s in
""^s_final^""
else
s_final
in
let s2 = Str.global_substitute
(Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)")
f
s
in
s2
(** Take a string and return the string where fully qualified module idents
have been replaced by links to the module referenced by the ident.*)
method create_fully_qualified_module_idents_links m_name s =
let f str_t =
let match_s = Str.matched_string str_t in
if List.mem match_s known_modules_names then
let (html_file, _) = Naming.html_files match_s in
""^(Name.get_relative m_name match_s)^""
else
match_s
in
let s2 = Str.global_substitute
(Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([A-Z][a-zA-Z_'0-9]*\\)")
f
s
in
s2
(** Print html code to display a [Types.type_expr].*)
method html_of_type_expr fmt m_name t =
let s = String.concat "\n"
(Str.split (Str.regexp "\n") (Odoc_info.string_of_type_expr t))
in
let s2 = Str.global_replace (Str.regexp "\n") " " s in
Format.fprintf fmt "@{%s@}"
(self#create_fully_qualified_idents_links m_name s2)
(** Print html code to display a [Types.class_type].*)
method html_of_class_type_expr fmt m_name t =
let s = String.concat "\n"
(Str.split (Str.regexp "\n") (Odoc_info.string_of_class_type t))
in
let s2 = Str.global_replace (Str.regexp "\n") " " s in
Format.fprintf fmt "@{%s@}"
(self#create_fully_qualified_idents_links m_name s2)
(** Print html code to display a [Types.type_expr list].*)
method html_of_type_expr_list fmt m_name sep l =
print_DEBUG "html#html_of_type_expr_list";
let s = Odoc_info.string_of_type_list sep l in
print_DEBUG "html#html_of_type_expr_list: 1";
let s2 = Str.global_replace (Str.regexp "\n") " " s in
print_DEBUG "html#html_of_type_expr_list: 2";
Format.fprintf fmt "@{%s@}"
(self#create_fully_qualified_idents_links m_name s2)
(** Print html code to display a [Types.module_type]. *)
method html_of_module_type fmt m_name t =
let s = String.concat "\n"
(Str.split (Str.regexp "\n") (Odoc_info.string_of_module_type t))
in
let s2 = Str.global_replace (Str.regexp "\n") " " s in
Format.fprintf fmt "@{%s@}"
(self#create_fully_qualified_module_idents_links m_name s2)
(** Generate a file containing the module type in the given file name. *)
method output_module_type in_title file mtyp =
let s = String.concat "\n"
(Str.split (Str.regexp "\n") (Odoc_info.string_of_module_type ~complete: true mtyp))
in
self#output_code in_title file s
(** Generate a file containing the class type in the given file name. *)
method output_class_type in_title file ctyp =
let s = String.concat "\n"
(Str.split (Str.regexp "\n") (Odoc_info.string_of_class_type ~complete: true ctyp))
in
self#output_code in_title file s
(** Print html code for a value. *)
method html_of_value fmt v =
Odoc_info.reset_type_names ();
Format.fprintf fmt "@{
";
self#keyword fmt "val";
(* html mark *)
Format.fprintf fmt " @{@}" (Naming.value_target v);
(match v.val_code with
None -> Format.fprintf fmt "%s" (Name.simple v.val_name)
| Some c ->
let file = Naming.file_code_value_complete_target v in
self#output_code v.val_name (Filename.concat !Odoc_args.target_dir file) c;
Format.fprintf fmt "@{%s@}" file (Name.simple v.val_name)
);
Format.pp_print_string fmt " : ";
self#html_of_type_expr fmt (Name.father v.val_name) v.val_type;
Format.fprintf fmt "@}";
self#html_of_info fmt v.val_info;
if !Odoc_args.with_parameter_list then
self#html_of_parameter_list fmt (Name.father v.val_name) v.val_parameters
else
self#html_of_described_parameter_list fmt (Name.father v.val_name) v.val_parameters
(** Print html code for an exception. *)
method html_of_exception fmt e =
Odoc_info.reset_type_names ();
Format.fprintf fmt "@{
";
self#keyword fmt "exception";
(* html mark *)
Format.fprintf fmt " @{@}" (Naming.exception_target e);
Format.pp_print_string fmt (Name.simple e.ex_name);
(match e.ex_args with
[] -> ()
| _ ->
Format.pp_print_string fmt " ";
self#keyword fmt "of";
Format.pp_print_string fmt " ";
self#html_of_type_expr_list fmt (Name.father e.ex_name) " * " e.ex_args
);
(match e.ex_alias with
None -> ()
| Some ea ->
Format.pp_print_string fmt " = ";
(
match ea.ea_ex with
None -> Format.pp_print_string fmt ea.ea_name
| Some e -> Format.fprintf fmt "@{%s@}" (Naming.complete_exception_target e) e.ex_name
)
);
Format.fprintf fmt "@}";
self#html_of_info fmt e.ex_info
(** Print html code for a type. *)
method html_of_type fmt t =
Odoc_info.reset_type_names ();
let father = Name.father t.ty_name in
Format.fprintf fmt " @{";
self#keyword fmt "type";
(* html mark *)
Format.fprintf fmt " " (Naming.type_target t);
(match t.ty_parameters with
[] -> ()
| tp :: [] -> self#html_of_type_expr fmt father tp; Format.pp_print_string fmt " "
| l ->
Format.pp_print_string fmt "(";
self#html_of_type_expr_list fmt father ", " l;
Format.pp_print_string fmt ") "
);
Format.fprintf fmt "%s " (Name.simple t.ty_name);
(match t.ty_manifest with
None -> ()
| Some typ -> Format.pp_print_string fmt "= ";
self#html_of_type_expr fmt father typ;
Format.pp_print_string fmt " "
);
(match t.ty_kind with
Type_abstract -> Format.fprintf fmt "@}"
| Type_variant l ->
Format.fprintf fmt "= @}@{
@{";
if r.rf_mutable then self#keyword fmt "mutable ";
Format.fprintf fmt "%s : " r.rf_name;
self#html_of_type_expr fmt father r.rf_type;
Format.fprintf fmt ";@}@}";
(
match r.rf_text with
None -> ()
| Some t ->
Format.fprintf fmt "@{
@{*)@}@}"
);
Format.fprintf fmt "@}"
)
l;
Format.fprintf fmt "@}}\n"
);
self#html_of_info fmt t.ty_info;
Format.pp_print_string fmt " \n"
(** Print html code for a class attribute. *)
method html_of_attribute fmt a =
let module_name = Name.father (Name.father a.att_value.val_name) in
Format.fprintf fmt "@{
";
self#keyword fmt "val";
(* html mark *)
Format.fprintf fmt " @{@}" (Naming.attribute_target a);
if a.att_mutable then
(
self#keyword fmt Odoc_messages.mutab;
Format.pp_print_string fmt " "
);
(match a.att_value.val_code with
None -> Format.pp_print_string fmt (Name.simple a.att_value.val_name)
| Some c ->
let file = Naming.file_code_attribute_complete_target a in
self#output_code a.att_value.val_name (Filename.concat !Odoc_args.target_dir file) c;
Format.fprintf fmt "@{%s@}" file (Name.simple a.att_value.val_name)
);
Format.pp_print_string fmt " : ";
self#html_of_type_expr fmt module_name a.att_value.val_type;
Format.fprintf fmt "@}";
self#html_of_info fmt a.att_value.val_info
(** Print html code for a class method. *)
method html_of_method fmt m =
let module_name = Name.father (Name.father m.met_value.val_name) in
Format.fprintf fmt "@{
";
self#keyword fmt "method" ;
(* html mark *)
Format.fprintf fmt " @{@}" (Naming.method_target m);
if m.met_private then
(
self#keyword fmt "private";
Format.pp_print_string fmt " ";
);
if m.met_virtual then
(
self#keyword fmt "virtual";
Format.pp_print_string fmt " ";
);
(match m.met_value.val_code with
None -> Format.pp_print_string fmt (Name.simple m.met_value.val_name)
| Some c ->
let file = Naming.file_code_method_complete_target m in
self#output_code m.met_value.val_name (Filename.concat !Odoc_args.target_dir file) c;
Format.fprintf fmt "@{%s@}" file (Name.simple m.met_value.val_name)
);
Format.pp_print_string fmt " : ";
self#html_of_type_expr fmt module_name m.met_value.val_type;
Format.fprintf fmt "@}";
self#html_of_info fmt m.met_value.val_info;
(if !Odoc_args.with_parameter_list then
self#html_of_parameter_list fmt module_name m.met_value.val_parameters
else
self#html_of_described_parameter_list fmt module_name m.met_value.val_parameters
)
(** Print html code for the description of a function parameter. *)
method html_of_parameter_description fmt p =
match Parameter.names p with
[] -> ()
| name :: [] ->
(
(* Only one name, no need for label for the description. *)
match Parameter.desc_by_name p name with
None -> ()
| Some t -> self#html_of_text fmt t
)
| l ->
(* A list of names, we display those with a description. *)
let l2 = List.filter (fun n -> (Parameter.desc_by_name p n) <> None) l in
List.iter
(fun n ->
match Parameter.desc_by_name p n with
None -> ()
| Some t ->
Format.fprintf fmt "@{%s@} : " n ;
self#html_of_text fmt t;
Format.pp_print_string fmt " \n"
)
l2
(** Print html code for a list of parameters. *)
method html_of_parameter_list fmt m_name l =
match l with
[] -> ()
| _ ->
Format.fprintf fmt "@{
%s@}"
(match Parameter.complete_name p with
"" -> "?"
| s -> s);
Format.fprintf fmt "@{
:@}@{
";
self#html_of_type_expr fmt m_name (Parameter.typ p);
Format.pp_print_string fmt " \n";
self#html_of_parameter_description fmt p;
Format.fprintf fmt "@}@}"
)
l;
Format.fprintf fmt "@}@}@}@}@}"
(** Print html code for the parameters which have a name and description. *)
method html_of_described_parameter_list fmt m_name l =
(* get the params which have a name, and at least one name described. *)
let l2 = List.filter
(fun p ->
List.exists
(fun n -> (Parameter.desc_by_name p n) <> None)
(Parameter.names p))
l
in
let f p =
Format.fprintf fmt "@{
@{%s@} : " (Parameter.complete_name p);
self#html_of_parameter_description fmt p;
Format.fprintf fmt "@}"
in
match l2 with
[] -> ()
| _ -> Format.fprintf fmt " "; List.iter f l2
(** Return html code for a list of module parameters. *)
method html_of_module_parameter_list fmt m_name l =
match l with
[] -> ()
| _ ->
Format.fprintf fmt "@{
";
self#html_of_module_type fmt m_name p.mp_type;
(match desc_opt with
None -> ()
| Some t -> Format.pp_print_string fmt " \n"; self#html_of_text fmt t
);
Format.fprintf fmt "@}@}"
)
l;
Format.fprintf fmt "@}@}@}@}"
(** Print html code for a module. *)
method html_of_module fmt ?(info=true) ?(complete=true) ?(with_link=true) m =
let (html_file, _) = Naming.html_files m.m_name in
let father = Name.father m.m_name in
Format.fprintf fmt "@{
";
self#keyword fmt "module";
Format.pp_print_string fmt " ";
if with_link then
Format.fprintf fmt "@{%s@}" html_file (Name.simple m.m_name)
else
Format.fprintf fmt "%s" (Name.simple m.m_name);
Format.pp_print_string fmt ": ";
self#html_of_module_type fmt father m.m_type;
Format.fprintf fmt "@}";
if info then
(if complete then self#html_of_info
else self#html_of_info_first_sentence) fmt m.m_info
(** Print html code for a module type. *)
method html_of_modtype fmt ?(info=true) ?(complete=true) ?(with_link=true) mt =
let (html_file, _) = Naming.html_files mt.mt_name in
let father = Name.father mt.mt_name in
Format.fprintf fmt "@{
";
self#keyword fmt "module type";
Format.pp_print_string fmt " ";
if with_link then
Format.fprintf fmt "@{%s@}" html_file (Name.simple mt.mt_name)
else
Format.fprintf fmt "%s" (Name.simple mt.mt_name);
(match mt.mt_type with
None -> ()
| Some mtyp ->
Format.pp_print_string fmt " = ";
self#html_of_module_type fmt father mtyp
);
Format.fprintf fmt "@}";
if info then
(if complete then self#html_of_info else self#html_of_info_first_sentence) fmt mt.mt_info
(** Print html code for an included module. *)
method html_of_included_module fmt im =
Format.fprintf fmt "@{
";
self#keyword fmt "include";
Format.pp_print_string fmt " ";
(
match im.im_module with
None -> Format.pp_print_string fmt im.im_name
| Some mmt ->
let (file, name) =
match mmt with
Mod m ->
let (html_file, _) = Naming.html_files m.m_name in
(html_file, m.m_name)
| Modtype mt ->
let (html_file, _) = Naming.html_files mt.mt_name in
(html_file, mt.mt_name)
in
Format.fprintf fmt "@{%s@}" file (Name.simple name)
);
Format.fprintf fmt "@}"
(** Print html code for a class. *)
method html_of_class fmt ?(complete=true) ?(with_link=true) c =
let father = Name.father c.cl_name in
Odoc_info.reset_type_names ();
let (html_file, _) = Naming.html_files c.cl_name in
Format.fprintf fmt "@{
";
self#keyword fmt "class";
Format.pp_print_string fmt " ";
(* we add a html tag, the same as for a type so we can
go directly here when the class name is used as a type name *)
Format.fprintf fmt "@{@}"
(Naming.type_target
{ ty_name = c.cl_name ;
ty_info = None ; ty_parameters = [] ;
ty_kind = Type_abstract ; ty_manifest = None ;
ty_loc = Odoc_info.dummy_loc });
print_DEBUG "html#html_of_class : virtual or not" ;
if c.cl_virtual then
(
self#keyword fmt "virtual";
Format.pp_print_string fmt " "
);
(
match c.cl_type_parameters with
[] -> ()
| l ->
Format.pp_print_string fmt "[";
self#html_of_type_expr_list fmt father ", " l;
Format.pp_print_string fmt "]"
);
print_DEBUG "html#html_of_class : with link or not" ;
(
if with_link then
Format.fprintf fmt "@{%s@}" html_file (Name.simple c.cl_name)
else
Format.pp_print_string fmt (Name.simple c.cl_name)
);
Format.pp_print_string fmt " : " ;
self#html_of_class_type_expr fmt father c.cl_type;
Format.fprintf fmt "@}";
print_DEBUG "html#html_of_class : info" ;
(if complete then self#html_of_info else self#html_of_info_first_sentence) fmt c.cl_info
(** Print html code for a class type. *)
method html_of_class_type fmt ?(complete=true) ?(with_link=true) ct =
Odoc_info.reset_type_names ();
let father = Name.father ct.clt_name in
let (html_file, _) = Naming.html_files ct.clt_name in
Format.fprintf fmt "@{
";
self#keyword fmt "class type";
Format.pp_print_string fmt " ";
(* we add a html tag, the same as for a type so we can
go directly here when the class type name is used as a type name *)
Format.fprintf fmt "@{@}"
(Naming.type_target
{ ty_name = ct.clt_name ;
ty_info = None ; ty_parameters = [] ;
ty_kind = Type_abstract ; ty_manifest = None ;
ty_loc = Odoc_info.dummy_loc });
if ct.clt_virtual then
(
self#keyword fmt "virtual";
Format.pp_print_string fmt " "
);
(
match ct.clt_type_parameters with
[] -> ()
| l ->
Format.pp_print_string fmt "[";
self#html_of_type_expr_list fmt father ", " l;
Format.pp_print_string fmt "]"
);
if with_link then
Format.fprintf fmt "@{%s@}" html_file (Name.simple ct.clt_name)
else
Format.pp_print_string fmt (Name.simple ct.clt_name);
Format.pp_print_string fmt " = ";
self#html_of_class_type_expr fmt father ct.clt_type;
Format.fprintf fmt "@}";
(if complete then self#html_of_info else self#html_of_info_first_sentence) fmt ct.clt_info
(** Get html code to represent a dag, represented as in Odoc_dag2html. *)
method html_of_dag dag =
let f n =
let (name, cct_opt) = n.Odoc_dag2html.valu in
(* if we have a c_opt = Some class then we take its information
because we are sure the name is complete. *)
let (name2, html_file) =
match cct_opt with
None -> (name, fst (Naming.html_files name))
| Some (Cl c) -> (c.cl_name, fst (Naming.html_files c.cl_name))
| Some (Cltype (ct, _)) -> (ct.clt_name, fst (Naming.html_files ct.clt_name))
in
let new_v =
"
\n"
in
{ n with Odoc_dag2html.valu = new_v }
in
let a = Array.map f dag.Odoc_dag2html.dag in
Odoc_dag2html.html_of_dag { Odoc_dag2html.dag = a }
(** Print html code for a module comment.*)
method html_of_module_comment fmt text =
Format.pp_print_string fmt " \n";
self#html_of_text fmt text;
Format.pp_print_string fmt "
\n"
(** Print html code for a class comment.*)
method html_of_class_comment fmt text =
(* Add some style if there is no style for the first part of the text. *)
let text2 =
match text with
| (Odoc_info.Raw s) :: q ->
(Odoc_info.Title (2, None, [Odoc_info.Raw s])) :: q
| _ -> text
in
self#html_of_text fmt text2
(** Print html code for the given list of inherited classes.*)
method generate_inheritance_info fmt inher_l =
let f inh =
match inh.ic_class with
None -> (* we can't make the link. *)
(Odoc_info.Code inh.ic_name) ::
(match inh.ic_text with
None -> []
| Some t -> (Odoc_info.Raw " ") :: t)
| Some cct ->
(* we can create the link. *)
let real_name = (* even if it should be the same *)
match cct with
Cl c -> c.cl_name
| Cltype (ct, _) -> ct.clt_name
in
let (class_file, _) = Naming.html_files real_name in
(Odoc_info.Link (class_file, [Odoc_info.Code real_name])) ::
(match inh.ic_text with
None -> []
| Some t -> (Odoc_info.Raw " ") :: t)
in
let text = [
Odoc_info.Bold [Odoc_info.Raw Odoc_messages.inherits] ;
Odoc_info.List (List.map f inher_l)
]
in
self#html_of_text fmt text
(** Generate html code for the inherited classes of the given class. *)
method generate_class_inheritance_info chanout cl =
let rec iter_kind k =
match k with
Class_structure ([], _) ->
()
| Class_structure (l, _) ->
self#generate_inheritance_info chanout l
| Class_constraint (k, ct) ->
iter_kind k
| Class_apply _
| Class_constr _ ->
()
in
iter_kind cl.cl_kind
(** Generate html code for the inherited classes of the given class type. *)
method generate_class_type_inheritance_info fmt clt =
match clt.clt_kind with
Class_signature ([], _) ->
()
| Class_signature (l, _) ->
self#generate_inheritance_info fmt l
| Class_type _ ->
()
(** A method to create index files. *)
method generate_elements_index :
'a.
'a list ->
('a -> Odoc_info.Name.t) ->
('a -> Odoc_info.info option) ->
('a -> string) -> string -> string -> unit =
fun elements name info target title simple_file ->
try
let (fmt,chanout) = self#formatter_of_file (Filename.concat !Odoc_args.target_dir simple_file) in
Format.fprintf fmt "@{";
self#header fmt (self#inner_title title);
Format.fprintf fmt "@{@{
@{
%s@}@}" title;
let sorted_elements = List.sort
(fun e1 -> fun e2 -> compare (Name.simple (name e1)) (Name.simple (name e2)))
elements
in
let groups = Odoc_info.create_index_lists sorted_elements (fun e -> Name.simple (name e)) in
let f_ele e =
let simple_name = Name.simple (name e) in
let father_name = Name.father (name e) in
Format.fprintf fmt "@{
@{
@{%s@} " (target e) simple_name;
if simple_name <> father_name then
Format.fprintf fmt "[@{%s@}]" (fst (Naming.html_files father_name)) father_name;
Format.fprintf fmt "@}@{
";
self#html_of_info_first_sentence fmt (info e);
Format.fprintf fmt "@}@}"
in
let f_group l =
match l with
[] -> ()
| e :: _ ->
let s =
match (Char.uppercase (Name.simple (name e)).[0]) with
'A'..'Z' as c -> String.make 1 c
| _ -> ""
in
Format.fprintf fmt "@{
@{
%s@}@}" s;
List.iter f_ele l
in
Format.fprintf fmt "@{
";
List.iter f_group groups ;
Format.fprintf fmt "@} \n@}@}";
Format.pp_print_flush fmt ();
close_out chanout
with
Sys_error s ->
raise (Failure s)
(** A method to generate a list of module/class files. *)
method generate_elements :
'a. ('a option -> 'a option -> 'a -> unit) -> 'a list -> unit =
fun f_generate l ->
let rec iter pre_opt = function
[] -> ()
| ele :: [] -> f_generate pre_opt None ele
| ele1 :: ele2 :: q ->
f_generate pre_opt (Some ele2) ele1 ;
iter (Some ele1) (ele2 :: q)
in
iter None l
(** Generate the code of the html page for the given class.*)
method generate_for_class pre post cl =
Odoc_info.reset_type_names ();
let (html_file, _) = Naming.html_files cl.cl_name in
let type_file = Naming.file_type_class_complete_target cl.cl_name in
try
let (fmt, chanout) = self#formatter_of_file (Filename.concat !Odoc_args.target_dir html_file) in
let pre_name = opt (fun c -> c.cl_name) pre in
let post_name = opt (fun c -> c.cl_name) post in
Format.fprintf fmt "@{";
self#header fmt
~nav: (Some (pre_name, post_name, cl.cl_name))
(self#inner_title cl.cl_name);
Format.fprintf fmt "@{";
self#navbar fmt pre_name post_name cl.cl_name;
Format.fprintf fmt "@{
@{
%s %s@{%s@}@}@} \n"
Odoc_messages.clas
(if cl.cl_virtual then "virtual " else "")
type_file
cl.cl_name;
self#html_of_class fmt ~with_link: false cl;
(* parameters *)
self#html_of_described_parameter_list fmt (Name.father cl.cl_name) cl.cl_parameters;
(* class inheritance *)
self#generate_class_inheritance_info fmt cl;
(* a horizontal line *)
Format.pp_print_string fmt "\n";
(* the various elements *)
List.iter
(fun element ->
match element with
Class_attribute a -> self#html_of_attribute fmt a
| Class_method m -> self#html_of_method fmt m
| Class_comment t -> self#html_of_class_comment fmt t
)
(Class.class_elements ~trans:false cl);
Format.fprintf fmt "@}@}";
Format.pp_print_flush fmt ();
close_out chanout;
(* generate the file with the complete class type *)
self#output_class_type
cl.cl_name
(Filename.concat !Odoc_args.target_dir type_file)
cl.cl_type
with
Sys_error s ->
raise (Failure s)
(** Generate the code of the html page for the given class type.*)
method generate_for_class_type pre post clt =
Odoc_info.reset_type_names ();
let (html_file, _) = Naming.html_files clt.clt_name in
let type_file = Naming.file_type_class_complete_target clt.clt_name in
try
let (fmt, chanout) = self#formatter_of_file (Filename.concat !Odoc_args.target_dir html_file) in
let pre_name = opt (fun ct -> ct.clt_name) pre in
let post_name = opt (fun ct -> ct.clt_name) post in
Format.fprintf fmt "@{";
self#header fmt
~nav: (Some (pre_name, post_name, clt.clt_name))
(self#inner_title clt.clt_name);
Format.fprintf fmt "@{";
self#navbar fmt pre_name post_name clt.clt_name;
Format.fprintf fmt "@{
@{
%s %s@{%s@}@}@} \n"
Odoc_messages.class_type
(if clt.clt_virtual then "virtual " else "")
type_file
clt.clt_name;
self#html_of_class_type fmt ~with_link: false clt;
(* class inheritance *)
self#generate_class_type_inheritance_info fmt clt;
(* a horizontal line *)
Format.pp_print_string fmt "\n";
(* the various elements *)
List.iter
(fun element ->
match element with
Class_attribute a -> self#html_of_attribute fmt a
| Class_method m -> self#html_of_method fmt m
| Class_comment t -> self#html_of_class_comment fmt t
)
(Class.class_type_elements ~trans: false clt);
Format.fprintf fmt "@}@}";
Format.pp_print_flush fmt ();
close_out chanout;
(* generate the file with the complete class type *)
self#output_class_type
clt.clt_name
(Filename.concat !Odoc_args.target_dir type_file)
clt.clt_type
with
Sys_error s ->
raise (Failure s)
(** Generate the html file for the given module type.
@raise Failure if an error occurs.*)
method generate_for_module_type pre post mt =
try
let (html_file, _) = Naming.html_files mt.mt_name in
let type_file = Naming.file_type_module_complete_target mt.mt_name in
let (fmt, chanout) = self#formatter_of_file (Filename.concat !Odoc_args.target_dir html_file) in
let pre_name = opt (fun mt -> mt.mt_name) pre in
let post_name = opt (fun mt -> mt.mt_name) post in
Format.fprintf fmt "@{";
self#header fmt
~nav: (Some (pre_name, post_name, mt.mt_name))
(self#inner_title mt.mt_name);
Format.fprintf fmt "@{";
self#navbar fmt pre_name post_name mt.mt_name;
Format.fprintf fmt "@{
@{
%s " Odoc_messages.module_type;
(match mt.mt_type with
Some _ -> Format.fprintf fmt "@{%s@}" type_file mt.mt_name
| None-> Format.pp_print_string fmt mt.mt_name
);
Format.fprintf fmt "@}@} \n";
self#html_of_modtype fmt ~with_link: false mt;
(* parameters for functors *)
self#html_of_module_parameter_list fmt "" (Module.module_type_parameters mt);
(* a horizontal line *)
Format.pp_print_string fmt "\n";
(* module elements *)
List.iter
(fun ele ->
match ele with
Element_module m -> self#html_of_module fmt ~complete: false m
| Element_module_type mt -> self#html_of_modtype fmt ~complete: false mt
| Element_included_module im -> self#html_of_included_module fmt im
| Element_class c ->self#html_of_class fmt ~complete: false c
| Element_class_type ct -> self#html_of_class_type fmt ~complete: false ct
| Element_value v -> self#html_of_value fmt v
| Element_exception e -> self#html_of_exception fmt e
| Element_type t -> self#html_of_type fmt t
| Element_module_comment text -> self#html_of_module_comment fmt text
)
(Module.module_type_elements mt);
Format.fprintf fmt "@}@}";
Format.pp_print_flush fmt ();
close_out chanout;
(* generate html files for submodules *)
self#generate_elements self#generate_for_module (Module.module_type_modules mt);
(* generate html files for module types *)
self#generate_elements self#generate_for_module_type (Module.module_type_module_types mt);
(* generate html files for classes *)
self#generate_elements self#generate_for_class (Module.module_type_classes mt);
(* generate html files for class types *)
self#generate_elements self#generate_for_class_type (Module.module_type_class_types mt);
(* generate the file with the complete module type *)
(
match mt.mt_type with
None -> ()
| Some mty -> self#output_module_type
mt.mt_name
(Filename.concat !Odoc_args.target_dir type_file)
mty
)
with
Sys_error s ->
raise (Failure s)
(** Generate the html file for the given module.
@raise Failure if an error occurs.*)
method generate_for_module pre post modu =
try
Odoc_info.verbose ("Generate for module "^modu.m_name);
let (html_file, _) = Naming.html_files modu.m_name in
let type_file = Naming.file_type_module_complete_target modu.m_name in
let (fmt, chanout) = self#formatter_of_file
(Filename.concat !Odoc_args.target_dir html_file)
in
let pre_name = opt (fun m -> m.m_name) pre in
let post_name = opt (fun m -> m.m_name) post in
Format.fprintf fmt "@{";
self#header fmt
~nav: (Some (pre_name, post_name, modu.m_name))
(self#inner_title modu.m_name);
Format.fprintf fmt "@{";
self#navbar fmt pre_name post_name modu.m_name ;
Format.fprintf fmt "@{
@{
%s @{%s@}@}@} \n"
(if Module.module_is_functor modu then Odoc_messages.functo else Odoc_messages.modul)
type_file modu.m_name;
self#html_of_module fmt ~with_link: false modu;
(* parameters for functors *)
self#html_of_module_parameter_list fmt "" (Module.module_parameters modu);
(* a horizontal line *)
Format.fprintf fmt "\n";
(* module elements *)
List.iter
(fun ele ->
print_DEBUG "html#generate_for_module : ele ->";
match ele with
Element_module m -> self#html_of_module fmt ~complete: false m
| Element_module_type mt -> self#html_of_modtype fmt ~complete: false mt
| Element_included_module im -> self#html_of_included_module fmt im
| Element_class c -> self#html_of_class fmt ~complete: false c
| Element_class_type ct -> self#html_of_class_type fmt ~complete: false ct
| Element_value v ->self#html_of_value fmt v
| Element_exception e ->self#html_of_exception fmt e
| Element_type t -> self#html_of_type fmt t
| Element_module_comment text -> self#html_of_module_comment fmt text
)
(Module.module_elements modu);
Format.fprintf fmt "@}@}";
Format.pp_print_flush fmt ();
close_out chanout;
(* generate html files for submodules *)
self#generate_elements self#generate_for_module (Module.module_modules modu);
(* generate html files for module types *)
self#generate_elements self#generate_for_module_type (Module.module_module_types modu);
(* generate html files for classes *)
self#generate_elements self#generate_for_class (Module.module_classes modu);
(* generate html files for class types *)
self#generate_elements self#generate_for_class_type (Module.module_class_types modu);
(* generate the file with the complete module type *)
self#output_module_type
modu.m_name
(Filename.concat !Odoc_args.target_dir type_file)
modu.m_type
with
Sys_error s ->
raise (Failure s)
(** Generate the [index.html] file corresponding to the given module list.
@raise Failure if an error occurs.*)
method generate_index module_list =
try
let title = match !Odoc_args.title with None -> "" | Some t -> self#escape t in
let (fmt, chanout) = self#formatter_of_file (Filename.concat !Odoc_args.target_dir index) in
let index_if_not_empty l url m =
match l with
[] -> ()
| _ -> Format.fprintf fmt "@{%s@} \n" url m
in
Format.fprintf fmt "@{";
self#header fmt self#title;
Format.fprintf fmt "@{@{
";
List.iter
(fun m ->
let (html, _) = Naming.html_files m.m_name in
Format.fprintf fmt "@{
@{
@{%s@}@}@{
" html m.m_name;
self#html_of_info_first_sentence fmt m.m_info;
Format.fprintf fmt "@}@}"
)
module_list;
Format.fprintf fmt "@}@}@}";
Format.pp_print_flush fmt ();
close_out chanout
with
Sys_error s ->
raise (Failure s)
(** Generate the values index in the file [index_values.html]. *)
method generate_values_index module_list =
self#generate_elements_index
list_values
(fun v -> v.val_name)
(fun v -> v.val_info)
Naming.complete_value_target
Odoc_messages.index_of_values
index_values
(** Generate the exceptions index in the file [index_exceptions.html]. *)
method generate_exceptions_index module_list =
self#generate_elements_index
list_exceptions
(fun e -> e.ex_name)
(fun e -> e.ex_info)
Naming.complete_exception_target
Odoc_messages.index_of_exceptions
index_exceptions
(** Generate the types index in the file [index_types.html]. *)
method generate_types_index module_list =
self#generate_elements_index
list_types
(fun t -> t.ty_name)
(fun t -> t.ty_info)
Naming.complete_type_target
Odoc_messages.index_of_types
index_types
(** Generate the attributes index in the file [index_attributes.html]. *)
method generate_attributes_index module_list =
self#generate_elements_index
list_attributes
(fun a -> a.att_value.val_name)
(fun a -> a.att_value.val_info)
Naming.complete_attribute_target
Odoc_messages.index_of_attributes
index_attributes
(** Generate the methods index in the file [index_methods.html]. *)
method generate_methods_index module_list =
self#generate_elements_index
list_methods
(fun m -> m.met_value.val_name)
(fun m -> m.met_value.val_info)
Naming.complete_method_target
Odoc_messages.index_of_methods
index_methods
(** Generate the classes index in the file [index_classes.html]. *)
method generate_classes_index module_list =
self#generate_elements_index
list_classes
(fun c -> c.cl_name)
(fun c -> c.cl_info)
(fun c -> fst (Naming.html_files c.cl_name))
Odoc_messages.index_of_classes
index_classes
(** Generate the class types index in the file [index_class_types.html]. *)
method generate_class_types_index module_list =
self#generate_elements_index
list_class_types
(fun ct -> ct.clt_name)
(fun ct -> ct.clt_info)
(fun ct -> fst (Naming.html_files ct.clt_name))
Odoc_messages.index_of_class_types
index_class_types
(** Generate the modules index in the file [index_modules.html]. *)
method generate_modules_index module_list =
self#generate_elements_index
list_modules
(fun m -> m.m_name)
(fun m -> m.m_info)
(fun m -> fst (Naming.html_files m.m_name))
Odoc_messages.index_of_modules
index_modules
(** Generate the module types index in the file [index_module_types.html]. *)
method generate_module_types_index module_list =
let module_types = Odoc_info.Search.module_types module_list in
self#generate_elements_index
list_module_types
(fun mt -> mt.mt_name)
(fun mt -> mt.mt_info)
(fun mt -> fst (Naming.html_files mt.mt_name))
Odoc_messages.index_of_module_types
index_module_types
(** Generate all the html files from a module list. The main
file is [index.html]. *)
method generate module_list =
(* init the style *)
self#init_style ;
(* init the lists of elements *)
list_values <- Odoc_info.Search.values module_list ;
list_exceptions <- Odoc_info.Search.exceptions module_list ;
list_types <- Odoc_info.Search.types module_list ;
list_attributes <- Odoc_info.Search.attributes module_list ;
list_methods <- Odoc_info.Search.methods module_list ;
list_classes <- Odoc_info.Search.classes module_list ;
list_class_types <- Odoc_info.Search.class_types module_list ;
list_modules <- Odoc_info.Search.modules module_list ;
list_module_types <- Odoc_info.Search.module_types module_list ;
(* prepare the page header *)
self#prepare_header module_list ;
(* Get the names of all known types. *)
let types = Odoc_info.Search.types module_list in
let type_names = List.map (fun t -> t.ty_name) types in
known_types_names <- type_names ;
(* Get the names of all class and class types. *)
let classes = Odoc_info.Search.classes module_list in
let class_types = Odoc_info.Search.class_types module_list in
let class_names = List.map (fun c -> c.cl_name) classes in
let class_type_names = List.map (fun ct -> ct.clt_name) class_types in
known_classes_names <- class_names @ class_type_names ;
(* Get the names of all known modules and module types. *)
let module_types = Odoc_info.Search.module_types module_list in
let modules = Odoc_info.Search.modules module_list in
let module_type_names = List.map (fun mt -> mt.mt_name) module_types in
let module_names = List.map (fun m -> m.m_name) modules in
known_modules_names <- module_type_names @ module_names ;
(* generate html for each module *)
if not !Odoc_args.index_only then
self#generate_elements self#generate_for_module module_list ;
try
self#generate_index module_list;
self#generate_values_index module_list ;
self#generate_exceptions_index module_list ;
self#generate_types_index module_list ;
self#generate_attributes_index module_list ;
self#generate_methods_index module_list ;
self#generate_classes_index module_list ;
self#generate_class_types_index module_list ;
self#generate_modules_index module_list ;
self#generate_module_types_index module_list ;
with
Failure s ->
prerr_endline s ;
incr Odoc_info.errors
method init_formatter fmt =
let htag s =
try
let i = String.index s ' ' in
String.sub s 0 i, String.sub s (i + 1) (String.length s - i - 1)
with Not_found -> s, ""
in
let mark_open_tag s =
let tag, vals = htag s in
match tag with
| "href" -> ""
| "mark" -> ""
| "ul" | "li" | "ol" | "html" | "body"
| "table" | "tr" | "td" | "head" ->
"<" ^ tag ^(if vals = "" then "" else " "^vals)^ ">\n"
| t -> "<" ^ t ^ " " ^ vals ^ ">"
in
let mark_close_tag s =
let tag, vals = htag s in
match tag with
| "href" -> ""
| "mark" -> ""
| "ul" | "li" | "ol" | "html" | "body" | "pre"
| "table" | "tr" | "td" | "head" -> "" ^ tag ^ ">\n"
| t -> "" ^ t ^ ">"
in
Format.pp_set_formatter_tag_functions fmt
{(Format.pp_get_formatter_tag_functions fmt ()) with
Format.mark_close_tag = mark_close_tag;
Format.mark_open_tag = mark_open_tag}
method formatter_of_file file =
let chanout = open_out file in
let fmt = Format.formatter_of_out_channel chanout in
self#init_formatter fmt;
(fmt, chanout)
initializer
Odoc_ocamlhtml.html_of_comment :=
(fun fmt -> fun s -> self#html_of_text fmt (Odoc_text.Texter.text_of_string s));
end