On Tue, Jun 05, 2012 at 08:01:57PM -0700, Tor Perkins wrote:
> 
> 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"...
> 
> Thanks for your time and consideration, and thanks for Vim!
> 
> - Tor

I've updated my patch so that it now applies to 7.3.543 without any
fuzz (please find attached).  The only substantive change was:

  lead_len = get_leader_len(ml_get(lnum), NULL, FALSE);

    becomes...

  lead_len = get_leader_len(ml_get(lnum), NULL, FALSE, TRUE);

Thanks!

- Tor

PS - I really like the new fo+=j patch that came w/ 7.3.541...  :^)

-- 
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-05 18:08:40.000000000 -0700
+++ ./src/testdir/test68.in	2012-06-06 08:36:53.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-05 18:08:40.000000000 -0700
+++ ./src/testdir/test68.ok	2012-06-06 08:36:53.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-05 18:08:40.000000000 -0700
+++ ./src/vim.h	2012-06-06 08:36:53.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-06 07:50:23.000000000 -0700
+++ ./src/ops.c	2012-06-06 08:36:53.000000000 -0700
@@ -4726,9 +4726,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;
@@ -4832,17 +4833,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
+                  }
+                }
 	    }
 
 	    /*
@@ -4881,6 +4898,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-06 07:50:23.000000000 -0700
+++ ./src/edit.c	2012-06-06 08:36:53.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-06 07:50:23.000000000 -0700
+++ ./src/misc1.c	2012-06-06 08:36:53.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, TRUE);
+      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