NetBSD Problem Report #58579
From www@netbsd.org Sun Aug 11 06:17:05 2024
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
client-signature RSA-PSS (2048 bits) client-digest SHA256)
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id 51EDD1A9242
for <gnats-bugs@gnats.NetBSD.org>; Sun, 11 Aug 2024 06:17:05 +0000 (UTC)
Message-Id: <20240811061704.22A661A9243@mollari.NetBSD.org>
Date: Sun, 11 Aug 2024 06:17:04 +0000 (UTC)
From: rvp@SDF.ORG
Reply-To: rvp@SDF.ORG
To: gnats-bugs@NetBSD.org
Subject: man(1) should make use of terminal width
X-Send-Pr-Version: www-1.0
>Number: 58579
>Category: bin
>Synopsis: man(1) should make use of terminal width
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sun Aug 11 06:20:00 +0000 2024
>Last-Modified: Tue Aug 13 05:35:01 +0000 2024
>Originator: RVP
>Release: NetBSD/amd64 10.99.11
>Organization:
>Environment:
NetBSD/amd64 10.99.11
>Description:
mandoc(1) has a `-O width=NNN' option which can be used for displaying
man-pages at some specified width. But, man(1) makes no use of this,
always formatting the display for 80 columns. It can do better...
>How-To-Repeat:
`man anything' on a wide terminal, then note the wasted real-estate on
the right.
>Fix:
This old patch (but, still applies cleanly) is the most non-instrusive
way that I could think of (ie. aside from fiddling with /etc/man.conf)
to fix this wastage. It makes man honour a MANWIDTH env. var. which can
be set to a COLUMN value or the special token `tty' which just means use
the current tty-width.
---START patch---
diff -urN a/man/man.c b/man/man.c
--- a/man/man.c 2020-04-09 11:28:32.000000000 +0000
+++ b/man/man.c 2020-11-14 08:21:48.576113574 +0000
@@ -44,6 +44,7 @@
#endif
#endif /* not lint */
+#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/stat.h>
@@ -51,6 +52,7 @@
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <glob.h>
@@ -101,6 +103,7 @@
/* other misc stuff */
const char *pager; /* pager to use */
size_t pagerlen; /* length of the above */
+ int manwidth; /* pass -O width= to mandoc(1) if > RMRG */
const char *machine; /* machine */
const char *machclass; /* machine class */
};
@@ -120,6 +123,9 @@
static void addpath(struct manstate *, const char *, size_t, const char *);
static const char *getclass(const char *);
static void printmanpath(struct manstate *);
+static int get_mw(void);
+static char *ins_mw(const char *, const char *, struct manstate *);
+
/*
* main function
@@ -222,6 +228,7 @@
else
m.pager = _PATH_PAGER;
m.pagerlen = strlen(m.pager);
+ m.manwidth = get_mw();
}
}
@@ -804,8 +811,11 @@
(void)cleanup();
exit(EXIT_FAILURE);
}
+ if ((b = ins_mw(fmt, "/usr/bin/mandoc", mp)) != NULL)
+ fmt = b;
(void)snprintf(buf, sizeof(buf), "%s > %s", fmt, tpath);
(void)snprintf(cmd, sizeof(cmd), fmtcheck_ok(buf, "%s"), p);
+ free(b);
(void)system(cmd);
(void)close(fd);
if ((*pathp = strdup(tpath)) == NULL) {
@@ -1077,3 +1087,61 @@
globfree(&pg);
}
}
+
+/*
+ * get_mw --
+ * Return a user-defined MANWIDTH or determine one if set to "tty",
+ * or -1 on errors.
+ */
+int
+get_mw(void)
+{
+ char *p, *ep;
+ int wid;
+
+ if ((p = getenv("MANWIDTH")) == NULL)
+ return -1;
+ if (strcmp(p, "tty") == 0) {
+ struct winsize ws;
+ if (!isatty(STDOUT_FILENO) ||
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0)
+ return -1;
+ return ws.ws_col;
+ }
+ errno = 0;
+ wid = (int)strtol(p, &ep, 10);
+ if (ep == p || *ep != '\0' || errno)
+ return -1;
+ return wid;
+}
+
+/*
+ * ins_mw --
+ * Insert a " -O width=NN " option right after the "/usr/bin/mandoc"
+ * command.
+ * Turns:
+ * 1. _build stuff /usr/bin/mandoc ->
+ * _build stuff /usr/bin/mandoc -O width=NN
+ * 2. _build stuff /usr/bin/mandoc stuff %s ->
+ * _build stuff /usr/bin/mandoc -O width=NN stuff %s
+ * etc.
+ * We do it this way because mandoc(1) doesn't allow options after
+ * filenames, so a simple append won't work.
+ */
+static char*
+ins_mw(const char* line, const char* s, struct manstate* mp)
+{
+ enum { RMRG = 3 }; /* Right margin to match mandoc's LHS */
+ const char* p;
+ char* ret;
+
+ if (mp->manwidth <= RMRG)
+ return NULL;
+ if ((p = strstr(line, s)) == NULL)
+ return NULL; /* not mandoc */
+ p += strlen(s);
+ if (asprintf(&ret, "%.*s -O width=%d %s",
+ (int)(p - line), line, mp->manwidth - RMRG, p) == -1)
+ return NULL;
+ return ret;
+}
---END patch---
>Audit-Trail:
From: matthew green <mrg@eterna23.net>
To: gnats-bugs@netbsd.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Subject: re: bin/58579: man(1) should make use of terminal width
Date: Sun, 11 Aug 2024 16:24:00 +1000
please, not by default. the linux default drives me insane.
.mrg.
From: RVP <rvp@SDF.ORG>
To: matthew green <mrg@eterna23.net>
Cc: gnats-bugs@netbsd.org
Subject: re: bin/58579: man(1) should make use of terminal width
Date: Sun, 11 Aug 2024 06:46:31 +0000 (UTC)
On Sun, 11 Aug 2024, matthew green wrote:
> please, not by default. the linux default drives me insane.
>
Patch won't do anything if you don't set a `MANWIDTH='.
-RVP
From: Valery Ushakov <uwe@stderr.spb.ru>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/58579: man(1) should make use of terminal width
Date: Mon, 12 Aug 2024 12:17:42 +0300
This patch assumes man uses /usr/bin/mandoc to format the man pages
(what about /usr/pkg/bin/mandoc when using bsd userland commands on a
linux system, say?) and hardcodes knowledge of its -Owidth option. I
don't think this is the right direction.
As I noted in a related mail thread a few years ago, one can *almost*
make MANWIDTH do the riht thing without any changes to the man command
with something like:
_build .[1-9ln] /usr/bin/mandoc ${COLUMNS+-Owidth=${MANWIDTH:-$COLUMNS}} %s
which, unfortunately, 1) relies on COLUMNS bashism to get the terminal
size and 2) needs to add test -t 0 logic which quickly becomes
unwieldy for a single line command.
Like phone I find full-width manpage in a large terminals unusable, so
the feature I miss w.r.t. MANWIDTH is constraints, an ability to
express: please, use full terminal width if it's below 108 columns,
but don't use more - I don't find 200 characters lines comfortable to
read, also, don't try to use less than, say 72, most man pages with
offset lists/displays won't fit into that anyway.
Any proposed solution must also support (being applicable to) nroff.
On obscenely fast machines the pro-mandoc speed argument is rather
weak and a user should be able to use the old
/usr/bin/nroff -msafer -man
for its _build command
For the record, the way to tell nroff the page width with either old
man or mandoc is by setting number registers LL (length of line, like
.ll directive) and LT (length of title, like .lt) in 'n' units, e.g.
to format a man page to the width of 120 characters:
nroff -rLL=120n -rLT='\n(LL' -Tman
-uwe
From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/58579: man(1) should make use of terminal width
Date: Tue, 13 Aug 2024 05:34:25 +0000 (UTC)
On Mon, 12 Aug 2024, gnats-admin@netbsd.org wrote:
> This patch assumes man uses /usr/bin/mandoc to format the man pages
> (what about /usr/pkg/bin/mandoc when using bsd userland commands on a
> linux system, say?) and hardcodes knowledge of its -Owidth option.
>
Yes, all that is deliberate: if the formatter isn't exactly `/usr/bin/mandoc',
do nothing; if MANWIDTH isn't set (or bogus), do nothing; etc.
> I don't think this is the right direction.
>
Oh, well... I can keep it as a local patch.
> As I noted in a related mail thread a few years ago, one can *almost*
> make MANWIDTH do the riht thing without any changes to the man command
> with something like:
>
> _build .[1-9ln] /usr/bin/mandoc ${COLUMNS+-Owidth=${MANWIDTH:-$COLUMNS}} %s
>
Yeah, I had a shell-script `pcols' for that:
_build .[1-9ln] /usr/bin/mandoc -O width=$(pcols)
but, adding it everywhere, then the merging _another_ file during updates was
just a headache.
> [...]
>
> Any proposed solution must also support (being applicable to) nroff.
> On obscenely fast machines the pro-mandoc speed argument is rather
> weak and a user should be able to use the old
>
> /usr/bin/nroff -msafer -man
>
> for its _build command
>
Right. I did think up a way to make this general--by introducing a new control
keyword. Like:
_build .[1-9ln] ##_cmd## %s
...
_cmd /usr/bin/mandoc -O width=%V
# _cmd /usr/bin/nroff -rLL=%Vn -Tman
then, replace %V with the column value and substitute `##_cmd##' with the
expanded string. But, again, this is even more intrusive... which is why I
went with the patch I sent in.
> For the record, the way to tell nroff the page width with either old
> man or mandoc is by setting number registers LL (length of line, like
> .ll directive) and LT (length of title, like .lt) in 'n' units, e.g.
> to format a man page to the width of 120 characters:
>
> nroff -rLL=120n -rLT='\n(LL' -Tman
>
LL I knew, but not LT. Thanks.
-RVP
(Contact us)
$NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2024
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.