summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-12-12 14:16:39 +0000
committerBram Moolenaar <Bram@vim.org>2021-12-12 14:16:39 +0000
commit6e371ecb27227ff8fedd8561d0f3880a17576848 (patch)
tree29129df4da69f0093ac1b763dffb2be45e84c587
parent9a4ec5a62632af040c278a189e256043740f5c7f (diff)
downloadvim-git-6e371ecb27227ff8fedd8561d0f3880a17576848.tar.gz
patch 8.2.3787: no proper formatting of a C line comment after a statementv8.2.3787
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.
-rw-r--r--src/change.c57
-rw-r--r--src/cindent.c29
-rw-r--r--src/edit.c3
-rw-r--r--src/normal.c2
-rw-r--r--src/proto/change.pro2
-rw-r--r--src/proto/search.pro1
-rw-r--r--src/search.c3
-rw-r--r--src/testdir/test_cindent.vim4
-rw-r--r--src/testdir/test_textformat.vim30
-rw-r--r--src/textformat.c9
-rw-r--r--src/version.c2
11 files changed, 118 insertions, 24 deletions
diff --git a/src/change.c b/src/change.c
index 308cc1812..04712144a 100644
--- a/src/change.c
+++ b/src/change.c
@@ -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();
diff --git a/src/cindent.c b/src/cindent.c
index ad3052249..4fa165e69 100644
--- a/src/cindent.c
+++ b/src/cindent.c
@@ -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
diff --git a/src/edit.c b/src/edit.c
index 8dd60941a..40d5c4e58 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -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;
diff --git a/src/normal.c b/src/normal.c
index d3c4c7875..2d7554804 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -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)
diff --git a/src/proto/change.pro b/src/proto/change.pro
index b1aa9d57e..502b2855f 100644
--- a/src/proto/change.pro
+++ b/src/proto/change.pro
@@ -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 : */
diff --git a/src/proto/search.pro b/src/proto/search.pro
index a6843a09a..27c609e20 100644
--- a/src/proto/search.pro
+++ b/src/proto/search.pro
@@ -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);
diff --git a/src/search.c b/src/search.c
index 5c01e4a3a..c5810ed0e 100644
--- a/src/search.c
+++ b/src/search.c
@@ -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;
diff --git a/src/testdir/test_cindent.vim b/src/testdir/test_cindent.vim
index c097ca766..c7ce2babe 100644
--- a/src/testdir/test_cindent.vim
+++ b/src/testdir/test_cindent.vim
@@ -1694,9 +1694,9 @@ func Test_cindent_1()
#endif
int y; // comment
- // comment
+ // comment
- // comment
+ // comment
{
Constructor(int a,
diff --git a/src/testdir/test_textformat.vim b/src/testdir/test_textformat.vim
index 2b7629277..62cefa1a0 100644
--- a/src/testdir/test_textformat.vim
+++ b/src/testdir/test_textformat.vim
@@ -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!
diff --git a/src/textformat.c b/src/textformat.c
index fb2ca950b..58ba0abca 100644
--- a/src/textformat.c
+++ b/src/textformat.c
@@ -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)
{
diff --git a/src/version.c b/src/version.c
index 0150ddb18..078c060ec 100644
--- a/src/version.c
+++ b/src/version.c
@@ -754,6 +754,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 3787,
+/**/
3786,
/**/
3785,