* Interactive mode for apropos/whatis.
@ 2011-12-14 10:33 Kristaps Dzonsons
0 siblings, 0 replies; only message in thread
From: Kristaps Dzonsons @ 2011-12-14 10:33 UTC (permalink / raw)
To: discuss
[-- Attachment #1: Type: text/plain, Size: 1294 bytes --]
Hi,
Let's be creative! I've cooked up a tiny little patch that does the
following.
(1) Add an `-I' mode to apropos.c (apropos/whatis).
(2) If `-I', prepend a choice number to each matching manual.
(3) If `-I', instead of returning, ask the user for their choice.
(4) Pipe result into MANPAGER/PAGER/more(1).
Or by way of example:
% MANPAGER=head ./whatis -I find
[1] File::Find(3p) - Traverse a directory tree.
[2] find(1) - walk a file hierarchy
[3] Pod::Find(3p) - find POD documents in directory trees
Choose a manual number: 2
FIND(1) General Commands Manual FIND(1)
NAME
find -- walk a file hierarchy
SYNOPSIS
find [-dHhLXx] [-f path] path ... [expression]
DESCRIPTION
find recursively descends the directory tree for each path
Thoughts on this? My reasoning was people will probably go from
apropos/whatis into man anyway. Might as well save them the trouble.
My original thought was to add a `man' mode, like `apropos', that
stipulated Nm~^key$ and routes to the first option. I went with the
above route to avoid the sticky part of sorting output properly. Of
course, with a few hours of work, the `man' mode is quite possible.
However, mandocdb(8) would need to respect the man.conf arguments more.
Thoughts?
Kristaps
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 2371 bytes --]
Index: apropos.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos.c,v
retrieving revision 1.24
diff -u -r1.24 apropos.c
--- apropos.c 12 Dec 2011 02:00:49 -0000 1.24
+++ apropos.c 14 Dec 2011 10:30:14 -0000
@@ -34,6 +34,7 @@
static void usage(void);
static char *progname;
+static int interactive;
int
main(int argc, char *argv[])
@@ -63,11 +64,14 @@
conf_file = NULL;
e = NULL;
- while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
+ while (-1 != (ch = getopt(argc, argv, "C:IM:m:S:s:")))
switch (ch) {
case ('C'):
conf_file = optarg;
break;
+ case ('I'):
+ interactive = 1;
+ break;
case ('M'):
defpaths = optarg;
break;
@@ -118,20 +122,78 @@
return(rc ? EXIT_SUCCESS : EXIT_FAILURE);
}
-/* ARGSUSED */
static void
list(struct res *res, size_t sz, void *arg)
{
- int i;
+ int i, choice;
+ int fds[2];
+ char *line;
+ const char *cmd;
+ size_t linesz;
+ pid_t pid;
+
+ if (0 == sz) {
+ fprintf(stderr, "Nothing matched your search.\n");
+ return;
+ }
qsort(res, sz, sizeof(struct res), cmp);
- for (i = 0; i < (int)sz; i++)
+ for (i = 0; i < (int)sz; i++) {
+ if (interactive)
+ printf("[%d] ", i + 1);
printf("%s(%s%s%s) - %s\n", res[i].title,
res[i].cat,
*res[i].arch ? "/" : "",
*res[i].arch ? res[i].arch : "",
res[i].desc);
+ }
+
+ if ( ! interactive)
+ return;
+
+ printf("Choose a manual number: ");
+
+ if (NULL != (line = fgetln(stdin, &linesz)) &&
+ linesz > 1 && '\n' == line[(int)linesz - 1]) {
+ line[(int)linesz - 1] = '\0';
+ choice = atoi(line);
+ } else
+ return;
+
+ if (choice < 1 || choice-- > (int)sz)
+ return;
+
+ cmd = getenv("PAGER");
+ if (getenv("MANPAGER"))
+ cmd = getenv("MANPAGER");
+ if (NULL == cmd)
+ cmd = "more";
+
+ if (0 == strcmp(res[choice].type, "cat")) {
+ execlp(cmd, cmd, res[choice].file, (char *)NULL);
+ perror(cmd);
+ return;
+ }
+
+ if (SIG_ERR == signal(SIGCHLD, SIG_IGN) ||
+ -1 == pipe(fds) || -1 == (pid = fork())) {
+ perror(NULL);
+ return;
+ }
+
+ if (pid > 0) {
+ close(fds[1]);
+ dup2(fds[0], STDIN_FILENO);
+ execlp(cmd, cmd, (char *)NULL);
+ } else {
+ close(fds[0]);
+ dup2(fds[1], STDOUT_FILENO);
+ cmd = "mandoc";
+ execlp(cmd, cmd, res[choice].file, (char *)NULL);
+ }
+
+ perror(cmd);
}
static int
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-12-14 10:33 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-14 10:33 Interactive mode for apropos/whatis Kristaps Dzonsons
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).