Plugins are written in OCaml. The compiled OCaml code is then loaded in Stog with the --plugin or --package options of stog (see Running Stog).

A plugin can register new base rules and new modules.

Registering base rules

A plugin can add rewrite rules to the rules of function base of module Base.

Here is an example:

(** Stog plugin example. *)

let fun_list stog env ?loc args subs =
  (* get the optional sep attribute ... *)
  let sep = Xtmpl_rewrite.opt_att args ("", "sep") in
  (* reverse the separator, for final list will be reversed *)
  let sep = List.rev sep in
  (* then insert the separator between all children of the node *)
  let rec iter acc = function
    [] -> List.rev acc
  | h :: q ->
      let acc =
        match acc with
          [] -> [h]
        | _ -> h :: sep @ acc
      in
      iter acc q
  in
  (* and finally return the stog structure untouched and the list of xml trees *)
  (stog, iter [] subs)
;;

(* register the new function, associated to tag "list".
  Before stog 0.3, this function was called [Stog_plug.register_fun]. *)
let () = Stog_plug.register_html_base_rule ("", "list") fun_list;;


Have a look at the Stog library reference documentation.

Registering modules

A plugin can also register a complete module, with named functions associated to levels. These levels can also be specified in the .stog/config file as explained here.

An example of such a plugin is stog_multi_doc.

Compilation

The plugin is simply compiled with

ocamlfind ocamlopt -package stog -rectypes -shared -o plugin_example.cmxs plugin_example.ml

for native code or

ocamlfind ocamlc -package stog -rectypes -c plugin_example.ml

for bytecode.

Using

The plugin is used by specifying it on the stog command line:

stog --plugin plugin_example.cmxs ...

or, if the plugin is installed with ocamlfind:

stog --package plugin_example ...

With our plugin example registering just a base rule, we can use the new "list":

<list sep="&lt;b&gt; -- &lt;/b&gt;"><span>first thing</span>second thing<div>something else</div></list>

This will be evaluated (reduced) to

<span>first thing</span><b> -- </b>second thing<b> -- </b><div>something else</div>

For information you can see the source code of the page.

<page title="Developing plugins"
navbar-doc="active"
>
<p>
Plugins are written in OCaml. The compiled OCaml code is then
loaded in Stog with the <icode>--plugin</icode> or <icode>--package</icode>
options of <icode>stog</icode> (see <page href="running"/>).
</p>
<p>
A plugin can register new base rules and new modules.
</p>
<prepare-toc>
<toc/>
<section id="baserules" title="Registering base rules">
<p>
A plugin can add rewrite rules to the rules of function
<doc href="module_base#base"/> of module <doc href="module_base">Base</doc>.
</p>
<p>
Here is an example:
</p>
<hcode lang="ocaml" defer_="1">
<include file="../src/plugins/plugin_example.ml" raw="true"/>
</hcode>
<p>
Have a look at the <doc href="/ref-doc/index"/>.
</p>
</section>

<section id="modules" title="Registering modules">
<p>
A plugin can also register a complete module, with named functions
associated to levels. These levels can also be specified in
the <code>.stog/config</code> file as explained
<doc href="funs#config_funs">here</doc>.
</p>
<p>An example of such a plugin is
<ext-a href="https://github.com/zoggy/stog/blob/master/plugins/stog_multi_doc.ml">stog_multi_doc</ext-a>.
</p>
</section>

<section id="compiling" title="Compilation">
<div id="codecompilation">
<p>
The plugin is simply compiled with
</p>
<command-line>ocamlfind ocamlopt -package stog -rectypes -shared -o plugin_example.cmxs plugin_example.ml</command-line>
<p>
for native code or
</p>
<command-line>ocamlfind ocamlc -package stog -rectypes -c plugin_example.ml</command-line>
<p>for bytecode.</p>
</div>
</section>

<section id="using" title="Using">
<div id="usingcode">
<p>
The plugin is used by specifying it on the <icode>stog</icode> command line:
</p>
<command-line>stog --plugin plugin_example.cmxs ...</command-line>
<p>or, if the plugin is installed with ocamlfind:</p>
<command-line>stog --package plugin_example ...</command-line>
</div>
<p>
With our plugin example registering just a base rule, we can use the new "list":
</p>
<hcode lang="xml"><![CDATA[
<list sep="&lt;b&gt; -- &lt;/b&gt;"><span>first thing</span>second thing<div>something else</div></list>]]>
</hcode>
<p>
This will be evaluated (reduced) to
</p>
<hcode defer_="1" lang="xml">
<list sep="&lt;b&gt; -- &lt;/b&gt;"><span>first thing</span>second thing<div>something else</div></list>
</hcode>
</section>

<!--
<section id="cache" title="Keeping the cache system in the loop">
<p>
The cache system (see <doc href="running"/>) must be aware
of dependencies of each document on other documents and files.
</p>
<p>
If a new rule defined by a plugin uses a file or implies a dependency
from a document to another, this rule must declare this dependency
using the <doc href="Stog_plug#VALadd_dep"><code>Stog_plug.add_dep</code></doc> function:
</p>
<ocaml>Stog_plug.add_dep : Stog_types.doc -> dependency -> unit</ocaml>
<p>
If a plugin computes information which could be cached, it can declare a
new cache for this informations, using the
<doc href="Stog_plug#VALregister_cache"><code>Stog_plug.register_cache</code></doc> function:
</p>
<ocaml>val register_cache : (module Stog_cache.Cache) -> unit</ocaml>
<p>
The Cache module to provide is very simple; have a look at the
<doc href="Stog_cache.Cache"><code>Stog_cache.Cache</code></doc>module type.
</p>
</section>
-->
</prepare-toc>
</page>