Merge pull request #17254 from zeertzjq/vim-8.2.3787

vim-patch:8.2.{3787,3932,3934,3935,3938}: text formatting patches
This commit is contained in:
zeertzjq 2022-02-01 04:23:59 +08:00 committed by GitHub
commit 5205bcc904
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 286 additions and 4901 deletions

View File

@ -952,11 +952,13 @@ int copy_indent(int size, char_u *src)
///
/// "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.
///
/// @param dir FORWARD or BACKWARD
///
/// @return true on success, false on failure
int open_line(int dir, int flags, int second_line_indent)
int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
{
char_u *next_line = NULL; // copy of the next line
char_u *p_extra = NULL; // what goes to next line
@ -969,6 +971,7 @@ int open_line(int dir, int flags, int second_line_indent)
bool retval = false; // 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
@ -977,6 +980,7 @@ int open_line(int dir, int flags, int second_line_indent)
pos_T *pos;
bool do_si = (!p_paste && curbuf->b_p_si && !curbuf->b_p_cin
&& *curbuf->b_p_inde == NUL);
bool do_cindent;
bool no_si = false; // reset did_si afterwards
int first_char = NUL; // init for GCC
int vreplace_mode;
@ -1189,11 +1193,30 @@ int open_line(int dir, int flags, int second_line_indent)
did_ai = true;
}
// May do indenting after opening a new line.
do_cindent = !p_paste && (curbuf->b_p_cin || *curbuf->b_p_inde != NUL)
&& in_cinkeys(dir == FORWARD ? KEY_OPEN_FORW : KEY_OPEN_BACK,
' ', linewhite(curwin->w_cursor.lnum));
// 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) {
if (flags & OPENLINE_DO_COM && dir == FORWARD) {
// Check for a line comment after code.
lead_len = get_leader_len(saved_line, &lead_flags, dir == BACKWARD, true);
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, false, true);
if (lead_len != 0) {
lead_len += comment_start;
if (did_do_comment != NULL) {
*did_do_comment = true;
}
}
}
}
} else {
lead_len = 0;
}
@ -1349,6 +1372,13 @@ int open_line(int dir, int flags, int second_line_indent)
STRLCPY(leader, saved_line, lead_len + 1);
// TODO(vim): handle multi-byte and double width chars
for (int li = 0; li < comment_start; li++) {
if (!ascii_iswhite(leader[li])) {
leader[li] = ' ';
}
}
// Replace leader with lead_repl, right or left adjusted
if (lead_repl != NULL) {
int c = 0;
@ -1758,13 +1788,7 @@ int open_line(int dir, int flags, int second_line_indent)
ai_col = (colnr_T)getwhitecols_curline();
}
// May do indenting after opening a new line.
if (!p_paste
&& (curbuf->b_p_cin
|| *curbuf->b_p_inde != NUL
)
&& 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();
}

View File

@ -6021,6 +6021,7 @@ static void internal_format(int textwidth, int second_indent, int flags, int for
char_u *saved_text = NULL;
colnr_T col;
colnr_T end_col;
bool did_do_comment = false;
virtcol = get_nolist_virtcol()
+ char2cells(c != NUL ? c : gchar_cursor());
@ -6136,8 +6137,7 @@ static void internal_format(int textwidth, int second_indent, int flags, int for
if (curwin->w_cursor.col <= (colnr_T)wantcol) {
break;
}
} else if ((cc >= 0x100 || !utf_allow_break_before(cc))
&& fo_multibyte) {
} else if ((cc >= 0x100 || !utf_allow_break_before(cc)) && fo_multibyte) {
int ncc;
bool allow_break;
@ -6294,11 +6294,18 @@ static void internal_format(int textwidth, int second_indent, int flags, int for
+ (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) {
if (!(flags & INSCHAR_COM_LIST)) {
@ -8292,6 +8299,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
int in_indent;
int oldState;
int cpc[MAX_MCO]; // composing characters
bool call_fix_indent = false;
// can't delete anything in an empty file
// can't backup past first character in buffer
@ -8435,6 +8443,8 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
beginline(BL_WHITE);
if (curwin->w_cursor.col < save_col) {
mincol = curwin->w_cursor.col;
// should now fix the indent to match with the previous line
call_fix_indent = true;
}
curwin->w_cursor.col = save_col;
}
@ -8569,6 +8579,11 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
if (curwin->w_cursor.col <= 1) {
did_ai = false;
}
if (call_fix_indent) {
fix_indent();
}
// It's a little strange to put backspaces into the redo
// buffer, but it makes auto-indent a lot easier to deal
// with.
@ -9183,7 +9198,7 @@ static bool ins_eol(int c)
AppendToRedobuff(NL_STR);
bool i = open_line(FORWARD,
has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM : 0,
old_indent);
old_indent, NULL);
old_indent = 0;
can_cindent = true;
// When inserting a line the cursor line must never be in a closed fold.

View File

@ -41,9 +41,7 @@ static pos_T *ind_find_start_comment(void) // XXX
pos_T *find_start_comment(int ind_maxcomment) // XXX
{
pos_T *pos;
char_u *line;
char_u *p;
pos_T *pos;
int64_t cur_maxcomment = ind_maxcomment;
for (;; ) {
@ -55,11 +53,9 @@ pos_T *find_start_comment(int ind_maxcomment) // XXX
* 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)
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) {
pos = NULL;
@ -110,8 +106,6 @@ static pos_T *ind_find_start_CORS(linenr_T *is_raw)
static pos_T *find_start_rawstring(int ind_maxcomment) // XXX
{
pos_T *pos;
char_u *line;
char_u *p;
long cur_maxcomment = ind_maxcomment;
for (;;)
@ -124,11 +118,9 @@ static pos_T *find_start_rawstring(int ind_maxcomment) // XXX
* 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;
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)
{
@ -143,7 +135,7 @@ static pos_T *find_start_rawstring(int ind_maxcomment) // XXX
* Skip to the end of a "string" and a 'c' character.
* If there is no string or character, return argument unmodified.
*/
static char_u *skip_string(char_u *p)
static const char_u *skip_string(const char_u *p)
{
int i;
@ -178,24 +170,24 @@ static char_u *skip_string(char_u *p)
continue; // continue for another string
}
} else if (p[0] == 'R' && p[1] == '"') {
// Raw string: R"[delim](...)[delim]"
char_u *delim = p + 2;
char_u *paren = vim_strchr(delim, '(');
// Raw string: R"[delim](...)[delim]"
const char_u *delim = p + 2;
const char_u *paren = vim_strchr(delim, '(');
if (paren != NULL) {
const ptrdiff_t delim_len = paren - delim;
if (paren != NULL) {
const ptrdiff_t delim_len = paren - delim;
for (p += 3; *p; ++p)
if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0
&& p[delim_len + 1] == '"')
{
p += delim_len + 1;
break;
}
if (p[0] == '"') {
continue; // continue for another string
}
for (p += 3; *p; p++) {
if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0
&& p[delim_len + 1] == '"') {
p += delim_len + 1;
break;
}
}
if (p[0] == '"') {
continue; // continue for another string
}
}
}
break; // no string found
}
@ -205,6 +197,16 @@ static char_u *skip_string(char_u *p)
return p;
}
/// @returns true if "line[col]" is inside a C string.
int is_pos_in_string(const char_u *line, colnr_T col)
{
const char_u *p;
for (p = line; *p && (colnr_T)(p - line) < col; p++) {
p = skip_string(p);
}
return !((colnr_T)(p - line) <= col);
}
/*
* Functions for C-indenting.
@ -218,7 +220,7 @@ static char_u *skip_string(char_u *p)
/*
* Return true if the string "line" starts with a word from 'cinwords'.
*/
bool cin_is_cinword(char_u *line)
bool cin_is_cinword(const char_u *line)
{
bool retval = false;
@ -246,10 +248,10 @@ bool cin_is_cinword(char_u *line)
* Skip over white space and C comments within the line.
* Also skip over Perl/shell comments if desired.
*/
static char_u *cin_skipcomment(char_u *s)
static const char_u *cin_skipcomment(const char_u *s)
{
while (*s) {
char_u *prev_s = s;
const char_u *prev_s = s;
s = skipwhite(s);
@ -283,7 +285,7 @@ static char_u *cin_skipcomment(char_u *s)
* Return TRUE if there is no code at *s. White space and comments are
* not considered code.
*/
static int cin_nocode(char_u *s)
static int cin_nocode(const char_u *s)
{
return *cin_skipcomment(s) == NUL;
}
@ -312,9 +314,9 @@ static pos_T *find_line_comment(void) // XXX
}
/// Checks if `text` starts with "key:".
static bool cin_has_js_key(char_u *text)
static bool cin_has_js_key(const char_u *text)
{
char_u *s = skipwhite(text);
const char_u *s = skipwhite(text);
char_u quote = 0;
if (*s == '\'' || *s == '"') {
@ -341,7 +343,7 @@ static bool cin_has_js_key(char_u *text)
/// Checks if string matches "label:"; move to character after ':' if true.
/// "*s" must point to the start of the label, if there is one.
static bool cin_islabel_skip(char_u **s)
static bool cin_islabel_skip(const char_u **s)
FUNC_ATTR_NONNULL_ALL
{
if (!vim_isIDc(**s)) { // need at least one ID character
@ -361,7 +363,7 @@ static bool cin_islabel_skip(char_u **s)
// Note: curwin->w_cursor must be where we are looking for the label.
bool cin_islabel(void) // XXX
{
char_u *s = cin_skipcomment(get_cursor_line_ptr());
const char_u *s = cin_skipcomment(get_cursor_line_ptr());
// Exclude "default" from labels, since it should be indented
// like a switch label. Same for C++ scope declarations.
@ -380,8 +382,8 @@ bool cin_islabel(void) // XXX
* label.
*/
pos_T cursor_save;
pos_T *trypos;
char_u *line;
pos_T *trypos;
const char_u *line;
cursor_save = curwin->w_cursor;
while (curwin->w_cursor.lnum > 1) {
@ -424,8 +426,8 @@ bool cin_islabel(void) // XXX
*/
static int cin_isinit(void)
{
char_u *s;
static char *skip[] = {"static", "public", "protected", "private"};
const char_u *s;
static char *skip[] = { "static", "public", "protected", "private" };
s = cin_skipcomment(get_cursor_line_ptr());
@ -460,7 +462,7 @@ static int cin_isinit(void)
* Recognize a switch label: "case .*:" or "default:".
*/
bool cin_iscase(
char_u *s,
const char_u *s,
bool strict // Allow relaxed check of case statement for JS
)
{
@ -503,7 +505,7 @@ bool cin_iscase(
/*
* Recognize a "default" switch label.
*/
static int cin_isdefault(char_u *s)
static int cin_isdefault(const char_u *s)
{
return STRNCMP(s, "default", 7) == 0
&& *(s = cin_skipcomment(s + 7)) == ':'
@ -513,7 +515,7 @@ static int cin_isdefault(char_u *s)
/*
* Recognize a "public/private/protected" scope declaration label.
*/
bool cin_isscopedecl(char_u *s)
bool cin_isscopedecl(const char_u *s)
{
int i;
@ -534,9 +536,9 @@ bool cin_isscopedecl(char_u *s)
#define FIND_NAMESPACE_LIM 20
// Recognize a "namespace" scope declaration.
static bool cin_is_cpp_namespace(char_u *s)
static bool cin_is_cpp_namespace(const char_u *s)
{
char_u *p;
const char_u *p;
bool has_name = false;
bool has_name_start = false;
@ -581,7 +583,7 @@ static bool cin_is_cpp_namespace(char_u *s)
* case 234: a = b;
* ^
*/
static char_u *after_label(char_u *l)
static const char_u *after_label(const char_u *l)
{
for (; *l; ++l) {
if (*l == ':') {
@ -608,10 +610,10 @@ static char_u *after_label(char_u *l)
*/
static int get_indent_nolabel(linenr_T lnum) // XXX
{
char_u *l;
const char_u *l;
pos_T fp;
colnr_T col;
char_u *p;
const char_u *p;
l = ml_get(lnum);
p = after_label(l);
@ -630,9 +632,9 @@ static int get_indent_nolabel(linenr_T lnum) // XXX
* label: if (asdf && asdfasdf)
* ^
*/
static int skip_label(linenr_T lnum, char_u **pp)
static int skip_label(linenr_T lnum, const char_u **pp)
{
char_u *l;
const char_u *l;
int amount;
pos_T cursor_save;
@ -713,8 +715,8 @@ static int cin_first_id_amount(void)
*/
static int cin_get_equal_amount(linenr_T lnum)
{
char_u *line;
char_u *s;
const char_u *line;
const char_u *s;
colnr_T col;
pos_T fp;
@ -752,7 +754,7 @@ static int cin_get_equal_amount(linenr_T lnum)
/*
* Recognize a preprocessor statement: Any line that starts with '#'.
*/
static int cin_ispreproc(char_u *s)
static int cin_ispreproc(const char_u *s)
{
if (*skipwhite(s) == '#')
return TRUE;
@ -763,9 +765,9 @@ static int cin_ispreproc(char_u *s)
/// continuation line of a preprocessor statement. Decrease "*lnump" to the
/// start and return the line in "*pp".
/// Put the amount of indent in "*amount".
static int cin_ispreproc_cont(char_u **pp, linenr_T *lnump, int *amount)
static int cin_ispreproc_cont(const char_u **pp, linenr_T *lnump, int *amount)
{
char_u *line = *pp;
const char_u *line = *pp;
linenr_T lnum = *lnump;
int retval = false;
int candidate_amount = *amount;
@ -799,7 +801,7 @@ static int cin_ispreproc_cont(char_u **pp, linenr_T *lnump, int *amount)
/*
* Recognize the start of a C or C++ comment.
*/
static int cin_iscomment(char_u *p)
static int cin_iscomment(const char_u *p)
{
return p[0] == '/' && (p[1] == '*' || p[1] == '/');
}
@ -807,7 +809,7 @@ static int cin_iscomment(char_u *p)
/*
* Recognize the start of a "//" comment.
*/
static int cin_islinecomment(char_u *p)
static int cin_islinecomment(const char_u *p)
{
return p[0] == '/' && p[1] == '/';
}
@ -822,8 +824,8 @@ static int cin_islinecomment(char_u *p)
* both apply in order to determine initializations).
*/
static char_u
cin_isterminated (
char_u *s,
cin_isterminated(
const char_u *s,
int incl_open, // include '{' at the end as terminator
int incl_comma // recognize a trailing comma
)
@ -872,9 +874,9 @@ cin_isterminated (
/// lines here.
/// @param[in] first_lnum Where to start looking.
/// @param[in] min_lnum The line before which we will not be looking.
static int cin_isfuncdecl(char_u **sp, linenr_T first_lnum, linenr_T min_lnum)
static int cin_isfuncdecl(const char_u **sp, linenr_T first_lnum, linenr_T min_lnum)
{
char_u *s;
const char_u *s;
linenr_T lnum = first_lnum;
linenr_T save_lnum = curwin->w_cursor.lnum;
int retval = false;
@ -975,12 +977,12 @@ done:
return retval;
}
static int cin_isif(char_u *p)
static int cin_isif(const char_u *p)
{
return STRNCMP(p, "if", 2) == 0 && !vim_isIDc(p[2]);
}
static int cin_iselse(char_u *p)
static int cin_iselse(const char_u *p)
{
if (*p == '}') { // accept "} else"
p = cin_skipcomment(p + 1);
@ -988,7 +990,7 @@ static int cin_iselse(char_u *p)
return STRNCMP(p, "else", 4) == 0 && !vim_isIDc(p[4]);
}
static int cin_isdo(char_u *p)
static int cin_isdo(const char_u *p)
{
return STRNCMP(p, "do", 2) == 0 && !vim_isIDc(p[2]);
}
@ -998,7 +1000,7 @@ static int cin_isdo(char_u *p)
* We only accept a "while (condition) ;", with only white space between the
* ')' and ';'. The condition may be spread over several lines.
*/
static int cin_iswhileofdo(char_u *p, linenr_T lnum) // XXX
static int cin_iswhileofdo(const char_u *p, linenr_T lnum) // XXX
{
pos_T cursor_save;
pos_T *trypos;
@ -1032,7 +1034,7 @@ static int cin_iswhileofdo(char_u *p, linenr_T lnum) // XXX
* Otherwise return !0 and update "*poffset" to point to the place where the
* string was found.
*/
static int cin_is_if_for_while_before_offset(char_u *line, int *poffset)
static int cin_is_if_for_while_before_offset(const char_u *line, int *poffset)
{
int offset = *poffset;
@ -1076,10 +1078,10 @@ probablyFound:
*/
static int cin_iswhileofdo_end(int terminated)
{
char_u *line;
char_u *p;
char_u *s;
pos_T *trypos;
const char_u *line;
const char_u *p;
const char_u *s;
pos_T *trypos;
int i;
if (terminated != ';') { // there must be a ';' at the end
@ -1119,7 +1121,7 @@ static int cin_iswhileofdo_end(int terminated)
return FALSE;
}
static int cin_isbreak(char_u *p)
static int cin_isbreak(const char_u *p)
{
return STRNCMP(p, "break", 5) == 0 && !vim_isIDc(p[5]);
}
@ -1139,10 +1141,10 @@ static int cin_isbreak(char_u *p)
*/
static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached) {
lpos_T *pos = &cached->lpos; // find position
char_u *s;
const char_u *s;
int class_or_struct, lookfor_ctor_init, cpp_base_class;
linenr_T lnum = curwin->w_cursor.lnum;
char_u *line = get_cursor_line_ptr();
const char_u *line = get_cursor_line_ptr();
if (pos->lnum <= lnum) {
return cached->found; // Use the cached result
@ -1310,10 +1312,10 @@ static int get_baseclass_amount(int col)
* white space and comments. Skip strings and comments.
* Ignore "ignore" after "find" if it's not NULL.
*/
static int cin_ends_in(char_u *s, char_u *find, char_u *ignore)
static int cin_ends_in(const char_u *s, const char_u *find, const char_u *ignore)
{
char_u *p = s;
char_u *r;
const char_u *p = s;
const char_u *r;
int len = (int)STRLEN(find);
while (*p != NUL) {
@ -1334,7 +1336,7 @@ static int cin_ends_in(char_u *s, char_u *find, char_u *ignore)
/*
* Return TRUE when "s" starts with "word" and then a non-ID character.
*/
static int cin_starts_with(char_u *s, char *word)
static int cin_starts_with(const char_u *s, const char *word)
{
int l = (int)STRLEN(word);
@ -1342,10 +1344,10 @@ static int cin_starts_with(char_u *s, char *word)
}
/// Recognize a `extern "C"` or `extern "C++"` linkage specifications.
static int cin_is_cpp_extern_c(char_u *s)
static int cin_is_cpp_extern_c(const char_u *s)
{
char_u *p;
int has_string_literal = false;
const char_u *p;
int has_string_literal = false;
s = cin_skipcomment(s);
if (STRNCMP(s, "extern", 6) == 0 && (s[6] == NUL || !vim_iswordc(s[6]))) {
@ -1384,9 +1386,9 @@ static int cin_is_cpp_extern_c(char_u *s)
*/
static int cin_skip2pos(pos_T *trypos)
{
char_u *line;
char_u *p;
char_u *new_p;
const char_u *line;
const char_u *p;
const char_u *new_p;
p = line = ml_get(trypos->lnum);
while (*p && (colnr_T)(p - line) < trypos->col) {
@ -1529,7 +1531,7 @@ static int corr_ind_maxparen(pos_T *startpos)
* Set w_cursor.col to the column number of the last unmatched ')' or '{' in
* line "l". "l" must point to the start of the line.
*/
static int find_last_paren(char_u *l, int start, int end)
static int find_last_paren(const char_u *l, int start, int end)
{
int i;
int retval = FALSE;
@ -1801,8 +1803,8 @@ int get_c_indent(void)
#define BRACE_AT_START 2 // '{' is at start of line
#define BRACE_AT_END 3 // '{' is at end of line
linenr_T ourscope;
char_u *l;
char_u *look;
const char_u *l;
const char_u *look;
char_u terminated;
int lookfor;
#define LOOKFOR_INITIAL 0
@ -1906,12 +1908,25 @@ int 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
// find how indented the line beginning the comment is
getvcol(curwin, trypos, &col, NULL, NULL);
amount = col;
goto theend;
if (cin_islinecomment(theline)) {
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
@ -3602,9 +3617,9 @@ laterend:
static int find_match(int lookfor, linenr_T ourscope)
{
char_u *look;
pos_T *theirscope;
char_u *mightbeif;
const char_u *look;
pos_T *theirscope;
const char_u *mightbeif;
int elselevel;
int whilelevel;

View File

@ -6685,9 +6685,8 @@ static void n_opencmd(cmdarg_T *cap)
(cap->cmdchar == 'o' ? 1 : 0))
)
&& open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
has_format_option(FO_OPEN_COMS)
? OPENLINE_DO_COM : 0,
0)) {
has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : 0,
0, NULL)) {
if (win_cursorline_standout(curwin)) {
// force redraw of cursorline
curwin->w_valid &= ~VALID_CROW;

View File

@ -4350,7 +4350,7 @@ void format_lines(linenr_T line_count, int avoid_fex)
int leader_len = 0; // leader len of current line
int next_leader_len; // leader len of next line
char_u *leader_flags = NULL; // flags for leader of current line
char_u *next_leader_flags; // flags for leader of next line
char_u *next_leader_flags = NULL; // flags for leader of next line
bool advance = true;
int second_indent = -1; // indent for second line (comment aware)
bool first_par_line = true;
@ -4467,7 +4467,14 @@ void format_lines(linenr_T line_count, int avoid_fex)
leader_len, leader_flags,
next_leader_len,
next_leader_flags)) {
is_end_par = true;
// Special case: If the next line starts with a line comment
// and this line has a line comment after some text, the
// paragraph doesn't really end.
if (next_leader_flags == NULL
|| STRNCMP(next_leader_flags, "://", 3) != 0
|| check_linecomment(get_cursor_line_ptr()) == MAXCOL) {
is_end_par = true;
}
}
/*

View File

@ -26,6 +26,7 @@
#include "nvim/func_attr.h"
#include "nvim/getchar.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/main.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
@ -2313,12 +2314,9 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
return (pos_T *)NULL; // never found it
}
/*
* Check if line[] contains a / / comment.
* Return MAXCOL if not, otherwise return the column.
* TODO: skip strings.
*/
static int check_linecomment(const char_u *line)
/// Check if line[] contains a / / comment.
/// @returns MAXCOL if not, otherwise return the column.
int check_linecomment(const char_u *line)
{
const char_u *p = line; // scan from start
// skip Lispish one-line comments
@ -2338,7 +2336,8 @@ static int check_linecomment(const char_u *line)
in_str = true;
}
} else if (!in_str && ((p - line) < 2
|| (*(p - 1) != '\\' && *(p - 2) != '#'))) {
|| (*(p - 1) != '\\' && *(p - 2) != '#'))
&& !is_pos_in_string(line, (colnr_T)(p - line))) {
break; // found!
}
p++;
@ -2348,9 +2347,11 @@ static int check_linecomment(const char_u *line)
}
} else {
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] != '*')) {
// 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;

View File

@ -1707,9 +1707,9 @@ func Test_cindent_1()
#endif
int y; // comment
// comment
// comment
// comment
// comment
{
Constructor(int a,

View File

@ -196,6 +196,104 @@ 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, '$'))
%del
let text =<< trim END
#if 0 // This is another long end of
// line comment that
// wraps.
END
call setline(1, text)
normal gq2j
let expected =<< trim END
#if 0 // This is another long
// end of line comment
// that wraps.
END
call assert_equal(expected, getline(1, '$'))
" Using "o" repeats the line comment, "O" does not.
%del
let text =<< trim END
nop;
val = val; // This is a comment
END
call setline(1, text)
normal 2Go
let expected =<< trim END
nop;
val = val; // This is a comment
//
END
call assert_equal(expected, getline(1, '$'))
normal 2GO
let expected =<< trim END
nop;
val = val; // This is a comment
//
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
{
val = val; // This is a comment
END
call setline(1, text)
exe "normal! 2Go\<C-U>x\<Esc>"
let expected =<< trim END
{
val = val; // This is a comment
x
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!

File diff suppressed because it is too large Load Diff