<<< Date Index >>>     <<< Thread Index >>>

Re: [PATCH] new fmtpipe updates



* On 2007.03.13, in <20070313210222.GB24389@xxxxxxxxxxxxxxxxx>,
*       "Brendan Cully" <brendan@xxxxxxxxxx> wrote:
> 
> On further reflection, I think your fmtpipe.3 patch should work well
> enough -- people will just have to get used to putting their string in
> extra quoting. But the one you submitted seems to have some garbage in
> it ('/tmp/ass', and an #if 0 block), and doesn't really quote things
> properly for shell (embedded single quotes would break it). Can you
> clean these things up, and maybe add the \| check?

These are fixed in fmtpipe.4, attached.

I've also added a mutt_xtitle program in mutt_xtitle.c, with hooks into
Makefile.am.  It's sufficient for a common case of setting xterm titles,
e.g.:

  set pager_format="mutt_xtitle '%-.20n: %.40s' '-%Z- %C/%m: %-20.20n   %s' |"

That should help make the xterm titlebar use case more out-of-box.
But if it's not important, feel free to ignore the Makefile.am and
mutt_xtitle.c hunks in the diff.

-- 
 -D.    dgc@xxxxxxxxxxxx        NSIT    University of Chicago
diff -r dc8f0c4a6287 Makefile.am
--- a/Makefile.am       Tue Mar 13 12:39:59 2007 -0700
+++ b/Makefile.am       Wed Mar 14 01:59:17 2007 -0500
@@ -2,7 +2,7 @@
 ## Use aclocal -I m4; automake --foreign
 
 AUTOMAKE_OPTIONS = 1.6 foreign
-EXTRA_PROGRAMS = mutt_dotlock pgpring pgpewrap makedoc
+EXTRA_PROGRAMS = mutt_dotlock pgpring pgpewrap makedoc mutt_xtitle
 
 if BUILD_IMAP
 IMAP_SUBDIR = imap
@@ -15,7 +15,7 @@ bin_SCRIPTS = muttbug flea @SMIMEAUX_TAR
 
 BUILT_SOURCES = keymap_defs.h patchlist.c
 
-bin_PROGRAMS = mutt @DOTLOCK_TARGET@ @PGPAUX_TARGET@
+bin_PROGRAMS = mutt mutt_xtitle @DOTLOCK_TARGET@ @PGPAUX_TARGET@
 mutt_SOURCES = $(BUILT_SOURCES) \
        addrbook.c alias.c attach.c base64.c browser.c buffy.c color.c \
        crypt.c cryptglue.c \
@@ -90,6 +90,10 @@ pgpring_LDADD = @LIBOBJS@ $(INTLLIBS)
 pgpring_LDADD = @LIBOBJS@ $(INTLLIBS) 
 pgpring_DEPENDENCIES = @LIBOBJS@ $(INTLDEPS)
 
+mutt_xtitle_SOURCES = mutt_xtitle.c
+mutt_xtitle_LDADD = @LIBOBJS@
+mutt_xtitle_DEPENDENCIES = @LIBOBJS@
+
 mutt_dotlock.c: dotlock.c
        cp $(srcdir)/dotlock.c mutt_dotlock.c
 
diff -r dc8f0c4a6287 PATCHES
--- a/PATCHES   Tue Mar 13 12:39:59 2007 -0700
+++ b/PATCHES   Wed Mar 07 14:06:01 2007 -0500
@@ -0,0 +1,1 @@
+patch-1.5.14.dgc.fmtpipe.3
diff -r dc8f0c4a6287 mutt.h
--- a/mutt.h    Tue Mar 13 12:39:59 2007 -0700
+++ b/mutt.h    Tue Mar 06 23:45:52 2007 -0500
@@ -143,7 +143,8 @@ typedef enum
   M_FORMAT_OPTIONAL    = (1<<3),
   M_FORMAT_STAT_FILE   = (1<<4), /* used by mutt_attach_fmt */
   M_FORMAT_ARROWCURSOR = (1<<5), /* reserve space for arrow_cursor */
-  M_FORMAT_INDEX       = (1<<6)  /* this is a main index entry */
+  M_FORMAT_INDEX       = (1<<6), /* this is a main index entry */
+  M_FORMAT_NOFILTER    = (1<<7)  /* do not allow filtering on this pass */
 } format_flag;
 
 /* types for mutt_add_hook() */
diff -r dc8f0c4a6287 mutt_xtitle.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/mutt_xtitle.c     Wed Mar 14 02:30:58 2007 -0500
@@ -0,0 +1,53 @@
+/*
+ *  Sets the window title to argv[1] (in an xterm-like way)
+ *  and echoes back remaining arguments.
+ *
+ *  Example usage:
+ *  set pager_format="mutt_xtitle '%-.20n: %.40s' '-%Z- %C/%m: %-20.20n   %s' 
|"
+ *
+ *  This sets the xterm title to show the sender's name and the subject
+ *  whenever viewing a message, and uses the default pager_format for
+ *  the actual header line in the pager.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main(int argc, char *argv[])
+{
+       FILE *tty;
+       int   i;
+
+       /* check for help patterns */
+       if (argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
+               fprintf(stderr,
+                "usage: set xyz_format=\"%s 'window title' "
+                "'other format text' |\"\n", argv[0]);
+               exit (2);
+       }
+
+       /* We'll write the xterm title sequence to /dev/tty if possible */
+    tty = fopen("/dev/tty", "w");
+    if (tty) {
+         fprintf(tty, "\033]0;%s\007", argv[1]);
+      fclose(tty);
+    }
+       /* or stdout as a fallback */
+    else {
+         printf("\033]0;%s\007", argv[1]);
+    }
+
+       /* write remaining arguments to stdout, space-separated */
+       for (i = 2; i < argc-1; i++) {
+         printf("%s ", argv[i]);
+    }
+
+       /* print final arg with no trailing space */
+    if (i == argc-1)
+         printf("%s", argv[i]);
+
+       exit (0);
+}
diff -r dc8f0c4a6287 muttlib.c
--- a/muttlib.c Tue Mar 13 12:39:59 2007 -0700
+++ b/muttlib.c Wed Mar 14 01:32:17 2007 -0500
@@ -996,12 +996,122 @@ void mutt_FormatString (char *dest,              /* 
   char prefix[SHORT_STRING], buf[LONG_STRING], *cp, *wptr = dest, ch;
   char ifstring[SHORT_STRING], elsestring[SHORT_STRING];
   size_t wlen, count, len, col, wid;
+  pid_t pid;
+  FILE *filter;
+  int n;
+  char *recycler;
 
   prefix[0] = '\0';
   destlen--; /* save room for the terminal \0 */
   wlen = (flags & M_FORMAT_ARROWCURSOR && option (OPTARROWCURSOR)) ? 3 : 0;
   col = wlen;
-    
+
+  if ((flags & M_FORMAT_NOFILTER) == 0)
+  {
+    int off = -1;
+
+    /* Do not consider filters if no pipe at end */
+    n = mutt_strlen(src);
+    if (n > 0 && src[n-1] == '|')
+    {
+      /* Scan backwards for backslashes */
+      off = n;
+      while (off > 0 && src[off-2] == '\\')
+        off--;
+    }
+
+    /* If number of backslashes is even, the pipe is real. */
+    /* n-off is the number of backslashes. */
+    if (off > 0 && ((n-off) % 2) == 0)
+    {
+      BUFFER *srcbuf, *word, *command;
+      char    srccopy[LONG_STRING];
+      int     i = 0;
+
+      dprint(2, (debugfile, "fmtpipe = %s\n", src));
+
+      strncpy(srccopy, src, n);
+      srccopy[n-1] = '\0';
+
+      /* prepare BUFFERs */
+      srcbuf = mutt_buffer_from(NULL, srccopy);
+      srcbuf->dptr = srcbuf->data;
+      word = mutt_buffer_init(NULL);
+      command = mutt_buffer_init(NULL);
+
+      /* Iterate expansions across successive arguments */
+      do {
+        char *p;
+
+        /* Extract the command name and copy to command line */
+        dprint(2, (debugfile, "fmtpipe +++: %s\n", srcbuf->dptr));
+        if (word->data)
+          *word->data = '\0';
+        mutt_extract_token(word, srcbuf, 0);
+        dprint(2, (debugfile, "fmtpipe %2d: %s\n", i++, word->data));
+        mutt_buffer_addch(command, '\'');
+        mutt_FormatString(buf, sizeof(buf), word->data, callback, data,
+                          flags | M_FORMAT_NOFILTER);
+        for (p = buf; p && *p; p++)
+        {
+          if (*p == '\'')
+            /* shell quoting doesn't permit escaping a single quote within
+             * single-quoted material.  double-quoting instead will lead
+             * shell variable expansions, so break out of the single-quoted
+             * span, insert a double-quoted single quote, and resume. */
+            mutt_buffer_addstr(command, "'\"'\"'");
+          else
+            mutt_buffer_addch(command, *p);
+        }
+        mutt_buffer_addch(command, '\'');
+        mutt_buffer_addch(command, ' ');
+      } while (MoreArgs(srcbuf));
+
+      dprint(2, (debugfile, "fmtpipe > %s\n", command->data));
+
+      wptr = dest;      /* reset write ptr */
+      wlen = (flags & M_FORMAT_ARROWCURSOR && option (OPTARROWCURSOR)) ? 3 : 0;
+      if ((pid = mutt_create_filter(command->data, NULL, &filter, NULL)))
+      {
+        n = fread(dest, 1, destlen /* already decremented */, filter);
+        fclose(filter);
+        dest[n] = '\0';
+        dprint(2, (debugfile, "fmtpipe < %s\n", dest));
+
+        if (pid != -1)
+          mutt_wait_filter(pid);
+  
+        /* If the result ends with '%', this indicates that the filter
+         * generated %-tokens that mutt can expand.  Eliminate the '%'
+         * marker and recycle the string through mutt_FormatString().
+         * To literally end with "%", use "%%". */
+        if (dest[--n] == '%')
+        {
+          dest[n] = '\0';               /* remove '%' */
+          if (dest[--n] != '%')
+          {
+            recycler = safe_strdup(dest);
+            if (recycler)
+            {
+              mutt_FormatString(dest, destlen++, recycler, callback, data, 
flags);
+              safe_free(&recycler);
+            }
+          }
+        }
+      }
+      else
+      {
+        /* Filter failed; erase write buffer */
+        *wptr = '\0';
+      }
+
+      mutt_buffer_free(&command);
+      mutt_buffer_free(&srcbuf);
+      mutt_buffer_free(&word);
+      return;
+    }
+  }
+
   while (*src && wlen < destlen)
   {
     if (*src == '%')