Greetings all,

Given these settings:
  
  :set tw=20
  :set formatoptions=tcq2
  :set smartindent

... and given this text:

    NOTE: blah blah
          blah blah
  
  # NOTE: blah blah
  #       blah blah

If I do gq{motion} on the top paragraph, formatting is unchanged (as
expected), however, gq{motion} (or gwap) on the bottom paragraph
results in this new formatting:
  
  # NOTE: blah blah
  # blah blah

So, even though I have both the 2 and q formatoptions, the second
line's indentation is not used when within a comment block...

The t and c formatoptions (for auto-wrap) are working properly with
formatoptions+=2 in both paragraphs.

I would prefer for Vim to be consistent; in this case, I think it
should handle auto-wrap and formatting in the same way.  So...
I've made a patch!

The patch applies against version 7.3.538 and doesn't mess with
the auto-wrap logic (it's working!).  It does mess with these funcs:

  format_lines()
    insertchar()
      internal_format()
        open_line()

The patch also fixes numeric list handling within comments (not just
2nd line indenting)...

I've tried my best to "tread lightly" and comment things pretty well.

I've run "make test" and it is OK.  I've also added two new tests to
the "test suite"...

I've attached the patch separately to preserve white space, etc..

Finally, below I include a more complex test case that showcases what
this patch can do (I hope it will be accepted by Bram)...

Thanks for your time and consideration, and thanks for Vim!

- Tor

PS - more test cases here:

== numbered list formatting ======================

vi:tw=25:formatoptions=tcqn:smartindent

    11 aaaa aaaa aaaa bbbb bbbb bbbb

    22 aaaa aaaa aaaa bbbb
       bbbb bbbb

    33 aaaa aaaa
       aaaa bbbb bbbb bbbb

  # 11 aaaa aaaa aaaa bbbb bbbb bbbb

  # 22 aaaa aaaa aaaa bbbb
  #    bbbb bbbb

  # 33 aaaa aaaa
  #    aaaa bbbb bbbb bbbb

> > 11 aaaa aaaa aaaa bbbb bbbb bbbb

> > 22 aaaa aaaa aaaa bbbb
> >    bbbb bbbb

> > 33 aaaa aaaa
> >    aaaa bbbb bbbb bbbb

  -- above = before, below = after --

    11 aaaa aaaa aaaa
       bbbb bbbb bbbb

    22 aaaa aaaa aaaa
       bbbb bbbb bbbb

    33 aaaa aaaa aaaa
       bbbb bbbb bbbb

  # 11 aaaa aaaa aaaa
  #    bbbb bbbb bbbb

  # 22 aaaa aaaa aaaa
  #    bbbb bbbb bbbb

  # 33 aaaa aaaa aaaa
  #    bbbb bbbb bbbb

> > 11 aaaa aaaa aaaa
> >    bbbb bbbb bbbb

> > 22 aaaa aaaa aaaa
> >    bbbb bbbb bbbb

> > 33 aaaa aaaa aaaa
> >    bbbb bbbb bbbb

== 2nd line indent formatting ====================

vi:tw=25:formatoptions=tcq2:smartindent

    xx aaaa aaaa aaaa bbbb
       bbbb bbbb

    xx aaaa aaaa
       aaaa bbbb bbbb bbbb

  # xx aaaa aaaa aaaa bbbb
  #    bbbb bbbb

  # xx aaaa aaaa
  #    aaaa bbbb bbbb bbbb

> > xx aaaa aaaa aaaa bbbb
> >    bbbb bbbb

> > xx aaaa aaaa
> >    aaaa bbbb bbbb bbbb

  -- above = before, below = after --

    xx aaaa aaaa aaaa 
       bbbb bbbb bbbb
                 
    xx aaaa aaaa aaaa
       bbbb bbbb bbbb 
                      
  # xx aaaa aaaa aaaa 
  #    bbbb bbbb bbbb
                 
  # xx aaaa aaaa aaaa
  #    bbbb bbbb bbbb 
                      
> > xx aaaa aaaa aaaa 
> >    bbbb bbbb bbbb
                 
> > xx aaaa aaaa aaaa
> >    bbbb bbbb bbbb 

-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff -up ./src/testdir/test68.in.org ./src/testdir/test68.in
--- ./src/testdir/test68.in.org	2012-06-02 07:40:50.000000000 -0700
+++ ./src/testdir/test68.in	2012-06-05 19:30:51.000000000 -0700
@@ -51,6 +51,27 @@ a b
 }
 
 STARTTEST
+/^{/+1
+:set tw=5 fo=qn comments=:#
+gwap
+ENDTEST
+
+{
+# 1 a b
+}
+
+STARTTEST
+/^{/+1
+:set tw=5 fo=q2 comments=:#
+gwap
+ENDTEST
+
+{
+# x
+#   a b
+}
+
+STARTTEST
 /^{/+2
 :set tw& fo=a
 I^^
diff -up ./src/testdir/test68.ok.org ./src/testdir/test68.ok
--- ./src/testdir/test68.ok.org	2012-06-02 07:40:50.000000000 -0700
+++ ./src/testdir/test68.ok	2012-06-05 19:30:56.000000000 -0700
@@ -34,5 +34,17 @@ a b
 }
 
 
+{
+# 1 a
+#   b
+}
+
+
+{
+# x a
+#   b
+}
+
+
 { 1aa ^^2bb }
 
diff -up ./src/vim.h.org ./src/vim.h
--- ./src/vim.h.org	2012-06-02 07:40:50.000000000 -0700
+++ ./src/vim.h	2012-06-05 16:31:39.000000000 -0700
@@ -1072,12 +1072,14 @@ extern char *(*dyn_libintl_textdomain)(c
 #define INSCHAR_DO_COM	2	/* format comments */
 #define INSCHAR_CTRLV	4	/* char typed just after CTRL-V */
 #define INSCHAR_NO_FEX	8	/* don't use 'formatexpr' */
+#define INSCHAR_COM_WITH_N_OR_2	16	/* format comments with num list or 2nd line indent */
 
 /* flags for open_line() */
 #define OPENLINE_DELSPACES  1	/* delete spaces after cursor */
 #define OPENLINE_DO_COM	    2	/* format comments */
 #define OPENLINE_KEEPTRAIL  4	/* keep trailing spaces */
 #define OPENLINE_MARKFIX    8	/* fix mark positions */
+#define OPENLINE_COM_WITH_N_OR_2	16	/* format comments with num list or 2nd line indent */
 
 /*
  * There are four history tables:
diff -up ./src/ops.c.org ./src/ops.c
--- ./src/ops.c.org	2012-06-02 07:40:50.000000000 -0700
+++ ./src/ops.c	2012-06-05 16:50:50.000000000 -0700
@@ -4597,9 +4597,10 @@ format_lines(line_count, avoid_fex)
     char_u	*leader_flags = NULL;	/* flags for leader of current line */
     char_u	*next_leader_flags;	/* flags for leader of next line */
     int		do_comments;		/* format comments */
+    int		do_comments_with_n_or_2 = 0;	/* format comments ('q') w/ 'n' or '2' */
 #endif
     int		advance = TRUE;
-    int		second_indent = -1;
+    int		second_indent = -1;		/* indent for second line (comment aware) */
     int		do_second_indent;
     int		do_number_indent;
     int		do_trail_white;
@@ -4703,17 +4704,33 @@ format_lines(line_count, avoid_fex)
 		    && (do_second_indent || do_number_indent)
 		    && prev_is_end_par
 		    && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
-#ifdef FEAT_COMMENTS
-		    && leader_len == 0
-		    && next_leader_len == 0
-#endif
 		    )
 	    {
-		if (do_second_indent
-			&& !lineempty(curwin->w_cursor.lnum + 1))
+		if (do_second_indent && !lineempty(curwin->w_cursor.lnum + 1)) {
+#ifdef FEAT_COMMENTS
+                  if ( leader_len == 0 && next_leader_len == 0 ) { /* no comment found */
+#endif
 		    second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1);
-		else if (do_number_indent)
+#ifdef FEAT_COMMENTS
+                  } else {
+                    second_indent = next_leader_len;
+                    do_comments_with_n_or_2 = 1;
+#endif
+                  }
+                }
+		else if (do_number_indent) {
+#ifdef FEAT_COMMENTS
+                  if ( leader_len == 0 && next_leader_len == 0 ) { /* no comment found */
+#endif
 		    second_indent = get_number_indent(curwin->w_cursor.lnum);
+#ifdef FEAT_COMMENTS
+                  } else {
+                    /* get_number_indent() is now "comment aware"... */
+                    second_indent = get_number_indent(curwin->w_cursor.lnum);
+                    do_comments_with_n_or_2 = 1;
+#endif
+                  }
+                }
 	    }
 
 	    /*
@@ -4752,6 +4769,7 @@ format_lines(line_count, avoid_fex)
 		insertchar(NUL, INSCHAR_FORMAT
 #ifdef FEAT_COMMENTS
 			+ (do_comments ? INSCHAR_DO_COM : 0)
+			+ (do_comments && do_comments_with_n_or_2 ? INSCHAR_COM_WITH_N_OR_2 : 0)
 #endif
 			+ (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
 		State = old_State;
diff -up ./src/edit.c.org ./src/edit.c
--- ./src/edit.c.org	2012-06-02 07:40:50.000000000 -0700
+++ ./src/edit.c	2012-06-05 16:31:14.000000000 -0700
@@ -5769,6 +5769,17 @@ insert_special(c, allow_modmask, ctrlv)
 # define WHITECHAR(cc) vim_iswhite(cc)
 #endif
 
+/*
+ * "flags": INSCHAR_FORMAT - force formatting
+ *          INSCHAR_CTRLV  - char typed just after CTRL-V
+ *          INSCHAR_NO_FEX - don't use 'formatexpr'
+ *
+ *   NOTE: passes the flags value straight through to internal_format() which,
+ *         beside INSCHAR_FORMAT (above), is also looking for these:
+ *
+ *          INSCHAR_DO_COM          - format comments
+ *          INSCHAR_COM_WITH_N_OR_2 - format comments w/ num list or 2nd line indent
+ */
     void
 insertchar(c, flags, second_indent)
     int		c;			/* character to insert or NUL */
@@ -6011,6 +6022,10 @@ insertchar(c, flags, second_indent)
 
 /*
  * Format text at the current insert position.
+ *
+ * If the INSCHAR_COM_WITH_N_OR_2 flag is present, then the value of
+ * second_indent will be the comment leader length sent to open_line().
+ *
  */
     static void
 internal_format(textwidth, second_indent, flags, format_only, c)
@@ -6289,13 +6304,22 @@ internal_format(textwidth, second_indent
 		+ (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
 #ifdef FEAT_COMMENTS
 		+ (do_comments ? OPENLINE_DO_COM : 0)
+		+ ((flags & INSCHAR_COM_WITH_N_OR_2) ? OPENLINE_COM_WITH_N_OR_2 : 0)
 #endif
-		, old_indent);
-	old_indent = 0;
+		,( (flags & INSCHAR_COM_WITH_N_OR_2) ? second_indent : old_indent ));
+	if ( ! ( flags & INSCHAR_COM_WITH_N_OR_2 ) ) old_indent = 0;
 
 	replace_offset = 0;
 	if (first_line)
 	{
+	    if ( ! (flags & INSCHAR_COM_WITH_N_OR_2) ) {
+              /*
+               * This section is for numeric lists w/o comments.  If comment
+               * indents are needed with numeric lists (formatoptions=nq), then
+               * the INSCHAR_COM_WITH_N_OR_2 flag will cause the corresponding
+               * OPENLINE_COM_WITH_N_OR_2 flag to be passed through to
+               * open_line() (as seen above)...
+               */
 	    if (second_indent < 0 && has_format_option(FO_Q_NUMBER))
 		second_indent = get_number_indent(curwin->w_cursor.lnum -1);
 	    if (second_indent >= 0)
@@ -6307,6 +6331,7 @@ internal_format(textwidth, second_indent
 #endif
 		    (void)set_indent(second_indent, SIN_CHANGED);
 	    }
+	    }
 	    first_line = FALSE;
 	}
 
diff -up ./src/misc1.c.org ./src/misc1.c
--- ./src/misc1.c.org	2012-06-02 07:40:50.000000000 -0700
+++ ./src/misc1.c	2012-06-05 16:56:55.000000000 -0700
@@ -423,27 +423,63 @@ get_number_indent(lnum)
 {
     colnr_T	col;
     pos_T	pos;
-    regmmatch_T	regmatch;
 
     if (lnum > curbuf->b_ml.ml_line_count)
 	return -1;
     pos.lnum = 0;
-    regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC);
-    if (regmatch.regprog != NULL)
-    {
-	regmatch.rmm_ic = FALSE;
-	regmatch.rmm_maxcol = 0;
-	if (vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
-							    (colnr_T)0, NULL))
-	{
-	    pos.lnum = regmatch.endpos[0].lnum + lnum;
-	    pos.col = regmatch.endpos[0].col;
+
+#ifdef FEAT_COMMENTS
+    if ( has_format_option(FO_Q_COMS) && has_format_option(FO_Q_NUMBER) ) {
+      regmatch_T  regmatch;
+      int lead_len;         /* length of comment leader */
+
+      lead_len = get_leader_len(ml_get(lnum), NULL, FALSE);
+      regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC);
+      if (regmatch.regprog != NULL) {
+        regmatch.rm_ic = FALSE;
+        /*
+         * vim_regexec() expects a pointer to a line.  This lets us
+         * start matching for the flp beyond any comment leader...
+         */
+        if (vim_regexec(&regmatch, ml_get(lnum) + lead_len, (colnr_T)0)) {
+          pos.lnum = lnum;
+          pos.col  = *regmatch.endp - (ml_get(lnum) + lead_len);
+          pos.col += lead_len;
 #ifdef FEAT_VIRTUALEDIT
 	    pos.coladd = 0;
 #endif
 	}
-	vim_free(regmatch.regprog);
+      }
+      vim_free(regmatch.regprog);
+    } else {
+      /*
+       * What follows is the orig code that is not "comment aware"...
+       *
+       * I'm not sure if regmmatch_T (multi-match) is needed in this case.
+       * It may be true that this section would work properly using the
+       * regmatch_T code above, in which case, these two seperate sections
+       * should be consolidated w/ FEAT_COMMENTS making lead_len > 0...
+       */
+#endif
+      regmmatch_T  regmatch;
+
+      regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC);
+
+      if (regmatch.regprog != NULL) {
+        regmatch.rmm_ic = FALSE;
+        regmatch.rmm_maxcol = 0;
+        if (vim_regexec_multi(&regmatch, curwin, curbuf, lnum, (colnr_T)0, NULL)) {   
+          pos.lnum = regmatch.endpos[0].lnum + lnum;
+          pos.col = regmatch.endpos[0].col;
+#ifdef FEAT_VIRTUALEDIT
+          pos.coladd = 0;
+#endif  
+        }
+        vim_free(regmatch.regprog);
+      }
+#ifdef FEAT_COMMENTS
     }
+#endif  
 
     if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL)
 	return -1;
@@ -502,15 +538,16 @@ cin_is_cinword(line)
  *	    OPENLINE_DO_COM	format comments
  *	    OPENLINE_KEEPTRAIL	keep trailing spaces
  *	    OPENLINE_MARKFIX	adjust mark positions after the line break
+ *	    OPENLINE_COM_WITH_N_OR_2	format comments with num list or 2nd line indent
  *
  * Return TRUE for success, FALSE for failure
  */
     int
-open_line(dir, flags, old_indent)
+open_line(dir, flags, second_line_indent)
     int		dir;		/* FORWARD or BACKWARD */
     int		flags;
-    int		old_indent;	/* indent for after ^^D in Insert mode */
-{
+    int         second_line_indent;     /* indent for after ^^D in Insert mode     */
+{                                       /* ... or if flag OPENLINE_COM_WITH_N_OR_2 */
     char_u	*saved_line;		/* copy of the original line */
     char_u	*next_line = NULL;	/* copy of the next line */
     char_u	*p_extra = NULL;	/* what goes to next line */
@@ -650,8 +687,8 @@ open_line(dir, flags, old_indent)
 	 * count white space on current line
 	 */
 	newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts);
-	if (newindent == 0)
-	    newindent = old_indent;	/* for ^^D command in insert mode */
+	if (newindent == 0 && ! (flags & OPENLINE_COM_WITH_N_OR_2) )
+	    newindent = second_line_indent;	/* for ^^D command in insert mode */
 
 #ifdef FEAT_SMARTINDENT
 	/*
@@ -1008,8 +1045,8 @@ open_line(dir, flags, old_indent)
 	if (lead_len)
 	{
 	    /* allocate buffer (may concatenate p_exta later) */
-	    leader = alloc(lead_len + lead_repl_len + extra_space +
-							      extra_len + 1);
+	    leader = alloc(lead_len + lead_repl_len + extra_space + extra_len + 1
+             + ( second_line_indent > 0 ? second_line_indent : 0 ) );
 	    allocated = leader;		    /* remember to free it later */
 
 	    if (leader == NULL)
@@ -1304,6 +1341,20 @@ open_line(dir, flags, old_indent)
     /* concatenate leader and p_extra, if there is a leader */
     if (lead_len)
     {
+      if (flags & OPENLINE_COM_WITH_N_OR_2 && second_line_indent > 0) {
+        /*
+         * Here whitespace is inserted after the comment char...
+         *
+         * Below, set_indent(newindent, SIN_INSERT) will insert the whitespace
+         * needed before the comment char.
+         */
+        int i;
+        int padding = second_line_indent - ( newindent + strlen(leader) );
+        for (i = 0; i < padding; i++) {
+          strcat(leader, " ");
+          newcol++;
+        }
+      }
 	STRCAT(leader, p_extra);
 	p_extra = leader;
 	did_ai = TRUE;	    /* So truncating blanks works with comments */

Raspunde prin e-mail lui