From e05929a09a697de3d2eb14d0f0a087a6fae22e11 Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 10 Sep 2024 17:40:08 -0700 Subject: [PATCH] Don't output a newline after `.SH` On macOS, `makewhatis` fails to parse `NAME` headings in man pages if there's a newline between `.SH` and `NAME`. This is silly, but I can't exactly get them to update it: ``` $ /usr/libexec/makewhatis -v -o /tmp/whatis outputs/out/share/man | head man directory outputs/out/share/man outputs/out/share/man/man5 reading outputs/out/share/man/man5/nix.conf.5 ignoring junk description "" reading outputs/out/share/man/man5/nix-profiles.5 ignoring junk description "" ``` Through a circuitous sequence of events, this results in shell completions for the `man` command being broken in Fish for man pages generated with Lowdown: https://git.lix.systems/lix-project/lix/issues/515 This patch, then, replaces the trailing newline after blocks with a trailing space for `.SH` blocks which only contain normal text in `nroff` output. The restriction that `.SH` blocks only contain normal text is because (for example) this doesn't render correctly: ``` .SH a \fIhttps://foo.com\fR now \fBworld\fR <\fIhttps://bar.com\fR> b ``` --- nroff.c | 29 +++++++++++++++++++++---- regress/diff/metadata-add.man | 3 +-- regress/diff/metadata-remove.man | 3 +-- regress/shift-heading-level-by-neg.man | 6 ++--- regress/shift-heading-level-by-zero.man | 3 +-- regress/simple.man | 3 +-- 6 files changed, 31 insertions(+), 16 deletions(-) diff --git a/nroff.c b/nroff.c index 4154ce3d..85d8c325 100644 --- a/nroff.c +++ b/nroff.c @@ -84,6 +84,7 @@ struct bnode { unsigned int colour; /* if BNODE_COLOUR */ #define BFONT_BLUE 0x01 #define BFONT_RED 0x02 + int trailingspace; /* BSCOPE_BLOCK .SH */ TAILQ_ENTRY(bnode) entries; }; @@ -369,6 +370,7 @@ bqueue_flush(const struct nroff *st, struct lowdown_buf *ob, const struct bnode *bn, *chk, *next; const char *cp; int nextblk; + char trailingchar; TAILQ_FOREACH(bn, bq, entries) { nextblk = 0; @@ -515,11 +517,11 @@ bqueue_flush(const struct nroff *st, struct lowdown_buf *ob, return 0; } - /* Finally, trailing newline. */ - + /* Finally, trailing newline/space. */ + trailingchar = bn->trailingspace ? ' ' : '\n'; if (nextblk && ob->size > 0 && - ob->data[ob->size - 1] != '\n' && - !hbuf_putc(ob, '\n')) + ob->data[ob->size - 1] != trailingchar && + !hbuf_putc(ob, trailingchar)) return 0; } @@ -840,6 +842,7 @@ rndr_header(struct nroff *st, struct bnodeq *obq, struct lowdown_buf *buf = NULL; const struct lowdown_buf *nbuf; int rc = 0; + const struct lowdown_node *child = NULL; level = (ssize_t)n->rndr_header.level + st->headers_offs; if (level < 1) @@ -857,6 +860,24 @@ rndr_header(struct nroff *st, struct bnodeq *obq, bqueue_block(obq, ".SS"); if (bn == NULL) return 0; + + if (level == 1 + && (child = TAILQ_FIRST(&n->children)) + && !TAILQ_NEXT(child, entries)) { + /* This is a first-level header and there is exactly one child. + * + * If the child is a `LOWDOWN_NORMAL_TEXT`, put + * a single space between the `.SH` and the + * heading instead of a newline. + * + * This renders headers as (e.g.) `.SH + * SYNOPSIS` instead of `.SH\nSYNOPSIS`, which + * is important for macOS `makewhatis`. + * + * See: https://github.com/kristapsdz/lowdown/pull/138 + */ + bn->trailingspace = child->type == LOWDOWN_NORMAL_TEXT; + } TAILQ_CONCAT(obq, bq, entries); st->post_para = 1; return 1; diff --git a/regress/diff/metadata-add.man b/regress/diff/metadata-add.man index 6c9d4953..6660b694 100644 --- a/regress/diff/metadata-add.man +++ b/regress/diff/metadata-add.man @@ -1,6 +1,5 @@ .\" -*- mode: troff; coding: utf-8 -*- .TH "" "7" "" -.SH -section +.SH section .LP body diff --git a/regress/diff/metadata-remove.man b/regress/diff/metadata-remove.man index 6c9d4953..6660b694 100644 --- a/regress/diff/metadata-remove.man +++ b/regress/diff/metadata-remove.man @@ -1,6 +1,5 @@ .\" -*- mode: troff; coding: utf-8 -*- .TH "" "7" "" -.SH -section +.SH section .LP body diff --git a/regress/shift-heading-level-by-neg.man b/regress/shift-heading-level-by-neg.man index 9bc57fbf..d192a0fa 100644 --- a/regress/shift-heading-level-by-neg.man +++ b/regress/shift-heading-level-by-neg.man @@ -1,9 +1,7 @@ -.SH -header 1 +.SH header 1 .LP 1 -.SH -header 2 +.SH header 2 .LP 2 .SS diff --git a/regress/shift-heading-level-by-zero.man b/regress/shift-heading-level-by-zero.man index bdf44eea..fad61bfe 100644 --- a/regress/shift-heading-level-by-zero.man +++ b/regress/shift-heading-level-by-zero.man @@ -1,5 +1,4 @@ -.SH -header 1 +.SH header 1 .LP 1 .SS diff --git a/regress/simple.man b/regress/simple.man index 0c356e02..1a0489f9 100644 --- a/regress/simple.man +++ b/regress/simple.man @@ -1,5 +1,4 @@ -.SH -An h1 header +.SH An h1 header .LP Paragraphs are separated by a blank line. .PP