Skip to content

Manpage output#428

Merged
aantron merged 7 commits intoocaml:masterfrom
Drup:manpage
May 2, 2020
Merged

Manpage output#428
aantron merged 7 commits intoocaml:masterfrom
Drup:manpage

Conversation

@Drup
Copy link
Copy Markdown
Contributor

@Drup Drup commented Apr 20, 2020

This is a WIP backend for manpages.

Example of output for the markup:
hello, this is groff

Example of types:
groff is entering the party

There is a little bit of code duplication between html and manpages which I'll fix later.

I'm opening this PR relatively early because I have questions:

  • What to do for includes ?
  • What to do for nested pages (typically, submodules) ? There is no notion of links, which makes navigation awkward. I'm tempted to try to include the subpages directly.
  • Which subpage should we actually output ? I'm tempted to output pages only for actual modules (and documentation pages), mostly because, if prefixed by the package, we have unicity of path. This means that each module is accessible through man package.Foo.Bar, which is easy.

As one can guess, manpages are ... limited. Outputing the rich odoc markup there is sometimes quite awkward, so I also welcome layout ideas. And no, we don't have access to colors. 😞

@Drup
Copy link
Copy Markdown
Contributor Author

Drup commented Apr 20, 2020

Also, I would like to point out the Troff submodule with some artistic semantics to make things tractable: https://github.com/Drup/odoc/blob/4d68e9827dc121c0aa2538df57cfb93e837c95ff/src/manpage/generator.ml#L25-L55. If anyone wants to delve into the semantics of groff commands and improve that, I would be happy to pass on the flame ...

@jonludlam
Copy link
Copy Markdown
Member

It seems to me that includes should always be expanded, perhaps with a header above saying where they came from - otherwise it might not even be possible to see the accurate contents (e.g. include Foo with type t := int).

I wouldn't have thought submodules should be expanded inline, otherwise man stdlib would be huge (and man core_kernel larger!) - I agree with the idea of enabling man package.Foo.Bar

Where you say

I'm tempted to output pages only for actual modules (and documentation pages)

do you mean not outputting them for module type/classes/etc?

Functors are a bit more interesting - perhaps we might expand each of the parameters at the top inline in the page?

Also: this is really great! Thanks for all the hard work you're putting into this!

@Drup
Copy link
Copy Markdown
Contributor Author

Drup commented Apr 21, 2020

It seems to me that includes should always be expanded, perhaps with a header above saying where they came from - otherwise it might not even be possible to see the accurate contents (e.g. include Foo with type t := int).

That was my initial idea as well, but I have not yet managed to find a layout making the header clear.

I wouldn't have thought submodules should be expanded inline, otherwise man stdlib would be huge (and man core_kernel larger!) - I agree with the idea of enabling man package.Foo.Bar

In more details, my current idea was to expand anything that does not get its own page. man stdlib would still be reasonable, since all the submodules have their own page. The question becomes: for what do we generate a page. The only choice I see which never causes any collisions is to generate a page only for modules with a valid (OCaml) path: Yes for A.B.C, no for A.B.module-type-C and no for A.module-type-C.B. Concretely, Map.S is expanded and Map.Make gets its own page.

An alternative choice would be to generate pages for everything that has a valid OCaml path. This is the choice made by ocamldoc, but then we can get collisions, and I'm not sure what to do with those.

@lpw25
Copy link
Copy Markdown
Contributor

lpw25 commented Apr 21, 2020

The user already has control over whether an include should start expanded or not in the html. I think you should just use that setting for deciding whether to show the contents of an include or not.

@Drup
Copy link
Copy Markdown
Contributor Author

Drup commented Apr 21, 2020

I wasn't clear. I'm mostly talking about regular declarations here, not includes:

module type S = sig
  <put the content here>
end

The problem for includes is more about the actual layout.

@jonludlam
Copy link
Copy Markdown
Member

Your current idea sounds fine to me @Drup - so we never give a separate page to an identifier that contains a module type.

Should we special-case Stdlib? Or at least give an option to allow it - we can currently do man List but with the suggestions above that would be man ocaml.Stdlib.List.

@lpw25
Copy link
Copy Markdown
Contributor

lpw25 commented Apr 21, 2020

I think following ocamldoc and then just letting say modules shadow module types if there is a collision is probably fine. This is much less problematic than usual because you have no links, so there is no risk of creating dead links by dropping a page.

This is the first necessary step to be able to inline whole pages as part
of a document, as is necessary in both the manpage and the latex output.

It also induces a small change of output for functors, as arguments
are now treated as full blown "declarations", and layed out as such.
Drup added 3 commits April 28, 2020 22:08
We now place the subpage on the right hand side part of the
definition, including the separator.

More precisely:
- module Foo (= Bar)
- module Foo (: Bar)
- module type Foo (: Bar)
- class foo (: bar)
- class type foo (= bar)
@Drup Drup force-pushed the manpage branch 2 times, most recently from 8253506 to e2de7b8 Compare April 28, 2020 20:17
@Drup
Copy link
Copy Markdown
Contributor Author

Drup commented Apr 28, 2020

I'm done with the first version.

I modified the IR to inline subpages at the semantically relevant place. For instance, for a module type with a subpage, we have some IR equivalent to module type FOO (= ModExpr) where the part in parens have additional content indicating the IR has a summary for a subpage.

The HTML renderer ignores those (for now), but the manpage one will inject the subpage when appropriate.
Here's what it looks like with some headers:
included_section

I expect this to be very useful for the LaTeX renderer, as well as opening the way for interesting HTML tweaking.

For the rest, I did as discussed: modules and classes have their own pages, everything else is injected. The files are named Path.To.thing.3o. The high-level layout is rather decent now, although some finer rendering could be improved.

Here are various things that requires further work:

  • There is some code duplication between html and manpage output, but I think fixing this should go in a larger patch working towards a more modular system
  • I'm again not happy with the output for functors.
  • Heading nested insides included pages do not work as well as they should, but I'm not even happy with the HTML output there, so that'll go in a separate patch.

@Drup
Copy link
Copy Markdown
Contributor Author

Drup commented Apr 30, 2020

ping @aantron :)

@aantron aantron self-requested a review April 30, 2020 15:11
@aantron aantron force-pushed the master branch 4 times, most recently from 44dd495 to cc1f437 Compare May 1, 2020 15:50
@aantron aantron merged commit 8810351 into ocaml:master May 2, 2020
@aantron
Copy link
Copy Markdown
Contributor

aantron commented May 2, 2020

Thank you!

@Drup Drup deleted the manpage branch May 5, 2020 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants