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

NetBSD Home
NetBSD PR Database Search

(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.