mandoc: workaround lack of macro parsing in list -width

GNU tools parse macros in the -width argument of lists.  mandoc does not,
so it calculates an excessive width.  This often squeezes the text into
a very narrow column, especially in nested lists.

Implement the easy workaround suggested in the TODO list.  When there is
only one macro, at the beginning of the -width argument, this fixes the
formatting as well as a complete solution.

Reviewed by:	bapt
Relnotes:	yes
MFC after:	1 week
Sponsored by:	Dell EMC Isilon
Differential Revision:	https://reviews.freebsd.org/D35245
This commit is contained in:
Eric van Gyzen 2022-05-17 12:46:59 -05:00
parent 89e58b955c
commit 9f6a619a7d
2 changed files with 49 additions and 7 deletions

View File

@ -563,9 +563,7 @@ are mere guesses, and some may be wrong.
reported again by Franco Fichtner Fri, 27 Sep 2013 21:02:28 +0200
reported again by Bruce Evans Fri, 17 Feb 2017 21:22:44 +0100 via bapt@
loc *** exist *** algo *** size ** imp ***
An easy partial fix would be to just skip the first word if it starts
with a dot, including any following white space, when measuring.
loc * exist * algo * size * imp ***
An easy partial fix has been implemented as skip_leading_dot_word().
- The \& zero-width character counts as output.
That is, when it is alone on a line between two .Pp,

View File

@ -1818,6 +1818,45 @@ post_bl_block(POST_ARGS)
}
}
/*
* If "in" begins with a dot, a word, and whitespace, return a dynamically
* allocated copy of "in" that skips all of those. Otherwise, return NULL.
*
* This is a partial workaround for the TODO list item beginning with:
* - When the -width string contains macros, the macros must be rendered
*/
static char *
skip_leading_dot_word(const char *in)
{
const char *iter = in;
const char *space;
if (*iter != '.')
return NULL;
iter++;
while (*iter != '\0' && !isspace(*iter))
iter++;
/*
* If the dot was followed by space or NUL,
* do not skip anything.
*/
if (iter == in + 1)
return NULL;
space = iter;
while (isspace(*iter))
iter++;
/*
* If the word was not followed by space,
* do not skip anything.
*/
if (iter == space)
return NULL;
return strdup(iter);
}
/*
* If the argument of -offset or -width is a macro,
* replace it with the associated default width.
@ -1827,18 +1866,23 @@ rewrite_macro2len(struct roff_man *mdoc, char **arg)
{
size_t width;
enum roff_tok tok;
char *newarg;
newarg = NULL;
if (*arg == NULL)
return;
else if ( ! strcmp(*arg, "Ds"))
width = 6;
else if ((tok = roffhash_find(mdoc->mdocmac, *arg, 0)) == TOKEN_NONE)
return;
else
else if ((tok = roffhash_find(mdoc->mdocmac, *arg, 0)) != TOKEN_NONE)
width = macro2len(tok);
else if ((newarg = skip_leading_dot_word(*arg)) == NULL)
return;
free(*arg);
mandoc_asprintf(arg, "%zun", width);
if (newarg != NULL)
*arg = newarg;
else
mandoc_asprintf(arg, "%zun", width);
}
static void