diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-06-07 20:01:46 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2022-06-09 21:26:23 +0800 |
commit | d6247a575c12f413e21ff5e7e94a86214246579d (patch) | |
tree | f523118e6d5f262eba282be387ad210978f6fa9a /src | |
parent | 3da3cfc864e89a2dca6917183915683373c85af8 (diff) | |
download | rneovim-d6247a575c12f413e21ff5e7e94a86214246579d.tar.gz rneovim-d6247a575c12f413e21ff5e7e94a86214246579d.tar.bz2 rneovim-d6247a575c12f413e21ff5e7e94a86214246579d.zip |
vim-patch:8.2.5066: lcs-leadmultispace
https://github.com/vim/vim/commit/aca12fd89b082dd9cc12ae085a84f1805747bbdf
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/message.c | 21 | ||||
-rw-r--r-- | src/nvim/option.c | 51 | ||||
-rw-r--r-- | src/nvim/screen.c | 19 | ||||
-rw-r--r-- | src/nvim/testdir/test_listchars.vim | 147 | ||||
-rw-r--r-- | src/nvim/window.c | 1 |
6 files changed, 226 insertions, 14 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index b5980612f8..f1dd8aadeb 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1232,6 +1232,7 @@ struct window_S { int lead; int trail; int *multispace; + int *leadmultispace; int conceal; } w_p_lcs_chars; diff --git a/src/nvim/message.c b/src/nvim/message.c index 2e57d11fb6..e3f87ed3e6 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1783,7 +1783,7 @@ void msg_prt_line(char_u *s, int list) } } // find end of leading whitespace - if (curwin->w_p_lcs_chars.lead) { + if (curwin->w_p_lcs_chars.lead || curwin->w_p_lcs_chars.leadmultispace != NULL) { lead = s; while (ascii_iswhite(lead[0])) { lead++; @@ -1873,13 +1873,28 @@ void msg_prt_line(char_u *s, int list) // the same in plain text. attr = HL_ATTR(HLF_0); } else if (c == ' ') { - if (lead != NULL && s <= lead) { + if (list && lead != NULL && s <= lead && in_multispace + && curwin->w_p_lcs_chars.leadmultispace != NULL) { + c = curwin->w_p_lcs_chars.leadmultispace[multispace_pos++]; + if (curwin->w_p_lcs_chars.leadmultispace[multispace_pos] == NUL) { + multispace_pos = 0; + } + attr = HL_ATTR(HLF_0); + } else if (lead != NULL && s <= lead && curwin->w_p_lcs_chars.lead) { c = curwin->w_p_lcs_chars.lead; attr = HL_ATTR(HLF_0); } else if (trail != NULL && s > trail) { c = curwin->w_p_lcs_chars.trail; attr = HL_ATTR(HLF_0); - } else if (list && in_multispace && curwin->w_p_lcs_chars.multispace != NULL) { + } else if (list && lead != NULL && s <= lead && in_multispace + && curwin->w_p_lcs_chars.leadmultispace != NULL) { + c = curwin->w_p_lcs_chars.leadmultispace[multispace_pos++]; + if (curwin->w_p_lcs_chars.leadmultispace[multispace_pos] == NUL) { + multispace_pos = 0; + } + attr = HL_ATTR(HLF_0); + } else if (list && in_multispace + && curwin->w_p_lcs_chars.multispace != NULL) { c = curwin->w_p_lcs_chars.multispace[multispace_pos++]; if (curwin->w_p_lcs_chars.multispace[multispace_pos] == NUL) { multispace_pos = 0; diff --git a/src/nvim/option.c b/src/nvim/option.c index a15c6f4854..b68ee9fd8c 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3552,13 +3552,15 @@ static int get_encoded_char_adv(char_u **p) /// @return error message, NULL if it's OK. static char *set_chars_option(win_T *wp, char_u **varp, bool set) { - int round, i, len, entries; + int round, i, len, len2, entries; char_u *p, *s; int c1; int c2 = 0; int c3 = 0; - char_u *last_multispace = NULL; // Last occurrence of "multispace:" - int multispace_len = 0; // Length of lcs-multispace string + char_u *last_multispace = NULL; // Last occurrence of "multispace:" + char_u *last_lmultispace = NULL; // Last occurrence of "leadmultispace:" + int multispace_len = 0; // Length of lcs-multispace string + int lead_multispace_len = 0; // Length of lcs-leadmultispace string struct chars_tab { int *cp; ///< char value @@ -3646,6 +3648,17 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set) } else { wp->w_p_lcs_chars.multispace = NULL; } + + if (wp->w_p_lcs_chars.leadmultispace != NULL) { + xfree(wp->w_p_lcs_chars.leadmultispace); + } + if (lead_multispace_len > 0) { + wp->w_p_lcs_chars.leadmultispace + = xmalloc(((size_t)lead_multispace_len + 1) * sizeof(int)); + wp->w_p_lcs_chars.leadmultispace[lead_multispace_len] = NUL; + } else { + wp->w_p_lcs_chars.leadmultispace = NULL; + } } } p = *varp; @@ -3694,6 +3707,7 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set) if (i == entries) { len = (int)STRLEN("multispace"); + len2 = (int)STRLEN("leadmultispace"); if ((varp == &p_lcs || varp == &wp->w_p_lcs) && STRNCMP(p, "multispace", len) == 0 && p[len] == ':' @@ -3725,6 +3739,37 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set) } p = s; } + } else if ((varp == &p_lcs || varp == &wp->w_p_lcs) + && STRNCMP(p, "leadmultispace", len2) == 0 + && p[len2] == ':' + && p[len2 + 1] != NUL) { + s = p + len2 + 1; + if (round == 0) { + // Get length of lcsmultispace string in first round + last_lmultispace = p; + lead_multispace_len = 0; + while (*s != NUL && *s != ',') { + c1 = get_encoded_char_adv(&s); + if (c1 == 0 || char2cells(c1) > 1) { + return e_invarg; + } + lead_multispace_len++; + } + if (lead_multispace_len == 0) { + // lcsmultispace cannot be an empty string + return e_invarg; + } + p = s; + } else { + int multispace_pos = 0; + while (*s != NUL && *s != ',') { + c1 = get_encoded_char_adv(&s); + if (p == last_lmultispace) { + wp->w_p_lcs_chars.leadmultispace[multispace_pos++] = c1; + } + } + p = s; + } } else { return e_invarg; } diff --git a/src/nvim/screen.c b/src/nvim/screen.c index fe306f8c6b..fb7e34214f 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -2453,6 +2453,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc if (wp->w_p_list && !has_fold && !end_fill) { if (wp->w_p_lcs_chars.space || wp->w_p_lcs_chars.multispace != NULL + || wp->w_p_lcs_chars.leadmultispace != NULL || wp->w_p_lcs_chars.trail || wp->w_p_lcs_chars.lead || wp->w_p_lcs_chars.nbsp) { @@ -2467,7 +2468,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc trailcol += (colnr_T)(ptr - line); } // find end of leading whitespace - if (wp->w_p_lcs_chars.lead) { + if (wp->w_p_lcs_chars.lead || wp->w_p_lcs_chars.leadmultispace != NULL) { leadcol = 0; while (ascii_iswhite(ptr[leadcol])) { leadcol++; @@ -3441,8 +3442,20 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc if ((trailcol != MAXCOL && ptr > line + trailcol && c == ' ') || (leadcol != 0 && ptr < line + leadcol && c == ' ')) { - c = (ptr > line + trailcol) ? wp->w_p_lcs_chars.trail - : wp->w_p_lcs_chars.lead; + if (leadcol != 0 && in_multispace && ptr < line + leadcol + && wp->w_p_lcs_chars.leadmultispace != NULL) { + c = wp->w_p_lcs_chars.leadmultispace[multispace_pos++]; + if (wp->w_p_lcs_chars.leadmultispace[multispace_pos] == NUL) { + multispace_pos = 0; + } + } else if (ptr > line + trailcol && wp->w_p_lcs_chars.trail) { + c = wp->w_p_lcs_chars.trail; + } else if (ptr < line + leadcol && wp->w_p_lcs_chars.lead) { + c = wp->w_p_lcs_chars.lead; + } else if (leadcol != 0 && c == ' ' && wp->w_p_lcs_chars.space) { + c = wp->w_p_lcs_chars.space; + } + n_attr = 1; extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr diff --git a/src/nvim/testdir/test_listchars.vim b/src/nvim/testdir/test_listchars.vim index b239c9c6b5..eed4d7e30c 100644 --- a/src/nvim/testdir/test_listchars.vim +++ b/src/nvim/testdir/test_listchars.vim @@ -132,7 +132,7 @@ func Test_listchars() \ 'h<<<<<<<<<<<$', \ '<<<<<<<<<<<<$', \ '>>>>0xx0<<<<$', - \ '$' + \ '$' \ ] redraw! for i in range(1, 5) @@ -162,7 +162,7 @@ func Test_listchars() \ ' hyYzZyYzZyY$', \ 'yYzZyYzZyYj $', \ 'yYzZ0yY0yYzZ$', - \ '$' + \ '$' \ ] redraw! for i in range(1, 5) @@ -172,7 +172,133 @@ func Test_listchars() call assert_equal(expected, split(execute("%list"), "\n")) + " Test leadmultispace + multispace + normal ggdG + set listchars=eol:$,multispace:yYzZ,nbsp:S + set listchars+=leadmultispace:.-+* + set list + + call append(0, [ + \ ' ffff ', + \ ' i i gg', + \ ' h ', + \ ' j ', + \ ' 0 0 ', + \ ]) + + let expected = [ + \ '.-+*ffffyYzZ$', + \ '.-i iSyYzZgg$', + \ ' hyYzZyYzZyY$', + \ '.-+*.-+*.-j $', + \ '.-+*0yY0yYzZ$', + \ '$' + \ ] + redraw! + call assert_equal('eol:$,multispace:yYzZ,nbsp:S,leadmultispace:.-+*', &listchars) + for i in range(1, 5) + call cursor(i, 1) + call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) + endfor + + call assert_equal(expected, split(execute("%list"), "\n")) + + " Test leadmultispace without multispace + normal ggdG + set listchars-=multispace:yYzZ + set listchars+=space:+,trail:>,eol:$ + set list + + call append(0, [ + \ ' ffff ', + \ ' i i gg', + \ ' h ', + \ ' j ', + \ ' 0 0 ', + \ ]) + + let expected = [ + \ '.-+*ffff>>>>$', + \ '.-i+i+++++gg$', + \ '+h>>>>>>>>>>$', + \ '.-+*.-+*.-j>$', + \ '.-+*0++0>>>>$', + \ '$', + \ ] + + redraw! + call assert_equal('eol:$,nbsp:S,leadmultispace:.-+*,space:+,trail:>,eol:$', &listchars) + for i in range(1, 5) + call cursor(i, 1) + call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) + endfor + + call assert_equal(expected, split(execute("%list"), "\n")) + + " Test leadmultispace only + normal ggdG + set listchars=eol:$ " Accommodate Nvim default + set listchars=leadmultispace:.-+* + set list + + call append(0, [ + \ ' ffff ', + \ ' i i gg', + \ ' h ', + \ ' j ', + \ ' 0 0 ', + \ ]) + + let expected = [ + \ '.-+*ffff ', + \ '.-i i gg', + \ ' h ', + \ '.-+*.-+*.-j ', + \ '.-+*0 0 ', + \ ' ', + \ ] + redraw! + call assert_equal('leadmultispace:.-+*', &listchars) + for i in range(1, 5) + call cursor(i, 1) + call assert_equal([expected[i - 1]], ScreenLines(i, 12)) + endfor + call assert_equal(expected, split(execute("%list"), "\n")) + + " Test leadmultispace and lead and space + normal ggdG + set listchars=eol:$ " Accommodate Nvim default + set listchars+=lead:<,space:- + set listchars+=leadmultispace:.-+* + set list + + call append(0, [ + \ ' ffff ', + \ ' i i gg', + \ ' h ', + \ ' j ', + \ ' 0 0 ', + \ ]) + + let expected = [ + \ '.-+*ffff----$', + \ '.-i-i-----gg$', + \ '<h----------$', + \ '.-+*.-+*.-j-$', + \ '.-+*0--0----$', + \ '$', + \ ] + redraw! + call assert_equal('eol:$,lead:<,space:-,leadmultispace:.-+*', &listchars) + for i in range(1, 5) + call cursor(i, 1) + call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) + endfor + call assert_equal(expected, split(execute("%list"), "\n")) + " the last occurrence of 'multispace:' is used + set listchars=eol:$ " Accommodate Nvim default + set listchars+=multispace:yYzZ set listchars+=space:x,multispace:XyY let expected = [ @@ -181,9 +307,10 @@ func Test_listchars() \ 'xhXyYXyYXyYX$', \ 'XyYXyYXyYXjx$', \ 'XyYX0Xy0XyYX$', - \ '$' + \ '$' \ ] redraw! + call assert_equal('eol:$,multispace:yYzZ,space:x,multispace:XyY', &listchars) for i in range(1, 5) call cursor(i, 1) call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) @@ -199,7 +326,7 @@ func Test_listchars() \ '>h<<<<<<<<<<$', \ '>>>>>>>>>>j<$', \ '>>>>0Xy0<<<<$', - \ '$' + \ '$' \ ] redraw! for i in range(1, 5) @@ -219,7 +346,7 @@ func Test_listchars() \ '>h<<<<<<<<<<$', \ '>>>>>>>>>>j<$', \ '>>>>0xx0<<<<$', - \ '$' + \ '$' \ ] redraw! for i in range(1, 5) @@ -315,11 +442,13 @@ func Test_listchars_invalid() call assert_fails('set listchars=x', 'E474:') call assert_fails('set listchars=x', 'E474:') call assert_fails('set listchars=multispace', 'E474:') + call assert_fails('set listchars=leadmultispace', 'E474:') " Too short call assert_fails('set listchars=space:', 'E474:') call assert_fails('set listchars=tab:x', 'E474:') call assert_fails('set listchars=multispace:', 'E474:') + call assert_fails('set listchars=leadmultispace:', 'E474:') " One occurrence too short call assert_fails('set listchars=space:,space:x', 'E474:') @@ -328,6 +457,8 @@ func Test_listchars_invalid() call assert_fails('set listchars=tab:xx,tab:x', 'E474:') call assert_fails('set listchars=multispace:,multispace:x', 'E474:') call assert_fails('set listchars=multispace:x,multispace:', 'E474:') + call assert_fails('set listchars=leadmultispace:,leadmultispace:x', 'E474:') + call assert_fails('set listchars=leadmultispace:x,leadmultispace:', 'E474:') " Too long call assert_fails('set listchars=space:xx', 'E474:') @@ -340,6 +471,8 @@ func Test_listchars_invalid() call assert_fails('set listchars=tab:xx·', 'E474:') call assert_fails('set listchars=multispace:·', 'E474:') call assert_fails('set listchars=multispace:xxx·', 'E474:') + call assert_fails('set listchars=leadmultispace:·', 'E474:') + call assert_fails('set listchars=leadmultispace:xxx·', 'E474:') " Has control character call assert_fails("set listchars=space:\x01", 'E474:') @@ -354,6 +487,10 @@ func Test_listchars_invalid() call assert_fails('set listchars=tab:xx\\x01', 'E474:') call assert_fails('set listchars=multispace:\\x01', 'E474:') call assert_fails('set listchars=multispace:xxx\\x01', 'E474:') + call assert_fails("set listchars=leadmultispace:\x01", 'E474:') + call assert_fails('set listchars=leadmultispace:\\x01', 'E474:') + call assert_fails("set listchars=leadmultispace:xxx\x01", 'E474:') + call assert_fails('set listchars=leadmultispace:xxx\\x01', 'E474:') enew! set ambiwidth& listchars& ff& diff --git a/src/nvim/window.c b/src/nvim/window.c index 5f4179944d..f429c493a7 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5085,6 +5085,7 @@ static void win_free(win_T *wp, tabpage_T *tp) clear_winopt(&wp->w_allbuf_opt); xfree(wp->w_p_lcs_chars.multispace); + xfree(wp->w_p_lcs_chars.leadmultispace); vars_clear(&wp->w_vars->dv_hashtab); // free all w: variables hash_init(&wp->w_vars->dv_hashtab); |