0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

updated for version 7.3.541

Problem:    When joining lines comment leaders need to be removed manually.
Solution:   Add the 'j' flag to 'formatoptions'. (Lech Lorens)
This commit is contained in:
Bram Moolenaar
2012-06-06 16:12:59 +02:00
parent bc256d91ea
commit 8134039744
13 changed files with 482 additions and 27 deletions

137
src/ops.c
View File

@@ -112,6 +112,9 @@ static void may_set_selection __ARGS((void));
# endif
#endif
static void dis_msg __ARGS((char_u *p, int skip_esc));
#if defined(FEAT_COMMENTS) || defined(PROTO)
static char_u *skip_comment __ARGS((char_u *line, int process, int include_space, int *is_comment));
#endif
#ifdef FEAT_VISUAL
static void block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int));
#endif
@@ -1987,7 +1990,7 @@ op_delete(oap)
curwin->w_cursor = curpos; /* restore curwin->w_cursor */
}
if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
(void)do_join(2, FALSE, FALSE);
(void)do_join(2, FALSE, FALSE, FALSE);
}
}
@@ -4197,17 +4200,98 @@ dis_msg(p, skip_esc)
ui_breakcheck();
}
#if defined(FEAT_COMMENTS) || defined(PROTO)
/*
* If "process" is TRUE and the line begins with a comment leader (possibly
* after some white space), return a pointer to the text after it. Put a boolean
* value indicating whether the line ends with an unclosed comment in
* "is_comment".
* line - line to be processed,
* process - if FALSE, will only check whether the line ends with an unclosed
* 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.
*/
static char_u *
skip_comment(line, process, include_space, is_comment)
char_u *line;
int process;
int include_space;
int *is_comment;
{
char_u *comment_flags = NULL;
int lead_len;
int leader_offset = get_last_leader_offset(line, &comment_flags);
*is_comment = FALSE;
if (leader_offset != -1)
{
/* Let's check whether the line ends with an unclosed comment.
* If the last comment leader has COM_END in flags, there's no comment.
*/
while (*comment_flags)
{
if (*comment_flags == COM_END
|| *comment_flags == ':')
break;
++comment_flags;
}
if (*comment_flags != COM_END)
*is_comment = TRUE;
}
if (process == FALSE)
return line;
lead_len = get_leader_len(line, &comment_flags, FALSE, include_space);
if (lead_len == 0)
return line;
/* Find:
* - COM_START,
* - COM_END,
* - colon,
* whichever comes first.
*/
while (*comment_flags)
{
if (*comment_flags == COM_START
|| *comment_flags == COM_END
|| *comment_flags == ':')
{
break;
}
++comment_flags;
}
/* If we found a colon, it means that we are not processing a line
* starting with an opening or a closing part of a three-part
* comment. That's good, because we don't want to remove those as
* this would be annoying.
*/
if (*comment_flags == ':' || *comment_flags == NUL)
line += lead_len;
return line;
}
#endif
/*
* Join 'count' lines (minimal 2) at cursor position.
* When "save_undo" is TRUE save lines for undo first.
* Set "use_formatoptions" to FALSE when e.g. processing
* backspace and comment leaders should not be removed.
*
* return FAIL for failure, OK otherwise
*/
int
do_join(count, insert_space, save_undo)
do_join(count, insert_space, save_undo, use_formatoptions)
long count;
int insert_space;
int save_undo;
int use_formatoptions UNUSED;
{
char_u *curr = NULL;
char_u *curr_start = NULL;
@@ -4221,6 +4305,13 @@ do_join(count, insert_space, save_undo)
linenr_T t;
colnr_T col = 0;
int ret = OK;
#if defined(FEAT_COMMENTS) || defined(PROTO)
int *comments;
int remove_comments = (use_formatoptions == TRUE)
&& has_format_option(FO_REMOVE_COMS);
int prev_was_comment;
#endif
if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1),
(linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
@@ -4232,6 +4323,17 @@ do_join(count, insert_space, save_undo)
spaces = lalloc_clear((long_u)count, TRUE);
if (spaces == NULL)
return FAIL;
#if defined(FEAT_COMMENTS) || defined(PROTO)
if (remove_comments)
{
comments = (int *)lalloc_clear((long_u)count * sizeof(int), TRUE);
if (comments == NULL)
{
vim_free(spaces);
return FAIL;
}
}
#endif
/*
* Don't move anything, just compute the final line length
@@ -4240,6 +4342,25 @@ do_join(count, insert_space, save_undo)
for (t = 0; t < count; ++t)
{
curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t));
#if defined(FEAT_COMMENTS) || defined(PROTO)
if (remove_comments)
{
/* We don't want to remove the comment leader if the
* previous line is not a comment. */
if (t > 0 && prev_was_comment)
{
char_u *new_curr = skip_comment(curr, TRUE, insert_space,
&prev_was_comment);
comments[t] = new_curr - curr;
curr = new_curr;
}
else
curr = skip_comment(curr, FALSE, insert_space,
&prev_was_comment);
}
#endif
if (insert_space && t > 0)
{
curr = skipwhite(curr);
@@ -4327,6 +4448,10 @@ do_join(count, insert_space, save_undo)
if (t == 0)
break;
curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1));
#if defined(FEAT_COMMENTS) || defined(PROTO)
if (remove_comments)
curr += comments[t - 1];
#endif
if (insert_space && t > 1)
curr = skipwhite(curr);
currsize = (int)STRLEN(curr);
@@ -4364,6 +4489,10 @@ do_join(count, insert_space, save_undo)
theend:
vim_free(spaces);
#if defined(FEAT_COMMENTS) || defined(PROTO)
if (remove_comments)
vim_free(comments);
#endif
return ret;
}
@@ -4788,7 +4917,7 @@ format_lines(line_count, avoid_fex)
(long)-next_leader_len);
#endif
curwin->w_cursor.lnum--;
if (do_join(2, TRUE, FALSE) == FAIL)
if (do_join(2, TRUE, FALSE, FALSE) == FAIL)
{
beep_flush();
break;
@@ -4844,7 +4973,7 @@ fmt_check_par(lnum, leader_len, leader_flags, do_comments)
ptr = ml_get(lnum);
if (do_comments)
*leader_len = get_leader_len(ptr, leader_flags, FALSE);
*leader_len = get_leader_len(ptr, leader_flags, FALSE, TRUE);
else
*leader_len = 0;