To: vim_dev@googlegroups.com Subject: Patch 8.2.3938 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3938 Problem: Line comment start is also found in a string. Solution: Skip line comments in a string. Files: src/cindent.c, src/proto/cindent.pro, src/search.c, src/testdir/test_textformat.vim *** ../vim-8.2.3937/src/cindent.c 2021-12-27 17:21:38.000449144 +0000 --- src/cindent.c 2021-12-29 18:00:43.171290685 +0000 *************** *** 66,73 **** } #endif - #if defined(FEAT_CINDENT) || defined(FEAT_SYN_HL) - /* * Skip to the end of a "string" and a 'c' character. * If there is no string or character, return argument unmodified. --- 66,71 ---- *************** *** 138,143 **** --- 136,156 ---- } /* + * Return TRUE if "line[col]" is inside a C string. + */ + int + is_pos_in_string(char_u *line, colnr_T col) + { + char_u *p; + + for (p = line; *p && (colnr_T)(p - line) < col; ++p) + p = skip_string(p); + return !((colnr_T)(p - line) <= col); + } + + #if defined(FEAT_CINDENT) || defined(FEAT_SYN_HL) + + /* * Find the start of a comment, not knowing if we are in a comment right now. * Search starts at w_cursor.lnum and goes backwards. * Return NULL when not inside a comment. *************** *** 152,159 **** find_start_comment(int ind_maxcomment) // XXX { pos_T *pos; - char_u *line; - char_u *p; int cur_maxcomment = ind_maxcomment; for (;;) --- 165,170 ---- *************** *** 164,173 **** // Check if the comment start we found is inside a string. // If it is then restrict the search to below this line and try again. ! line = ml_get(pos->lnum); ! for (p = line; *p && (colnr_T)(p - line) < pos->col; ++p) ! p = skip_string(p); ! if ((colnr_T)(p - line) <= pos->col) break; cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1; if (cur_maxcomment <= 0) --- 175,181 ---- // Check if the comment start we found is inside a string. // If it is then restrict the search to below this line and try again. ! if (!is_pos_in_string(ml_get(pos->lnum), pos->col)) break; cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1; if (cur_maxcomment <= 0) *************** *** 188,195 **** find_start_rawstring(int ind_maxcomment) // XXX { pos_T *pos; - char_u *line; - char_u *p; int cur_maxcomment = ind_maxcomment; for (;;) --- 196,201 ---- *************** *** 200,209 **** // Check if the raw string start we found is inside a string. // If it is then restrict the search to below this line and try again. ! line = ml_get(pos->lnum); ! for (p = line; *p && (colnr_T)(p - line) < pos->col; ++p) ! p = skip_string(p); ! if ((colnr_T)(p - line) <= pos->col) break; cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1; if (cur_maxcomment <= 0) --- 206,212 ---- // Check if the raw string start we found is inside a string. // If it is then restrict the search to below this line and try again. ! if (!is_pos_in_string(ml_get(pos->lnum), pos->col)) break; cur_maxcomment = curwin->w_cursor.lnum - pos->lnum - 1; if (cur_maxcomment <= 0) *** ../vim-8.2.3937/src/proto/cindent.pro 2019-12-12 11:55:15.000000000 +0000 --- src/proto/cindent.pro 2021-12-29 18:02:24.999114508 +0000 *************** *** 1,5 **** --- 1,6 ---- /* cindent.c */ int cin_is_cinword(char_u *line); + int is_pos_in_string(char_u *line, colnr_T col); pos_T *find_start_comment(int ind_maxcomment); int cindent_on(void); void parse_cino(buf_T *buf); *** ../vim-8.2.3937/src/search.c 2021-12-12 14:16:34.989862195 +0000 --- src/search.c 2021-12-29 18:06:39.946692667 +0000 *************** *** 2714,2720 **** /* * Check if line[] contains a / / comment. * Return MAXCOL if not, otherwise return the column. - * TODO: skip strings. */ int check_linecomment(char_u *line) --- 2714,2719 ---- *************** *** 2746,2752 **** in_str = TRUE; } else if (!in_str && ((p - line) < 2 ! || (*(p - 1) != '\\' && *(p - 2) != '#'))) break; // found! ++p; } --- 2745,2752 ---- in_str = TRUE; } else if (!in_str && ((p - line) < 2 ! || (*(p - 1) != '\\' && *(p - 2) != '#')) ! && !is_pos_in_string(line, (colnr_T)(p - line))) break; // found! ++p; } *************** *** 2758,2766 **** #endif while ((p = vim_strchr(p, '/')) != NULL) { ! // accept a double /, unless it's preceded with * and followed by *, ! // because * / / * is an end and start of a C comment ! if (p[1] == '/' && (p == line || p[-1] != '*' || p[2] != '*')) break; ++p; } --- 2758,2768 ---- #endif while ((p = vim_strchr(p, '/')) != NULL) { ! // Accept a double /, unless it's preceded with * and followed by *, ! // because * / / * is an end and start of a C comment. ! // Only accept the position if it is not inside a string. ! if (p[1] == '/' && (p == line || p[-1] != '*' || p[2] != '*') ! && !is_pos_in_string(line, (colnr_T)(p - line))) break; ++p; } *** ../vim-8.2.3937/src/testdir/test_textformat.vim 2021-12-29 16:05:28.026222402 +0000 --- src/testdir/test_textformat.vim 2021-12-29 18:05:13.674832781 +0000 *************** *** 261,266 **** --- 261,281 ---- END call assert_equal(expected, getline(1, '$')) + " Using "o" does not repeat a comment in a string + %del + let text =<< trim END + nop; + val = " // This is not a comment"; + END + call setline(1, text) + normal 2Gox + let expected =<< trim END + nop; + val = " // This is not a comment"; + x + END + call assert_equal(expected, getline(1, '$')) + " Using CTRL-U after "o" fixes the indent %del let text =<< trim END *** ../vim-8.2.3937/src/version.c 2021-12-29 17:38:42.301517624 +0000 --- src/version.c 2021-12-29 17:57:11.799676795 +0000 *************** *** 751,752 **** --- 751,754 ---- { /* Add new patch number below this line */ + /**/ + 3938, /**/ -- Drink wet cement and get really stoned. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///