1
0
mirror of https://github.com/skeeto/w64devkit.git synced 2026-10-23 06:08:56 +03:00

Let MANROFFOPT choose ragged-right manual pages

nroff now accepts groff's -d option to define a string, and man appends
$MANROFFOPT to the nroff command line, as man-db does. Since nroff
already honors the man(7) AD string, MANROFFOPT=-dAD=l sets pages
ragged-right instead of adjusting them to both margins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Christopher Wellons
2026-10-22 20:48:38 -04:00
parent 4fbc4d1f72
commit 2845baff59
4 changed files with 102 additions and 21 deletions

View File

@@ -1,4 +1,4 @@
.TH MAN 1 2026-10-20 "w64devkit" "w64devkit Manual"
.TH MAN 1 2026-10-22 "w64devkit" "w64devkit Manual"
.SH NAME
man \- display manual pages
.SH SYNOPSIS
@@ -157,7 +157,10 @@ The page is its standard input, and its options are
.BI \-T charset\fR,
.BI \-rLL= w n\fR,
and
.BI \-rLT= w n\fR.
.BI \-rLT= w n\fR,
followed by the value of
.B MANROFFOPT
when that is set.
Its output and error messages go to the pager.
.PP
The
@@ -323,6 +326,18 @@ still counts, and then nothing is displayed.
.B MANPATH
Manual directories to search first, separated by semicolons.
.TP
.B MANROFFOPT
Further options for
.BR nroff ,
added to its command line, where
.B sh
splits them into words.
For example,
.B \-dAD=l
sets man(7) pages ragged-right instead of adjusting them to both
margins; see
.BR nroff (1).
.TP
.B PAGER
The pager, when
.B MANPAGER
@@ -413,6 +428,15 @@ Save a page as plain text, formatted for a 100-column display:
$ COLUMNS=100 man gcc >gcc.txt
.EE
.RE
.PP
Show pages with a ragged right margin, for example from
.IR $HOME/.profile :
.PP
.RS 4
.EX
export MANROFFOPT=\-dAD=l
.EE
.RE
.SH NOTES
Differences from the
.B man

View File

@@ -1,4 +1,4 @@
.TH NROFF 1 2026-10-20 "w64devkit" "w64devkit Manual"
.TH NROFF 1 2026-10-22 "w64devkit" "w64devkit Manual"
.SH NAME
nroff \- format manual pages for a terminal
.SH SYNOPSIS
@@ -8,6 +8,7 @@ nroff \- format manual pages for a terminal
.RB [ \-Tascii " | " \-Tutf8 ]
[\fB\-rLL=\fIN\fBn\fR]
[\fB\-r\fIreg\fB=\fIN\fR]
[\fB\-d\fIname\fB=\fIstring\fR]
.RB [ \-w ]
.RI [ file ...]
.SH DESCRIPTION
@@ -57,7 +58,9 @@ a line also breaks after an em dash written as
.B \e(em
between two letters.
man(7) pages are adjusted to both margins, as in groff, unless the page
asks otherwise; mdoc(7) pages are left-aligned, as in mandoc.
asks otherwise or
.B \-dAD=l
is given; mdoc(7) pages are left-aligned, as in mandoc.
.PP
Bold text is written between the SGR escape sequences
.B ESC[1m
@@ -562,9 +565,10 @@ are approximated.
.SH OPTIONS
Options are not grouped.
The arguments of
.B \-T
.BR \-T ,
.BR \-r ,
and
.B \-r
.B \-d
may be attached or separate, and
.B \-\-
ends the options.
@@ -622,6 +626,37 @@ which
.BR man (1)
passes, has no effect.
.TP
\fB\-d\fIname\fB=\fIstring\fR
Define the string
.I name
as
.IR string ,
as
.B .ds
does.
Without
.BR = ,
the first character is the name and the rest is the string, as in
groff.
A man(7) page reads the string
.B AD
at
.B .TH
and at each paragraph macro to choose its adjustment, as groff does:
.B l
sets text ragged-right,
.B c
centers it,
.B r
aligns it right, and anything else, the default, adjusts it to both
margins.
.BR man (1)
passes this option from
.BR MANROFFOPT ,
so
.B MANROFFOPT=\-dAD=l
gives ragged-right pages.
.TP
.B \-w
Warn on standard error, with file names and line numbers, about unknown
macros, requests, escapes, and glyphs, undefined strings,

View File

@@ -9,11 +9,12 @@ Run the formatter in the manpath element, or in the user's directory for
an explicit path, so that .so requests in page bodies resolve. Look up
x86_64-w64-mingw32-NAME and i686-w64-mingw32-NAME as NAME when there is
no page under the full name. Accept backslashes in absolute paths, and
CRLF in .so stubs.
CRLF in .so stubs. Append $MANROFFOPT to the formatter options, as
man-db does, so that, e.g., MANROFFOPT=-dAD=l sets pages ragged-right.
---
miscutils/man.c | 90 +++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 60 insertions(+), 30 deletions(-)
miscutils/man.c | 92 +++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 62 insertions(+), 30 deletions(-)
--- a/miscutils/man.c
+++ b/miscutils/man.c
@@ -70,7 +71,13 @@ CRLF in .so stubs.
//testcase:
// cd /usr/share/man/man2
// man ./path_resolution.2.gz
@@ -163,13 +180,20 @@
@@ -158,18 +175,27 @@
open_zipped(man_filename, /*die_if_not_compressed:*/ 0); /* guaranteed to use fd 0 (STDIN_FILENO) */
if (man) {
int w = get_terminal_width(-1);
+ const char *opt = getenv("MANROFFOPT");
if (w > 10)
w -= 2;
/* "2>&1" is added so that nroff errors are shown in pager too.
* Otherwise it may show just empty screen.
*/
@@ -78,8 +85,9 @@ CRLF in .so stubs.
- G.tbl, G.nroff, w, w,
- G.pager);
- } else {
+ cmd = xasprintf("%s -T%s -rLL=%un -rLT=%un%s%s",
+ cmd = xasprintf("%s -T%s -rLL=%un -rLT=%un%s%s%s%s",
+ G.nroff, GetACP() == CP_UTF8 ? "utf8" : "ascii", w, w,
+ opt ? " " : "", opt ? opt : "",
+ G.pager ? " 2>&1 | " : "", G.pager ? G.pager : "");
+ } else if (G.pager) {
cmd = xstrdup(G.pager);
@@ -95,7 +103,7 @@ CRLF in .so stubs.
free(cmd);
return 1;
}
@@ -273,8 +297,7 @@
@@ -273,8 +299,7 @@
char *token[2];
#if ENABLE_PLATFORM_MINGW32
char **ptr;
@@ -105,7 +113,7 @@ CRLF in .so stubs.
#endif
INIT_G();
@@ -285,8 +308,9 @@
@@ -285,8 +310,9 @@
/* add system drive prefix to filenames, if necessary */
for (ptr = argv; *ptr; ++ptr) {
if (strchr(*ptr, '/') || strchr(*ptr, '\\'))
@@ -116,7 +124,7 @@ CRLF in .so stubs.
chdir_system_drive();
#endif
@@ -309,8 +333,6 @@
@@ -309,8 +335,6 @@
if (!token[1])
continue;
if (strcmp("DEFINE", token[0]) == 0) {
@@ -125,7 +133,7 @@ CRLF in .so stubs.
G.nroff = if_redefined(G.nroff, "nroff", token[1]);
G.pager = if_redefined(G.pager, "pager", token[1]);
} else
@@ -328,15 +350,9 @@
@@ -328,15 +352,9 @@
#if ENABLE_PLATFORM_MINGW32
/* allow man pages to be stored relative to the executable */
@@ -144,7 +152,7 @@ CRLF in .so stubs.
#else
if (!man_path_list) {
static const char *const mpl[] ALIGN_PTR = { "/usr/man", "/usr/share/man", NULL };
@@ -356,7 +372,10 @@
@@ -356,7 +374,10 @@
if (!isatty(STDOUT_FILENO)) {
putenv((char*)"GROFF_NO_SGR=1");
@@ -156,7 +164,7 @@ CRLF in .so stubs.
}
/* is 1st ARG a SECTION? */
@@ -371,9 +390,12 @@
@@ -371,9 +392,12 @@
const char *cur_path;
int cur_mp;
int found = 0;
@@ -171,7 +179,7 @@ CRLF in .so stubs.
goto check_found;
}
@@ -383,7 +405,8 @@
@@ -383,7 +407,8 @@
const char *cur_sect = sec_list;
/* is MANPAGE of the form NAME.SECTION? */
@@ -181,7 +189,7 @@ CRLF in .so stubs.
if (sect_ext && is_section_name(conf_sec_list, sect_ext + 1)) {
*sect_ext = '\0';
cur_sect = sect_ext + 1;
@@ -402,7 +425,7 @@
@@ -402,7 +427,7 @@
cur_path,
"cat\0man" + (cat0man1 * 4),
sect_len, cur_sect,
@@ -190,7 +198,7 @@ CRLF in .so stubs.
sect_len, cur_sect);
found_here = show_manpage(man_filename, cat0man1, 0);
found |= found_here;
@@ -421,6 +444,13 @@
@@ -421,6 +446,13 @@
}
check_found:
if (!found) {

View File

@@ -6919,12 +6919,14 @@ static void run(Ctx *c, Arena scratch)
static void usage(Output *out)
{
print(out, S(
"usage: nroff [-man|-mdoc] [-Tascii|-Tutf8] [-rLL=Nn] [-w] [FILE...]\n"
"usage: nroff [-man|-mdoc] [-Tascii|-Tutf8] [-rLL=Nn] [-dNAME=STR] [-w]"
" [FILE...]\n"
" -m* accepted and ignored; the format is detected\n"
" -t accepted and ignored; tbl is built in\n"
" -Tascii ASCII output (default)\n"
" -Tutf8 UTF-8 output\n"
" -rLL=N line length (default: $MANWIDTH, $COLUMNS, or 78)\n"
" -dAD=l ragged-right man(7) pages (also c, r; default b)\n"
" -w warn about unsupported input\n"
" -h print this message\n"
"With no FILE, or when FILE is -, read standard input.\n"));
@@ -7007,6 +7009,18 @@ static i32 nroff(i32 argc, u8 **argv, Plt *plt, Arena mem)
Scaled v = scaled(val, 'u');
if (v.ok) setreg(c, key, v.value);
}
} else if (arg.data[1] == 'd') {
Str d = cuthead(arg, 2);
if (!d.len && i+1<argc) {
d = import(argv[++i]);
}
Cut kv = cut(d, '=');
if (!kv.ok) {
// groff: -dcs defines the one-character name c
kv.head = takehead(d, 1);
kv.tail = cuthead(d, 1);
}
if (kv.head.len) setstring(c, kv.head, kv.tail);
} else if (equals(arg, S("-w")) || startswith(arg, S("-w")) ||
startswith(arg, S("-W"))) {
c->warn = arg.data[1] == 'w';