summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/ocamldoc/odoc_man.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/ocamldoc/odoc_man.ml')
-rw-r--r--ocaml-binary-annot/ocamldoc/odoc_man.ml1089
1 files changed, 1089 insertions, 0 deletions
diff --git a/ocaml-binary-annot/ocamldoc/odoc_man.ml b/ocaml-binary-annot/ocamldoc/odoc_man.ml
new file mode 100644
index 0000000000..612bc11a02
--- /dev/null
+++ b/ocaml-binary-annot/ocamldoc/odoc_man.ml
@@ -0,0 +1,1089 @@
+(***********************************************************************)
+(* 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. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** The man pages generator. *)
+open Odoc_info
+open Parameter
+open Value
+open Type
+open Exception
+open Class
+open Module
+open Search
+
+let man_suffix = ref Odoc_messages.default_man_suffix
+let man_section = ref Odoc_messages.default_man_section
+
+let man_mini = ref false
+
+let new_buf () = Buffer.create 1024
+let bp = Printf.bprintf
+let bs = Buffer.add_string
+
+(** A class used to get a [text] 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 man code.
+ Add a pair here to handle a tag.*)
+ val mutable tag_functions = ([] : (string * (Odoc_info.text -> string)) list)
+
+ (** Return man code for a [text]. *)
+ method virtual man_of_text : Buffer.t -> Odoc_info.text -> unit
+
+ (** Print groff string for an author list. *)
+ method man_of_author_list b l =
+ match l with
+ [] -> ()
+ | _ ->
+ bs b ".B \"";
+ bs b Odoc_messages.authors;
+ bs b "\"\n:\n";
+ bs b (String.concat ", " l);
+ bs b "\n.sp\n"
+
+ (** Print groff string for the given optional version information.*)
+ method man_of_version_opt b v_opt =
+ match v_opt with
+ None -> ()
+ | Some v ->
+ bs b ".B \"";
+ bs b Odoc_messages.version;
+ bs b "\"\n:\n";
+ bs b v;
+ bs b "\n.sp\n"
+
+ (** Printf groff string for the \@before information. *)
+ method man_of_before b = function
+ [] -> ()
+ | l ->
+ List.iter
+ (fun (v, text) ->
+ bp b ".B \"%s" Odoc_messages.before;
+ bs b v;
+ bs b "\"\n";
+ self#man_of_text b text;
+ bs b "\n";
+ bs b "\n.sp\n"
+ )
+ l
+
+
+ (** Print groff string for the given optional since information.*)
+ method man_of_since_opt b s_opt =
+ match s_opt with
+ None -> ()
+ | Some s ->
+ bs b ".B \"";
+ bs b Odoc_messages.since;
+ bs b "\"\n";
+ bs b s;
+ bs b "\n.sp\n"
+
+ (** Print groff string for the given list of raised exceptions.*)
+ method man_of_raised_exceptions b l =
+ match l with
+ [] -> ()
+ | (s, t) :: [] ->
+ bs b ".B \"";
+ bs b Odoc_messages.raises;
+ bs b (" "^s^"\"\n");
+ self#man_of_text b t;
+ bs b "\n.sp\n"
+ | _ ->
+ bs b ".B \"";
+ bs b Odoc_messages.raises;
+ bs b "\"\n";
+ List.iter
+ (fun (ex, desc) ->
+ bs b ".sp\n.B \"";
+ bs b ex;
+ bs b "\"\n";
+ self#man_of_text b desc;
+ bs b "\n"
+ )
+ l;
+ bs b "\n.sp\n"
+
+ (** Print groff string for the given "see also" reference. *)
+ method man_of_see b (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#man_of_text b t_ref
+
+ (** Print groff string for the given list of "see also" references.*)
+ method man_of_sees b l =
+ match l with
+ [] -> ()
+ | see :: [] ->
+ bs b ".B \"";
+ bs b Odoc_messages.see_also;
+ bs b "\"\n";
+ self#man_of_see b see;
+ bs b "\n.sp\n"
+ | _ ->
+ bs b ".B \"";
+ bs b Odoc_messages.see_also;
+ bs b "\"\n";
+ List.iter
+ (fun see ->
+ bs b ".sp\n";
+ self#man_of_see b see;
+ bs b "\n"
+ )
+ l;
+ bs b "\n.sp\n"
+
+ (** Print groff string for the given optional return information.*)
+ method man_of_return_opt b return_opt =
+ match return_opt with
+ None -> ()
+ | Some s ->
+ bs b ".B ";
+ bs b Odoc_messages.returns;
+ bs b "\n";
+ self#man_of_text b s;
+ bs b "\n.sp\n"
+
+ (** Print man code for the given list of custom tagged texts. *)
+ method man_of_custom b l =
+ let buf = Buffer.create 50 in
+ List.iter
+ (fun (tag, text) ->
+ try
+ let f = List.assoc tag tag_functions in
+ Buffer.add_string buf (f text)
+ with
+ Not_found ->
+ Odoc_info.warning (Odoc_messages.tag_not_handled tag)
+ )
+ l
+
+ (** Print the groff string to display an optional info structure. *)
+ method man_of_info b info_opt =
+ match info_opt with
+ None -> ()
+ | Some info ->
+ let module M = Odoc_info in
+ (
+ match info.M.i_deprecated with
+ None -> ()
+ | Some d ->
+ bs b ".B \"";
+ bs b Odoc_messages.deprecated;
+ bs b "\"\n";
+ self#man_of_text b d;
+ bs b "\n.sp\n"
+ );
+ (
+ match info.M.i_desc with
+ None -> ()
+ | Some d when d = [Odoc_info.Raw ""] -> ()
+ | Some d ->
+ self#man_of_text b d;
+ bs b "\n.sp\n"
+ );
+ self#man_of_author_list b info.M.i_authors;
+ self#man_of_version_opt b info.M.i_version;
+ self#man_of_before b info.M.i_before;
+ self#man_of_since_opt b info.M.i_since;
+ self#man_of_raised_exceptions b info.M.i_raised_exceptions;
+ self#man_of_return_opt b info.M.i_return_value;
+ self#man_of_sees b info.M.i_sees;
+ self#man_of_custom b info.M.i_custom
+ end
+
+module Generator =
+struct
+
+(** This class is used to create objects which can generate a simple html documentation. *)
+class man =
+ let re_slash = Str.regexp_string "/" in
+ object (self)
+ inherit info
+
+ (** Get a file name from a complete name. *)
+ method file_name name =
+ let s = Printf.sprintf "%s.%s" name !man_suffix in
+ Str.global_replace re_slash "slash" s
+
+ (** Escape special sequences of characters in a string. *)
+ method escape (s : string) =
+ let len = String.length s in
+ let b = Buffer.create len in
+ for i = 0 to len - 1 do
+ match s.[i] with
+ '\\' -> Buffer.add_string b "\\(rs"
+ | '.' -> Buffer.add_string b "\\&."
+ | '\'' -> Buffer.add_string b "\\&'"
+ | '-' -> Buffer.add_string b "\\-"
+ | c -> Buffer.add_char b c
+ done;
+ Buffer.contents b
+
+ (** Open a file for output. Add the target directory.*)
+ method open_out file =
+ let f = Filename.concat !Global.target_dir file in
+ open_out f
+
+ (** Print groff string for a text, without correction of blanks. *)
+ method private man_of_text2 b t =
+ List.iter (self#man_of_text_element b) t
+
+ (** Print the groff string for a text, with blanks corrected. *)
+ method man_of_text b t =
+ let b2 = new_buf () in
+ self#man_of_text2 b2 t ;
+ let s = Buffer.contents b2 in
+ let s2 = Str.global_replace (Str.regexp "\n[ ]*") "\n" s in
+ bs b (Str.global_replace (Str.regexp "\n\n") "\n" s2)
+
+ (** Return the given string without no newlines. *)
+ method remove_newlines s =
+ Str.global_replace (Str.regexp "[ ]*\n[ ]*") " " s
+
+ (** Print the groff string for a text element. *)
+ method man_of_text_element b te =
+ match te with
+ | Odoc_info.Raw s -> bs b (self#escape s)
+ | Odoc_info.Code s ->
+ bs b "\n.B ";
+ bs b ((Str.global_replace (Str.regexp "\n") "\n.B " (self#escape s))^"\n")
+ | Odoc_info.CodePre s ->
+ bs b "\n.B ";
+ bs b ((Str.global_replace (Str.regexp "\n") "\n.B " (self#escape s))^"\n")
+ | Odoc_info.Verbatim s ->
+ bs b (self#escape s)
+ | Odoc_info.Bold t
+ | Odoc_info.Italic t
+ | Odoc_info.Emphasize t
+ | Odoc_info.Center t
+ | Odoc_info.Left t
+ | Odoc_info.Right t ->
+ self#man_of_text2 b t
+ | Odoc_info.List tl ->
+ List.iter
+ (fun t -> bs b "\n.sp\n \\-"; self#man_of_text2 b t; bs b "\n")
+ tl;
+ bs b "\n"
+ | Odoc_info.Enum tl ->
+ List.iter
+ (fun t -> bs b "\n.sp\n \\-"; self#man_of_text2 b t; bs b "\n")
+ tl;
+ bs b "\n"
+ | Odoc_info.Newline ->
+ bs b "\n.sp\n"
+ | Odoc_info.Block t ->
+ bs b "\n.sp\n";
+ self#man_of_text2 b t;
+ bs b "\n.sp\n"
+ | Odoc_info.Title (n, l_opt, t) ->
+ self#man_of_text2 b [Odoc_info.Code (Odoc_info.string_of_text t)]
+ | Odoc_info.Latex _ ->
+ (* don't care about LaTeX stuff in HTML. *)
+ ()
+ | Odoc_info.Link (s, t) ->
+ self#man_of_text2 b t
+ | Odoc_info.Ref (name, _, _) ->
+ self#man_of_text_element b
+ (Odoc_info.Code (Odoc_info.use_hidden_modules name))
+ | Odoc_info.Superscript t ->
+ bs b "^{"; self#man_of_text2 b t
+ | Odoc_info.Subscript t ->
+ bs b "_{"; self#man_of_text2 b t
+ | Odoc_info.Module_list _ ->
+ ()
+ | Odoc_info.Index_list ->
+ ()
+ | Odoc_info.Custom (s,t) -> self#man_of_custom_text b s t
+ | Odoc_info.Target (target, code) -> self#man_of_Target b ~target ~code
+
+ method man_of_custom_text b s t = ()
+
+ method man_of_Target b ~target ~code =
+ if String.lowercase target = "man" then bs b code else ()
+
+ (** Print groff string to display code. *)
+ method man_of_code b s = self#man_of_text b [ Code s ]
+
+ (** Take a string and return the string where fully qualified idents
+ have been replaced by idents relative to the given module name.*)
+ method relative_idents m_name s =
+ let f str_t =
+ let match_s = Str.matched_string str_t in
+ Odoc_info.apply_if_equal
+ Odoc_info.use_hidden_modules
+ match_s
+ (Name.get_relative m_name 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 groff string to display a [Types.type_expr].*)
+ method man_of_type_expr b m_name t =
+ let s = String.concat "\n"
+ (Str.split (Str.regexp "\n") (Odoc_print.string_of_type_expr t))
+ in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string to display a [Types.class_type].*)
+ method man_of_class_type_expr b m_name t =
+ let s = String.concat "\n"
+ (Str.split (Str.regexp "\n") (Odoc_print.string_of_class_type t))
+ in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string to display a [Types.type_expr list].*)
+ method man_of_type_expr_list ?par b m_name sep l =
+ let s = Odoc_str.string_of_type_list ?par sep l in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string to display the parameters of a type.*)
+ method man_of_type_expr_param_list b m_name t =
+ match t.ty_parameters with
+ [] -> ()
+ | l ->
+ let s = Odoc_str.string_of_type_param_list t in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string to display a [Types.module_type]. *)
+ method man_of_module_type b m_name t =
+ let s = String.concat "\n"
+ (Str.split (Str.regexp "\n") (Odoc_print.string_of_module_type t))
+ in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n"
+
+ (** Print groff string code for a value. *)
+ method man_of_value b v =
+ Odoc_info.reset_type_names () ;
+ bs b "\n.I val ";
+ bs b (Name.simple v.val_name);
+ bs b " \n: ";
+ self#man_of_type_expr b (Name.father v.val_name) v.val_type;
+ bs b ".sp\n";
+ self#man_of_info b v.val_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string code for an exception. *)
+ method man_of_exception b e =
+ Odoc_info.reset_type_names () ;
+ bs b "\n.I exception ";
+ bs b (Name.simple e.ex_name);
+ bs b " \n";
+ (
+ match e.ex_args with
+ [] -> ()
+ | _ ->
+ bs b ".B of ";
+ self#man_of_type_expr_list
+ ~par: false
+ b (Name.father e.ex_name) " * " e.ex_args
+ );
+ (
+ match e.ex_alias with
+ None -> ()
+ | Some ea ->
+ bs b " = ";
+ bs b
+ (
+ match ea.ea_ex with
+ None -> ea.ea_name
+ | Some e -> e.ex_name
+ )
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b e.ex_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a type. *)
+ method man_of_type b t =
+ Odoc_info.reset_type_names () ;
+ let father = Name.father t.ty_name in
+ bs b ".I type ";
+ self#man_of_type_expr_param_list b father t;
+ (
+ match t.ty_parameters with
+ [] -> ()
+ | _ -> bs b ".I "
+ );
+ bs b (Name.simple t.ty_name);
+ bs b " \n";
+ let priv = t.ty_private = Asttypes.Private in
+ (
+ match t.ty_manifest with
+ None -> ()
+ | Some typ ->
+ bs b "= ";
+ if priv then bs b "private ";
+ self#man_of_type_expr b father typ
+ );
+ (
+ match t.ty_kind with
+ Type_abstract -> ()
+ | Type_variant l ->
+ bs b "=";
+ if priv then bs b " private";
+ bs b "\n ";
+ List.iter
+ (fun constr ->
+ bs b ("| "^constr.vc_name);
+ (
+ match constr.vc_args, constr.vc_text with
+ [], None -> bs b "\n "
+ | [], (Some t) ->
+ bs b " (* ";
+ self#man_of_text b t;
+ bs b " *)\n "
+ | l, None ->
+ bs b "\n.B of ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ bs b " "
+ | l, (Some t) ->
+ bs b "\n.B of ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ bs b ".I \" \"\n";
+ bs b "(* ";
+ self#man_of_text b t;
+ bs b " *)\n "
+ )
+ )
+ l
+ | Type_record l ->
+ bs b "= ";
+ if priv then bs b "private ";
+ bs b "{";
+ List.iter
+ (fun r ->
+ bs b (if r.rf_mutable then "\n\n.B mutable \n" else "\n ");
+ bs b (r.rf_name^" : ");
+ self#man_of_type_expr b father r.rf_type;
+ bs b ";";
+ (
+ match r.rf_text with
+ None -> ()
+ | Some t ->
+ bs b " (* ";
+ self#man_of_text b t;
+ bs b " *) "
+ );
+ )
+ l;
+ bs b "\n }\n"
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b t.ty_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a class attribute. *)
+ method man_of_attribute b a =
+ bs b ".I val ";
+ if a.att_virtual then bs b ("virtual ");
+ if a.att_mutable then bs b (Odoc_messages.mutab^" ");
+ bs b ((Name.simple a.att_value.val_name)^" : ");
+ self#man_of_type_expr b (Name.father a.att_value.val_name) a.att_value.val_type;
+ bs b "\n.sp\n";
+ self#man_of_info b a.att_value.val_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a class method. *)
+ method man_of_method b m =
+ bs b ".I method ";
+ if m.met_private then bs b "private ";
+ if m.met_virtual then bs b "virtual ";
+ bs b ((Name.simple m.met_value.val_name)^" : ");
+ self#man_of_type_expr b
+ (Name.father m.met_value.val_name) m.met_value.val_type;
+ bs b "\n.sp\n";
+ self#man_of_info b m.met_value.val_info;
+ bs b "\n.sp\n"
+
+ (** Groff for a list of parameters. *)
+ method man_of_parameter_list b m_name l =
+ match l with
+ [] -> ()
+ | _ ->
+ bs b "\n.B ";
+ bs b Odoc_messages.parameters;
+ bs b ": \n";
+ List.iter
+ (fun p ->
+ bs b ".sp\n";
+ bs b "\"";
+ bs b (Parameter.complete_name p);
+ bs b "\"\n";
+ self#man_of_type_expr b m_name (Parameter.typ p);
+ bs b "\n";
+ self#man_of_parameter_description b p;
+ bs b "\n"
+ )
+ l;
+ bs b "\n"
+
+ (** Groff for the description of a function parameter. *)
+ method man_of_parameter_description b 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 -> bs b "\n "; self#man_of_text b t
+ )
+ | l ->
+ (* A list of names, we display those with a description. *)
+ List.iter
+ (fun n ->
+ match Parameter.desc_by_name p n with
+ None -> ()
+ | Some t ->
+ self#man_of_code b (n^" : ");
+ self#man_of_text b t
+ )
+ l
+
+ (** Print groff string for a list of module parameters. *)
+ method man_of_module_parameter_list b m_name l =
+ match l with
+ [] -> ()
+ | _ ->
+ bs b ".B \"";
+ bs b Odoc_messages.parameters;
+ bs b ":\"\n";
+ List.iter
+ (fun (p, desc_opt) ->
+ bs b ".sp\n";
+ bs b ("\""^p.mp_name^"\"\n");
+ self#man_of_module_type b m_name p.mp_type;
+ bs b "\n";
+ (
+ match desc_opt with
+ None -> ()
+ | Some t -> self#man_of_text b t
+ );
+ bs b "\n"
+ )
+ l;
+ bs b "\n\n"
+
+ (** Print groff string for a class. *)
+ method man_of_class b c =
+ Odoc_info.reset_type_names () ;
+ let father = Name.father c.cl_name in
+ bs b ".I class ";
+ if c.cl_virtual then bs b "virtual ";
+ (
+ match c.cl_type_parameters with
+ [] -> ()
+ | l ->
+ bs b (Odoc_str.string_of_class_type_param_list l);
+ bs b " "
+ );
+ bs b (Name.simple c.cl_name);
+ bs b " : " ;
+ self#man_of_class_type_expr b father c.cl_type;
+ bs b "\n.sp\n";
+ self#man_of_info b c.cl_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a class type. *)
+ method man_of_class_type b ct =
+ Odoc_info.reset_type_names () ;
+ bs b ".I class type ";
+ if ct.clt_virtual then bs b "virtual " ;
+ (
+ match ct.clt_type_parameters with
+ [] -> ()
+ | l ->
+ bs b (Odoc_str.string_of_class_type_param_list l);
+ bs b " "
+ );
+ bs b (Name.simple ct.clt_name);
+ bs b " = " ;
+ self#man_of_class_type_expr b (Name.father ct.clt_name) ct.clt_type;
+ bs b "\n.sp\n";
+ self#man_of_info b ct.clt_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a module. *)
+ method man_of_module b m =
+ bs b ".I module ";
+ bs b (Name.simple m.m_name);
+ bs b " : ";
+ self#man_of_module_type b (Name.father m.m_name) m.m_type;
+ bs b "\n.sp\n";
+ self#man_of_info b m.m_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a module type. *)
+ method man_of_modtype b mt =
+ bs b ".I module type ";
+ bs b (Name.simple mt.mt_name);
+ bs b " = ";
+ (match mt.mt_type with
+ None -> ()
+ | Some t ->
+ self#man_of_module_type b (Name.father mt.mt_name) t
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b mt.mt_info;
+ bs b "\n.sp\n"
+
+ (** Print groff string for a module comment.*)
+ method man_of_module_comment b text =
+ bs b "\n.PP\n";
+ self#man_of_text b [Code ("=== "^(Odoc_misc.string_of_text text)^" ===")];
+ bs b "\n.PP\n"
+
+ (** Print groff string for a class comment.*)
+ method man_of_class_comment b text =
+ bs b "\n.PP\n";
+ self#man_of_text b [Code ("=== "^(Odoc_misc.string_of_text text)^" ===")];
+ bs b "\n.PP\n"
+
+ (** Print groff string for an included module. *)
+ method man_of_included_module b m_name im =
+ bs b ".I include ";
+ (
+ match im.im_module with
+ None -> bs b im.im_name
+ | Some mmt ->
+ let name =
+ match mmt with
+ Mod m -> m.m_name
+ | Modtype mt -> mt.mt_name
+ in
+ bs b (self#relative_idents m_name name)
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b im.im_info;
+ bs b "\n.sp\n"
+
+ (** Generate the man page for the given class.*)
+ method generate_for_class cl =
+ Odoc_info.reset_type_names () ;
+ let date = Unix.time () in
+ let file = self#file_name cl.cl_name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^cl.cl_name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+
+ let abstract =
+ match cl.cl_info with
+ None | Some { i_desc = None } -> "no description"
+ | Some { i_desc = Some t } ->
+ let s = Odoc_info.string_of_text (Odoc_info.first_sentence_of_text t) in
+ self#remove_newlines s
+ in
+
+ bs b ".SH NAME\n";
+ bs b (cl.cl_name^" \\- "^abstract^"\n");
+ bs b (".SH "^Odoc_messages.clas^"\n");
+ bs b (Odoc_messages.clas^" "^cl.cl_name^"\n");
+ bs b (".SH "^Odoc_messages.documentation^"\n");
+ bs b ".sp\n";
+ self#man_of_class b cl;
+
+ (* parameters *)
+ self#man_of_parameter_list b "" cl.cl_parameters;
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+
+(*
+ (* class inheritance *)
+ self#generate_class_inheritance_info chanout cl;
+*)
+ (* the various elements *)
+ List.iter
+ (fun element ->
+ match element with
+ Class_attribute a ->
+ self#man_of_attribute b a
+ | Class_method m ->
+ self#man_of_method b m
+ | Class_comment t ->
+ self#man_of_class_comment b t
+ )
+ (Class.class_elements cl);
+
+ Buffer.output_buffer chanout b;
+ close_out chanout
+ with
+ Sys_error s ->
+ incr Odoc_info.errors ;
+ prerr_endline s
+
+ (** Generate the man page for the given class type.*)
+ method generate_for_class_type ct =
+ Odoc_info.reset_type_names () ;
+ let date = Unix.time () in
+ let file = self#file_name ct.clt_name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^ct.clt_name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+
+ let abstract =
+ match ct.clt_info with
+ None | Some { i_desc = None } -> "no description"
+ | Some { i_desc = Some t } ->
+ let s = Odoc_info.string_of_text (Odoc_info.first_sentence_of_text t) in
+ self#remove_newlines s
+ in
+
+ bs b ".SH NAME\n";
+ bs b (ct.clt_name^" \\- "^abstract^"\n");
+ bs b (".SH "^Odoc_messages.class_type^"\n");
+ bs b (Odoc_messages.class_type^" "^ct.clt_name^"\n");
+ bs b (".SH "^Odoc_messages.documentation^"\n");
+ bs b ".sp\n";
+
+ self#man_of_class_type b ct;
+
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+(*
+ (* class inheritance *)
+ self#generate_class_inheritance_info chanout cl;
+*)
+ (* the various elements *)
+ List.iter
+ (fun element ->
+ match element with
+ Class_attribute a ->
+ self#man_of_attribute b a
+ | Class_method m ->
+ self#man_of_method b m
+ | Class_comment t ->
+ self#man_of_class_comment b t
+ )
+ (Class.class_type_elements ct);
+
+ Buffer.output_buffer chanout b;
+ close_out chanout
+ with
+ Sys_error s ->
+ incr Odoc_info.errors ;
+ prerr_endline s
+
+ (** Generate the man file for the given module type.
+ @raise Failure if an error occurs.*)
+ method generate_for_module_type mt =
+ let date = Unix.time () in
+ let file = self#file_name mt.mt_name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^mt.mt_name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+
+ let abstract =
+ match mt.mt_info with
+ None | Some { i_desc = None } -> "no description"
+ | Some { i_desc = Some t } ->
+ let s = Odoc_info.string_of_text (Odoc_info.first_sentence_of_text t) in
+ self#remove_newlines s
+ in
+ bs b ".SH NAME\n";
+ bs b (mt.mt_name^" \\- "^abstract^"\n");
+ bs b (".SH "^Odoc_messages.module_type^"\n");
+ bs b (Odoc_messages.module_type^" "^mt.mt_name^"\n");
+ bs b (".SH "^Odoc_messages.documentation^"\n");
+ bs b ".sp\n";
+ bs b (Odoc_messages.module_type^"\n");
+ bs b (".BI \""^(Name.simple mt.mt_name)^"\"\n");
+ bs b " = ";
+ (
+ match mt.mt_type with
+ None -> ()
+ | Some t ->
+ self#man_of_module_type b (Name.father mt.mt_name) t
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b mt.mt_info;
+ bs b "\n.sp\n";
+
+ (* parameters for functors *)
+ self#man_of_module_parameter_list b "" (Module.module_type_parameters mt);
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+
+ (* module elements *)
+ List.iter
+ (fun ele ->
+ match ele with
+ Element_module m ->
+ self#man_of_module b m
+ | Element_module_type mt ->
+ self#man_of_modtype b mt
+ | Element_included_module im ->
+ self#man_of_included_module b mt.mt_name im
+ | Element_class c ->
+ self#man_of_class b c
+ | Element_class_type ct ->
+ self#man_of_class_type b ct
+ | Element_value v ->
+ self#man_of_value b v
+ | Element_exception e ->
+ self#man_of_exception b e
+ | Element_type t ->
+ self#man_of_type b t
+ | Element_module_comment text ->
+ self#man_of_module_comment b text
+ )
+ (Module.module_type_elements mt);
+
+ Buffer.output_buffer chanout b;
+ close_out chanout
+
+ with
+ Sys_error s ->
+ incr Odoc_info.errors ;
+ prerr_endline s
+
+ (** Generate the man file for the given module.
+ @raise Failure if an error occurs.*)
+ method generate_for_module m =
+ let date = Unix.time () in
+ let file = self#file_name m.m_name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^m.m_name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+
+ let abstract =
+ match m.m_info with
+ None | Some { i_desc = None } -> "no description"
+ | Some { i_desc = Some t } ->
+ let s = Odoc_info.string_of_text (Odoc_info.first_sentence_of_text t) in
+ self#remove_newlines s
+ in
+
+ bs b ".SH NAME\n";
+ bs b (m.m_name^" \\- "^abstract^"\n");
+ bs b (".SH "^Odoc_messages.modul^"\n");
+ bs b (Odoc_messages.modul^" "^m.m_name^"\n");
+ bs b (".SH "^Odoc_messages.documentation^"\n");
+ bs b ".sp\n";
+ bs b (Odoc_messages.modul^"\n");
+ bs b (".BI \""^(Name.simple m.m_name)^"\"\n");
+ bs b " : ";
+ self#man_of_module_type b (Name.father m.m_name) m.m_type;
+ bs b "\n.sp\n";
+ self#man_of_info b m.m_info;
+ bs b "\n.sp\n";
+
+ (* parameters for functors *)
+ self#man_of_module_parameter_list b "" (Module.module_parameters m);
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+
+ (* module elements *)
+ List.iter
+ (fun ele ->
+ match ele with
+ Element_module m ->
+ self#man_of_module b m
+ | Element_module_type mt ->
+ self#man_of_modtype b mt
+ | Element_included_module im ->
+ self#man_of_included_module b m.m_name im
+ | Element_class c ->
+ self#man_of_class b c
+ | Element_class_type ct ->
+ self#man_of_class_type b ct
+ | Element_value v ->
+ self#man_of_value b v
+ | Element_exception e ->
+ self#man_of_exception b e
+ | Element_type t ->
+ self#man_of_type b t
+ | Element_module_comment text ->
+ self#man_of_module_comment b text
+ )
+ (Module.module_elements m);
+
+ Buffer.output_buffer chanout b;
+ close_out chanout
+
+ with
+ Sys_error s ->
+ raise (Failure s)
+
+ (** Create the groups of elements to generate pages for. *)
+ method create_groups module_list =
+ let name res_ele =
+ match res_ele with
+ Res_module m -> m.m_name
+ | Res_module_type mt -> mt.mt_name
+ | Res_class c -> c.cl_name
+ | Res_class_type ct -> ct.clt_name
+ | Res_value v -> Name.simple v.val_name
+ | Res_type t -> Name.simple t.ty_name
+ | Res_exception e -> Name.simple e.ex_name
+ | Res_attribute a -> Name.simple a.att_value.val_name
+ | Res_method m -> Name.simple m.met_value.val_name
+ | Res_section _ -> assert false
+ in
+ let all_items_pre = Odoc_info.Search.search_by_name module_list (Str.regexp ".*") in
+ let all_items = List.filter
+ (fun r -> match r with Res_section _ -> false | _ -> true)
+ all_items_pre
+ in
+ let sorted_items = List.sort (fun e1 -> fun e2 -> compare (name e1) (name e2)) all_items in
+ let rec f acc1 acc2 l =
+ match l with
+ [] -> acc2 :: acc1
+ | h :: q ->
+ match acc2 with
+ [] -> f acc1 [h] q
+ | h2 :: q2 ->
+ if (name h) = (name h2) then
+ if List.mem h acc2 then
+ f acc1 acc2 q
+ else
+ f acc1 (acc2 @ [h]) q
+ else
+ f (acc2 :: acc1) [h] q
+ in
+ f [] [] sorted_items
+
+ (** Generate a man page for a group of elements with the same name.
+ A group must not be empty.*)
+ method generate_for_group l =
+ let name =
+ Name.simple
+ (
+ match List.hd l with
+ Res_module m -> m.m_name
+ | Res_module_type mt -> mt.mt_name
+ | Res_class c -> c.cl_name
+ | Res_class_type ct -> ct.clt_name
+ | Res_value v -> v.val_name
+ | Res_type t -> t.ty_name
+ | Res_exception e -> e.ex_name
+ | Res_attribute a -> a.att_value.val_name
+ | Res_method m -> m.met_value.val_name
+ | Res_section (s,_) -> s
+ )
+ in
+ let date = Unix.time () in
+ let file = self#file_name name in
+ try
+ let chanout = self#open_out file in
+ let b = new_buf () in
+ bs b (".TH \""^name^"\" ");
+ bs b !man_section ;
+ bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b "OCamldoc ";
+ bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
+ bs b ".SH NAME\n";
+ bs b (name^" \\- all "^name^" elements\n\n");
+
+ let f ele =
+ match ele with
+ Res_value v ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father v.val_name)^"\n");
+ self#man_of_value b v
+ | Res_type t ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father t.ty_name)^"\n");
+ self#man_of_type b t
+ | Res_exception e ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father e.ex_name)^"\n");
+ self#man_of_exception b e
+ | Res_attribute a ->
+ bs b ("\n.SH "^Odoc_messages.clas^" "^(Name.father a.att_value.val_name)^"\n");
+ self#man_of_attribute b a
+ | Res_method m ->
+ bs b ("\n.SH "^Odoc_messages.clas^" "^(Name.father m.met_value.val_name)^"\n");
+ self#man_of_method b m
+ | Res_class c ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father c.cl_name)^"\n");
+ self#man_of_class b c
+ | Res_class_type ct ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father ct.clt_name)^"\n");
+ self#man_of_class_type b ct
+ | _ ->
+ (* normalement on ne peut pas avoir de module ici. *)
+ ()
+ in
+ List.iter f l;
+ Buffer.output_buffer chanout b;
+ close_out chanout
+ with
+ Sys_error s ->
+ incr Odoc_info.errors ;
+ prerr_endline s
+
+ (** Generate all the man pages from a module list. *)
+ method generate module_list =
+ let sorted_module_list = Sort.list (fun m1 -> fun m2 -> m1.m_name < m2.m_name) module_list in
+ let groups = self#create_groups sorted_module_list in
+ let f group =
+ match group with
+ [] ->
+ ()
+ | [Res_module m] -> self#generate_for_module m
+ | [Res_module_type mt] -> self#generate_for_module_type mt
+ | [Res_class cl] -> self#generate_for_class cl
+ | [Res_class_type ct] -> self#generate_for_class_type ct
+ | l ->
+ if !man_mini then
+ ()
+ else
+ self#generate_for_group l
+ in
+ List.iter f groups
+ end
+end
+
+module type Man_generator = module type of Generator