##
open Printf
open Camlmix
#use "version.ml";;
#load "../utils.cmo";;
#use "topfind";;
#require "caml2html";;
#require "mikmatch_pcre";;
#load "../unmix.cmo";;
#load "../print_ocaml.cmo";;
#directory "..";;
open Utils
open Print_ocaml
##
## include_file "../doctype" ##
<html>
<head>
## title "Camlmix" ##
## include_file "../charset" ##
## include_file "../stylesheet" ##
## include_file "../ocaml-stylesheet" ##
## include_file "../icon" ##
## include_file "../commonlinks" ##
</head>
<body>
## include_file "../hitcounter" ##
## include_file "../start_big_table" ##
## top_menu camlmix ##
<h1>Camlmix ## include_file "../1camel" ##<br>
<span class=title2>OCaml-stuffed templates</span></h1>

<p>[<a href="#intro">intro</a>] 
[<a href="#example">example</a>] 
[<a href="#advanced">advanced</a>] 
[<a href="#download">download</a>]

<h2 id=intro>Introduction</h2>
<p>
Camlmix is a generic preprocessor which converts text with embedded 
<a href="http://caml.inria.fr">OCaml</a> into an 
<a href="http://caml.inria.fr">OCaml</a> program with embedded text.
It produces text documents from one or several templates.
Camlmix is <span style="text-decoration: underline"><b>not</b> a 
<a href="/extend-ocaml-syntax.html">Camlp4 syntax extension</a></span>.

<br>
The basic syntaxic rules are:
<ul>
<li> ## camlmixcode 
"Some text ### (* Some OCaml statements *) ... ### More text ..." ##
<li> ## camlmixcode 
"Some text ###= (* Some OCaml string expression *) ... ### More text ..." ##
<li> ## camlmixcode 
"This prints actually 2 # symbols: ####" ##
</ul>

<p>
Camlmix does not provide a library for text-processing, but 
all existing libraries and syntax extensions can be used, such
as 
<a href="http://www.eleves.ens.fr/home/frisch/soft.html#HereDoc">HereDoc</a>, 
<a href="/micmatch.html">Micmatch</a> or 
<a href="http://www.ocaml-programming.de/packages/documentation/xstrp4/">xstrp4</a>. 
You can also find some examples of code in the 
<a href="/toolbox.html">Camlmix Toolbox</a> if you are not familiar with
I/O in OCaml.


<h2 id=example>Example</h2>
<p>
The file <code>example.mlx</code> contains the following:

## print_with camlmixpre ##
###
open Printf
let color col s =
  sprintf "<span style=\"color:%s\">%s</span>" col s
###
This is ###= color "red" "red text" ###,
but that is a ###= color "blue" "blue one" ###.
## () ##

<p>
The command
<pre>
camlmix example.mlx -o example.html
</pre>
<p>
will produce the following <code>example.html</code> file:
## print_with htmlpre ##
This is <span style="color:red">red text</span>,
but that is a <span style="color:blue">blue one</span>.
## () ##
<p>
This piece of HTML will be displayed as:
This is <span style="color:red">red text</span>,
but that is a <span style="color:blue">blue one</span>.

<p>
You may now have a look at the 
<a href="index-src.html">Camlmix/HTML colorized source of this web page</a>,
which was itself made using a Camlmix template.

<p>
Camlmix also allows you to convert a template into a regular OCaml source file
which is equipped with a single function named <code>render</code>:
<pre>
camlmix example.mlx -c -fun -co example.ml 
</pre>
<p>
The signature of the <code>render</code> function would be:
## print_with ocamlpre ##
val render : ?print:(string -> unit) -> 'a -> unit
## () ##
<p>
where the <code>'a</code> parameter stands for the type of the argument which
is passed to the rendering function. It is available in the template
under the name <code>param</code>, and its usage determines its
actual type. The <code>print</code> function is the one which is used
to handle text. By default, it prints the text onto stdout, but
it can be replaced by any other function, as long as the user-defined
code of the template uses it.
<p>
The result <code>example.ml</code> is a regular OCaml file which would
be integrated into a regular OCaml program.

<p>
The full set of features and options is described in 
<a href="camlmix-help.txt">the output of <code>camlmix -help</code></a>


<h2 id=advanced>Advanced features</h2>

<h3>Directives</h3>
<p>
A block of code that starts with an <code>@</code> character will not
be handled as OCaml code but as a sequence of directives for
Camlmix.
<p>
There is one useful directive: <code>include</code>.
This mechanism allows the insertion of templates and subtemplates that
inherit the whole OCaml environment, and possibly modify it. 
These templates are not only
parametrized by string variables but also by any type of OCaml data,
including functions, and even by types and modules!
<p>
The <code>include</code> directive reads a file
(e.g. <code>included.mlx</code>)
in the Camlmix syntax exactly as if its
contents was inserted in the current file (e.g. <code>main.mlx</code>):
<p>
<code>main.mlx:</code>
## print_with camlmixpre ##
###
let print_counter = (* increments the counter and displays its new value *)
  let n = ref 0 in
  fun () -> incr n; print_int !n
###
Should be 1: ### print_counter () ###
Should be 2: ### @include "included.mlx" ###
Should be 3: ### print_counter () ###
## () ##
<p>
<code>included.mlx:</code>
## print_with camlmixpre ##
### print_counter () ###
## () ## 
<p>
<code>camlmix main.mlx</code> returns the following:
<pre>

Should be 1: 1
Should be 2: 2

Should be 3: 3
</pre>

<p>
This is not totally satisfying because two undesired empty lines were inserted.
In Camlmix 1.2, you can skip whitespace until the end of the line and the
newline character by using
<code>.###</code> instead of <code>###</code> as the closing delimiter.
This results in the following program:
## print_with camlmixpre ##
###
let print_counter = (* increments the counter and displays its new value *)
  let n = ref 0 in
  fun () -> incr n; print_int !n
.###
Should be 1: ### print_counter () ###
Should be 2: ### @include "included.mlx" .###
Should be 3: ### print_counter () ###
## () ##
<p>
which now produces:
<pre>
Should be 1: 1
Should be 2: 2
Should be 3: 3
</pre>


<p>
A <code>skip</code> directive also exists: it ignores the next block of text.
It is not much useful since the <code>.###</code> delimiter was introduced in
Camlmix 1.2.
It was useful when a block of OCaml had to follow a block of directives,
without printing anything between them:
## print_with camlmixpre ##
### @include "somefile.mlx"; skip (* skips the newline character(s) -> *) ###
### print_something () ###
## () ##


<h3>Runtime hooks</h3>
<p>
The OCaml program that is generated from the Camlmix files first defines
a module called Camlmix. This module contains several variables that are 
updated automatically and possibly explicitely by the user.
Its signature is:

##
let comment s = printf "<p class=comment>\n%s" s
##

## print_with ocamlpre ##
module Camlmix :
  sig
    val source : string ref
    val line : int ref
    val char : int ref  
## print_with comment ##
<code>source</code>, <code>line</code> and <code>char</code> 
refer to the location of the first 
character of the current block in its source file
(source file, line number starting from 1, position in the line
starting from 1). They are updated automatically at the beginning
of each code block or text block.

## print_with ocamlpre ##
    val printer : (string -> unit) ref 
## print_with comment ##
the function that prints the text blocks

## print_with ocamlpre ##
    val print_with : (string -> unit) -> unit
## print_with comment ##
<code>print_with f</code> prints the next block of text using 
<code>f</code> instead
of the current printer.
Its behavior is undefined if it is called several 
times in the same OCaml block.

## print_with ocamlpre ##
    val print_if : bool -> unit
## print_with comment ##
<code>print_if cond</code> prints the next block of text only 
if <code>cond</code> is true.
It uses <code>print_with</code>.

## print_with ocamlpre ##
  end
## () ##

<h3>Command line options</h3>

## Sys.command "camlmix -help > camlmix-help.txt 2>&1" ##
<p>
The command line options are returned by 
<a href="camlmix-help.txt"><code>camlmix -help</code></a>.



<h2 id=download>Download</h2>

<p>
Camlmix can be installed automatically from 
<a href="http://www.ocaml-programming.de/godi/">GODI</a>.
<p>
You can also use the traditional way. 
Just download the source code:
## download (sprintf "camlmix-%s.tar.bz2" version) ##
or ## download (sprintf "camlmix-%s.tar.gz" version) ##. 
It should work on any platform where
OCaml is available.

<p>
I would be happy if you send me any positive or negative feedback.

<p>
Thanks to Nadji Gauthier, Jean-Baptiste Rouquier, Arthur E., Janne Hellsten
and those that I forget, for their contributions.

## camlmix_footer () ##
## include_file "../end_big_table" ##
</body>
</html>