The Ocgi library
The cgi_template toolPrinciplecgi_template is a tool to generate OCaml code from templates. Basically, it takes a template file foo.html and ouputs foo.ml and foo.mli. The generated module has the following interface:val string : ... -> unit -> string val print : ... -> Format.formatter -> stringwhere ... are parameters of the template. ParametersThe parameters of the template are indicated in the template by a specific syntax. Here is an example of template, in file foo.html:
<h1><{title}></h1>
<div class="date"><{?date}></div>
<{text}>
Then, the command
cgi_template foo.htmlcreates the Foo module with the following interface (foo.mli): val string : title:string -> ?date:string -> text:string -> unit -> string val print : title:string -> ?date:string -> text:string -> Format.formatter -> unitParameters of a template are indicated in the template between <{ and }>. The parameter name must be
a valid OCaml short identifier. A question mark indicates that the parameter
is optional and its default value is the empty string.
Inserting OCaml codeOCaml code can be inserted in templates, between<[ and
]>. This code must be a valid OCaml expression of type
string. Example:
Current time is <[ let t = Unix.localtime (Unix.time ()) in Printf.sprintf "%02d:%02d" t.Unix.tm_hour t.Unix.tm_min ]>. Describing form fieldsIf at least one form field is described in the template (see below), then the interface of the generated module will include, in addition to thestring and print functions:
type t =
{
... (* one field per form field described in the template *)
}
val read : Ocgi.Env.cgi_env -> t
val reform : ... -> Ocgi.Env.cgi_env -> string
The read function takes a cgi environment and returns
a record of type t. If errors occur while analyzing
the cgi arguments to fill the record, the function raises
the Ocgi.Args.Read_errors exception.The reform function acts like the string
function, but can use the given cgi environment to pre-fill
form fields. This function is useful to display the form when
an error occured, for example a mandatory field not filled, with
the fields containing the values the user typed in.
Form fields are described with the following syntax: <!--input kind="entry" name="myfield" -->This describes a form field named "myfield", whose value must be given when instanciating the template (since we have "myfield" and not "?myfield"). The "kind" attribute determines the "type" attribute in the final HTML code. Here are the possible values for the "kind" attribute:
string, print
and reform functions for each form field described in the
template.
Other attributes can be specified in the form field description. type="int"can be used to indicate that the record field corresponding to this form field should be of type int or int option depending of the "mandatory" attribute (see below). trans="int_of_string"can be used to specify OCaml returning the correct type from a string. By default, the type of record field is string and the translation function is the identity. mandatory="\"Missing parameter myfield!\""can be used to indicate that the parameter is mandatory, and that a Ocgi.Args.Missing_argument exception will be raised
when trying to get this form field value in the read function (the
exception will then be embedded in the Ocgi.Args.Read_errors
exception). The value of the "mandatory" attribute is the error message
in parameter of the Ocgi.Args.Missing_argument exception.
When the "mandatory" attribute is not specified, the record field
corresponding to the form field is an option type.
Other attributes specified in the form field description are kept in the final HTML when instanciating the template. For the "mandatory" and "trans" attributes, another syntax can be used which does not need quotes to be escaped: mandatory=[["Missing parameter myfield!"]] Headers and footersOCaml code can be specified to be inserted as header or footer of the generated .ml and .mli files.To specify headers, use the following syntax at the beginning of the template: <!--mlheader=[[ open Ocgi ]]--> <!--mliheader=[[ open Ocgi ]]-->For footer, use the following syntax at the end of the template: <!--mlfooter=[[ let f x = .... ]]--> <!--mlifooter=[[ val f : .... ]]--> |