odoc Support¶
neocaml includes a dedicated tree-sitter mode for
odoc documentation pages.
neocaml-odoc-mode activates automatically for .mld files and
provides font-lock, indentation, imenu, and language injection into
code blocks.
Grammar Installation¶
The mode requires its own tree-sitter grammar, separate from the main OCaml grammars. It will prompt you to install the grammar on first use, or you can install it manually:
M-x neocaml-odoc-install-grammar
With a prefix argument (C-u), the command reinstalls even if the
grammar is already present.
Note
The odoc grammar requires tree-sitter ABI version 14+ (tree-sitter >= 0.24). If your Emacs was built against an older tree-sitter, you may need to update it. See Troubleshooting for details.
Font-lock¶
Every odoc construct gets its own face, so you can remap any of them without disturbing the others:
| Face | Markup |
|---|---|
neocaml-odoc-heading-face |
{0 Title} through {5 ...} |
neocaml-odoc-bold-face |
{b ...} |
neocaml-odoc-italic-face |
{i ...} |
neocaml-odoc-emphasis-face |
{e ...} |
neocaml-odoc-tag-face |
@param, @return, @since, ... |
neocaml-odoc-tag-name-face |
the name in @param name and @raise Exn |
neocaml-odoc-tag-value-face |
the version in @before 1.0 |
neocaml-odoc-code-face |
[inline code] and code blocks |
neocaml-odoc-verbatim-face |
{v ... v} |
neocaml-odoc-language-face |
the language tag of {@ocaml[...]} |
neocaml-odoc-math-face |
{m ...} and {math ...} |
neocaml-odoc-reference-face |
{!Module.value} |
neocaml-odoc-link-face |
{:https://...} and media targets |
neocaml-odoc-escape-face |
\{, \}, \[, \], \@ |
neocaml-odoc-markup-face |
{^ ...}, {_ ...} |
neocaml-odoc-raw-markup-face |
{%html: ...%} |
neocaml-odoc-list-face |
{ul ...}, {ol ...} |
neocaml-odoc-bracket-face |
the delimiters themselves |
Bracket highlighting is a level-4 feature, so raise
treesit-font-lock-level to 4 if you want the delimiters coloured.
Language Injection¶
On Emacs 30+, code inside a {@lang[...]} block gets full syntax
highlighting for that language:
{@ocaml[
let greet name = Printf.printf "Hello, %s!\n" name
]}
OCaml, dune, and opam are injected, each when its grammar is
installed; delimited blocks such as {delim@ocaml[...]delim} are
injected too. A block in any other language still reads as code, via
neocaml-odoc-code-face.
Language injection activates automatically. No configuration is needed.
Imenu¶
Imenu indexes the page under two categories:
- Heading: every
{0 ...}through{5 ...}, named by its title - Tag:
@param,@return,@raise,@deprecated,@since,@versionand@author
Headings also act as defuns, so C-M-a and C-M-e move between
sections.
Configuration¶
;; odoc indentation (default: 2)
(setq neocaml-odoc-indent-offset 4)