(* 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))