From: Alejandro Colomar <alx@kernel.org>
To: Seth McDonald <sethmcmail@pm.me>
Cc: linux-man@vger.kernel.org,
"Douglas McIlroy" <douglas.mcilroy@dartmouth.edu>,
"G. Branden Robinson" <branden@debian.org>,
наб <nabijaczleweli@nabijaczleweli.xyz>
Subject: Re: [RFC PATCH v1 0/2] New sman(1) script
Date: Tue, 27 Jan 2026 14:47:40 +0100 [thread overview]
Message-ID: <aXixqbsZcY-tbCJ4@devuan> (raw)
In-Reply-To: <cover.1769497513.git.sethmcmail@pm.me>
[-- Attachment #1: Type: text/plain, Size: 7421 bytes --]
[CC += Doug, Branden, наб]
Hi Seth!
On 2026-01-27T09:20:26+0000, Seth McDonald wrote:
> G'day,
>
> When parsing man pages, I've noticed I'm often only interested in a
> particular set of sections within the page (e.g. SYNOPSIS, HISTORY).
> And since skimming through the page to get to these sections can get
> monotonous, I wrote up a small bash script to automate the process.
Agree. I wrote mansect(1) for the same exact reason.
> As far as I can tell, no program in src/bin/ can currently do this. The
> closest is mansect(1), but that outputs the source code rather than the
> rendered page.
You could use mansect(1) for that, and pipe it to man(1) (or groff(1)).
$ mansect 'STANDARDS|HISTORY' man2/chmod.2 \
| MANWIDTH=64 man /dev/stdin \
| cat;
chmod(2) System Calls Manual chmod(2)
STANDARDS
POSIX.1‐2024.
HISTORY
chmod()
SVr4, POSIX.1‐1988, 4.4BSD.
fchmod()
SVr4, 4.4BSD, SUSv1, POSIX.1‐1996.
fchmodat()
POSIX.1‐2008. Linux 2.6.16, glibc 2.4.
AT_SYMLINK_NOFOLLOW
POSIX.1‐2008, glibc 2.32, Linux 6.5.
Linux man‐pages (unreleased) (date) chmod(2)
> So I've improved the script somewhat and written a brief
> man page for it, as included in this patch set.
That covers the main use case of mansect(1), so I think this specialized
wrapper could be useful.
> The main advantage to this script as opposed to manually awk(1)ing or
> sed(1)ing man pages is it can preserve the bold/italic formatting in a
> rendered man page. It currently does so by using sed(1) to locate the
> section headers with regex which includes the relevant ANSI escape codes
> dictating bold and regular text.
Agree.
> I would consider this script a WIP still, and likely shouldn't yet be
> pushed without further edits. The purpose of this patch set is to gauge
> interest in and comments on this script, moreso than to be immediately
> applied to the repo.
I'm somewhat interested. I think I didn't write it myself back then
because I wasn't yet sure if that was the good design. With time, I
think it makes sense to write it.
One of the question I still ask myself about it is whether it should use
find(1) or `man -w` to find the file names. That is, should it accept
manual page names and search in the system, or should the user decide by
using find(1) or `man -w` explicitly and piping it to mansect(1)?
find man2/ -type f | xargs mansect 'STANDARD|SHISTORY' | man /dev/stdin;
man -w printf.3 | xargs mansect 'STANDARD|SHISTORY' | man /dev/stdin;
vs
mansect 'STANDARD|SHISTORY' man2/ | man /dev/stdin;
mansect 'STANDARD|SHISTORY' printf.3 | man /dev/stdin;
I still think when in doubt, it's better to keep it simple, so I use
find(1), and let users find the files with man(1) if they need, and
run a pipe.
Back then I also opted for the simplicity of allowing users to decide
the formatter with which to format the manual page, which BTW is useful
to test different ones (mandoc(1), groff(1)). However, having a wrapper
that calls man(1) seems useful.
> As an example, the script currently re-renders the whole man page for
> each section in a for loop, rather than printing each section from the
> same rendered page, which would likely be more performant.
I honestly can't read that script. My ability to read other people's
bash(1) scripts is quite limited. :)
About the interface, I think I like more the interface of mansect(1),
which is
mansect section [file ...]
I think that's ideal. We don't need an argument like man(1)'s -s,
because that would be more easily specified as
mansectf LIBRARY printf.3;
The .3 disambiguates without needing a separate argument. However,
I don't think we want to do librarian work here, and think we should
entirely refrain from accepting manual page names like man(1). I think
we should only accept file names. It should be trivial for someone to
use
man -w printf.3 | xargs mansectf LIBRARY;
That simplifies the parsing logic. By having all non-trailing arguments
be mandatory, the interface is more obvious, and easier to remember.
Almost all Unix programs have such an interface, where there are fixed
arguments, and then goes a possibly-empty list of files (or file-like
entities) on which to work, and when the list is empty, the file is
/dev/stdin.
About specifying several sections, I prefer using a single argument, for
the same reasons: having just one mandatory argument with that meaning,
and then a list of files. You can use '|' within the section argument
to specify more than one (this is documented in mansect(1)).
man -w printf.3 | xargs mansectf 'LIBRARY|STANDARDS';
Then, about the implementation, it checks the existence of commands,
which is unnecessary: the shell will complain for us if they don't
exist.
$ foo
bash: foo: command not found
Keep it simple.
Then you export a few things:
+[[ $MAN_KEEP_FORMATTING ]] && export MAN_KEEP_FORMATTING=1
+[[ $MANWIDTH ]] && export MANWIDTH
That seems redundant. If it is already exported, the childs will
inherit that.
And then about the main work, it can be done by calling mansect(1) in
a pipeline.
With that in mind, I've written my own approach, which I've called
mansectf.
$ cat src/bin/mansectf;
#!/bin/bash
#
# Copyright, the authors of the Linux man-pages project
# SPDX-License-Identifier: GPL-3.0-or-later
set -Eefuo pipefail;
mansect "$@" \
| man /dev/stdin;
Does this work for you? I look at it and wonder if it's worth
a separate script, but then it might be useful for people who are less
experienced with man(1). To be fair, few people know that man(1) can
accept stdin, and even if they know, sometimes convenience wrappers
improve readability: for example, printf(1) is unnecessary given that
fprintf(3) exists, yet it's thoroughly used and I find it essential.
printf("foo");
fprintf(stdout, "foo");
So, I think such a thin wrapper can have its place, as it's the main use
case of mansect(1).
> I also named
> the script sman(1) primarily because I can't think of a better name.
There already exist two programs with that name:
$ apt-file find bin/sman
axiom: /usr/lib/axiom-20210105dp1/bin/sman
fricas: /usr/lib/fricas/target/x86_64-pc-linux-gnu/bin/sman
Alternatively, I've thought of calling it mansectf(1), where the
trailing 'f' means 'formatted' (as in printf(1)). After all, this is
a thin wrapper around mansect(1) that formats the output.
> Feel free to give your thoughts!
I've CCed a few people to hear their thoughts.
Have a lovely day!
Alex
>
> Seth McDonald (2):
> src/bin/sman: Add script
> man/man1/sman.1: Add man page
>
> man/man1/sman.1 | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
> src/bin/sman | 54 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 123 insertions(+)
> create mode 100644 man/man1/sman.1
> create mode 100755 src/bin/sman
>
> Range-diff against v0:
> -: ------------ > 1: d093a884e5fb src/bin/sman: Add script
> -: ------------ > 2: e1849d315c95 man/man1/sman.1: Add man page
>
> base-commit: 6754bd1a126ed1e9b7d9c2bc1d221681f5182bb3
> --
> 2.47.3
>
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2026-01-27 13:47 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-27 9:20 [RFC PATCH v1 0/2] New sman(1) script Seth McDonald
2026-01-27 9:20 ` [RFC PATCH v1 1/2] src/bin/sman: Add script Seth McDonald
2026-01-28 16:52 ` наб
2026-01-28 17:19 ` Alejandro Colomar
2026-01-28 19:07 ` G. Branden Robinson
2026-01-28 22:02 ` наб
2026-01-28 22:31 ` G. Branden Robinson
2026-01-27 9:20 ` [RFC PATCH v1 2/2] man/man1/sman.1: Add man page Seth McDonald
2026-01-27 13:47 ` Alejandro Colomar [this message]
2026-01-28 4:44 ` [RFC PATCH v1 0/2] New sman(1) script Seth McDonald
2026-01-28 5:48 ` G. Branden Robinson
2026-01-28 14:36 ` Alejandro Colomar
2026-01-28 14:47 ` Alejandro Colomar
2026-01-28 18:55 ` [PATCH v2] src/bin/mansectf, man/man1/mansectf.1: Add program and manual page Alejandro Colomar
2026-01-29 5:50 ` Seth McDonald
2026-01-29 11:27 ` Alejandro Colomar
2026-01-29 14:31 ` New PARAMETERS section in manual pages (was: [PATCH v2] src/bin/mansectf, man/man1/mansectf.1: Add program and manual page) Alejandro Colomar
2026-01-29 20:24 ` G. Branden Robinson
2026-01-29 22:06 ` Alejandro Colomar
2026-01-29 22:20 ` G. Branden Robinson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aXixqbsZcY-tbCJ4@devuan \
--to=alx@kernel.org \
--cc=branden@debian.org \
--cc=douglas.mcilroy@dartmouth.edu \
--cc=linux-man@vger.kernel.org \
--cc=nabijaczleweli@nabijaczleweli.xyz \
--cc=sethmcmail@pm.me \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox