Good toolchain for writing a user manual?

It’s time to start writing a user manual for diagrams. Haddock documentation is great when you have only, say, forgotten the type of the frobnitz function. However, it is woefully inadequate when you are just trying to figure out how to wibble your fromps (it turns out, of course, that frobnitz is quite general and can be used for, among other things, wibbling fromps; but how would you know to look in the Diagrams.Frobnostication module in the first place?).

So I’m looking for tools I can use to help write and publish the manual. For something short like a tutorial, pandoc works like a charm, but the user manual is going to be a much larger and more complex beast. Here are my requirements. I want to:

  • write in Markdown (or some similar sort of markup language)
  • have the ability to generate not just a single HTML file, but multiple ones with appropriate next/previous links, a table of contents, and so on
  • include Haskell code and generate a syntax-highlighted version in the output; the source (or something easily generated from the source) should also be an actual, valid literate Haskell file that people can load in ghci
  • have good support for internal hyperlinks, so different parts of the manual can easily link to one another.

And some "nice-to-have" features:

  • I’d like easy hooks into the build process, so I can (for example) replace certain snippets of Haskell code with links to the images generated by the code.
  • I’d like to be able to incorporate doc-review, or something like it, so people can comment on each paragraph in the manual.
  • I want to mark some regions as "collapsible" so they will initially be displayed as just a "placeholder" of some sort which can be expanded and collapsed by clicking. These could include things like extra technical information which many readers will not care about, extra explanation for users unfamiliar with Haskell, and so on.

So — any ideas? Perhaps I really want the system used for the Yesod wiki, but I’m assuming it would not be cheap. The most viable thing I have considered so far is using pandoc to generate docbook, and from there generating chunked HTML. This is nice in some ways but not ideal: pandoc actually can’t do syntax highlighting when writing anything other than HTML; I don’t know how I would include collapsible sections; and you can only use two heading levels if you want valid literate Haskell.

It’s quite likely that there’s no single thing that will do exactly what I want, and I’m quite willing to do some “glue” work to put some pieces together. But I’d like to avoid as much wheel-reinvention as possible. Any ideas?


About Brent

Associate Professor of Computer Science at Hendrix College. Functional programmer, mathematician, teacher, pianist, follower of Jesus.
This entry was posted in projects, writing. Bookmark the permalink.

17 Responses to Good toolchain for writing a user manual?

  1. Philipp says:

    Have you considered emacs org-mode? It has a very simple markup language and many of the features you describe (export to many formats, html, LaTeX, and others, internal and external links, collapsible headings).

    With org-babel, you can also include code blocks (in many languages, haskell among them) that have syntax highlighting. You can extract the code blocks to different files, or even include the results of executing a code block into the document.

    I have used it to write documentation and found it very useful for the task.

    • Brent says:

      Hmm, interesting idea! I use org-mode all the time for organization, but I hadn’t thought of using it for this purpose. I will look into it.

  2. yoric says:

    In our experience around Opa, asciidoc is acceptable, but far from perfect.

  3. You might look into Jekyll.. It’s more geared towards websites, but I believe it can do any of the things you say (except maybe “have good support for internal hyperlinks, so different parts of the manual can easily link to one another”, since I’m not sure what you mean by that). It’s worth a look at least.

    There are a lot of other similar tools, including some that are written in Haskell.

  4. Luke Plant says:

    Have you looked at Sphinx?

    It is based on ReStructuredText, which is a format supported by pandoc, and is ‘Markdown-like’ i.e. mainly plain text with conventions for formatting.

    Sphinx adds various extensions to ReST to help with source code, and various extension points to add your own things. Most of the Python world are standardising on using Sphinx for docs.

    It supports syntax highlighting for Haskell via Pygments –

    It has excellent support for internal hyperlinks.

    Converting to a literate Haskell file would be harder, but should be possible using a bit of glue.

  5. Luke Plant says:

    I found this directive that might help with literate Haskell:

    You would then have to put your Haskell in a separate file, which might be what you want.

  6. John MacFarlane says:

    You should be able to do everything you want using pandoc + a little scripting uisng the pandoc API:

    Note that pandoc already allows markdown+lhs as an input format.

    • Brent says:

      Yes, I’ve used the pandoc API before and it’s fantastic. I also use the markdown+lhs input format all the time. But as I noted above, pandoc currently doesn’t do syntax highlighting when outputting docbook, and the inability to have more than two heading levels when using markdown+lhs is a problem for me as well. Do you have any ideas for getting around these issues? I’d also be willing to contribute to pandoc to get it to a place where it will work well for me, if the way forward is relatively clear.

      • John MacFarlane says:

        If you’re writing a bit of Haskell glue, you can easily split the Pandoc document into several documents by sections — just split the Block list on Header 1 elements. You can then write a separate HTML document for each section. (You’d probably want to add some Prev/Next/Up links, and you’d also have to adjust any existing internal links to point to the proper files, but this shouldn’t be too hard using the API.)

        More than two heading levels in LHS: I’m less sure what to do here. You can’t start headings with ‘#’, since that has a special meaning in column 1 in literate Haskell files, and setext headers only give you two levels. But here’s a workaround: put a space before your ‘###’. This will be parsed as a Para, not a Header 3, but you can then go through with generics and transform every Para (Str “#” : Str “#” : Str “#” : xs) to a Header 3 xs.

        For Haskell code sections that link to pictures, you can use delimited code blocks with a special class (say, picturelink). Then have your script find code blocks with this attribute, run the code, create the image, and insert a link.

  7. Heinrich Apfelmus says:

    You can use pandoc as a library and implement the desired functionality yourself. (Hyperlinking is a bit problematic, though; last time I tried this, pandoc doesn’t give you access to the unique identifiers.) I converted my operational monad tutorial from markdown to LaTeX with this method.

    Whether this is a good use of your time, I don’t know, but that’s probably how I would do it. Also, I would be interested in contributing to / reusing such a project.

    A piece of wisdom concerning the markup: in contrast to markdown, restructured text is extensible. It’s extremely likely that you run into a situation where you want to include some extended attribute (like “collapsed”) and then you have a problem with markdown. Maybe John McFarlane has some ideas here. I don’t really know whether ReST is really better here, though.

    (That seems to be a general problem: If an existing system does not do everything you want, you’re screwed. That’s why I like the pandoc-as-a-library approach.)

    • Brent says:

      Ah, thanks for the wisdom re: extended attributes. I had considered that problem but wasn’t aware that ReST was extensible, which is good to know; I’ll take a look at it. And you’re right about the pandoc-as-a-library approach.

  8. Ben Moseley says:

    Skribe/Scribe, Skribilo / lout / Nonpareil ? (No personal experience with these though).

  9. solrize says:

    I may be an old fogey but I still don’t understand what’s wrong with texinfo. It has simple semantic markup, it’s easy to edit with a text editor, it can generate hypertext or real typeset manuals (using TeX) with chapters and sections, and it’s been around for decades so it’s free of trendy crap. I still use it.

  10. Heinrich Apfelmus says:

    Hello Brent,

    any update on your quest for a good tool? Sooner or later, I have to write a tutorial for my reactive-banana library, hence my interest.

    Some time ago, I have even come up with a layout that features a wide margin for annotations.

  11. S. Günther says:

    Since it hasn’t been mentioned here: you could also look at whether you can make dexy do what you want.

  12. HansBKK says:

    Note that Pandoc (now released v1.9, major enhancements) has supported a pretty complete subset of reST as both input and output, so it’s not an either-or. A followup post show what you ended up doing here would be great BTW. . .

    • Brent says:

      Pandoc 1.9 looks awesome! I do love pandoc and use it for quite a lot. However, pandoc still does not support the “user-extensible” portions of reST, such as user-defined roles and containers. These features are critical for me, since I want to be able to invent new “semantic markup” on a per-document basis and then write custom processors for it.

      A followup post explaining what I ended up doing is a good idea. For now, the short answer is that I use standard python docutils tools to parse reST to XML, and then hxt for transforming the XML into various other formats.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.