I’m happy to announce that neocaml 0.11 is out! I never got aroundto writing about 0.10, which was mostly about neocaml-utop (a utop backendthat talks to utop via its native editor protocol), but 0.11 is a differentstory. Its changelog is twice as long as that of any release before it, and bynow I’ve stopped pretending that a grand 1.0 is just around the corner.1There’s a lot in there, but three things stand out for me - OxCaml support,indentation styles, and much better support for documentation. Here’s why…OxCamlOxCaml is Jane Street’s set of extensions to OCaml - modes andmodalities, kinds, unboxed types, stack allocation and so on. You can use themtoday with an OxCaml compiler switch, and Jane Street’s libraries use them allover the place. A lot of the heavy lifting happened upstream, astree-sitter-ocaml 0.26 learned to parse OxCaml, and Tim McGilchristbumped neocaml’s grammars to it. 314eter (the tree-sitter-ocamlmaintainer) once again cut an ABI 14 build of the release, so wedidn’t have to break anyone’s Emacs. (see the 0.9 postfor the whole ABI saga) Huge thanks to both of them!A grammar that parses the code is only half of the job, though. Here’s a bit ofOxCaml:1234567type point : immutable_data = { x : float; y : float }type vec = #{ dx : float#; dy : float# }let length (xs @ local) = List.length xslet make () : int list @ local = exclave_ [ 1; 2; 3 ]neocaml now highlights and indents all of this. The new keywords (stack_,exclave_, local_, global_, borrow_ and kind_), modes and modalities,kinds, unboxed types and literals (float#, #1.0, #(...)), immutablearrays ([: ... :]) and comprehensions are all covered. The indentationfollows the way ocamlformat lays out Jane Street’s own OxCaml libraries (e.g.portable, unique and parallel), which is why the body of an exclave_isn’t indented, while those of stack_ and local_ are.2 Kind definitionsalso show up in imenu and work with the defun navigation commands.If you don’t write OxCaml, nothing changes for you - plain OCaml looks exactlythe way it did before. If you do, there’s nothing to turn on in neocaml. Justmake sure Emacs sees your OxCaml switch and you’ll get its ocamllsp andocamlformat as well. The docs have all the details.Indentation stylesHere’s a confession - neocaml’s indentation used to be a bit of a mix. Somelayouts followed ocamlformat’s conventional profile, some followedjanestreet, and a few followed neither. That’s a problem, as OCaml doesn’thave one indentation style everyone follows. ocamlformat ships severalprofiles, Jane Street’s code doesn’t look like the compiler’s, and plenty ofprojects never run a formatter at all.So 0.11 lets you pick one of three styles via neocaml-indent-style: ocp-indent, which indents the way ocp-indent does out of the box conventional, after ocamlformat’s default profile (used by ocaml.org, ppxlib and Irmin) janestreet, after ocamlformat’s janestreet profile (used by Jane Street’s libraries, dune and ocaml-lsp)They agree on most things and differ on a handful of layouts, e.g. how far thebody of a match case goes:1234567891011(* ocp-indent and janestreet *)match value with| Some payload -> finish payload| None -> 0(* conventional *)match value with| Some payload -> finish payload| None -> 0The best part is that most of the time you won’t have to pick a style yourself.By default neocaml looks for the project’s .ocamlformat and picks the stylethat matches its profile (it also respects cases-exp-indent). Without an.ocamlformat it checks for an .ocp-indent file, and without either you getthe ocp-indent style, as that’s what most projects that don’t use ocamlformatindent with. (e.g. opam, Rocq, Frama-C, Eio and the compiler itself) You canalso set the style per project in .dir-locals.el, or switch it for thecurrent buffer with M-x neocaml-set-indent-style.I also wanted to know how well all of this works on real code, instead ofguessing. So I wrote a couple of small scripts (they live in dev/) that formata bunch of OCaml files with each ocamlformat profile and count the linesneocaml would indent differently. I ran them on the almost 300 files of theopam packages in my default switch (mostly Jane Street’s base), and 0.10didn’t look great. About one line in ten had no indentation rule at all, soTAB simply left it wherever you typed it, and only 81.9% of the lines landedwhere ocamlformat’s conventional profile puts them (77.8% for janestreet).Ouch! With the matching style, 0.11 gets 97.5% and 98% of them right.3 Notperfect, but pretty close!Keep in mind that indentation only places the lines you’ve broken, it doesn’tbreak them for you. If you run ocamlformat on save it has the final wordanyway, but with the matching style less of what you type moves around whenyou save.odoc and doc commentsThe third big theme is documentation. A few months ago mlemerresuggested (#60) that neocaml should render the ocamldoc markup incomments, instead of showing it as a soup of braces. I loved the idea, and in0.11 doc comments finally look like documentation - {b bold} is bold, {iitalic} is italic, [code], {[ ... ]} and {@ocaml[ ... ]} are shown ascode, and {!references} and tags like @param get faces of their own. Thisis the new doc-markup font-lock feature, and it’s enabled at the defaultfont-lock level.Tim also contributed neocaml-odoc-mode (#46) for odoc’s standalone.mld documentation pages, built on Tim’s own Tree-sitter grammar forodoc. You get font-lock for headings, inline markup, references,links, tags, lists and tables, plus indentation and imenu. On Emacs 30+ thecode in {@ocaml[...]}, {@dune[...]} and {@opam[...]} blocks ishighlighted as well, using the grammars for those languages. Run M-xneocaml-odoc-install-grammar to get started, and check out the odocdocs for more.While I was at it, I also fixed M-q and M-j in comments. Embarrassingly,M-q used to always fill the first paragraph of a comment, no matter where youwere in it, and it merged code blocks into the text around them. M-j nowcontinues the * of comments that start each line with one.Grab BagThose are just the highlights, of course. Here are a few more things that Ithink you’ll like: neocaml-mlx-mode for .mlx files (OCaml with JSX, as used by Melange andReact), contributed by Akira Komamura commands for running the tests of the current file and dealing with dune’spromotions (C-c C-o T, C-c C-o = and C-c C-o P), with their ownbindings in neocaml-cram-mode the toplevel’s responses in the REPL are now highlighted with Tree-sitter,just like your code each dune project in a monorepo gets its own REPL neocaml-format-buffer replaces only the text that changed, so point andthe window positions stay putUpgradingMost setups will keep working just fine, but a few changes in this releaserequire some action on your part: neocaml needs tree-sitter-ocaml 0.26 now, so reinstall the OCaml grammarswith C-u M-x neocaml-install-grammars. The dune grammar moved to its newhome, ocaml-dune/tree-sitter-dune, so reinstall it as wellwith C-u M-x neocaml-dune-install-grammar. neocaml will warn you if yourgrammars are too old. Some keybindings clashed with ocaml-eglot and merlin, so they had to move. Inthe REPL minor modes sending the phrase at point is now C-c C-e, sending itand moving to the next one C-c C-s, loading the file C-c C-u andinterrupting the toplevel C-c C-q. The dune commands moved from C-c C-dto C-c C-o. The default indentation changed. If your project uses neither ocamlformatnor ocp-indent a few layouts will move, so set neocaml-indent-style if theocp-indent style is not your cup of tea.EpilogueWith OxCaml, mlx and odoc on board, neocaml now covers pretty much every kindof OCaml file I can think of. Famous last words, right?So, what’s next? I don’t really have any big plans for 0.12. I’d like to switchneocaml-mlx-mode to the dedicated grammar fromtree-sitter-mlx once it has an ABI 14 release, and there’sthe usual pile of smaller ideas in the roadmap. No promises, though.Big thanks to Tim McGilchrist, who did a ton of work on the grammars(OCaml, dune, opam and menhir) and the odoc support! Thanks to AkiraKomamura for bringing mlx to neocaml, and to Alessio Duèfor fixing a sexp navigation bug! And thanks to everyone who reported problemsand shared ideas - many of the improvements in 0.11 started as an issue onGitHub.As usual - update from MELPA, play with it, andlet me know how it goes. The full list of changes is in the releasenotes.That’s all I have for you today. Keep hacking! See the 0.6 post for how that went the last time. ↩︎ That’s how ocamlformat formats Jane Street’s code, and I’ve learned to trust it more than my own intuition here. ↩︎ That’s about 77,000 lines formatted with ocamlformat 0.27.0. The numbers depend on the code and the ocamlformat version, so take them with a grain of salt. ↩︎