(* odoc_xref --
* ocamldoc custom html generator with support for library cross-references
*
* Hendrik Tews Copyright (C) 2012
*
* This file is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License in file COPYING in this or one of the parent
* directories for more details.
*
* You should have received a copy of the GNU General Public License
* along with this file. If not, see
* .
*
*
******************************************************************************
* Documentation
*
* This ocamldoc custom generator extends the builtin html generator
* to support cross-references to other libraries. A custom text
* element of the form
*
* {xref library_name kind id}
*
* is replaced with a link to id of kind kind in library library_name.
* For instance:
*
* {xref stdlib val Pervasives.print_endline}
* {xref stdlib type Scanf.Scanning.scanbuf}
*
* The base URL for the library must be specified with the -libxref
* option, see below. The kind should be one of type, exc, val,
* att, meth or module. The id must always be fully qualified, even
* Pervasives must be given.
*
* To link anchor XXXname in an ocamldoc generated file MODNAME.html
* at url URL you have to use
*
* {xref somelib XXX MODNAME.name}
*
* and run odoc_xref with option -libxref somelib URL.
*
* To link the file MODNAME.html, use
*
* {xref somelib mod MODNAME}
*
*
******************************************************************************
* Compile with
*
* ocamlopt.opt -I +ocamldoc -shared -o odoc_xref.cmxs odoc_xref.ml
*
* or
*
* ocamlc -I +ocamldoc -c odoc_xref.ml
*
*
******************************************************************************
* Run as
*
* ocamldoc -g odoc_xref.cmo -libxref stdlib URL -libxref olib URL files...
*
* ocamldoc.opt -g odoc_xref.cmxs -libxref stdlib URL -libxref olib URL ...
*
*
******************************************************************************
*
* $Id: odoc_xref.ml,v 1.2 2012-03-13 15:04:23 tews Exp $
*)
open Odoc_info
let library_urls = Hashtbl.create 53
let _ = Hashtbl.add library_urls "stdlib"
"file:///usr/share/doc/ocaml-doc/ocaml.html/libref"
let option_libname = ref ""
let add_library_url url =
Hashtbl.add library_urls !option_libname url
let _ =
Odoc_args.add_option
("-libxref",
Arg.Tuple [Arg.Set_string option_libname;
Arg.String add_library_url],
" reference library libname at url")
let is_white_space = function
| ' '
| '\t'
| '\n' -> true
| _ -> false
let split_first_word s =
let l = String.length s in
let i = ref 0 in
while !i < l && is_white_space s.[!i] do incr i done;
if !i = l
then ("", "")
else
let j = ref !i in
while !j < l && not (is_white_space s.[!j]) do incr j done;
let k = ref !j in
while !k < l && is_white_space s.[!k] do incr k done;
(String.sub s !i (!j - !i), String.sub s !k (l - !k))
let split_last_dot_word s =
let l = String.length s in
let i = ref (l - 1) in
while !i >= 0 && is_white_space s.[!i] do decr i done;
if !i < 0
then ("", "")
else
let j = try String.rindex_from s !i '.' with Not_found -> -1 in
let first_part = if j < 0 then "" else String.sub s 0 j in
(first_part, String.sub s (j + 1) (l - j - 1))
let kind_hash = Hashtbl.create 11
let _ =
List.iter (fun (a,b) -> Hashtbl.add kind_hash a b)
[("type", "TYPE");
("exc", "EXCEPTION");
("val", "VAL");
("att", "ATT");
("meth", "METHOD");
]
let get_kind k =
try
Hashtbl.find kind_hash k
with
| Not_found -> k
class html_xref =
object (self)
inherit Odoc_html.html as super
method html_of_lib_xref b xref_string =
let (lib, rest) = split_first_word xref_string in
let (kind, name) = split_first_word rest in
let kind = get_kind kind in
let (mod_name, val_name) = split_last_dot_word name in
let file_url =
if mod_name = "" then val_name ^ ".html"
else if kind = "mod" then name ^ ".html"
else if kind = "class" then name ^ "-c.html"
else Printf.sprintf "%s.html#%s%s" mod_name kind val_name
in
Printf.bprintf b "%s"
(Hashtbl.find library_urls lib)
file_url
name
method html_of_custom_text b s t =
match (s, t) with
| ("xref", [Raw xref]) -> self#html_of_lib_xref b xref
| _ -> super#html_of_custom_text b s t
end
let _ = Odoc_args.set_doc_generator
(Some (new html_xref :> Odoc_args.doc_generator))