]> granicus.if.org Git - vim/commitdiff
patch 8.2.3787: no proper formatting of a C line comment after a statement v8.2.3787
authorBram Moolenaar <Bram@vim.org>
Sun, 12 Dec 2021 14:16:39 +0000 (14:16 +0000)
committerBram Moolenaar <Bram@vim.org>
Sun, 12 Dec 2021 14:16:39 +0000 (14:16 +0000)
Problem:    No proper formatting of a C line comment after a statement.
Solution:   Find the start of the line comment, insert the comment leader and
            indent the comment properly.

src/change.c
src/cindent.c
src/edit.c
src/normal.c
src/proto/change.pro
src/proto/search.pro
src/search.c
src/testdir/test_cindent.vim
src/testdir/test_textformat.vim
src/textformat.c
src/version.c

index 308cc181205866577c271911d30e28263e102743..04712144acbaac71329ad7e3e8e726a4e94da1c7 100644 (file)
@@ -1356,6 +1356,8 @@ del_bytes(
  *
  * "second_line_indent": indent for after ^^D in Insert mode or if flag
  *                       OPENLINE_COM_LIST
+ * "did_do_comment" is set to TRUE when intentionally putting the comment
+ * leader in fromt of the new line.
  *
  * Return OK for success, FAIL for failure
  */
@@ -1363,7 +1365,8 @@ del_bytes(
 open_line(
     int                dir,            // FORWARD or BACKWARD
     int                flags,
-    int                second_line_indent)
+    int                second_line_indent,
+    int                *did_do_comment UNUSED)
 {
     char_u     *saved_line;            // copy of the original line
     char_u     *next_line = NULL;      // copy of the next line
@@ -1378,6 +1381,7 @@ open_line(
     int                retval = FAIL;          // return value
     int                extra_len = 0;          // length of p_extra string
     int                lead_len;               // length of comment leader
+    int                comment_start = 0;      // start index of the comment leader
     char_u     *lead_flags;    // position in 'comments' for comment leader
     char_u     *leader = NULL;         // copy of comment leader
     char_u     *allocated = NULL;      // allocated memory
@@ -1393,6 +1397,9 @@ open_line(
                                        && *curbuf->b_p_inde == NUL
 # endif
                        );
+#ifdef FEAT_CINDENT
+    int                do_cindent;
+#endif
     int                no_si = FALSE;          // reset did_si afterwards
     int                first_char = NUL;       // init for GCC
 #endif
@@ -1632,12 +1639,43 @@ open_line(
        did_ai = TRUE;
     }
 
+#ifdef FEAT_CINDENT
+    // May do indenting after opening a new line.
+    do_cindent = !p_paste && (curbuf->b_p_cin
+#  ifdef FEAT_EVAL
+                   || *curbuf->b_p_inde != NUL
+#  endif
+               )
+           && in_cinkeys(dir == FORWARD
+               ? KEY_OPEN_FORW
+               : KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum));
+#endif
+
     // Find out if the current line starts with a comment leader.
     // This may then be inserted in front of the new line.
     end_comment_pending = NUL;
     if (flags & OPENLINE_DO_COM)
+    {
        lead_len = get_leader_len(saved_line, &lead_flags,
                                                        dir == BACKWARD, TRUE);
+#ifdef FEAT_CINDENT
+       if (lead_len == 0 && do_cindent)
+       {
+           comment_start = check_linecomment(saved_line);
+           if (comment_start != MAXCOL)
+           {
+               lead_len = get_leader_len(saved_line + comment_start,
+                                          &lead_flags, dir == BACKWARD, TRUE);
+               if (lead_len != 0)
+               {
+                   lead_len += comment_start;
+                   if (did_do_comment != NULL)
+                       *did_do_comment = TRUE;
+               }
+           }
+       }
+#endif
+    }
     else
        lead_len = 0;
     if (lead_len > 0)
@@ -1799,8 +1837,15 @@ open_line(
                lead_len = 0;
            else
            {
+               int li;
+
                vim_strncpy(leader, saved_line, lead_len);
 
+               // TODO: handle multi-byte and double width chars
+               for (li = 0; li < comment_start; ++li)
+                   if (!VIM_ISWHITE(leader[li]))
+                       leader[li] = ' ';
+
                // Replace leader with lead_repl, right or left adjusted
                if (lead_repl != NULL)
                {
@@ -2247,15 +2292,7 @@ open_line(
 #endif
 #ifdef FEAT_CINDENT
     // May do indenting after opening a new line.
-    if (!p_paste
-           && (curbuf->b_p_cin
-#  ifdef FEAT_EVAL
-                   || *curbuf->b_p_inde != NUL
-#  endif
-               )
-           && in_cinkeys(dir == FORWARD
-               ? KEY_OPEN_FORW
-               : KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum)))
+    if (do_cindent)
     {
        do_c_expr_indent();
        ai_col = (colnr_T)getwhitecols_curline();
index ad3052249dc8fdee4440299fda58656351ce9cae..4fa165e699cfd54e83a672e4adfcc0e9c13aebd9 100644 (file)
@@ -2144,13 +2144,30 @@ get_c_indent(void)
 
     // If we're inside a "//" comment and there is a "//" comment in a
     // previous line, lineup with that one.
-    if (cin_islinecomment(theline)
-           && (trypos = find_line_comment()) != NULL) // XXX
+    if (cin_islinecomment(theline))
     {
-       // find how indented the line beginning the comment is
-       getvcol(curwin, trypos, &col, NULL, NULL);
-       amount = col;
-       goto theend;
+       pos_T   linecomment_pos;
+
+       trypos = find_line_comment(); // XXX
+       if (trypos == NULL && curwin->w_cursor.lnum > 1)
+       {
+           // There may be a statement before the comment, search from the end
+           // of the line for a comment start.
+           linecomment_pos.col =
+                         check_linecomment(ml_get(curwin->w_cursor.lnum - 1));
+           if (linecomment_pos.col != MAXCOL)
+           {
+               trypos = &linecomment_pos;
+               trypos->lnum = curwin->w_cursor.lnum - 1;
+           }
+       }
+       if (trypos  != NULL)
+       {
+           // find how indented the line beginning the comment is
+           getvcol(curwin, trypos, &col, NULL, NULL);
+           amount = col;
+           goto theend;
+       }
     }
 
     // If we're inside a comment and not looking at the start of the
index 8dd60941a043995af517ca2adba1006c2bd00ca7..40d5c4e5830d58e4d0add38ef05e6e6c8c2dc8ae 100644 (file)
@@ -5147,7 +5147,8 @@ ins_eol(int c)
 
     AppendToRedobuff(NL_STR);
     i = open_line(FORWARD,
-           has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM : 0, old_indent);
+           has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM : 0, old_indent,
+           NULL);
     old_indent = 0;
 #ifdef FEAT_CINDENT
     can_cindent = TRUE;
index d3c4c7875cb560ddecf3a9d469c5f3828fbc2752..2d75548046005121dc7524b7161f7e879b808c39 100644 (file)
@@ -6511,7 +6511,7 @@ n_opencmd(cmdarg_T *cap)
                       ) == OK
                && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
                         has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : 0,
-                                                                     0) == OK)
+                                                               0, NULL) == OK)
        {
 #ifdef FEAT_CONCEAL
            if (curwin->w_p_cole > 0 && oldline != curwin->w_cursor.lnum)
index b1aa9d57ec81109eae4473f0ac12239cb488c3fa..502b2855fd88c7c1a34e5447cf379e92192cd7c5 100644 (file)
@@ -27,7 +27,7 @@ void ins_str(char_u *s);
 int del_char(int fixpos);
 int del_chars(long count, int fixpos);
 int del_bytes(long count, int fixpos_arg, int use_delcombine);
-int open_line(int dir, int flags, int second_line_indent);
+int open_line(int dir, int flags, int second_line_indent, int *did_do_comment);
 int truncate_line(int fixpos);
 void del_lines(long nlines, int undo);
 /* vim: set ft=c : */
index a6843a09ae470f10032f48ce5e3129b7b6d0ee75..27c609e200743d04b5e12a9af918330ddc7d5374 100644 (file)
@@ -29,6 +29,7 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat);
 int searchc(cmdarg_T *cap, int t_cmd);
 pos_T *findmatch(oparg_T *oap, int initc);
 pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int maxtravel);
+int check_linecomment(char_u *line);
 void showmatch(int c);
 int current_search(long count, int forward);
 int linewhite(linenr_T lnum);
index 5c01e4a3aee2103420b65c2a94df8605b0305ab6..c5810ed0e7328c49c5e0bfe30d80ff4a4af888dd 100644 (file)
@@ -16,7 +16,6 @@
 static void set_vv_searchforward(void);
 static int first_submatch(regmmatch_T *rp);
 #endif
-static int check_linecomment(char_u *line);
 #ifdef FEAT_FIND_ID
 static void show_pat_in_path(char_u *, int,
                                         int, int, FILE *, linenr_T *, long);
@@ -2717,7 +2716,7 @@ findmatchlimit(
  * Return MAXCOL if not, otherwise return the column.
  * TODO: skip strings.
  */
-    static int
+    int
 check_linecomment(char_u *line)
 {
     char_u  *p;
index c097ca766d463679b263387a217184f0af53baaf..c7ce2babe281f753ac844e6f17b1c25b5ea89259 100644 (file)
@@ -1694,9 +1694,9 @@ func Test_cindent_1()
   #endif
 
   int y;               // comment
-  // comment
+                       // comment
 
-  // comment
+                       // comment
 
   {
        Constructor(int a,
index 2b7629277716fc5bfa6dd7c0930d488a40ef7555..62cefa1a0f2891b9c6bf67e3dbc4a5b88861e69a 100644 (file)
@@ -196,6 +196,36 @@ func Test_text_format()
   enew!
 endfunc
 
+func Test_format_c_comment()
+  new
+  setl ai cindent tw=40 et fo=croql
+  let text =<< trim END
+      var = 2345;  // asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf
+  END
+  call setline(1, text)
+  normal gql
+  let expected =<< trim END
+      var = 2345;  // asdf asdf asdf asdf asdf
+                   // asdf asdf asdf asdf asdf
+  END
+  call assert_equal(expected, getline(1, '$'))
+
+  %del
+  let text =<< trim END
+      var = 2345;  // asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf
+  END
+  call setline(1, text)
+  normal gql
+  let expected =<< trim END
+      var = 2345;  // asdf asdf asdf asdf asdf
+                   // asdf asdf asdf asdf asdf
+                   // asdf asdf
+  END
+  call assert_equal(expected, getline(1, '$'))
+
+  bwipe!
+endfunc
+
 " Tests for :right, :center and :left on text with embedded TAB.
 func Test_format_align()
   enew!
index fb2ca950bf02bd52886e7748f74a40c89a00ffad..58ba0abca3ff255c10565903473a98fac6a87007 100644 (file)
@@ -89,6 +89,7 @@ internal_format(
        colnr_T col;
        colnr_T end_col;
        int     wcc;                    // counter for whitespace chars
+       int     did_do_comment = FALSE;
 
        virtcol = get_nolist_virtcol()
                + char2cells(c != NUL ? c : gchar_cursor());
@@ -352,10 +353,16 @@ internal_format(
                + (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
                + (do_comments ? OPENLINE_DO_COM : 0)
                + ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0)
-               , ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent));
+               , ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent),
+               &did_do_comment);
        if (!(flags & INSCHAR_COM_LIST))
            old_indent = 0;
 
+       // If a comment leader was inserted, may also do this on a following
+       // line.
+       if (did_do_comment)
+           no_leader = FALSE;
+
        replace_offset = 0;
        if (first_line)
        {
index 0150ddb1859f131e3ec1c416b2d14121cd92a07a..078c060ec1a5f318d5abaf199a9ee124d9d82aa8 100644 (file)
@@ -753,6 +753,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3787,
 /**/
     3786,
 /**/