vim-patch:8.0.0453 (#6266)

Problem:    Adding fold marker creates new comment.
Solution:   Use an existing comment if possible. (LemonBoy, closes vim/vim#1549)

025a6b708a
This commit is contained in:
Matthieu Coudron 2017-03-13 01:54:35 +01:00 committed by Justin M. Keyes
parent c42aebf23e
commit 71d4b81b4c
4 changed files with 58 additions and 33 deletions

View File

@ -29,6 +29,7 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/undo.h"
#include "nvim/ops.h"
/* local declarations. {{{1 */
/* typedef fold_T {{{2 */
@ -1593,29 +1594,32 @@ static void foldCreateMarkers(linenr_T start, linenr_T end)
/*
* Add "marker[markerlen]" in 'commentstring' to line "lnum".
*/
static void foldAddMarker(linenr_T lnum, char_u *marker, size_t markerlen)
static void foldAddMarker(linenr_T lnum, const char_u *marker, size_t markerlen)
{
char_u *cms = curbuf->b_p_cms;
char_u *line;
char_u *newline;
char_u *p = (char_u *)strstr((char *)curbuf->b_p_cms, "%s");
bool line_is_comment = false;
/* Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end */
// Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end
line = ml_get(lnum);
size_t line_len = STRLEN(line);
if (u_save(lnum - 1, lnum + 1) == OK) {
// Check if the line ends with an unclosed comment
skip_comment(line, false, false, &line_is_comment);
newline = xmalloc(line_len + markerlen + STRLEN(cms) + 1);
STRCPY(newline, line);
if (p == NULL)
// Append the marker to the end of the line
if (p == NULL || line_is_comment) {
STRLCPY(newline + line_len, marker, markerlen + 1);
else {
} else {
STRCPY(newline + line_len, cms);
memcpy(newline + line_len + (p - cms), marker, markerlen);
STRCPY(newline + line_len + (p - cms) + markerlen, p + 2);
}
ml_replace(lnum, newline, FALSE);
ml_replace(lnum, newline, false);
}
}
@ -2535,10 +2539,10 @@ static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot)
* 1 2 3
* 1 2 3
* top 2 3 4 5
* 2 3 4 5
* bot 2 3 4 5
* 3 5 6
* 3 5 6
* 2 3 4 5
* bot 2 3 4 5
* 3 5 6
* 3 5 6
*
* 1: not changed
* 2: truncate to stop above "top"

View File

@ -2318,7 +2318,7 @@ ml_append_int (
*
* return FAIL for failure, OK otherwise
*/
int ml_replace(linenr_T lnum, char_u *line, int copy)
int ml_replace(linenr_T lnum, char_u *line, bool copy)
{
if (line == NULL) /* just checking... */
return FAIL;

View File

@ -3438,43 +3438,47 @@ dis_msg (
os_breakcheck();
}
/*
* 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(char_u *line, int process, int include_space, int *is_comment)
/// If \p "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".
///
/// @param line - line to be processed
/// @param process - if false, will only check whether the line ends
/// with an unclosed comment,
/// @param include_space - whether to skip space following the comment leader
/// @param[out] is_comment - whether the current line ends with an unclosed
/// comment.
char_u *skip_comment(
char_u *line, bool process, bool include_space, bool *is_comment
)
{
char_u *comment_flags = NULL;
int lead_len;
int leader_offset = get_last_leader_offset(line, &comment_flags);
*is_comment = FALSE;
*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 == ':')
|| *comment_flags == ':') {
break;
++comment_flags;
}
comment_flags++;
}
if (*comment_flags != COM_END) {
*is_comment = true;
}
if (*comment_flags != COM_END)
*is_comment = TRUE;
}
if (process == FALSE)
if (process == false) {
return line;
}
lead_len = get_leader_len(line, &comment_flags, FALSE, include_space);
lead_len = get_leader_len(line, &comment_flags, false, include_space);
if (lead_len == 0)
return line;
@ -3496,8 +3500,9 @@ static char_u *skip_comment(char_u *line, int process, int include_space, int *i
* starting with 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)
if (*comment_flags == ':' || *comment_flags == NUL) {
line += lead_len;
}
return line;
}
@ -3531,7 +3536,7 @@ int do_join(size_t count,
int *comments = NULL;
int remove_comments = (use_formatoptions == TRUE)
&& has_format_option(FO_REMOVE_COMS);
int prev_was_comment;
bool prev_was_comment;
if (save_undo && u_save(curwin->w_cursor.lnum - 1,
curwin->w_cursor.lnum + (linenr_T)count) == FAIL) {

View File

@ -96,6 +96,22 @@ func! Test_indent_fold2()
bw!
endfunc
func Test_folds_marker_in_comment()
new
call setline(1, ['" foo', 'bar', 'baz'])
setl fen fdm=marker
setl com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\" cms=\"%s
norm! zf2j
setl nofen
:1y
call assert_equal(['" foo{{{'], getreg(0,1,1))
:+2y
call assert_equal(['baz"}}}'], getreg(0,1,1))
set foldmethod&
bwipe!
endfunc
func Test_manual_fold_with_filter()
if !executable('cat')
return