I've attached a patch that modifies how the latex version of the api docs is
generated.  I've uploaded the api document as it's generated with this patch
applied to [1].  A short description of the changes:

- use a latex style for the class descriptions
- use a proper pretty printer for the output

diffstat says:

 b/ocaml/idl/xenclass.sty       |  127 ++++++++++++++++++++++++++
 ocaml/idl/OMakefile            |    4 
 ocaml/idl/latex_backend.ml     |  193 +++++++++++++++++++----------------------
 ocaml/idl/xenenterpriseapi.tex |    1 
 4 files changed, 222 insertions(+), 103 deletions(-)

The changes make use of prettier[2].

There are further improvements possible, but first I'd like to get some
feedback on whether this is considered an improvement or not. :-)

Cheers,
M

[1] http://dl.dropbox.com/u/187401/xenenterpriseapi-prettier.pdf
[2] https://github.com/magthe/prettier

-- 
Magnus Therning                            [email protected]
XenServer Security Lead

There does not now, nor will there ever, exist a programming language
in which it is the least bit hard to write bad programs.
     -- Flon's Axiom

Most software today is very much like an Egyptian pyramid with
millions of bricks piled on top of each other, with no structural
integrity, but just done by brute force and thousands of slaves.
     -- Alan Kay
Prettier latex output.

diff -r dd7e1f8d25ff ocaml/idl/OMakefile
--- a/ocaml/idl/OMakefile
+++ b/ocaml/idl/OMakefile
@@ -6,7 +6,7 @@
 PSTOPDF = $(shell bash -c "which pstopdf || which ps2pdf || which ps2pdf14 || 
echo false")
 
 OCAMLINCLUDES  = ocaml_backend ../database
-OCAMLPACKS     = xml-light2 sexpr log
+OCAMLPACKS     = xml-light2 sexpr log prettier
 
 CAMLP4_FILES = datamodel_types
 
@@ -29,7 +29,7 @@
 SHARED_EPS = vm_lifecycle.eps
 OPEN_TEX = xenapi.tex xenapi-coversheet.tex xenapi-datamodel.tex
 OPEN_EPS = xenapi-datamodel-graph.eps xen.eps
-CLOSED_TEX = xenenterpriseapi.tex xenenterpriseapi-coversheet.tex 
xenenterpriseapi-datamodel.tex
+CLOSED_TEX = xenenterpriseapi.tex xenenterpriseapi-coversheet.tex 
xenenterpriseapi-datamodel.tex xenclass.sty
 CLOSED_EPS = xenenterpriseapi-datamodel-graph.eps citrix_logo_black.eps
 
 DOCDIR = $(ROOT)/ocaml/autogen/doc
diff -r dd7e1f8d25ff ocaml/idl/latex_backend.ml
--- a/ocaml/idl/latex_backend.ml
+++ b/ocaml/idl/latex_backend.ml
@@ -19,6 +19,7 @@
 open Dm_api
 
 open Stringext
+open Prettier
 
 let rec formatted_wrap formatter s = 
   let split_in_2 c s =
@@ -111,6 +112,20 @@
   | Ref obj -> (escape obj)^" ref"
   | Record obj -> escape obj ^ " record"
 
+let rec ty_2_doc = function
+       | String -> text "string"
+       | Int -> text "int"
+       | Float -> text "float"
+       | Bool -> text "bool"
+       | DateTime -> text "datetime"
+       | Enum (n, _) -> text (escape n)
+       | Set i -> if (is_prim_type i)
+               then (ty_2_doc i) <|> text " Set"
+               else text "(" <|> (ty_2_doc i) <|> text ") Set"
+       | Map (a, b) -> text "(" <|> (ty_2_doc a) <|> text " $\\rightarrow$ " 
<|> (ty_2_doc b) <|> text ") Map"
+       | Ref o -> text (escape o) <|> text " ref"
+       | Record o -> text (escape o) <|> text " record"
+
 let of_ty_opt = function
     None -> "void" | Some(ty, _) -> of_ty ty
 
@@ -189,87 +204,6 @@
      escape p.param_name; "&";
      escape p.param_doc; "\\\\ \\hline"; "\n"]
 
-let mk_latex_error err =
-  sprintf "{\\tt %s}" (escape err.err_name)
-
-let space = "\\vspace{0.3cm}"
-  
-(* Make a latex section for an API-specified message *)
-let latex_section_of_message closed section_prefix x =
-  String.concat "\n"
-    ([
-       String.concat "" ["\\"^section_prefix^"subsection{RPC name:~"; escape 
x.msg_name; "}\n"];
-       "{\\bf Overview:} ";
-       if x.msg_release.internal_deprecated_since <> None
-       then "{\\bf This message is deprecated}"
-       else "";
-       wrap (full_stop (escape x.msg_doc));
-       " \\noindent {\\bf Signature:} ";
-
-       let section_contents = 
-          (String.concat " "
-             [if is_prim_opt_type x.msg_result then of_ty_opt_verbatim 
x.msg_result
-             else "("^(of_ty_opt_verbatim x.msg_result)^")";
-             x.msg_name;
-             String.concat ""
-               [
-                 "(";   
-                 String.concat ", "
-                   ((if x.msg_session then ["session_id s"] else []) @
-                      (List.map (fun p -> of_ty_verbatim p.param_type ^ " " ^ 
p.param_name) x.msg_params));
-                 ")"
-               ]
-             ]) in
-       String.concat ""
-        (if closed then
-           ["\n\n{\\parbox{ \\columnwidth }{\\tt ~~~~~~~";
-            escape section_contents;
-           "}}\n\n"]
-         else
-           ["\\begin{verbatim} ";
-            section_contents;
-           "\\end{verbatim}\n\n"])
-     ] @
-       
-       (if x.msg_params=[] then []
-       else
-           [
-             "\\noindent{\\bf Arguments:}\n\n ";
-             space;
-             
-             "\\begin{tabular}{|c|c|p{7cm}|}\n \\hline";
-             "{\\bf type} & {\\bf name} & {\\bf description} \\\\ \\hline";
-             String.concat "\n" ((List.map mk_latex_param) x.msg_params);
-             "\\end{tabular}\n";
-           ]) @
-
-       [
-        space;
-        "\n \\noindent {\\bf Return Type:} ";      
-        "{\\tt ";
-        of_ty_opt x.msg_result; "}\n\n";
-        escape (desc_of_ty_opt x.msg_result);
-         space
-       ] @
-
-       (if x.msg_errors=[] then [space; space]
-       else
-           [
-              "";
-              wrap (sprintf "\\noindent{\\bf Possible Error Codes:} %s"
-                     (String.concat ", " ((List.map mk_latex_error)
-                                             x.msg_errors)));
-              "\\vspace{0.6cm}"
-           ]))
-    
-(* Make a load of sections for a list of functions, fb.
-   if section_prefix="" then we make subsections for each function.
-   if section_prefix="sub" then we make subsubsections for each function. *)
-
-let latex_of_funblock closed section_prefix fb =
-  String.concat "\n" (List.map (latex_section_of_message closed 
section_prefix) fb)
-
-
 (**
  * The header for the table containing the fields of the given class.  This
  * table has an additional column if closed is true.
@@ -315,24 +249,6 @@
        else
            (class_header x closed) @ field_tex @ class_footer)  
     
-let of_obj x closed =
-  [ 
-    "\\newpage";
-    "\\section{Class: "^(escape x.name)^"}" ]
-  @ (field_table_of_obj false x closed)
-  @
-      [
-       "\\subsection{RPCs associated with class: "^(escape x.name)^"}"
-      ]
-    @
-      (if x.messages=[] then
-          ["\n\n";
-           "{\\bf Class "^(escape x.name)^" has no additional RPCs associated 
with it.}"]
-       else
-          [
-            latex_of_funblock closed "sub" x.messages
-          ])
-
 let error_signature name params =
   if params = [] then
 "
@@ -440,6 +356,81 @@
 
 let first_sentence s =
   List.hd (String.split '.' s)
+
+let build_class_section system =
+       let build_fields c =
+               match c.contents with
+                       | [] -> line <|> text "\\noxapifields"
+                       | _ ->
+                               let build_one i = match i with
+                                       | Namespace _ -> nil (* ignore 
namespaces *)
+                                       | Field f ->
+                                               let field_qual = match 
f.qualifier with
+                                                       | RW -> "\\RW"
+                                                       | DynamicRO -> "\\ROrun"
+                                                       | StaticRO -> "\\ROins"
+                                               in
+                                               text (sprintf 
"\\xapifield{%s}{%s}{" field_qual (escape f.field_name)) <|>
+                                               ty_2_doc f.ty <|>
+                                               text (sprintf "}{%s}" (escape 
f.field_description))
+                               in
+                               let all_fields = List.fold_right
+                                               (fun d r -> line <|> d <|> r)
+                                               (List.map build_one c.contents)
+                                               nil
+                               in
+                               line <|> text "\\begin{xapiclassfields}" <|>
+                               nest 4 all_fields <|>
+                               line <|> text "\\end{xapiclassfields}"
+       in
+       let build_methods c =
+               let build_one m =
+                       text (sprintf "%% method: %s" (escape m.msg_name));
+                       let b = text (sprintf "\\begin{xapimethod}{%s}{%s}" 
(escape m.msg_name) (escape m.msg_doc)) in
+                       let e = text "\\end{xapimethod}" in
+                       let r =
+                               let ret_ty, ret_doc = match m.msg_result with
+                                       | None -> text "void", ""
+                                       | Some (t, d) -> ty_2_doc t, d
+                               in
+                               text "\\xapimethret{" <|> ret_ty <|> text 
(sprintf "}{%s}" (escape ret_doc))
+                       in
+                       let s = if m.msg_session
+                               then line <|> text 
"\\xapimethargig{session\\_id}{s}"
+                               else nil
+                       in
+                       let arg p = text "\\xapimetharg{" <|> ty_2_doc 
p.param_type <|> text (sprintf "}{%s}{%s}" (escape p.param_name) (escape 
p.param_doc)) in
+                       let all_args = List.fold_right
+                                       (fun d r -> line <|> d <|> r)
+                                       (List.map arg m.msg_params)
+                                       nil
+                       in
+                       let all_errs = match m.msg_errors with
+                               | [] -> nil
+                               | _ -> List.fold_right
+                                       (fun e r -> line <|> text (sprintf 
"\\xapimetherr{%s}" (escape e.err_name)) <|> r)
+                                       m.msg_errors
+                                       nil
+                       in
+                       b <|> nest 4 (line <|> r <|> s <|> all_args <|> 
all_errs) <|> line <|> e
+               in
+               let all_methods = List.fold_right
+                               (fun d r -> line <|> d <|> r)
+                               (List.map build_one c.messages)
+                               nil
+               in
+               line <|> text "\\begin{xapiclassmethods}" <|>
+               nest 4 all_methods <|>
+               line <|> text "\\end{xapiclassmethods}"
+       in
+       let build_class c =
+               line <|> text (sprintf "\\begin{xapiclass}{%s}{%s}" (escape 
c.name) (escape c.description)) <|>
+               nest 4 (build_fields c) <|>
+               nest 4 (build_methods c) <|>
+               line <|> text "\\end{xapiclass}"
+       in
+       let all_parts = List.map build_class system in
+       List.fold_right (fun d r -> line <|> d <|> r) all_parts nil
 
 let all api closed =
   (* Remove private messages that are only used internally (e.g. 
get_record_internal) *)
@@ -554,8 +545,8 @@
                      print_string vgap) system;
         error_section()
       end;
-    List.iter (fun x -> List.iter print_endline (of_obj x closed);
-                 print_string vgap) system;
+       (* List.iter (fun x -> List.iter print_endline (of_obj x closed); 
print_string vgap) system; *)
+       print_endline (layout (build_class_section system));
     if not closed then
       begin
         error_section()
diff -r dd7e1f8d25ff ocaml/idl/xenclass.sty
--- /dev/null
+++ b/ocaml/idl/xenclass.sty
@@ -0,0 +1,127 @@
+%NAME: xenclass.sty
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{xenclass}[2010/02/19]
+\RequirePackage{ifthen}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%  Xapi Class Environment %%%%%%%%%%%%%%%%%%%%%%%%%
+
+\newcommand{\xapicl...@name}{}
+\newcommand{\xapicl...@description}{}
+\newenvironment{xapiclass}[2]{%
+    \renewcommand{\xapicl...@name}{#1}%
+    \renewcommand{\xapicl...@description}{#2}%
+    \newpage \section{Class: \xapicl...@name}%
+    } {}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%  Xapi Class Field Environment 
%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\newcommand{\ROrun}{\ensuremath{\mathit{RO}_\mathit{run}}}
+\newcommand{\ROins}{\ensuremath{\mathit{RO}_\mathit{ins}}}
+\newcommand{\RW}{\ensuremath{\mathit{RW}}}
+
+\newcommand{\xapifield}[4]{ #1 & { \tt #2 } & #3 & #4 \\ }
+\newcommand{\noxapifields}{%
+    \subsection{Fields for class: \xapicl...@name }%
+    \begin{longtable}{|lllp{0.38\textwidth}|}%
+    \hline%
+    \multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf \xapicl...@name } \\%
+    \multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em 
\xapicl...@description }} \\%
+    \hline %
+    \multicolumn{4}{|c|}{ \bf Class \xapicl...@name~has no fields. } \\%
+    \hline \end{longtable}%
+    }
+
+\newenvironment{xapiclassfields}{%
+    \subsection{Fields for class: \xapicl...@name }%
+    \begin{longtable}{|lllp{0.38\textwidth}|}%
+    \hline%
+    \multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf \xapicl...@name } \\%
+    \multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em 
\xapicl...@description }} \\%
+    \hline%
+    Quals & Field & Type & Description \\%
+    \hline%
+    }{ \hline \end{longtable} }
+
+\newenvironment{xapiclassmethods}{%
+    \subsection{RPCs associated with class: \xapicl...@name}%
+    }{}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%  Xapi Class Method Environment 
%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\newcommand{\xapimet...@name}{}
+\newcommand{\xapimet...@returntype}{}
+\newcommand{\xapimet...@returndesc}{}
+\newcommand{\xapimethret}[2]{%
+    \renewcommand{\xapimet...@returntype}{#1} 
\renewcommand{\xapimet...@returndesc}{#2}%
+    }
+\newtoks{\xapimet...@argtoks}
+\newboolean{xapimet...@args}
+\newcommand{\xapimet...@comma}{}
+\newcommand{\xapimetharg}[3]{%
+    \setboolean{xapimet...@args}{true}%
+    \xapimet...@argtoks=\expandafter{\the\xapimethod@argtoks 
\xapimet...@argshow{#1}{#2}{#3}}%
+    }
+\newcommand{\xapimethargig}[2]{%
+    \xapimet...@argtoks=\expandafter{\the\xapimethod@argtoks 
\xapimet...@argshowig{#1}{#2}{}}%
+    }
+\newtoks{\xapimet...@errortoks}
+\newboolean{xapimet...@errors}
+\newcommand{\xapimetherr}[1]{%
+    \setboolean{xapimet...@errors}{true}%
+    \xapimet...@errortoks=\expandafter{\the\xapimethod@errortoks 
\xapimet...@errorshow{#1}}%
+    }
+\newenvironment{xapimethod}[2]{%
+    \renewcommand{\xapimet...@name}{#1}%
+    \xapimet...@argtoks={}%
+    \setboolean{xapimet...@args}{false}%
+    \xapimet...@errortoks={}%
+    \setboolean{xapimet...@errors}{false}%
+    \subsubsection{RPC name: #1}%
+    {\bf Overview:} \linebreak #2%
+    }{%
+    \let\xapimet...@comma=\empty%
+    \let\xapimet...@argshow=\xapimethod@argshowcommaseparated%
+    \let\xapimet...@argshowig=\xapimethod@argshowcommaseparated%
+    %
+    \par\vspace{3mm}\noindent \textbf{Signature:} \linebreak%
+    \texttt{(\xapimet...@returntype) \xapimet...@name~(}%
+    \the\xapimet...@argtoks%
+    \texttt{)}%
+    %
+    \ifthenelse{\boolean{xapimet...@args}}{%
+        \par\vspace{3mm}\noindent \textbf{Arguments:} \linebreak%
+        \let\xapimet...@argshow=\xapimethod@argshowtabular%
+        \let\xapimet...@argshowig=\xapimethod@argshowtabularig%
+        \begin{tabular}{|c|c|p{7cm}|}%
+        \hline%
+        {\bf type} & {\bf name} & {\bf description} \\ \hline%
+        \the\xapimet...@argtoks%
+        \end{tabular}%
+        }{}
+    %
+    \par\vspace{3mm}\noindent\textbf{Return Type:} 
\texttt{\xapimet...@returntype}\par\xapimethod@returndesc%
+    %
+    \ifthenelse{\boolean{xapimet...@errors}}{%
+        \let\xapimet...@comma=\empty%
+        \let\xapimet...@errorshow=\xapimethod@errorshowcommaseparated%
+        \par\noindent\textbf{Possible Error Codes:} %
+        \the\xapimet...@errortoks%
+        }{}%
+    }
+
+\newcommand{\xapimet...@argshowcommaseparated}[3]{%
+    \xapimet...@comma%
+    \texttt{#1 #2}%
+    \def\xapimet...@comma{, }%
+    }
+
+\newcommand{\xapimet...@argshowtabular}[3]{%
+    \texttt{#1} & #2 & #3 \\ \hline%
+    }
+\newcommand{\xapimet...@argshowtabularig}[3]{}
+
+\newcommand{\xapimet...@errorshowcommaseparated}[1]{%
+    \texttt{\xapimet...@comma #1}%
+    \def\xapimet...@comma{, }%
+    }
diff -r dd7e1f8d25ff ocaml/idl/xenenterpriseapi.tex
--- a/ocaml/idl/xenenterpriseapi.tex
+++ b/ocaml/idl/xenenterpriseapi.tex
@@ -12,6 +12,7 @@
 \usepackage{graphics}
 \usepackage{longtable}
 \usepackage{fancyhdr}
+\usepackage{xenclass}
 \pagestyle{fancy}
 
 \setlength\topskip{0cm}
_______________________________________________
xen-api mailing list
[email protected]
http://lists.xensource.com/mailman/listinfo/xen-api

Reply via email to