Hi Ingo, At 2026-08-07T17:20:17+0200, Ingo Schwarze wrote: > G. Branden Robinson wrote on Sun, Jul 26, 2026 at 04:40:39PM -0500: > > > mandoc(1) advocates frequently boast of its speed relative to groff, > > and they have a point. > > This is not particularly accurate.
I don't have a grievance with you, but rather with mandoc(1)'s partisans, which one can readily find online. J. C. Roberts's 2010 article on (then) mdocml for Undeadly set an unhelpful precedent. https://www.undeadly.org/cgi?action=article&sid=20100604082319&mode=expanded (Maybe Roberts is OpenBSD's answer to Joe "Zonker" Brockmeier, supplementing his journalism with a generous helping of brand-building.) I don't have any other screamingly good examples, and I'm not sure it's worth calling out random Internet users specifically. But occasionally when doing a web search I bump into overstated claims that grate because they combine deep ignorance with such vehement confidence. > I only boast that mandoc(1) -T ascii and -T utf8 rendering is > significantly faster than groff(1)'s, where the comparison makes sense > because the output is intended (with few exceptions) to be > byte-by-byte identical. Yes, and that's accurate, though I'll consider seriously any substantial gap-closers that don't harm rendering correctness. > > I can rig up a rough apples-to-apples comparison by > > having that tool produce a PDF of all of groff's man pages. > > This makes no sense whatsoever. It is still comparing apples to > oranges. The -T ps and -T pdf formatters of groff(1) are real > typesetters. In mandoc(1), they are not. What mandoc(1) -T ps > produces is basically still terminal output in PostScript format, with > a few very minimal, very basic beautifications, but absolutely not > real typesetting in any sense. In mandoc(1), -T pdf output is > functionally identical to -T ps output, profiting from none of the > distinctive features of the PDF language. I think a lot of mandoc(1) advocates--meaning users, or, worse, "boosters" who don't actually even read man pages all that frequently--don't understand these distinctions. That said, in the limit, these sorts of people don't _read_ much of anything, either, so it's hard to reach them by updating documentation, no matter how scrupulous you are. > You can certainly use "mandoc -T ps" or -T pdf if for some reason, > you find it subjectively more readable than terminal output, but > comparing the speed_of something that is massively defective in > many respects is not useful. A problem I perceive is that mandoc(1) fails to correct distorted views if the user runs "mandoc -T ps" (or "-T pdf") observes that it goes fast and exits with status 0. Fanbois conclude from this that the rendering was correct, sometimes without bothering to inspect the output at all. Where a problem really threatens is that if mandoc(1) fails to correctly render (in PS or PDF format) a man page maintained by a third party, those same partisans are apt to conclude that the _document_ was written incorrectly. Thus, in the hands of fanbois, mandoc(1) can become a tool for damaging the reputation of innocent third parties. _That_ is objectionable. > I always say that if you need real PostScript or PDF output, use > groff(1), not mandoc(1). I encourage you to say this even more often, and more loudly. > mandoc -T ps was basically an experiment of Kristaps' more than a > decade ago, and has only received minimal maintenance ever since. The > source file of the formatter is called "term_ps.c" for a reason: it is > a thin layer over the terminal formatter. I cast no shade on it as a worthy experiment and a revealing exploration. But if it is not a production-grade module of the code, users must be made aware of this fact. I'd say the same of the Mulley/Lemberg approach to the problem of getting groff to produce HTML, a point to which I'll return below. I perceive that they adopted a strategy avowedly not short of ambition. > A fairer comparison would be to compare "mandoc -T pdf" speed > to "groff -T ascii" speed (still not a useful comparison, but at > least slightly more fair). Here, _I_ perceive a lack of an apples-to-apples comparison, because I see the much more complicated rendering operations demanded by typesetting (contra typewriting) as sufficiently great to compel a qualitiative shift in what is measured. I guess we're looking at the problem from different perspectives. > Probably, the mandoc(1) manual should warn that -T ps and -T pdf > are not indended as serious typesetting and should warn against their > use for most purposes. Please, yes! > > 'Course, there are important caveats. Browsing through the output, > > I have some observations. > > > > * mandoc(1)'s output is not hyperlinked at all, neither internally > > nor to external URLs. > > True. Isn't that feature specific to PDF and absent from PostScript? Yes. > The fundamental software architecture of mandoc(1) prevents using any > PDF features not provided by PostScript. That would need a > completely new formatting layer term_pdf.c, which does not exist. Similarly, Deri wrote a new output driver for groff rather than extending grops(1). > > * Because there are no internal hyperlinks, mandoc(1) didn't need to > > perform multiple passes. That virtually guarantees a win on > > elapsed time to generate the document. > > The fundamental architecture of mandoc(1) never does multiple > formatting passes. Instead, it builds an abstract syntax tree (AST) > of macros and requests, than transforms that AST with so-called > validation modules, which are independent of the output format. In > addition to regularizing the AST, the validators adds information > to the AST the any output module might need. While it would be > possible to add PDF-specific information to the AST at the validation > stage, nothing of the kind is done. GNU troff performs similar operations. It wasn't until I really got deep into its internals that I came to understand how much like a compiler it really operates. Or, perhaps more accurately, how much like an assembler. Assemblers work on instructions. GNU troff works on "output lines". When an assembler has encoded an instruction, it fires and forgets. Similarly-- and leaving diversions aside--once GNU troff has processed the characters and nodes of a pending output line, and has added to it any applicable adjustment, margin character, and line number, it translates that line's contents into "grout" instructions and forgets about the line utterly. > You might argue that mandoc(1)'s is a four-pass architecture in the > first place (first pass: the parsers; second and third passes: the > validators; fourth pass: the formatters) but that feels sophistic. > Groff similarly does multiple passes over the document, albeit > different ones (macro preprocessing, troff parsing, output > postprocessing), even in single-pass mode. By "pass" I mean an iteration over the entire input stream until EOF is reached. Because a *roff is designed to work in a pipeline, it doesn't really perform "passes" in this sense. It's true that each preprocessor performs a "pass" over the entire input, but only one each.[1] GNU troff doesn't perform multiple passes; interpolations, be they of escape sequences (including register and string "expansions") or macros, are performed in-place at the current input stream pointer, and thus scanned into immediately. Ultimately what remains are requests and non-interpolating escape sequences, and the formatter implements handlers for each distinct specimen of these. Those operations variously populate the pending output line or update either the environment or global state (register/string/macro dictionaries, user-defined characters, the compatibility mode stack, and so on). > > * There's no navigation pane. Wanna navigate the document? Key in > > a page number and play Battleship to find the material you seek, > > or work that scroll bar, plebe. > > Again, isn't that a PDF rather than PostScript feature? Yes. > > * In my opinion, mandoc(1)'s output is esthetically inferior, > > I strongly agree, and it's no surprise because no work was ever done > to achieve good typography. The whole point was whether it is > feasible to create syntactically valid PostScript code from a > terminal formatter with limited effort, and the answer turned out > to be "yes, to a certain extent." Right--and again, I think it was a worthy experiment. But it is not production-grade as mandoc(1)'s terminal and HTML output formats are. > > with the possible exception of the base type size being larger > > and thus arguably gentler on the reader. > > > > * On the other hand, that decision swells the document to 675 pages. > > > > * We can _easily_ increase the base type size from 10p to 11p or 12p > > if we decide that's a good thing to do. I predict the impact on > > production time to be negligible. (Worth testing, though!) > > I don't think it's worth wasting time on testing that. For > comparison, mandoc(1) does not even provide any way to change the type > size, neither via command line options, configuration files, or > in-document requests or macros. Real typography is simply out of > scope. The roff(7) manual distributed with mandoc(1) says, for > example: > > ps [[+|-]size] > Change point size. Currently ignored. > > \s'[+|-]number' > Change point size; ignored by mandoc(1). Alternative forms > \s[+|-]n, \s[+|-]'number', \s[[+|-]number], and \s[+|-][number] > are also parsed and ignored. I've learned never to discuss type size without also covering vertical spacing. So here you go. :) vs [[+|‐]height] Change vertical spacing. Currently ignored. > > * mandoc(1)'s bullet glyphs are ugly--they're an 'o' overstruck with > > a '+', to me, the glyphs seem to lack a precisely identical > > center. > > Well, not only is mandoc(1) PostScript outpout based on terminal > output, but on -T ascii output specifically (and not on -T utf8). The > only fonts it can use are 96-glyph Times ASCII fonts. Strictly, only 94, then, because space (32) and delete (127) don't print. > Again, not intended for real typography. Such a limited glyph repertoire is a significant limitation, IMO. > > * Similar ugliness afflicts groff_mmse(7) (p. 78). Notice how ö is > > rendered. > > > > * Neutral apostrophes ' render incorrectly as ’ and copy-and-paste > > that way, too. > > > > * A hyphen-minus - _renders_ as a hyphen ‐, but copies and pastes > > correctly. > > > > * ± renders unhelpfully as "+-" (p. 144). > > > > * Between bad table layout (see below), refusal to format non-Basic > > Latin glyphs, and 1970s line-printer-style overstriking, the entire > > groff_char(7) document (pp. 187-222) is an utter disaster. > > All that sounds related to being an ASCII rather than a UTF-8 output > mode. I agree, except for the second point. Does "mandoc -T ps" emit the PostScript "quoteright" or "quotesingle" glyph for `'`? 'Course, if the font doesn't distinguish these--or worse, "quotesingle" is unavailable--your output is up a creek anyway. > > * I see errors (missing space between words) in synopsis formatting; > > mandoc(1)'s support for the groff man `SY` and `YS` extensions may > > be lacking--or, since mandoc(1) hasn't had a release in a few > > years, those flaws might be fixed in its "HEAD".[...] > > If that is reproducible in -T ascii mode, it's possibly a .SY > formatting bug in the man_term.c formatter. If not, i'd be somewhat > surprised. I can't reproduce the problem in that output format. $ mandoc -T ascii ~/groff-1.24.1/share/man/man1/chem.1 |head chem(1) General Commands Manual chem(1) Name chem - embed chemical structure diagrams in groff documents Synopsis chem [--] [file ...] chem -h > > * To my surprise, example displays are not set in a monospaced font. > > Yes, i think there is even a TODO entry for that. It's a major task > though since right now, mandoc(1) -T ps only supports four fonts: > Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic. > Again, never intended as real typography. > > > People have ridden our rears about failing to do that when > > generating HTML,[...] and traditionally mdoc(7) mavens are proud > > to a fault of spattering their documents with Courier like cream > > pie filling at the end of a Keystone Kops short feature. > > > > * Table layout is poor. See, e.g., page 46. > > I doubt that anyone has ever tested -T ps with tbl(7). That's...a bit of a gap. > > + There's no separation between the columns. > > > > + The existence of the `BI` (bold-italic) font is ignored. > > > > + The width of text blocks is computed strongly suboptimally. (The > > "x" column modifier appears to be completely ignored.) > > > > + Even worse, line wrapping is permitted before the period at the end > > of a sentence. That's _really_ bad, QA-wise. mandoc(1) doesn't > > seem to mess this up when formatting regular text; why would it > > here? Ahh, it may be a parser issue. The line that gets > > incorrectly broken is a macro call inside a text block. > > I@T{ > > Indent text by > > .BR \[rs]n[Si] . > > T} > > I'll bet that a macro argument boundary is being misinterpreted as > > a break opportunity. This might be due to misinterpretation or > > misimplementation of the `\c` escape sequence. Or not, since > > mandoc(1) is not a *roff, and the "macros" it recognizes are not > > implemented atop a substrate of formatter requests and escape > > sequences. > > See the tbl(7) manual page distributed with mandoc(1): > > COMPATIBILITY > The mandoc(1) implementation of tbl doesn't support mdoc(7) and > man(7) macros and eqn(7) equations inside tables. > > There is also a TODO entry for that, but supporting macros inside > tbl(7) is among the hardest TODOs that exist. I sympathize. The challenges with groff that I think I understand seem only to get taller with time... > > + In fact, macro calls within tbl(1) text blocks seem to be > > largely ignored. Changes of typeface that should occur, don't. > > See, e.g., the table on page 47. > > > > + Table columns are misaligned when the headings are in bold but > > the rest of the table is not. See, e.g., the table on page 49. > > > > + The table spanning pp. 128-129 is so badly damaged that it's > > nearly incomprehensible. > > > > + mandoc(1) oversets not just the line but the page when employing > > its "semantic" glyph fallbacks. See p. 220. > > > > * Some of the widow/orphan management is cringe, but ours often can > > be too--this is one reason people want Knuth-Plass. On the other > > hand, groff's man pages (and other documents) often mitigate this > > with careful use of `ne` requests and I think mandoc(1) might be > > ignoring these. > > Yes. See roff(7) in the mandoc(1) package: > > ne [height] > Declare the need for the specified minimum vertical space > before the next trap or the bottom of the page. Currently > ignored. > > The reason for ignoring that request is that it is very hard to > implement in mandoc(1) because it constitutes a fundamental layering > violation from the mandoc perspective. Well, it's also an operation you require _only for an output format that will be paginated_. The terminal won't be--you always do what groff calls "continuous rendering", and you don't automatically hyphenate or adjust either. Thus this is further support for the proposition that mandoc(1) doesn't do typesetting. You understand that. A lot of your users don't. [...] > Again, i don't think anybody ever considered or tested what -T ps > might do with eqn(1), in much the same way as it was never considered > or tested for tbl(1). A gap. > > * Separation of man(7) paragraph tags from the paragraph body is too > > narrow; see, e.g., the bottom of p. 144. To be fair, groff man(7) > > used to have this problem, too.[...] > > > > * I observe that the mandoc(1)-generated PDF is 11 MB; ours is 1.6 > > MB. Bad old bloated GNU stuff once again, eh?[...] > > Heh. Of course not. But that mandoc(1) produces unnecessarily large > PostScript output is simply due to it having a poor understanding of > the PostScript langauge in the first place, and doing everything in > an incredibly pedestrian way. Much is explained by the fact that "mandoc -T ps" was an exploratory experiment, and "mandoc -T pdf" a thin wrapper around (or simple translator of) that experiment. > > I terminated my survey (except to peek ahead at eqn(1)) at page 223 > > of 675. I think I've seen enough to produce an informed opinion. > > > > I've attached the respective PDF documents. The different > > _ordering_ of the man page documents within is not mandoc(1)'s fault > > but merely an artifact of my laziness in employing a shell variable > > as shown above. > > > > I don't expect any of these observations to impact > > BSD/mdoc/mandoc(1) partisans' assessment of its superiority to groff > > in any way. It: > > * goes fast; > > I do *not* claim that mandoc(1) is superior to groff(1). You don't. But you have users who are overselling your work. Strangely, groff doesn't seem to suffer this problem. If someone has exhibits of people doing so, please report them to this list so that our community is aware of the distortions. I have no problem correcting the record. Other readers here might be willing to help, and they might prove a better first-line resource, as for some reason I have a reputation as an intimidating figure. (Anyone who knows me in real life appreciates what a laughable notion that is.) > What i claim is: > > 1. mandoc(1) output quality is about equal to groff(1) for -T ascii > and -T utf8, and mandoc is significantly faster in those modes. I concur. > 2. mandoc(1) output quality is vastly superior to groff(1) for -T > html, to the point that groff cannot really be takes seriously in > this respect. mandoc(1) indeed generates good HTML. groff's HTML output is measurably improved in the forthcoming 1.25, but it still has a ways to go. Let's circle back to this issue in, say, 2½ years. I have plans. In the meantime I could add an unconditional warning diagnostic to grohtml(1) such that when it runs, it warns the reader of its beta status, just as the man page does. On the other hand, I've never seen _anyone_ oversell groff's ability as an HTML document generator. Whatever juice mandoc(1)'s fanbois are into, it's some potent stuff. > 3. groff(1) output quality is vastly superior to mandoc(1) for -T ps > and -T pdf, to the point that mandoc cannot really be taken > seriously in this respect. > > > * isn't copylefted; > > * isn't in C++. > > While that is true, it is completely immaterial when it comes to real > typesetting: ability to do the job matters way more than any personal > preferance regarding programming languages or licenses. Your priorities are not the same as the boosters'. One can't truly correct people who refuse to engage with empirically measurable phenomena, but one can undercut them with frank documentation. Or by withdrawing support for output formats that were no more than an interesting experiment in the first place. That's the strongest statement you could make that mandoc(1) is _not_ in the typesetting business. > > Whether mandoc(1) faithfully manifests the principle of the Unix > > philosophy holding that a tool should "do one thing and do it well", > > I leave open to consideration. > > I doesn't really adhere to that philosophy on a technical level; groff > is closer to that philosophy technically, in so far as mandoc is one > monolithic blob whereas groff (the package) consists of multiple > programs that each do one thing well and can be piped together. Right. > That technical failure of mandoc at the Unix philosophy is in part > intentional because one can argue that there is no such failure on > a user-oriented level. From the user perspective, the one thing > is "read a manual" and the user should not need to care that this > one task can be broken down into multiple subtasks of source file > searching by man(1), preprocessing, formatting, and postprocessing. The thing is that an author of a *roff system had a broader conception of what it was for than reading man pages at a terminal. Those who were up on their Vannevar Bush or Ted Nelson might even have conceived vaguely of what we now refer to as a "web browser", but in any case the scope of the tool was by no means limited to technical manuals. By 1981, when Kernighan had refactored Ossanna troff into typesetter- independent troff, it cannot have been hard to imagine that output devices would become parameterized in capability in many different ways. Thus Kernighan's foresighted "device extension command" and the then-new `\X` escape sequence, which did not exist in Ossanna troff. > Admittedly, the mandoc(1) command line options are easier to get > right than groff(1)'s - most of the time, mandoc(1) needs none > whatsoever. Than again, the man-db + groff(1) combo is far from > bad in this respect - no user needs to construct pipes by hand, the > man(1) and groff(1) wrapper programs handle all that reasonably > well, albeit groff(1) (but not man(1)) occasionally requires a few > arcane command line options. Yes. Layering, and the separation of "librarian" concerns (man(1)) from "rendering" concerns (groff(1)), assists the user here. > Also, mandoc(1) adheres to the Unix one-task philosophy in so far > as the one thing it does is "reading manuals" but not "general > purpose typography" - which is obviously a downside at the same > time as allowing some simplification. And even that aspect is not > followed strictly, in part due to historical reasons: Kristaps is > an adventurous child who loves to play, so he wondered about > PostScript and added the -T ps mode (which is arguably out of scope > for are pure manual reader, and has consequently be much neglected). That's why I gently suggest the radical possibility that you simply withdraw these features from mandoc(1). I don't think any lesser measure, even copious disclaimers in its own man pages, and emphatic steering of the reader to groff specifically if typesetting is what they want, will make a serious impact on the problem of partisan boosters promising more than mandoc(1) has chosen as its mission to deliver. > I am guilty of adding even more stuff that has little to do with > the one task "read manuals", for example -T markdown output mode, > simply because i could never come up with a reasonable idea where > else to put such stuff, given that the mandoc(1) programs > (intentionally!) lacks a modular design on the command line level - > of course, the source code organization is modular just fine. I think you have an easier task here, because Markdown output can be conceived as simply another variation on typewriting, cf. typesetting. It might be interesting to someday add a gromarkdown(1) output driver for groff. For now, I'll await expression of demand. :) Regards, Branden [1] preconv(1) will seek its input if it can, to make a better guess of the character encoding of the input stream.
signature.asc
Description: PGP signature
