Pulling this subthread out from the "1.6.0 release plans" thread, where
I first posted the patch.

This patch adds a new option, $reflow_space_quotes, to add a space after
each quote level in a format=flowed email.  The option is used in the
pager and for (non f=f) replies to f=f emails.

Changes from the previous version of the patch are:
  * Turn $reflow_space_quotes on by default.

  * Enable $reflow_space_quotes in the pager even when $text_flowed is
    set.  Editing f=f is hard enough; there's no reason to subject
    them to viewing it non-spaced too, I think.

  * Add a documentation section to the manual "Support for viewing and
    non-flowed replies"

I've tested the patch a bit more from when I posted it yesterday, but
heartily welcome more testing and feedback.

-- 
Kevin J. McCarthy
GPG Fingerprint: 8975 A9B3 3AA3 7910 385C  5308 ADEF 7684 8031 6BDA
http://www.8t8.us/configs/gpg-key-transition-statement.txt
# HG changeset patch
# User Kevin McCarthy <[email protected]>
# Date 1449956111 28800
#      Sat Dec 12 13:35:11 2015 -0800
# Node ID d2e51114b400ea6587dd1772f9aa8332a7f46d94
# Parent  02bc14ed15697cdc13f73f07f9be225226361f96
Add $reflow_space_quotes option. (closes #3309)

When viewing and replying to a flowed email, add spacing between the
quotes to improve readability and interoperability with non-flowed
replies.

Add a section to the documentation discussing support for viewing and
non-flowed replies to flowed emails.

diff --git a/doc/manual.xml.head b/doc/manual.xml.head
--- a/doc/manual.xml.head
+++ b/doc/manual.xml.head
@@ -1607,16 +1607,54 @@
 For example, <emphasis>vim</emphasis> provides the <literal>w</literal>
 flag for its <literal>formatoptions</literal> setting to assist in
 creating <literal>f=f</literal> messages, see <literal>:help
 fo-table</literal> for details.
 </para>
 
 </sect3>
 
+<sect3 id="ff-pager">
+<title>Support for viewing and non-flowed replies</title>
+
+<para>
+  Mutt has some support for viewing and replying to
+  <literal>format=flowed</literal> messages.  In order to take advantage of 
these,
+  <link linkend="reflow-text">$reflow_text</link> must be set.
+</para>
+
+<itemizedlist>
+  <listitem>
+  <para>
+    Paragraphs are automatically reflowed and wrapped at a width specified
+    by <link linkend="reflow-wrap">$reflow_wrap</link>.
+  </para>
+  </listitem>
+  <listitem>
+  <para>
+    By default, the quoting style of <literal>format=flowed</literal>
+    messages can be difficult to read, and doesn't intermix well with
+    non-flowed replies.
+    Setting <link linkend="reflow-space-quotes">$reflow_space_quotes</link>
+    adds spaces after each level of quoting when in the pager and
+    replying in a non-flowed format
+    (i.e. with <link linkend="text-flowed">$text_flowed</link> unset).
+  </para>
+  </listitem>
+  <listitem>
+  <para>
+    If <link linkend="reflow-space-quotes">$reflow_space_quotes</link>
+    is unset, mutt will still add one trailing space after all the
+    quotes in the pager (but not when replying).
+  </para>
+  </listitem>
+</itemizedlist>
+
+</sect3>
+
 </sect2>
 
 </sect1>
 
 <sect1 id="forwarding-mail">
 <title>Forwarding and Bouncing Mail</title>
 
 <para>
diff --git a/init.h b/init.h
--- a/init.h
+++ b/init.h
@@ -2375,16 +2375,27 @@
   ** This specifies the file into which your outgoing messages should be
   ** appended.  (This is meant as the primary method for saving a copy of
   ** your messages, but another way to do this is using the ``$my_hdr''
   ** command to create a ``Bcc:'' field with your email address in it.)
   ** .pp
   ** The value of \fI$$record\fP is overridden by the $$force_name and
   ** $$save_name variables, and the ``$fcc-hook'' command.
   */
+  { "reflow_space_quotes",     DT_BOOL, R_NONE, OPTREFLOWSPACEQUOTES, 1 },
+  /*
+  ** .pp
+  ** This option controls how quotes from format=flowed messages are displayed
+  ** in the pager and when replying (with $$text_flowed \fIunset\fP).
+  ** When set, this option adds spaces after each level of quote marks, turning
+  ** ">>>foo" into "> > > foo".
+  ** .pp
+  ** \fBNote:\fP If $$reflow_text is \fIunset\fP, this option has no effect.
+  ** Also, this option does not affect replies when $$text_flowed is \fIset\fP.
+  */
   { "reflow_text",     DT_BOOL, R_NONE, OPTREFLOWTEXT, 1 },
   /*
   ** .pp
   ** When \fIset\fP, Mutt will reformat paragraphs in text/plain
   ** parts marked format=flowed.  If \fIunset\fP, Mutt will display paragraphs
   ** unaltered from how they appear in the message body.  See RFC3676 for
   ** details on the \fIformat=flowed\fP format.
   ** .pp
diff --git a/mutt.h b/mutt.h
--- a/mutt.h
+++ b/mutt.h
@@ -404,16 +404,17 @@
   OPTPOPAUTHTRYALL,
   OPTPOPLAST,
 #endif
   OPTPOSTPONEENCRYPT,
   OPTPRINTDECODE,
   OPTPRINTSPLIT,
   OPTPROMPTAFTER,
   OPTREADONLY,
+  OPTREFLOWSPACEQUOTES,
   OPTREFLOWTEXT,
   OPTREPLYSELF,
   OPTRESOLVE,
   OPTREVALIAS,
   OPTREVNAME,
   OPTREVREAL,
   OPTRFC2047PARAMS,
   OPTSAVEADDRESS,
diff --git a/rfc3676.c b/rfc3676.c
--- a/rfc3676.c
+++ b/rfc3676.c
@@ -56,40 +56,86 @@
   {
     quoted++;
     p++;
   }
 
   return quoted;
 }
 
-static size_t print_indent (int ql, STATE *s, int sp)
+/* Determines whether to add spacing between/after each quote level:
+ *    >>>foo
+ * becomes
+ *    > > > foo
+ */
+static int space_quotes (STATE *s)
+{
+  /* Allow quote spacing in the pager even for OPTTEXTFLOWED,
+   * but obviously not when replying.
+   */
+  if (option (OPTTEXTFLOWED) && (s->flags & M_REPLYING))
+    return 0;
+
+  return option (OPTREFLOWSPACEQUOTES);
+}
+
+/* Determines whether to add a trailing space to quotes:
+ *    >>> foo
+ * as opposed to
+ *    >>>foo
+ */
+static int add_quote_suffix (STATE *s, int ql)
+{
+  if (s->flags & M_REPLYING)
+    return 0;
+
+  if (space_quotes (s))
+    return 0;
+
+  if (!ql && !s->prefix)
+    return 0;
+
+  /* The prefix will add its own space */
+  if (!option (OPTTEXTFLOWED) && s->prefix)
+    return 0;
+
+  return 1;
+}
+
+static size_t print_indent (int ql, STATE *s, int add_suffix)
 {
   int i;
   size_t wid = 0;
 
   if (s->prefix)
   {
     /* use given prefix only for format=fixed replies to format=flowed,
      * for format=flowed replies to format=flowed, use '>' indentation
      */
     if (option (OPTTEXTFLOWED))
       ql++;
     else
     {
       state_puts (s->prefix, s);
       wid = mutt_strwidth (s->prefix);
-      sp = 0;
     }
   }
   for (i = 0; i < ql; i++)
+  {
     state_putc ('>', s);
-  if (sp)
+    if (space_quotes (s) )
+      state_putc (' ', s);
+  }
+  if (add_suffix)
     state_putc (' ', s);
-  return ql + sp + wid;
+
+  if (space_quotes (s))
+    ql *= 2;
+
+  return ql + add_suffix + wid;
 }
 
 static void flush_par (STATE *s, flowed_state_t *fst)
 {
   if (fst->width > 0)
   {
     state_putc ('\n', s);
     fst->width = 0;
@@ -107,20 +153,20 @@
   {
     /* When replying, force a wrap at FLOWED_MAX to comply with RFC3676
      * guidelines */
     if (width > FLOWED_MAX)
       width = FLOWED_MAX;
     ++ql; /* When replying, we will add an additional quote level */
   }
   /* adjust the paragraph width subtracting the number of prefix chars */
-  width -= ql;
-  /* When displaying (not replying), there will be a space between the prefix
+  width -= space_quotes (s) ? ql*2 : ql;
+  /* When displaying (not replying), there may be a space between the prefix
    * string and the paragraph */
-  if ((s->flags & M_REPLYING) == 0 && ql > 0)
+  if (add_quote_suffix (s, ql))
     --width;
   /* failsafe for really long quotes */
   if (width <= 0)
     width = FLOWED_MAX; /* arbitrary, since the line will wrap */
   return width;
 }
 
 static void print_flowed_line (char *line, STATE *s, int ql,
@@ -178,33 +224,32 @@
          state_putc (' ', s);
       state_putc ('\n', s);
       fst->width = 0;
       fst->spaces = 0;
       words = 0;
     }
 
     if (!words && !fst->width)
-      fst->width = print_indent (ql, s, !(s->flags & M_REPLYING) &&
-                                (ql > 0 || s->prefix));
+      fst->width = print_indent (ql, s, add_quote_suffix (s, ql));
     fst->width += w + fst->spaces;
     for ( ; fst->spaces; fst->spaces--)
       state_putc (' ', s);
     state_puts (p, s);
     words++;
   }
 
   if (term)
     flush_par (s, fst);
 }
 
 static void print_fixed_line (const char *line, STATE *s, int ql,
                              flowed_state_t *fst)
 {
-  print_indent (ql, s, !(s->flags & M_REPLYING) && (ql > 0 || s->prefix));
+  print_indent (ql, s, add_quote_suffix (s, ql));
   if (line && *line)
     state_puts (line, s);
   state_putc ('\n', s);
 
   fst->width = 0;
   fst->spaces = 0;
 }
 

Attachment: signature.asc
Description: PGP signature

Reply via email to