nmh-workers
[Top] [All Lists]

[Nmh-workers] [PATCH] scan message numbers from stdin

2008-08-15 16:45:59
This is, I suppose, a bit controversial, since it's a UI change.
But, combined with having pick write out numbers as it finds them
(uip/pick.c r1.15), this is insanely useful.  You can 'pick
whatever | scan -' and interrupt it when you find what you're
looking for.

You could expand this compatibly so that 'scan /some/file' would
scan the messages listed therein, but I haven't done so because I
don't see the use.  You'd have to use absolute paths, to
disambiguate such file from sequence names.

It may also be useful to support folder names in the stream, but
I haven't encountered a use for that, either, so it remains
unimplemented.  Since I ignore /^\+/ lines now, that expansion,
too, would be compatible.


=== modified file 'ChangeLog'
--- ChangeLog   2008-08-15 02:47:29 +0000
+++ ChangeLog   2008-08-15 23:38:06 +0000
@@ -1,3 +1,9 @@
+2008-08-15  Eric Gillespie  <epg(_at_)pretzelnet(_dot_)org>
+
+       * man/scan.man, test/tests/scan/test-scan, uip/scan.c: If `-' is
+       specified instead of a message list, read message numbers from the
+       standard input and scan those.
+
 2008-08-14  Eric Gillespie  <epg(_at_)pretzelnet(_dot_)org>
 
        * test/setup-test: Don't run autogen.sh unless needed.  Build in a

=== modified file 'man/scan.man'
--- man/scan.man        2008-08-03 22:14:23 +0000
+++ man/scan.man        2008-08-15 23:29:04 +0000
@@ -10,7 +10,7 @@ scan \- produce a one line per message s
 .na
 .B scan
 .RI [ +folder ]
-.RI [ msgs ]
+.RI [ msgs " | " \- ]
 .RB [ \-clear " | " \-noclear ]
 .RB [ \-form
 .IR formatfile ]
@@ -199,6 +199,11 @@ so interrupting a long
 listing preserves the new context.
 .B nmh
 purists hate this idea.
+.PP
+If `-' is specified for
+.RI msgs
+.B scan
+will read message numbers from the standard input and scan those.
 
 .SH FILES
 .fc ^ ~

=== modified file 'test/tests/scan/test-scan'
--- test/tests/scan/test-scan   2008-08-14 06:32:03 +0000
+++ test/tests/scan/test-scan   2008-08-15 23:15:31 +0000
@@ -21,6 +21,10 @@ cat > $expected <<EOF
   10  09/29 Test10             Testing message 10<<This is message number 10 >>
 EOF
 
+# check standard scan
 scan -width 80 +inbox > $actual
+diff -u $expected $actual
 
+# check scan -
+pick | scan -width 80 - > $actual
 diff -u $expected $actual

=== modified file 'uip/scan.c'
--- uip/scan.c  2007-11-04 11:54:32 +0000
+++ uip/scan.c  2008-08-15 23:25:10 +0000
@@ -59,19 +59,77 @@ extern struct msgs *fmt_current_folder;     
 void clear_screen(void);  /* from termsbr.c */
 
 
+/* scan `msgnum' in `folder', passing `nfs' and `width' to `scan'.  Use `mp',
+ * `seqnum', and `num_unseen_seq' to determine if `msgnum' is unseen.
+ * If `hdrflag' is not NULL and points to non-zero, print a header and set
+ * *hdrflag to 0. */
+static void
+scan_msgfile (char *folder, int msgnum, char *nfs, int width,
+             struct msgs *mp, int seqnum[], int num_unseen_seq,
+             int *hdrflag)
+{
+    FILE *in;
+    char *cp;
+    int unseen, i, state;
+
+    if ((in = fopen (cp = m_name (msgnum), "r")) == NULL) {
+       admonish (cp, "unable to open message");
+       return;
+    }
+
+#ifndef JLR
+    if (hdrflag != NULL && *hdrflag) {
+       printf ("FOLDER %s\t%s\n", folder, dtimenow(1));
+    }
+#endif /* JLR */
+
+    /*
+     * Check if message is in any sequence given
+     * by Unseen-Sequence profile entry.
+     */
+    unseen = 0;
+    for (i = 0; i < num_unseen_seq; i++) {
+       if (in_sequence(mp, seqnum[i], msgnum)) {
+           unseen = 1;
+           break;
+       }
+    }
+
+    switch (state = scan (in, msgnum, 0, nfs, width,
+                         msgnum == mp->curmsg, unseen,
+                         folder, 0L, 1)) {
+    case SCNMSG:
+    case SCNENC:
+    case SCNERR:
+       break;
+
+    default:
+       adios (NULL, "scan() botch (%d)", state);
+
+    case SCNEOF:
+       advise (NULL, "message %d: empty", msgnum);
+       break;
+    }
+    if (hdrflag != NULL) {
+       *hdrflag = 0;
+    }
+    fclose (in);
+}
+
 int
 main (int argc, char **argv)
 {
     int clearflag = 0, hdrflag = 0, ontty;
     int width = 0, revflag = 0;
     int i, state, msgnum;
-    int seqnum[NUMATTRS], unseen, num_unseen_seq = 0;
+    int seqnum[NUMATTRS], num_unseen_seq = 0;
     char *cp, *maildir, *file = NULL, *folder = NULL;
     char *form = NULL, *format = NULL, buf[BUFSIZ];
     char **argp, *nfs, **arguments;
     struct msgs_array msgs = { 0, 0, NULL };
     struct msgs *mp;
     FILE *in;
+    boolean from_stdin = FALSE;
 
 #ifdef LOCALE
     setlocale(LC_ALL, "");
@@ -89,7 +147,11 @@ main (int argc, char **argv)
      * Parse arguments
      */
     while ((cp = *argp++)) {
-       if (*cp == '-') {
+       if (cp[0] == '-') {
+           if (cp[1] == '\0') {
+               from_stdin = TRUE;
+               continue;
+           }
            switch (smatch (++cp, switches)) {
                case AMBIGSW: 
                    ambigsw (cp, switches);
@@ -156,8 +218,12 @@ main (int argc, char **argv)
                adios (NULL, "only one folder at a time!");
            else
                folder = pluspath (cp);
-       } else
-               app_msgarg(&msgs, cp);
+       } else {
+           if (from_stdin) {
+               adios (NULL, "\"msgs\" must be '-' OR message numbers");
+           }
+           app_msgarg(&msgs, cp);
+       }
     }
 
     if (!context_find ("path"))
@@ -172,7 +238,7 @@ main (int argc, char **argv)
      * We are scanning a maildrop file
      */
     if (file) {
-       if (msgs.size)
+       if (from_stdin || msgs.size)
            adios (NULL, "\"msgs\" not allowed with -file");
        if (folder)
            adios (NULL, "\"+folder\" not allowed with -file");
@@ -207,7 +273,7 @@ main (int argc, char **argv)
      * We are scanning a folder
      */
 
-    if (!msgs.size)
+    if (!from_stdin && !msgs.size)
        app_msgarg(&msgs, "all");
     if (!folder)
        folder = getfolder (1);
@@ -224,14 +290,16 @@ main (int argc, char **argv)
     if (mp->nummsg == 0)
        adios (NULL, "no messages in %s", folder);
 
-    /* parse all the message ranges/sequences and set SELECTED */
-    for (msgnum = 0; msgnum < msgs.size; msgnum++)
-       if (!m_convert (mp, msgs.msgs[msgnum]))
-           done(1);
-    seq_setprev (mp);                  /* set the Previous-Sequence */
+    if (!from_stdin) {
+       /* parse all the message ranges/sequences and set SELECTED */
+       for (msgnum = 0; msgnum < msgs.size; msgnum++)
+           if (!m_convert (mp, msgs.msgs[msgnum]))
+               done(1);
+       seq_setprev (mp);       /* set the Previous-Sequence */
+       seq_save (mp);          /* synchronize message sequences */
+    }
 
     context_replace (pfolder, folder); /* update current folder         */
-    seq_save (mp);                     /* synchronize message sequences */
     context_save ();                   /* save the context file         */
 
     /*
@@ -258,64 +326,43 @@ main (int argc, char **argv)
        fmt_current_folder = mp;
 #endif
 
-    for (msgnum = revflag ? mp->hghsel : mp->lowsel;
-        (revflag ? msgnum >= mp->lowsel : msgnum <= mp->hghsel);
-        msgnum += (revflag ? -1 : 1)) {
-       if (is_selected(mp, msgnum)) {
-           if ((in = fopen (cp = m_name (msgnum), "r")) == NULL) {
-#if 0
-               if (errno != EACCES)
-#endif
-                   admonish (cp, "unable to open message");
-#if 0
-               else
-                   printf ("%*d  unreadable\n", DMAXFOLDER, msgnum);
-#endif
+    if (from_stdin) {
+       char *line;
+       size_t len;
+       while (vfgets(stdin, &line) == OK) {
+           if (line[0] == '+')
+               /* Maybe support changing folder here?  Hmm.  One use is for
+                * pick +foo | scan - when current folder is bar; even if pick
+                * set current folder asap (it doesn't), it's still a race and
+                * scan may still read current folder before pick sets it.
+                * So, we could add an option to pick to output the folder. */
+               continue;
+           /* Convert msgnum string to int. */
+           len = strlen(line) - 1;
+           line[len] = '\0';
+           msgnum = m_atoi (line);
+           if (msgnum == 0) {
+               admonish (line, "invalid message number");
                continue;
            }
 
-#ifndef JLR
-           if (hdrflag) {
-               printf ("FOLDER %s\t%s\n", folder, dtimenow(1));
-           }
-#endif /* JLR */
-
-           /*
-            * Check if message is in any sequence given
-            * by Unseen-Sequence profile entry.
-            */
-           unseen = 0;
-           for (i = 0; i < num_unseen_seq; i++) {
-               if (in_sequence(mp, seqnum[i], msgnum)) {
-                   unseen = 1;
-                   break;
-               }
-           }
+           scan_msgfile (folder, msgnum, nfs, width,
+                         mp, seqnum, num_unseen_seq, &hdrflag);
 
-           switch (state = scan (in, msgnum, 0, nfs, width,
-                       msgnum == mp->curmsg, unseen,
-                       folder, 0L, 1)) {
-               case SCNMSG: 
-               case SCNENC: 
-               case SCNERR: 
-                   break;
-
-               default: 
-                   adios (NULL, "scan() botch (%d)", state);
-
-               case SCNEOF: 
-#if 0
-                   printf ("%*d  empty\n", DMAXFOLDER, msgnum);
-#else
-                   advise (NULL, "message %d: empty", msgnum);
-#endif
-                   break;
-           }
-           hdrflag = 0;
-           fclose (in);
            if (ontty)
                fflush (stdout);
        }
+    } else {
+       for (msgnum = revflag ? mp->hghsel : mp->lowsel;
+            (revflag ? msgnum >= mp->lowsel : msgnum <= mp->hghsel);
+            msgnum += (revflag ? -1 : 1)) {
+           if (is_selected(mp, msgnum)) {
+               scan_msgfile (folder, msgnum, nfs, width,
+                             mp, seqnum, num_unseen_seq, &hdrflag);
+               if (ontty)
+                   fflush (stdout);
+           }
+       }
     }
 
 #ifdef LBL



_______________________________________________
Nmh-workers mailing list
Nmh-workers(_at_)nongnu(_dot_)org
http://lists.nongnu.org/mailman/listinfo/nmh-workers

<Prev in Thread] Current Thread [Next in Thread>