Skip to content

Commit

Permalink
TMP: Add an MDX manual using odoc .mld files
Browse files Browse the repository at this point in the history
Signed-off-by: Nathan Rebours <[email protected]>
  • Loading branch information
NathanReb committed Jul 21, 2022
1 parent 9150bcd commit 52c4e7d
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 0 deletions.
2 changes: 2 additions & 0 deletions doc/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(documentation
(package mdx))
2 changes: 2 additions & 0 deletions doc/dune_stanza.mld
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{0 Dune Stanza}

111 changes: 111 additions & 0 deletions doc/index.mld
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{0 MDX Manual}

Welcome to the MDX Manual!

MDX is a tool to help developpers and authors keep their documentation
up-to-date.
It ensures that the code examples you write compile and behave the way you
expect them to by actually running them.

It is for example used to verify all of
{{:https://dev.realworldocaml.org/}Realworlocaml}'s examples!

MDX is released on opam. You can install it in your switch by running:
{@sh[
opam install mdx
]}

{1 Basic Usage}

You can use MDX with your Markdown or [.mli] documentation, where it will ensure
the correctness of code respectively written in multi-line code blocks and
verbatim code blocks.

To enable MDX, you need to add [(mdx)] stanzas to the right dune files. Before
that you will need to enable MDX for your project by adding the following to
your [dune-project]:

{@dune[
(using mdx 0.2)
]}

You can then add the following in the relevant dune file:
{@dune[
(mdx)
]}
That will enable MDX on all markdown files in the folder.
The MDX stanza can be further configured. If you want to know more about it,
visit the {{!page-mdx_dune_stanza}corresponding section of this manual} or the
one in
{{:https://dune.readthedocs.io/en/latest/dune-files.html#mdx-since-2-4}dune's manual}.

MDX supports various type of code blocks but the most common are OCaml toplevel
blocks so we'll look at one of those for our example. In a markdown file, you
would write something along those lines:

{@markdown[
Let's look at how good OCaml is with integers and strings:
```ocaml
# 1 + 2;;
- : int = 2
# "a" ^ "bc";;
- : string = "ab"
```
]}

The content of the toplevel blocks looks just like an interactive toplevel
session. Phrases, i.e. the toplevel "input", start with a [#] and end with [;;].
Each of them is followed by the toplevel evaluation, or "output" which you
probably are already familiar with.

Now you probably have noticed that [1 + 2] is not equal to [3] nor ["a" ^ "bc"]
to ["ab"]. Somebody must have updated the phrases but they then forgot to update
the evaluation.

That's exactly what MDX is here for!

If MDX were enabled for this file and they ran [dune runtest], here's what they
would have gotten:

{@sh[
$ dune runtest
File "README.md", line 1, characters 0-0:
git (internal) (exit 1)
(cd _build/default && /usr/bin/git --no-pager diff --no-index --color=always -u README.md .mdx/README.md.corrected)
diff --git a/README.md b/.mdx/README.md.corrected
index 181b86f..458ecec 100644
--- a/README.md
+++ b/.mdx/README.md.corrected
@@ -1,13 +1,13 @@
Let's look at how good OCaml is with integers and strings:
```ocaml
# 1 + 2;;
-- : int = 2
+- : int = 3
# "a" ^ "bc";;
-- : string = "ab"
+- : string = "abc"
```
]}

The test run just failed and dune is showing the diff between what we have
locally and what should be, according to MDX.
This uses dune's promotion workflow so at this point you can either investigate
it further if you're surprised by this diff or if you're happy with it, simply
accept it by running:

{@sh[
dune promote
]}

Now the documentation is up-to-date and running [dune runtest] again should be
successful!

{1 Table of Content}
- {{!page-markdown_syntax}Markdown MDX Syntax}
- {{!page-mli_syntax}.mli MDX Syntax}
- {{!page-types_of_blocks}Types of Blocks}
- {{!page-labels}Labels}
- {{!page-dune_stanza}Dune stanza}
- {{!page-preludes}Preludes}
- {{!page-using_libs}Using Libraries in your code examples}
50 changes: 50 additions & 0 deletions doc/labels.mld
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{0 Labels}

MDX blocks behaviour can be customised through the use of labels.

This section documents in detail what each existing label does and how to use
it.

{1:env Env}

{2 Description}

This label allows you to assign an environment to an OCaml block. That means
you benefit from whole the code that has been previously evaluated in that
environment, be it from other code blocks or {{!page-preludes}preludes}.

{2 Syntax}

[env=<value>]

The environement label expects a single string value which corresponds to the
name of the environment to use.

[.mli] example:
{v
(** Here is how to use this function:
{@ocaml env=foo[
# f 0;;
- : int = 0
]} *)
v}

[.md] example:
{@markdown[
Here is how to use this function:
<!-- $MDX env=foo -->
```ocaml
# f 0;;
- : int = 0
```
]}

{2 Applies to}

- {{!page-types_of_blocks.ocaml_toplevel} OCaml Toplevel Blocks}
- {{!page-types_of_blocks.ocaml} OCaml Blocks}

{2 Default}

When absent, the block will be evaluated in the default environment, e.g.
the environment shared by all blocks without an [env] label.
1 change: 1 addition & 0 deletions doc/markdown_syntax.mld
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO
1 change: 1 addition & 0 deletions doc/mli_syntax.mld
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO
12 changes: 12 additions & 0 deletions doc/preludes.mld
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{0 Preludes}

Preludes are fragments of code that can be evaluated ahead of running the
code in OCaml and OCaml toplevel MDX blocks. They can be used to globally
open modules, register toplevel printers, set some globals like
[Printexc.record_backtrace], you name it!

They are especially useful if you want to hide or share this kind of setup
phase, e.g. if you are writing polished documentation you want to publish
or you are using MDX to add tests in your mli files directly.

TODO
27 changes: 27 additions & 0 deletions doc/types_of_blocks.mld
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{0 Types of Blocks}

MDX searches for code blocks within your documentation to make sure they are up
to date.
It supports different type of block contents, each have their own behaviour.

If a code block does not belong to one of the categories described below, MDX
will simply ignore it.

The type of a block can either be set explicitly using a label, otherwise MDX
will try to infer the type of the block based on its language tag, labels and
content.
Setting the block type explicitly allows MDX to better report syntax errors
or invalid labels.

{1:ocaml_toplevel OCaml Toplevel Blocks}

OCaml Toplevel Blocks are composed of a sequence of toplevel phrases, starting
with a [#] and a space and ending with [;;] followed by the output of the
toplevel evaluation of the phrase.


{1:ocaml OCaml Blocks}

{1:file_include File Include Blocks}

{1:shell Shell Blocks}
1 change: 1 addition & 0 deletions doc/using_libs.mld
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO

0 comments on commit 52c4e7d

Please sign in to comment.