From: Ingo Schwarze <schwarze@usta.de>
To: Paul Onyschuk <ptmelville@gmail.com>
Cc: discuss@mdocml.bsd.lv
Subject: man(1) replacement
Date: Sun, 10 Aug 2014 03:23:05 +0200 [thread overview]
Message-ID: <20140810012305.GB32716@iris.usta.de> (raw)
In-Reply-To: <20140809190923.aa172f22b838ade5621fe601@gmail.com>
Hi Paul,
Paul Onyschuk wrote on Sat, Aug 09, 2014 at 07:09:23PM +0200:
> I also have additional question. Are there any plans for providing
> man(1) command also? This would make mdocml a possible, standalone
> replacement for groff and man-db combination (typical in Linux
> distributions).
Well, that's almost ready, actually; not for 1.13.1, though.
The file implementing it is manpage.c. Try this:
make clean
make
sudo ./makewhatis
make manpage
./manpage setitimer
Ironically, there isn't a manpage for manpage(1). ;-)
What it does is basically this:
It takes the same options and arguments as apropos(1), except that
the -O option is not available.
If it finds exactly one result, it shows that manual, just like the
traditional man(1).
If it finds more than one result, it shows the list of manuals,
similar to apropos(1), but with serial numbers in front.
When running on a terminal, it interactively asks you to
select one of the numbers, defaulting to number 1, then shows
that manual.
I dislike the interactive prompting so much that i never enabled
it in the build, but when you say "make manpage", it does build
and run.
Obviously, commands like
manpage ls
are almost useless, and
manpage Nm~^ls\$
which is equivalent to "man ls", is hard to type.
Having reconsidered all this, here is what i will do for 1.13.2:
* Provide one single binary program, integrating all the
functionality of mandoc(1), man(1), apropos(1), and whatis(1).
* Provide four argument input modes:
- filenames: ["mandoc"]
Each argument is a relative or absolute pathname to a file,
like in traditional mandoc(1).
- names: ["man"]
Each argument is a complete, literal name of a manual,
like in traditional man(1).
- words: ["man -f"]
Each argument is a literal string and will be matched against
whole words in manual names, like in traditional whatis(1).
- expressions: ["man -k"]
Arguments are full apropos(1) expressions.
As a special case, arguments containing neither '=' nor '~'
are literal strings and will be matched against substrings in
manual names and descriptions, like in traditional apropos(1).
* Provide five output modes:
- one: ["man"]
Among the matching files, one will be selected according
to traditional precedence rules, and this one file will
be formatted and shown. If on a terminal, the command is man,
and -c was not given, a pager is used.
- all: ["man -a"]
All matching files will be formatted and shown one after
the other, using a pager as above.
- filenames: ["man -w"]
Only the filenames of all matching files are shown.
- list: ["man -k", "man -f"]
The names and descriptions of all matching files will be
listed like in traditional apropos(1) and whatis(1).
- ask: ["man -i"]
If there is exactly one matching file, it will be formatted
and shown. If there is more than one, the names and
descriptions will be listed, and if on a terminal, the user
will be asked for a choice, like in manpage(1).
The following combinations are useful:
arguments output command alias comment
--------- ------ ------- ----- -------
filenames all mandoc no change
names one man new in mandoc
names ask man -i completely new
names all man -a new in mandoc
names filenames man -w new in mandoc
words list man -f whatis no change
words ask man -fi whatis -i completely new
words all man -fa whatis -a completely new
words filenames man -fw whatis -w completely new
expressions list man -k apropos no change
expressions ask man -ki apropos -i replaces manpage(1)
expressions all man -ka apropos -a completely new
expressions filenames man -kw apropos -w completely new
That looks like a compact, consistent, and feature-complete interface:
* man(1) defaults to arguments:names, output:one as before
* -f switches to arguments:words, output:list as before
* -k switches to arguments:expressions, output:list as before
* -i switches to output:ask in all three cases (new)
* -a switches to output:all in all three cases (new for -fk)
* -w switches to output:filenames in all three cases (new for -fk)
* output:one would be useless with -f and -k
* all except output:all would be useless with mandoc(1)
I'm not likely to turn into an avid user of -i, but in that complete
feature set, i no longer dislike it so much that i feel unwilling
to integrate it: in that set, it looks like a reasonable companion
of the names/one standard mode. Going from names to expressions,
the following naturally correspond to each other:
man -w -> man -kw
man -a -> man -ka
man -> man -ki
Without -i, there would be an ugly hole in the lower right corner
of the table, no sane way to get from an expression search to the
display of one single page...
Arguably, -i alone is rarely useful, nobody will type "man -i chmod"
instead of "man 2 chmod" (when remembering chmod as ambiguous) or
instead of just "man chmod" (when forgetting about the ambiguity).
So -i could be made to imply -k, making life easier for people who
want to use man -ki. Then again, that makes the interface less
consistent, and some people may wish to set "alias man='man -i'"
as long as that doesn't imply -k; but nobody is likely to want -k
by default. So i tend to have -i not imply -k.
Implementing all this looks nearly trivial: Basically, all the
required code is already available in main.c, apropos.c, and
manpage.c, it merely needs some reshuffling and polishing.
So, thanks for asking that question. :-)
If you switch to that system when 1.13.2 comes out, you just have
to remember one thing: It strictly requires keeping the mandoc.db(5)
files up-to-date in all your manual trees. If you manually copy a
new page to /usr/local/man/man1/foo.1 and forget to run "makewhatis
-d /usr/local/man man1/foo.1" then "man foo" will *not* find your
new page!
And, admittedly, it causes some slowdown. Querying a database
is not for free. On my notebook:
$ time sh -c 'for i in `jot 100`; do man -w ksh; done > /dev/null'
0m1.47s real 0m0.32s user 0m1.12s system
$ time sh -c 'for i in `jot 100`; do whatis ksh; done > /dev/null'
0m2.53s real 0m1.74s user 0m0.78s system
$ time sh -c 'for i in `jot 100`; do mandoc cat.1; done > /dev/null'
0m0.58s real 0m0.24s user 0m0.29s system
$ time sh -c 'for i in `jot 100`; do mandoc ksh.1; done > /dev/null'
0m5.12s real 0m4.08s user 0m0.97s system
$ time sh -c 'for i in `jot 100`; do man ksh; done > /dev/null'
0m5.89s real 0m4.23s user 0m1.58s system
So:
- find a manual with traditional man: 15 milliseconds
- find a manual in the SQL database: 25 milliseconds
- format a small manual: 5 milliseconds
- format a huge manual: 50 milliseconds
That looks like roughly a 50% increase in man page serving
time, 15+5=20 -> 25+5=30 milliseconds, very imprecisely.
Not relevant on modern hardware, but likely noticable
on a VAX...
Yours,
Ingo
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
next prev parent reply other threads:[~2014-08-10 1:23 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-09 10:38 Portability of fts() functions Paul Onyschuk
2014-08-09 15:49 ` Ingo Schwarze
2014-08-09 17:09 ` Paul Onyschuk
2014-08-09 21:59 ` Ingo Schwarze
2014-08-09 23:26 ` Paul Onyschuk
2014-08-10 2:46 ` Ingo Schwarze
2014-08-10 1:23 ` Ingo Schwarze [this message]
2014-08-10 10:53 ` Paul Onyschuk
2014-08-11 3:28 ` Ingo Schwarze
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=20140810012305.GB32716@iris.usta.de \
--to=schwarze@usta.de \
--cc=discuss@mdocml.bsd.lv \
--cc=ptmelville@gmail.com \
/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;
as well as URLs for NNTP newsgroup(s).