diff options
author | Marco Hinz <mh.codebro@gmail.com> | 2019-01-25 16:45:29 +0100 |
---|---|---|
committer | Marco Hinz <mh.codebro@gmail.com> | 2019-01-26 14:45:48 +0100 |
commit | 2ae97f3d4c572387aa639af5d8550235bf0a2979 (patch) | |
tree | 77613f3e9a6adb7a62c4f1da5ac045c337128618 | |
parent | 2418aa3a4ac8f560373b940dbe0443fc79ab65ad (diff) | |
download | rneovim-2ae97f3d4c572387aa639af5d8550235bf0a2979.tar.gz rneovim-2ae97f3d4c572387aa639af5d8550235bf0a2979.tar.bz2 rneovim-2ae97f3d4c572387aa639af5d8550235bf0a2979.zip |
vim-patch:8.1.0759: showing two characters for tab is limited
Problem: Showing two characters for tab is limited.
Solution: Allow for a third character for "tab:" in 'listchars'. (Nathaniel
Braun, Ken Takata, closes vim/vim#3810)
https://github.com/vim/vim/commit/83a52171ba00b2b9fd2d1d22a07e38fc9fc69c1e
-rw-r--r-- | runtime/doc/options.txt | 25 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/message.c | 17 | ||||
-rw-r--r-- | src/nvim/option.c | 12 | ||||
-rw-r--r-- | src/nvim/screen.c | 53 | ||||
-rw-r--r-- | src/nvim/testdir/test_listchars.vim | 32 |
6 files changed, 115 insertions, 25 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 61482282f6..732305b6aa 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3662,11 +3662,26 @@ A jump table for the options with a short description can be found at |Q_op|. omitted, there is no extra character at the end of the line. *lcs-tab* - tab:xy Two characters to be used to show a tab. The first - char is used once. The second char is repeated to - fill the space that the tab normally occupies. - "tab:>-" will show a tab that takes four spaces as - ">---". When omitted, a tab is show as ^I. + tab:xy[z] Two or three characters to be used to show a tab. + The third character is optional. + + tab:xy The 'x' is always used, then 'y' as many times as will + fit. Thus "tab:>-" displays: + > + >- + >-- + etc. + + tab:xyz The 'z' is always used, then 'x' is prepended, and + then 'y' is used as many times as will fit. Thus + "tab:<->" displays: + > + <> + <-> + <--> + etc. + + When "tab:" is omitted, a tab is shown as ^I. *lcs-space* space:c Character to show for a space. When omitted, spaces are left blank. diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index a284ed5292..09d22c4233 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1016,6 +1016,7 @@ struct window_S { int space; int tab1; ///< first tab character int tab2; ///< second tab character + int tab3; ///< third tab character int trail; int conceal; } w_p_lcs_chars; diff --git a/src/nvim/message.c b/src/nvim/message.c index c83c013225..1330460867 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1517,10 +1517,11 @@ void msg_prt_line(char_u *s, int list) int col = 0; int n_extra = 0; int c_extra = 0; - char_u *p_extra = NULL; /* init to make SASC shut up */ + int c_final = 0; + char_u *p_extra = NULL; // init to make SASC shut up int n; int attr = 0; - char_u *trail = NULL; + char_u *trail = NULL; int l; if (curwin->w_p_list) { @@ -1543,7 +1544,9 @@ void msg_prt_line(char_u *s, int list) while (!got_int) { if (n_extra > 0) { n_extra--; - if (c_extra) { + if (n_extra == 0 && c_final) { + c = c_final; + } else if (c_extra) { c = c_extra; } else { assert(p_extra != NULL); @@ -1572,9 +1575,13 @@ void msg_prt_line(char_u *s, int list) if (!list) { c = ' '; c_extra = ' '; + c_final = NUL; } else { - c = curwin->w_p_lcs_chars.tab1; + c = (n_extra == 0 && curwin->w_p_lcs_chars.tab3) + ? curwin->w_p_lcs_chars.tab3 + : curwin->w_p_lcs_chars.tab1; c_extra = curwin->w_p_lcs_chars.tab2; + c_final = curwin->w_p_lcs_chars.tab3; attr = HL_ATTR(HLF_8); } } else if (c == 160 && list && curwin->w_p_lcs_chars.nbsp != NUL) { @@ -1583,6 +1590,7 @@ void msg_prt_line(char_u *s, int list) } else if (c == NUL && list && curwin->w_p_lcs_chars.eol != NUL) { p_extra = (char_u *)""; c_extra = NUL; + c_final = NUL; n_extra = 1; c = curwin->w_p_lcs_chars.eol; attr = HL_ATTR(HLF_AT); @@ -1591,6 +1599,7 @@ void msg_prt_line(char_u *s, int list) n_extra = n - 1; p_extra = transchar_byte(c); c_extra = NUL; + c_final = NUL; c = *p_extra++; /* Use special coloring to be able to distinguish <hex> from * the same in plain text. */ diff --git a/src/nvim/option.c b/src/nvim/option.c index 77728a16e8..d8e5b78e80 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3405,7 +3405,7 @@ static char_u *set_chars_option(win_T *wp, char_u **varp) { int round, i, len, entries; char_u *p, *s; - int c1, c2 = 0; + int c1 = 0, c2 = 0, c3 = 0; struct chars_tab { int *cp; ///< char value @@ -3462,6 +3462,7 @@ static char_u *set_chars_option(win_T *wp, char_u **varp) } if (varp == &wp->w_p_lcs) { wp->w_p_lcs_chars.tab1 = NUL; + wp->w_p_lcs_chars.tab3 = NUL; } } p = *varp; @@ -3471,6 +3472,7 @@ static char_u *set_chars_option(win_T *wp, char_u **varp) if (STRNCMP(p, tab[i].name, len) == 0 && p[len] == ':' && p[len + 1] != NUL) { + c1 = c2 = c3 = 0; s = p + len + 1; // TODO(bfredl): use schar_T representation and utfc_ptr2len @@ -3488,12 +3490,20 @@ static char_u *set_chars_option(win_T *wp, char_u **varp) if (mb_char2cells(c2) > 1 || (c2len == 1 && c2 > 127)) { continue; } + if (!(*s == ',' || *s == NUL)) { + int c3len = utf_ptr2len(s); + c3 = mb_cptr2char_adv((const char_u **)&s); + if (mb_char2cells(c3) > 1 || (c3len == 1 && c3 > 127)) { + continue; + } + } } if (*s == ',' || *s == NUL) { if (round) { if (tab[i].cp == &wp->w_p_lcs_chars.tab2) { wp->w_p_lcs_chars.tab1 = c1; wp->w_p_lcs_chars.tab2 = c2; + wp->w_p_lcs_chars.tab3 = c3; } else if (tab[i].cp != NULL) { *(tab[i].cp) = c1; } diff --git a/src/nvim/screen.c b/src/nvim/screen.c index c1fb001cc4..29a71fc0e1 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -2055,6 +2055,7 @@ win_line ( char_u *p_extra = NULL; // string of extra chars, plus NUL char_u *p_extra_free = NULL; // p_extra needs to be freed int c_extra = NUL; // extra chars, all the same + int c_final = NUL; // final char, mandatory if set int extra_attr = 0; // attributes when n_extra != 0 static char_u *at_end_str = (char_u *)""; // used for p_extra when displaying // curwin->w_p_lcs_chars.eol at @@ -2066,6 +2067,7 @@ win_line ( int saved_n_extra = 0; char_u *saved_p_extra = NULL; int saved_c_extra = 0; + int saved_c_final = 0; int saved_char_attr = 0; int n_attr = 0; /* chars with special attr */ @@ -2644,6 +2646,7 @@ win_line ( /* Draw the cmdline character. */ n_extra = 1; c_extra = cmdwin_type; + c_final = NUL; char_attr = win_hl_attr(wp, HLF_AT); } } @@ -2662,6 +2665,7 @@ win_line ( p_extra_free[n_extra] = NUL; p_extra = p_extra_free; c_extra = NUL; + c_final = NUL; char_attr = win_hl_attr(wp, HLF_FC); } } @@ -2675,6 +2679,7 @@ win_line ( int text_sign; // Draw cells with the sign value or blank. c_extra = ' '; + c_final = NUL; char_attr = win_hl_attr(wp, HLF_SC); n_extra = win_signcol_width(wp); @@ -2685,6 +2690,7 @@ win_line ( int symbol_blen = (int)STRLEN(p_extra); if (p_extra != NULL) { c_extra = NUL; + c_final = NUL; // symbol(s) bytes + (filling spaces) (one byte each) n_extra = symbol_blen + (win_signcol_width(wp) - mb_string2cells(p_extra)); @@ -2736,8 +2742,11 @@ win_line ( rl_mirror(extra); p_extra = extra; c_extra = NUL; - } else + c_final = NUL; + } else { c_extra = ' '; + c_final = NUL; + } n_extra = number_width(wp) + 1; char_attr = win_hl_attr(wp, HLF_N); @@ -2795,8 +2804,10 @@ win_line ( // draw "deleted" diff line(s) if (char2cells(wp->w_p_fcs_chars.diff) > 1) { c_extra = '-'; + c_final = NUL; } else { c_extra = wp->w_p_fcs_chars.diff; + c_final = NUL; } if (wp->w_p_rl) { n_extra = col + 1; @@ -2809,6 +2820,7 @@ win_line ( /* Draw 'showbreak' at the start of each broken line. */ p_extra = p_sbr; c_extra = NUL; + c_final = NUL; n_extra = (int)STRLEN(p_sbr); char_attr = win_hl_attr(wp, HLF_AT); need_showbreak = false; @@ -2830,6 +2842,7 @@ win_line ( /* Continue item from end of wrapped line. */ n_extra = saved_n_extra; c_extra = saved_c_extra; + c_final = saved_c_final; p_extra = saved_p_extra; char_attr = saved_char_attr; } else { @@ -3027,20 +3040,18 @@ win_line ( } } - /* - * Get the next character to put on the screen. - */ - /* - * The "p_extra" points to the extra stuff that is inserted to - * represent special characters (non-printable stuff) and other - * things. When all characters are the same, c_extra is used. - * "p_extra" must end in a NUL to avoid mb_ptr2len() reads past - * "p_extra[n_extra]". - * For the '$' of the 'list' option, n_extra == 1, p_extra == "". - */ + // Get the next character to put on the screen. + // + // The "p_extra" points to the extra stuff that is inserted to + // represent special characters (non-printable stuff) and other + // things. When all characters are the same, c_extra is used. + // If c_final is set, it will compulsorily be used at the end. + // "p_extra" must end in a NUL to avoid mb_ptr2len() reads past + // "p_extra[n_extra]". + // For the '$' of the 'list' option, n_extra == 1, p_extra == "". if (n_extra > 0) { - if (c_extra != NUL) { - c = c_extra; + if (c_extra != NUL || (n_extra == 1 && c_final != NUL)) { + c = (n_extra == 1 && c_final != NUL) ? c_final : c_extra; mb_c = c; // doesn't handle non-utf-8 multi-byte! if (enc_utf8 && utf_char2len(c) > 1) { mb_utf8 = true; @@ -3147,6 +3158,7 @@ win_line ( mb_utf8 = (c >= 0x80); n_extra = (int)STRLEN(p_extra); c_extra = NUL; + c_final = NUL; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; extra_attr = win_hl_attr(wp, HLF_8); @@ -3199,6 +3211,7 @@ win_line ( p_extra = extra; n_extra = (int)STRLEN(extra) - 1; c_extra = NUL; + c_final = NUL; c = *p_extra++; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; @@ -3233,6 +3246,7 @@ win_line ( if (n_skip > 0 && mb_l > 1 && n_extra == 0) { n_extra = 1; c_extra = MB_FILLER_CHAR; + c_final = NUL; c = ' '; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; @@ -3392,6 +3406,7 @@ win_line ( - vcol % (int)wp->w_buffer->b_p_ts - 1; } c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; + c_final = NUL; if (ascii_iswhite(c)) { if (c == TAB) /* See "Tab alignment" below. */ @@ -3523,12 +3538,15 @@ win_line ( mb_utf8 = false; // don't draw as UTF-8 if (wp->w_p_list) { - c = wp->w_p_lcs_chars.tab1; + c = (n_extra == 0 && wp->w_p_lcs_chars.tab3) + ? wp->w_p_lcs_chars.tab3 + : wp->w_p_lcs_chars.tab1; if (wp->w_p_lbr) { c_extra = NUL; /* using p_extra from above */ } else { c_extra = wp->w_p_lcs_chars.tab2; } + c_final = wp->w_p_lcs_chars.tab3; n_attr = tab_len + 1; extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr @@ -3539,6 +3557,7 @@ win_line ( c = 0xc0; } } else { + c_final = NUL; c_extra = ' '; c = ' '; } @@ -3566,6 +3585,7 @@ win_line ( p_extra = at_end_str; n_extra = 1; c_extra = NUL; + c_final = NUL; } } if (wp->w_p_list && wp->w_p_lcs_chars.eol > 0) { @@ -3593,6 +3613,7 @@ win_line ( if ((dy_flags & DY_UHEX) && wp->w_p_rl) rl_mirror(p_extra); /* reverse "<12>" */ c_extra = NUL; + c_final = NUL; if (wp->w_p_lbr) { char_u *p; @@ -3716,6 +3737,7 @@ win_line ( /* Double-width character being overwritten by the "precedes" * character, need to fill up half the character. */ c_extra = MB_FILLER_CHAR; + c_final = NUL; n_extra = 1; n_attr = 2; extra_attr = win_hl_attr(wp, HLF_AT); @@ -4231,6 +4253,7 @@ win_line ( saved_n_extra = n_extra; saved_p_extra = p_extra; saved_c_extra = c_extra; + saved_c_final = c_final; saved_char_attr = char_attr; n_extra = 0; lcs_prec_todo = wp->w_p_lcs_chars.prec; diff --git a/src/nvim/testdir/test_listchars.vim b/src/nvim/testdir/test_listchars.vim index 57ea7ca5a9..4899f59910 100644 --- a/src/nvim/testdir/test_listchars.vim +++ b/src/nvim/testdir/test_listchars.vim @@ -42,6 +42,38 @@ func Test_listchars() call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) endfor + " tab with 3rd character. + set listchars-=tab:>- + set listchars+=tab:<=>,trail:- + let expected = [ + \ '<======>aa<====>$', + \ '..bb<==>--$', + \ '...cccc>-$', + \ 'dd........ee--<>$', + \ '-$' + \ ] + redraw! + for i in range(1, 5) + call cursor(i, 1) + call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) + endfor + + set listchars-=trail:- + let expected = [ + \ '<======>aa<====>$', + \ '..bb<==>..$', + \ '...cccc>.$', + \ 'dd........ee..<>$', + \ '.$' + \ ] + redraw! + for i in range(1, 5) + call cursor(i, 1) + call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) + endfor + + set listchars-=tab:<=> + set listchars+=tab:>- set listchars+=trail:< set nolist normal ggdG |