# HG changeset patch # User Bram Moolenaar # Date 1339601335 -7200 # Node ID 443c50cd3e8811b58a4ca131ab21abd18aea9489 # Parent 88a2cac374ea80b98f18e3a1a122ab5e0e396332 updated for version 7.3.552 Problem: Formatting inside comments does not use the "2" flag in 'formatoptions'. Solution: Support the "2" flag. (Tor Perkins) diff --git a/src/edit.c b/src/edit.c --- a/src/edit.c +++ b/src/edit.c @@ -1463,7 +1463,7 @@ normalchar: * what check_abbr() expects. */ (has_mbyte && c >= 0x100) ? (c + ABBR_OFF) : #endif - c) && c != Ctrl_RSB)) + c) && c != Ctrl_RSB)) { insert_special(c, FALSE, FALSE); #ifdef FEAT_RIGHTLEFT @@ -5769,6 +5769,16 @@ insert_special(c, allow_modmask, ctrlv) # define WHITECHAR(cc) vim_iswhite(cc) #endif +/* + * "flags": INSCHAR_FORMAT - force formatting + * INSCHAR_CTRLV - char typed just after CTRL-V + * INSCHAR_NO_FEX - don't use 'formatexpr' + * + * NOTE: passes the flags value straight through to internal_format() which, + * beside INSCHAR_FORMAT (above), is also looking for these: + * INSCHAR_DO_COM - format comments + * INSCHAR_COM_LIST - format comments with num list or 2nd line indent + */ void insertchar(c, flags, second_indent) int c; /* character to insert or NUL */ @@ -6011,6 +6021,9 @@ insertchar(c, flags, second_indent) /* * Format text at the current insert position. + * + * If the INSCHAR_COM_LIST flag is present, then the value of second_indent + * will be the comment leader length sent to open_line(). */ static void internal_format(textwidth, second_indent, flags, format_only, c) @@ -6289,23 +6302,36 @@ internal_format(textwidth, second_indent + (fo_white_par ? OPENLINE_KEEPTRAIL : 0) #ifdef FEAT_COMMENTS + (do_comments ? OPENLINE_DO_COM : 0) -#endif - , old_indent); - old_indent = 0; + + ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0) +#endif + , ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent)); + if (!(flags & INSCHAR_COM_LIST)) + old_indent = 0; replace_offset = 0; if (first_line) { - if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) - second_indent = get_number_indent(curwin->w_cursor.lnum -1); - if (second_indent >= 0) - { + if (!(flags & INSCHAR_COM_LIST)) + { + /* + * This section is for numeric lists w/o comments. If comment + * indents are needed with numeric lists (formatoptions=nq), + * then the INSCHAR_COM_LIST flag will cause the corresponding + * OPENLINE_COM_LIST flag to be passed through to open_line() + * (as seen above)... + */ + if (second_indent < 0 && has_format_option(FO_Q_NUMBER)) + second_indent = get_number_indent(curwin->w_cursor.lnum -1); + if (second_indent >= 0) + { #ifdef FEAT_VREPLACE - if (State & VREPLACE_FLAG) - change_indent(INDENT_SET, second_indent, FALSE, NUL, TRUE); - else -#endif - (void)set_indent(second_indent, SIN_CHANGED); + if (State & VREPLACE_FLAG) + change_indent(INDENT_SET, second_indent, + FALSE, NUL, TRUE); + else +#endif + (void)set_indent(second_indent, SIN_CHANGED); + } } first_line = FALSE; } diff --git a/src/misc1.c b/src/misc1.c --- a/src/misc1.c +++ b/src/misc1.c @@ -423,27 +423,70 @@ get_number_indent(lnum) { colnr_T col; pos_T pos; - regmmatch_T regmatch; if (lnum > curbuf->b_ml.ml_line_count) return -1; pos.lnum = 0; - regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC); - if (regmatch.regprog != NULL) - { - regmatch.rmm_ic = FALSE; - regmatch.rmm_maxcol = 0; - if (vim_regexec_multi(®match, curwin, curbuf, lnum, - (colnr_T)0, NULL)) - { - pos.lnum = regmatch.endpos[0].lnum + lnum; - pos.col = regmatch.endpos[0].col; + +#ifdef FEAT_COMMENTS + if (has_format_option(FO_Q_COMS) && has_format_option(FO_Q_NUMBER)) + { + regmatch_T regmatch; + int lead_len; /* length of comment leader */ + + lead_len = get_leader_len(ml_get(lnum), NULL, FALSE, TRUE); + regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC); + if (regmatch.regprog != NULL) + { + regmatch.rm_ic = FALSE; + + /* vim_regexec() expects a pointer to a line. This lets us + * start matching for the flp beyond any comment leader... */ + if (vim_regexec(®match, ml_get(lnum) + lead_len, (colnr_T)0)) + { + pos.lnum = lnum; + pos.col = *regmatch.endp - (ml_get(lnum) + lead_len); + pos.col += lead_len; #ifdef FEAT_VIRTUALEDIT - pos.coladd = 0; -#endif + pos.coladd = 0; +#endif + } } vim_free(regmatch.regprog); } + else + { + /* + * What follows is the orig code that is not "comment aware"... + * + * I'm not sure if regmmatch_T (multi-match) is needed in this case. + * It may be true that this section would work properly using the + * regmatch_T code above, in which case, these two seperate sections + * should be consolidated w/ FEAT_COMMENTS making lead_len > 0... + */ +#endif + regmmatch_T regmatch; + + regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC); + + if (regmatch.regprog != NULL) + { + regmatch.rmm_ic = FALSE; + regmatch.rmm_maxcol = 0; + if (vim_regexec_multi(®match, curwin, curbuf, + lnum, (colnr_T)0, NULL)) + { + pos.lnum = regmatch.endpos[0].lnum + lnum; + pos.col = regmatch.endpos[0].col; +#ifdef FEAT_VIRTUALEDIT + pos.coladd = 0; +#endif + } + vim_free(regmatch.regprog); + } +#ifdef FEAT_COMMENTS + } +#endif if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL) return -1; @@ -502,14 +545,18 @@ cin_is_cinword(line) * OPENLINE_DO_COM format comments * OPENLINE_KEEPTRAIL keep trailing spaces * OPENLINE_MARKFIX adjust mark positions after the line break + * OPENLINE_COM_LIST format comments with list or 2nd line indent + * + * "second_line_indent": indent for after ^^D in Insert mode or if flag + * OPENLINE_COM_LIST * * Return TRUE for success, FALSE for failure */ int -open_line(dir, flags, old_indent) +open_line(dir, flags, second_line_indent) int dir; /* FORWARD or BACKWARD */ int flags; - int old_indent; /* indent for after ^^D in Insert mode */ + int second_line_indent; { char_u *saved_line; /* copy of the original line */ char_u *next_line = NULL; /* copy of the next line */ @@ -650,8 +697,8 @@ open_line(dir, flags, old_indent) * count white space on current line */ newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts); - if (newindent == 0) - newindent = old_indent; /* for ^^D command in insert mode */ + if (newindent == 0 && !(flags & OPENLINE_COM_LIST)) + newindent = second_line_indent; /* for ^^D command in insert mode */ #ifdef FEAT_SMARTINDENT /* @@ -1008,8 +1055,8 @@ open_line(dir, flags, old_indent) if (lead_len) { /* allocate buffer (may concatenate p_exta later) */ - leader = alloc(lead_len + lead_repl_len + extra_space + - extra_len + 1); + leader = alloc(lead_len + lead_repl_len + extra_space + extra_len + + (second_line_indent > 0 ? second_line_indent : 0)); allocated = leader; /* remember to free it later */ if (leader == NULL) @@ -1304,6 +1351,20 @@ open_line(dir, flags, old_indent) /* concatenate leader and p_extra, if there is a leader */ if (lead_len) { + if (flags & OPENLINE_COM_LIST && second_line_indent > 0) + { + int i; + int padding = second_line_indent - (newindent + STRLEN(leader)); + + /* Here whitespace is inserted after the comment char. + * Below, set_indent(newindent, SIN_INSERT) will insert the + * whitespace needed before the comment char. */ + for (i = 0; i < padding; i++) + { + STRCAT(leader, " "); + newcol++; + } + } STRCAT(leader, p_extra); p_extra = leader; did_ai = TRUE; /* So truncating blanks works with comments */ @@ -4966,8 +5027,8 @@ add_pathsep(p) char_u * FullName_save(fname, force) char_u *fname; - int force; /* force expansion, even when it already looks - like a full path name */ + int force; /* force expansion, even when it already looks + * like a full path name */ { char_u *buf; char_u *new_fname = NULL; diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -1727,8 +1727,8 @@ op_delete(oap) * and the delete is within one line. */ if (( #ifdef FEAT_CLIPBOARD - ((clip_unnamed & CLIP_UNNAMED) && oap->regname == '*') || - ((clip_unnamed & CLIP_UNNAMED_PLUS) && oap->regname == '+') || + ((clip_unnamed & CLIP_UNNAMED) && oap->regname == '*') || + ((clip_unnamed & CLIP_UNNAMED_PLUS) && oap->regname == '+') || #endif oap->regname == 0) && oap->motion_type != MLINE && oap->line_count == 1) @@ -4208,10 +4208,10 @@ dis_msg(p, skip_esc) * "is_comment". * line - line to be processed, * process - if FALSE, will only check whether the line ends with an unclosed - * comment, + * comment, * include_space - whether to also skip space following the comment leader, * is_comment - will indicate whether the current line ends with an unclosed - * comment. + * comment. */ static char_u * skip_comment(line, process, include_space, is_comment) @@ -4723,9 +4723,11 @@ format_lines(line_count, avoid_fex) char_u *leader_flags = NULL; /* flags for leader of current line */ char_u *next_leader_flags; /* flags for leader of next line */ int do_comments; /* format comments */ + int do_comments_list = 0; /* format comments with 'n' or '2' */ #endif int advance = TRUE; - int second_indent = -1; + int second_indent = -1; /* indent for second line (comment + * aware) */ int do_second_indent; int do_number_indent; int do_trail_white; @@ -4828,18 +4830,46 @@ format_lines(line_count, avoid_fex) if (first_par_line && (do_second_indent || do_number_indent) && prev_is_end_par - && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count + && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) + { + if (do_second_indent && !lineempty(curwin->w_cursor.lnum + 1)) + { +#ifdef FEAT_COMMENTS + if (leader_len == 0 && next_leader_len == 0) + { + /* no comment found */ +#endif + second_indent = + get_indent_lnum(curwin->w_cursor.lnum + 1); #ifdef FEAT_COMMENTS - && leader_len == 0 - && next_leader_len == 0 -#endif - ) - { - if (do_second_indent - && !lineempty(curwin->w_cursor.lnum + 1)) - second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1); + } + else + { + second_indent = next_leader_len; + do_comments_list = 1; + } +#endif + } else if (do_number_indent) - second_indent = get_number_indent(curwin->w_cursor.lnum); + { +#ifdef FEAT_COMMENTS + if (leader_len == 0 && next_leader_len == 0) + { + /* no comment found */ +#endif + second_indent = + get_number_indent(curwin->w_cursor.lnum); +#ifdef FEAT_COMMENTS + } + else + { + /* get_number_indent() is now "comment aware"... */ + second_indent = + get_number_indent(curwin->w_cursor.lnum); + do_comments_list = 1; + } +#endif + } } /* @@ -4878,6 +4908,8 @@ format_lines(line_count, avoid_fex) insertchar(NUL, INSCHAR_FORMAT #ifdef FEAT_COMMENTS + (do_comments ? INSCHAR_DO_COM : 0) + + (do_comments && do_comments_list + ? INSCHAR_COM_LIST : 0) #endif + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent); State = old_State; diff --git a/src/testdir/test68.in b/src/testdir/test68.in --- a/src/testdir/test68.in +++ b/src/testdir/test68.in @@ -51,6 +51,27 @@ a b } STARTTEST +/^{/+1 +:set tw=5 fo=qn comments=:# +gwap +ENDTEST + +{ +# 1 a b +} + +STARTTEST +/^{/+1 +:set tw=5 fo=q2 comments=:# +gwap +ENDTEST + +{ +# x +# a b +} + +STARTTEST /^{/+2 :set tw& fo=a I^^ diff --git a/src/testdir/test68.ok b/src/testdir/test68.ok --- a/src/testdir/test68.ok +++ b/src/testdir/test68.ok @@ -34,5 +34,17 @@ a b } +{ +# 1 a +# b +} + + +{ +# x a +# b +} + + { 1aa ^^2bb } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -715,6 +715,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 552, +/**/ 551, /**/ 550, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -1072,12 +1072,14 @@ extern char *(*dyn_libintl_textdomain)(c #define INSCHAR_DO_COM 2 /* format comments */ #define INSCHAR_CTRLV 4 /* char typed just after CTRL-V */ #define INSCHAR_NO_FEX 8 /* don't use 'formatexpr' */ +#define INSCHAR_COM_LIST 16 /* format comments with list/2nd line indent */ /* flags for open_line() */ #define OPENLINE_DELSPACES 1 /* delete spaces after cursor */ #define OPENLINE_DO_COM 2 /* format comments */ #define OPENLINE_KEEPTRAIL 4 /* keep trailing spaces */ #define OPENLINE_MARKFIX 8 /* fix mark positions */ +#define OPENLINE_COM_LIST 16 /* format comments with list/2nd line indent */ /* * There are four history tables: