cursor_save = curwin->w_cursor;
ind_maxp_wk = ind_maxparen;
retry:
- if ((trypos = findmatchlimit(NULL, c, 0, ind_maxp_wk)) != NULL)
+ if ((trypos = findmatchlimit(NULL, c, FM_SKIPCOMM, ind_maxp_wk)) != NULL)
{
// check if the ( is in a // comment
if ((colnr_T)cin_skip2pos(trypos) > trypos->col)
++p;
++curwin->w_cursor.col;
}
- if ((trypos = findmatchlimit(NULL, 0, 0,
+ if ((trypos = findmatchlimit(NULL, 0, FM_SKIPCOMM,
curbuf->b_ind_maxparen)) != NULL
&& *cin_skipcomment(ml_get_pos(trypos) + 1) == ';')
retval = TRUE;
static pos_T pos_copy;
cursor_save = curwin->w_cursor;
- while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP, 0)) != NULL)
+ while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP | FM_SKIPCOMM, 0)) != NULL)
{
pos_copy = *trypos; // copy pos_T, next findmatch will change it
trypos = &pos_copy;
line = ml_get_curline();
look_col = (int)(look - line);
curwin->w_cursor.col = look_col + 1;
- if ((trypos = findmatchlimit(NULL, ')', 0,
+ if ((trypos = findmatchlimit(NULL, ')', FM_SKIPCOMM,
curbuf->b_ind_maxparen))
!= NULL
&& trypos->lnum == our_paren_pos.lnum
* flags: FM_BACKWARD search backwards (when initc is '/', '*' or '#')
* FM_FORWARD search forwards (when initc is '/', '*' or '#')
* FM_BLOCKSTOP stop at start/end of block ({ or } in column 0)
- * FM_SKIPCOMM skip comments (not implemented yet!)
+ * FM_SKIPCOMM skip over comments (cursor must start outside a block comment)
*
* "oap" is only used to set oap->motion_type for a linewise motion, it can be
* NULL
int comment_col = MAXCOL; // start of / / comment
int lispcomm = FALSE; // inside of Lisp-style comment
int lisp = curbuf->b_p_lisp; // engage Lisp-specific hacks ;)
+ int skip_comments = (flags & FM_SKIPCOMM) != 0;
+ int in_block_comment = FALSE; // inside /* */ block comment
pos = curwin->w_cursor;
pos.coladd = 0;
CLEAR_POS(&match_pos);
// backward search: Check if this line contains a single-line comment
- if ((backwards && comment_dir) || lisp)
+ if ((backwards && comment_dir) || lisp || skip_comments)
comment_col = check_linecomment(linep);
if (lisp && comment_col != MAXCOL && pos.col > (colnr_T)comment_col)
lispcomm = TRUE; // find match inside this comment
+ // skip // comment portion at starting position
+ if (skip_comments && !in_block_comment && comment_col != MAXCOL
+ && backwards && pos.col > (colnr_T)comment_col)
+ pos.col = comment_col;
while (!got_int)
{
line_breakcheck();
// Check if this line contains a single-line comment
- if (comment_dir || lisp)
+ if (comment_dir || lisp || skip_comments)
comment_col = check_linecomment(linep);
// skip comment
if (lisp && comment_col != MAXCOL)
pos.col = comment_col;
+ else if (skip_comments && !in_block_comment
+ && comment_col != MAXCOL
+ && pos.col > (colnr_T)comment_col)
+ pos.col = comment_col;
}
else
{
pos.col = 0;
do_quotes = -1;
line_breakcheck();
- if (lisp) // find comment pos in new line
+ if (lisp || skip_comments) // find comment pos in new line
comment_col = check_linecomment(linep);
}
else
}
}
+ // Track block comment state when FM_SKIPCOMM is set.
+ // Backward: '/' of end-marker enters comment; '*' of start-marker exits.
+ // Forward: '/' of start-marker enters comment; '/' of end-marker exits.
+ if (skip_comments && !comment_dir)
+ {
+ if (backwards)
+ {
+ // Guard pos.col < comment_col: don't misread '*/' at the '//'
+ // position as a block-comment end-marker.
+ if (!in_block_comment && pos.col > 0
+ && linep[pos.col - 1] == '*' && linep[pos.col] == '/'
+ && (comment_col == MAXCOL || (int)pos.col < comment_col))
+ in_block_comment = TRUE;
+ else if (in_block_comment && pos.col > 0
+ && linep[pos.col - 1] == '/' && linep[pos.col] == '*')
+ in_block_comment = FALSE;
+ }
+ else
+ {
+ // Guard pos.col < comment_col: don't treat '/*' inside a '//'
+ // comment as a block-comment start-marker.
+ if (!in_block_comment && linep[pos.col] == '/'
+ && linep[pos.col + 1] == '*'
+ && (comment_col == MAXCOL || (int)pos.col < comment_col))
+ in_block_comment = TRUE;
+ else if (in_block_comment && pos.col > 0
+ && linep[pos.col - 1] == '*' && linep[pos.col] == '/')
+ in_block_comment = FALSE;
+ }
+ }
+
/*
* If FM_BLOCKSTOP given, stop at a '{' or '}' in column 0.
*/
&& check_prevcol(linep, pos.col - 1, '#', NULL))
break;
+ // Skip matches inside comments when FM_SKIPCOMM is set.
+ if (skip_comments && (in_block_comment
+ || (comment_col != MAXCOL && (int)pos.col >= comment_col)))
+ break;
+
// Check for match outside of quotes, and inside of
// quotes when the start is also inside of quotes.
if ((!inquote || start_in_quotes == TRUE)
bwipe!
enddef
+" Brackets inside comments must not affect C indent calculation (FM_SKIPCOMM)
+def Test_cindent_comment_brackets()
+ # stray } in inline block comment must not confuse enclosing-brace search
+ new
+ setl cindent sw=4
+ var code =<< trim [CODE]
+ int foo() {
+ /* } */
+ int bar;
+ }
+ [CODE]
+ setline(1, code)
+ cursor(3, 1)
+ normal ==
+ assert_equal(' int bar;', getline(3))
+ bwipe!
+
+ # stray } in // line comment: same
+ new
+ setl cindent sw=4
+ var code2 =<< trim [CODE]
+ int foo() {
+ // }
+ int bar;
+ }
+ [CODE]
+ setline(1, code2)
+ cursor(3, 1)
+ normal ==
+ assert_equal(' int bar;', getline(3))
+ bwipe!
+
+ # stray } on continuation line inside multi-line block comment
+ new
+ setl cindent sw=4
+ var code3 =<< trim [CODE]
+ int foo() {
+ /*
+ }
+ */
+ int bar;
+ }
+ [CODE]
+ setline(1, code3)
+ cursor(5, 1)
+ normal ==
+ assert_equal(' int bar;', getline(5))
+ bwipe!
+
+ # { in inline block comment must not be treated as enclosing brace
+ new
+ setl cindent sw=4
+ var code4 =<< trim [CODE]
+ int foo() {
+ /* { */
+ int bar;
+ }
+ [CODE]
+ setline(1, code4)
+ cursor(3, 1)
+ normal ==
+ assert_equal(' int bar;', getline(3))
+ bwipe!
+
+ # ) in inline block comment must not be treated as enclosing brace
+ new
+ setl cindent sw=4
+ var code5 =<< trim [CODE]
+ some_func(arg1,
+ /* ) */ arg2,
+ arg3);
+ [CODE]
+ setline(1, code5)
+ cursor(3, 1)
+ normal ==
+ assert_equal(' arg3);', getline(3))
+ bwipe!
+
+enddef
+
" vim: shiftwidth=2 sts=2 expandtab