diff options
author | Marco Hinz <mh.codebro@gmail.com> | 2019-01-23 01:41:00 +0100 |
---|---|---|
committer | Marco Hinz <mh.codebro@gmail.com> | 2019-01-26 14:45:47 +0100 |
commit | 352811fe5ff900e8d95695477dff821a5b860912 (patch) | |
tree | 94e91687fada2afefa3eee857473af5eb6a3f03f | |
parent | ec5a4d862d71729569acf4afac4c371a09edc314 (diff) | |
download | rneovim-352811fe5ff900e8d95695477dff821a5b860912.tar.gz rneovim-352811fe5ff900e8d95695477dff821a5b860912.tar.bz2 rneovim-352811fe5ff900e8d95695477dff821a5b860912.zip |
options: make 'fillchars'/'listchars' local to window
Using 'listchars' is a nice way to highlight tabs that were included by accident
for buffers that set 'expandtab'.
But maybe one does not want this for buffers that set 'noexpandtab', so now one
can use:
autocmd FileType go let &l:listchars .= ',tab: '
-rw-r--r-- | runtime/doc/options.txt | 2 | ||||
-rw-r--r-- | runtime/doc/vim_diff.txt | 7 | ||||
-rw-r--r-- | src/nvim/buffer.c | 2 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 28 | ||||
-rw-r--r-- | src/nvim/charset.c | 6 | ||||
-rw-r--r-- | src/nvim/eval.c | 4 | ||||
-rw-r--r-- | src/nvim/globals.h | 20 | ||||
-rw-r--r-- | src/nvim/indent.c | 2 | ||||
-rw-r--r-- | src/nvim/message.c | 31 | ||||
-rw-r--r-- | src/nvim/misc1.c | 4 | ||||
-rw-r--r-- | src/nvim/mouse.c | 2 | ||||
-rw-r--r-- | src/nvim/option.c | 119 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 4 | ||||
-rw-r--r-- | src/nvim/options.lua | 12 | ||||
-rw-r--r-- | src/nvim/screen.c | 90 |
15 files changed, 181 insertions, 152 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index bcefa1f56b..61482282f6 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3653,7 +3653,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'listchars'* *'lcs'* 'listchars' 'lcs' string (default: "tab:> ,trail:-,nbsp:+" Vi default: "eol:$") - global + local to window Strings to use in 'list' mode and for the |:list| command. It is a comma separated list of string settings. diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index db856ceb65..13d1c14117 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -37,8 +37,8 @@ a complete and centralized reference of those differences. - 'display' defaults to "lastline,msgsep" - 'encoding' is UTF-8 (cf. 'fileencoding' for file-content encoding) - 'fillchars' defaults (in effect) to "vert:│,fold:·" -- 'fsync' is disabled - 'formatoptions' defaults to "tcqj" +- 'fsync' is disabled - 'history' defaults to 10000 (the maximum) - 'hlsearch' is set by default - 'incsearch' is set by default @@ -184,9 +184,10 @@ Options: 'cpoptions' flags: |cpo-_| 'display' flag `msgsep` to minimize scrolling when showing messages 'guicursor' works in the terminal - 'fillchars' flags: `msgsep` (see 'display' above) - and `eob` for |hl-EndOfBuffer| marker + 'fillchars' local to window. flags: `msgsep` (see 'display' above) and `eob` + for |hl-EndOfBuffer| marker 'inccommand' shows interactive results for |:substitute|-like commands + 'listchars' local to window 'scrollback' 'statusline' supports unlimited alignment sections 'tabline' %@Func@foo%X can call any function on mouse-click diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index c15a6f1330..96d0eaf815 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3676,7 +3676,7 @@ int build_stl_str_hl( { // In list mode virtcol needs to be recomputed colnr_T virtcol = wp->w_virtcol; - if (wp->w_p_list && lcs_tab1 == NUL) { + if (wp->w_p_list && wp->w_p_lcs_chars.tab1 == NUL) { wp->w_p_list = FALSE; getvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL); wp->w_p_list = TRUE; diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 05688790c2..a284ed5292 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -248,6 +248,10 @@ typedef struct { # define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn' char_u *wo_winhl; # define w_p_winhl w_onebuf_opt.wo_winhl // 'winhighlight' + char_u *wo_fcs; +# define w_p_fcs w_onebuf_opt.wo_fcs // 'fillchars' + char_u *wo_lcs; +# define w_p_lcs w_onebuf_opt.wo_lcs // 'listchars' LastSet wo_scriptID[WV_COUNT]; // SIDs for window-local options # define w_p_scriptID w_onebuf_opt.wo_scriptID @@ -1003,6 +1007,30 @@ struct window_S { colnr_T w_old_visual_col; ///< last known start of visual part colnr_T w_old_curswant; ///< last known value of Curswant + // 'listchars' characters. Defaults set in set_chars_option(). + struct { + int eol; + int ext; + int prec; + int nbsp; + int space; + int tab1; ///< first tab character + int tab2; ///< second tab character + int trail; + int conceal; + } w_p_lcs_chars; + + // 'fillchars' characters. Defaults set in set_chars_option(). + struct { + int stl; + int stlnc; + int vert; + int fold; + int diff; + int msgsep; + int eob; + } w_p_fcs_chars; + /* * "w_topline", "w_leftcol" and "w_skipcol" specify the offsets for * displaying the buffer. diff --git a/src/nvim/charset.c b/src/nvim/charset.c index c220c4e347..010a155716 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -749,7 +749,7 @@ int vim_strnsize(char_u *s, int len) /// /// @return Number of characters. #define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \ - if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) { \ + if (*(p) == TAB && (!(wp)->w_p_list || wp->w_p_lcs_chars.tab1)) { \ const int ts = (int) (buf)->b_p_ts; \ return (ts - (int)(col % ts)); \ } else { \ @@ -1149,7 +1149,7 @@ static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp) { int n; - if ((*s == TAB) && (!wp->w_p_list || lcs_tab1)) { + if ((*s == TAB) && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) { n = (int)wp->w_buffer->b_p_ts; return n - (col % n); } @@ -1241,7 +1241,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, // When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set // use a simple loop. // Also use this when 'list' is set but tabs take their normal size. - if ((!wp->w_p_list || (lcs_tab1 != NUL)) + if ((!wp->w_p_list || (wp->w_p_lcs_chars.tab1 != NUL)) && !wp->w_p_lbr && (*p_sbr == NUL) && !wp->w_p_bri ) { diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 1c6fb5d2f8..993edec5ef 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -16425,7 +16425,9 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) if ((syntax_flags & HL_CONCEAL) && curwin->w_p_cole < 3) { cchar = syn_get_sub_char(); if (cchar == NUL && curwin->w_p_cole == 1) { - cchar = (lcs_conceal == NUL) ? ' ' : lcs_conceal; + cchar = (curwin->w_p_lcs_chars.conceal == NUL) + ? ' ' + : curwin->w_p_lcs_chars.conceal; } if (cchar != NUL) { utf_char2bytes(cchar, str); diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 8a76ca2bee..ccdf8f87ab 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -842,26 +842,6 @@ extern char_u *compiled_sys; * directory is not a local directory, globaldir is NULL. */ EXTERN char_u *globaldir INIT(= NULL); -// 'listchars' characters. Defaults are overridden in set_chars_option(). -EXTERN int lcs_eol INIT(= '$'); -EXTERN int lcs_ext INIT(= NUL); -EXTERN int lcs_prec INIT(= NUL); -EXTERN int lcs_nbsp INIT(= NUL); -EXTERN int lcs_space INIT(= NUL); -EXTERN int lcs_tab1 INIT(= NUL); -EXTERN int lcs_tab2 INIT(= NUL); -EXTERN int lcs_trail INIT(= NUL); -EXTERN int lcs_conceal INIT(= ' '); - -// 'fillchars' characters. Defaults are overridden in set_chars_option(). -EXTERN int fill_stl INIT(= ' '); -EXTERN int fill_stlnc INIT(= ' '); -EXTERN int fill_vert INIT(= 9474); // │ -EXTERN int fill_fold INIT(= 183); // · -EXTERN int fill_diff INIT(= '-'); -EXTERN int fill_msgsep INIT(= ' '); -EXTERN int fill_eob INIT(= '~'); - /* Whether 'keymodel' contains "stopsel" and "startsel". */ EXTERN int km_stopsel INIT(= FALSE); EXTERN int km_startsel INIT(= FALSE); diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 19456da45c..9e13b8a7f9 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -61,7 +61,7 @@ int get_indent_str(char_u *ptr, int ts, int list) for (; *ptr; ++ptr) { // Count a tab for what it is worth. if (*ptr == TAB) { - if (!list || lcs_tab1) { // count a tab for what it is worth + if (!list || curwin->w_p_lcs_chars.tab1) { // count a tab for what it is worth count += ts - (count % ts); } else { // In list mode, when tab is not set, count screen char width diff --git a/src/nvim/message.c b/src/nvim/message.c index 0f8ff74b12..4bcc58fc99 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1527,7 +1527,7 @@ void msg_prt_line(char_u *s, int list) list = TRUE; /* find start of trailing whitespace */ - if (list && lcs_trail) { + if (list && curwin->w_p_lcs_chars.trail) { trail = s + STRLEN(s); while (trail > s && ascii_iswhite(trail[-1])) --trail; @@ -1535,7 +1535,7 @@ void msg_prt_line(char_u *s, int list) /* output a space for an empty line, otherwise the line will be * overwritten */ - if (*s == NUL && !(list && lcs_eol != NUL)) + if (*s == NUL && !(list && curwin->w_p_lcs_chars.eol != NUL)) msg_putchar(' '); while (!got_int) { @@ -1550,9 +1550,9 @@ void msg_prt_line(char_u *s, int list) } else if ((l = utfc_ptr2len(s)) > 1) { col += utf_ptr2cells(s); char buf[MB_MAXBYTES + 1]; - if (lcs_nbsp != NUL && list + if (curwin->w_p_lcs_chars.nbsp != NUL && list && (utf_ptr2char(s) == 160 || utf_ptr2char(s) == 0x202f)) { - utf_char2bytes(lcs_nbsp, (char_u *)buf); + utf_char2bytes(curwin->w_p_lcs_chars.nbsp, (char_u *)buf); buf[utfc_ptr2len((char_u *)buf)] = NUL; } else { memmove(buf, s, (size_t)l); @@ -1564,25 +1564,25 @@ void msg_prt_line(char_u *s, int list) } else { attr = 0; c = *s++; - if (c == TAB && (!list || lcs_tab1)) { + if (c == TAB && (!list || curwin->w_p_lcs_chars.tab1)) { /* tab amount depends on current column */ n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1; if (!list) { c = ' '; c_extra = ' '; } else { - c = lcs_tab1; - c_extra = lcs_tab2; + c = curwin->w_p_lcs_chars.tab1; + c_extra = curwin->w_p_lcs_chars.tab2; attr = HL_ATTR(HLF_8); } - } else if (c == 160 && list && lcs_nbsp != NUL) { - c = lcs_nbsp; + } else if (c == 160 && list && curwin->w_p_lcs_chars.nbsp != NUL) { + c = curwin->w_p_lcs_chars.nbsp; attr = HL_ATTR(HLF_8); - } else if (c == NUL && list && lcs_eol != NUL) { + } else if (c == NUL && list && curwin->w_p_lcs_chars.eol != NUL) { p_extra = (char_u *)""; c_extra = NUL; n_extra = 1; - c = lcs_eol; + c = curwin->w_p_lcs_chars.eol; attr = HL_ATTR(HLF_AT); s--; } else if (c != NUL && (n = byte2cells(c)) > 1) { @@ -1594,10 +1594,10 @@ void msg_prt_line(char_u *s, int list) * the same in plain text. */ attr = HL_ATTR(HLF_8); } else if (c == ' ' && trail != NULL && s > trail) { - c = lcs_trail; + c = curwin->w_p_lcs_chars.trail; attr = HL_ATTR(HLF_8); - } else if (c == ' ' && list && lcs_space != NUL) { - c = lcs_space; + } else if (c == ' ' && list && curwin->w_p_lcs_chars.space != NUL) { + c = curwin->w_p_lcs_chars.space; attr = HL_ATTR(HLF_8); } } @@ -1955,7 +1955,8 @@ static void msg_scroll_up(void) if (dy_flags & DY_MSGSEP) { if (msg_scrolled == 0) { grid_fill(&default_grid, Rows-p_ch-1, Rows-p_ch, 0, (int)Columns, - fill_msgsep, fill_msgsep, HL_ATTR(HLF_MSGSEP)); + curwin->w_p_fcs_chars.msgsep, curwin->w_p_fcs_chars.msgsep, + HL_ATTR(HLF_MSGSEP)); } int nscroll = MIN(msg_scrollsize()+1, Rows); grid_del_lines(&default_grid, Rows-nscroll, 1, Rows, 0, Columns); diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index a66ded13f1..6bcfb87368 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -1286,7 +1286,7 @@ int plines_win_nofold(win_T *wp, linenr_T lnum) * If list mode is on, then the '$' at the end of the line may take up one * extra column. */ - if (wp->w_p_list && lcs_eol != NUL) + if (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL) col += 1; /* @@ -1336,7 +1336,7 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column) // screen position of the TAB. This only fixes an error when the TAB wraps // from one screen line to the next (when 'columns' is not a multiple of // 'ts') -- webb. - if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || lcs_tab1)) { + if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) { col += win_lbr_chartabsize(wp, line, s, col, NULL) - 1; } diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 22f5497f1e..48fd765e1b 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -731,7 +731,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col) } else { if (!(row > 0 && ptr == ptr_row_offset) && (wp->w_p_cole == 1 || (wp->w_p_cole == 2 - && (lcs_conceal != NUL + && (wp->w_p_lcs_chars.conceal != NUL || syn_get_sub_char() != NUL)))) { // At least one placeholder character will be displayed. decr(); diff --git a/src/nvim/option.c b/src/nvim/option.c index 6b1c5c998f..e153653480 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2121,10 +2121,10 @@ static void didset_options2(void) (void)opt_strings_flags(p_cb, p_cb_values, &cb_flags, true); // Parse default for 'fillchars'. - (void)set_chars_option(&p_fcs); + (void)set_chars_option(curwin, &curwin->w_p_fcs); // Parse default for 'listchars'. - (void)set_chars_option(&p_lcs); + (void)set_chars_option(curwin, &curwin->w_p_lcs); // Parse default for 'wildmode'. check_opt_wim(); @@ -2567,10 +2567,19 @@ did_set_string_option ( // 'ambiwidth' if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) { errmsg = e_invarg; - } else if (set_chars_option(&p_lcs) != NULL) { - errmsg = (char_u *)_("E834: Conflicts with value of 'listchars'"); - } else if (set_chars_option(&p_fcs) != NULL) { - errmsg = (char_u *)_("E835: Conflicts with value of 'fillchars'"); + } else { + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (set_chars_option(wp, &wp->w_p_lcs) != NULL) { + errmsg = (char_u *)_("E834: Conflicts with value of 'listchars'"); + goto ambw_end; + } + if (set_chars_option(wp, &wp->w_p_fcs) != NULL) { + errmsg = (char_u *)_("E835: Conflicts with value of 'fillchars'"); + goto ambw_end; + } + } +ambw_end: + {} // clint prefers {} over ; as an empty statement } } /* 'background' */ @@ -2756,14 +2765,10 @@ did_set_string_option ( } s = skip_to_option_part(s); } - } - /* 'listchars' */ - else if (varp == &p_lcs) { - errmsg = set_chars_option(varp); - } - /* 'fillchars' */ - else if (varp == &p_fcs) { - errmsg = set_chars_option(varp); + } else if (varp == &curwin->w_p_lcs) { // 'listchars' + errmsg = set_chars_option(curwin, varp); + } else if (varp == &curwin->w_p_fcs) { // 'fillchars' + errmsg = set_chars_option(curwin, varp); } /* 'cedit' */ else if (varp == &p_cedit) { @@ -3394,53 +3399,55 @@ skip: /// Handle setting 'listchars' or 'fillchars'. /// Assume monocell characters /// -/// @param varp either &p_lcs ('listchars') or &p_fcs ('fillchar') +/// @param varp either &curwin->w_p_lcs or &curwin->w_p_fcs /// @return error message, NULL if it's OK. -static char_u *set_chars_option(char_u **varp) +static char_u *set_chars_option(win_T *wp, char_u **varp) { int round, i, len, entries; - char_u *p, *s; + char_u *p, *s; int c1, c2 = 0; - struct charstab { + + struct chars_tab { int *cp; ///< char value char *name; ///< char id int def; ///< default value }; - static struct charstab filltab[] = { - { &fill_stl, "stl" , ' ' }, - { &fill_stlnc, "stlnc", ' ' }, - { &fill_vert, "vert" , 9474 }, // │ - { &fill_fold, "fold" , 183 }, // · - { &fill_diff, "diff" , '-' }, - { &fill_msgsep, "msgsep", ' ' }, - { &fill_eob, "eob", '~' }, + struct chars_tab *tab; + + struct chars_tab fcs_tab[] = { + { &wp->w_p_fcs_chars.stl, "stl", ' ' }, + { &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' }, + { &wp->w_p_fcs_chars.vert, "vert", 9474 }, // │ + { &wp->w_p_fcs_chars.fold, "fold", 183 }, // · + { &wp->w_p_fcs_chars.diff, "diff", '-' }, + { &wp->w_p_fcs_chars.msgsep, "msgsep", ' ' }, + { &wp->w_p_fcs_chars.eob, "eob", '~' }, }; - static struct charstab lcstab[] = { - { &lcs_eol, "eol", NUL }, - { &lcs_ext, "extends", NUL }, - { &lcs_nbsp, "nbsp", NUL }, - { &lcs_prec, "precedes", NUL }, - { &lcs_space, "space", NUL }, - { &lcs_tab2, "tab", NUL }, - { &lcs_trail, "trail", NUL }, - { &lcs_conceal, "conceal", NUL }, + struct chars_tab lcs_tab[] = { + { &wp->w_p_lcs_chars.eol, "eol", NUL }, + { &wp->w_p_lcs_chars.ext, "extends", NUL }, + { &wp->w_p_lcs_chars.nbsp, "nbsp", NUL }, + { &wp->w_p_lcs_chars.prec, "precedes", NUL }, + { &wp->w_p_lcs_chars.space, "space", NUL }, + { &wp->w_p_lcs_chars.tab2, "tab", NUL }, + { &wp->w_p_lcs_chars.trail, "trail", NUL }, + { &wp->w_p_lcs_chars.conceal, "conceal", NUL }, }; - struct charstab *tab; - if (varp == &p_lcs) { - tab = lcstab; - entries = ARRAY_SIZE(lcstab); + if (varp == &wp->w_p_lcs) { + tab = lcs_tab; + entries = ARRAY_SIZE(lcs_tab); } else { - tab = filltab; - entries = ARRAY_SIZE(filltab); + tab = fcs_tab; + entries = ARRAY_SIZE(fcs_tab); if (*p_ambw == 'd') { // XXX: If ambiwidth=double then "|" and "·" take 2 columns, which is // forbidden (TUI limitation?). Set old defaults. - filltab[2].def = '|'; - filltab[3].def = '-'; + fcs_tab[2].def = '|'; + fcs_tab[3].def = '-'; } else { - filltab[2].def = 9474; // │ - filltab[3].def = 183; // · + fcs_tab[2].def = 9474; // │ + fcs_tab[3].def = 183; // · } } @@ -3453,8 +3460,8 @@ static char_u *set_chars_option(char_u **varp) *(tab[i].cp) = tab[i].def; } } - if (varp == &p_lcs) { - lcs_tab1 = NUL; + if (varp == &wp->w_p_lcs) { + wp->w_p_lcs_chars.tab1 = NUL; } } p = *varp; @@ -3472,7 +3479,7 @@ static char_u *set_chars_option(char_u **varp) if (mb_char2cells(c1) > 1 || (c1len == 1 && c1 > 127)) { continue; } - if (tab[i].cp == &lcs_tab2) { + if (tab[i].cp == &wp->w_p_lcs_chars.tab2) { if (*s == NUL) { continue; } @@ -3484,9 +3491,9 @@ static char_u *set_chars_option(char_u **varp) } if (*s == ',' || *s == NUL) { if (round) { - if (tab[i].cp == &lcs_tab2) { - lcs_tab1 = c1; - lcs_tab2 = c2; + if (tab[i].cp == &wp->w_p_lcs_chars.tab2) { + wp->w_p_lcs_chars.tab1 = c1; + wp->w_p_lcs_chars.tab2 = c2; } else if (tab[i].cp != NULL) *(tab[i].cp) = c1; @@ -5613,6 +5620,8 @@ static char_u *get_varp(vimoption_T *p) case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap); case PV_SCL: return (char_u *)&(curwin->w_p_scl); case PV_WINHL: return (char_u *)&(curwin->w_p_winhl); + case PV_FCS: return (char_u *)&(curwin->w_p_fcs); + case PV_LCS: return (char_u *)&(curwin->w_p_lcs); default: IEMSG(_("E356: get_varp ERROR")); } /* always return a valid pointer to avoid a crash! */ @@ -5691,6 +5700,8 @@ void copy_winopt(winopt_T *from, winopt_T *to) to->wo_fmr = vim_strsave(from->wo_fmr); to->wo_scl = vim_strsave(from->wo_scl); to->wo_winhl = vim_strsave(from->wo_winhl); + to->wo_fcs = vim_strsave(from->wo_fcs); + to->wo_lcs = vim_strsave(from->wo_lcs); check_winopt(to); // don't want NULL pointers } @@ -5721,6 +5732,8 @@ static void check_winopt(winopt_T *wop) check_string_option(&wop->wo_cocu); check_string_option(&wop->wo_briopt); check_string_option(&wop->wo_winhl); + check_string_option(&wop->wo_fcs); + check_string_option(&wop->wo_lcs); } /* @@ -5741,12 +5754,16 @@ void clear_winopt(winopt_T *wop) clear_string_option(&wop->wo_cocu); clear_string_option(&wop->wo_briopt); clear_string_option(&wop->wo_winhl); + clear_string_option(&wop->wo_fcs); + clear_string_option(&wop->wo_lcs); } void didset_window_options(win_T *wp) { check_colorcolumn(wp); briopt_check(wp); + set_chars_option(wp, &wp->w_p_fcs); + set_chars_option(wp, &wp->w_p_lcs); parse_winhl_opt(wp); } diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 7b99b6f266..c80de4d46b 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -486,7 +486,6 @@ EXTERN long *p_linespace; // 'linespace' EXTERN char_u *p_lispwords; // 'lispwords' EXTERN long p_ls; // 'laststatus' EXTERN long p_stal; // 'showtabline' -EXTERN char_u *p_lcs; // 'listchars' EXTERN int p_lz; // 'lazyredraw' EXTERN int p_lpl; // 'loadplugins' @@ -638,7 +637,6 @@ EXTERN long p_ul; ///< 'undolevels' EXTERN long p_ur; ///< 'undoreload' EXTERN long p_uc; ///< 'updatecount' EXTERN long p_ut; ///< 'updatetime' -EXTERN char_u *p_fcs; ///< 'fillchar' EXTERN char_u *p_shada; ///< 'shada' EXTERN char_u *p_vdir; ///< 'viewdir' EXTERN char_u *p_vop; ///< 'viewoptions' @@ -814,6 +812,8 @@ enum { , WV_WRAP , WV_SCL , WV_WINHL + , WV_FCS + , WV_LCS , WV_COUNT // must be the last one }; diff --git a/src/nvim/options.lua b/src/nvim/options.lua index aba8f8b893..c3aff87bbf 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -806,11 +806,11 @@ return { }, { full_name='fillchars', abbreviation='fcs', - type='string', list='onecomma', scope={'global'}, + type='string', list='onecomma', scope={'window'}, deny_duplicates=true, vi_def=true, - redraw={'all_windows'}, - varname='p_fcs', + alloced=true, + redraw={'current_window'}, defaults={if_true={vi=''}} }, { @@ -1425,11 +1425,11 @@ return { }, { full_name='listchars', abbreviation='lcs', - type='string', list='onecomma', scope={'global'}, + type='string', list='onecomma', scope={'window'}, deny_duplicates=true, vim=true, - redraw={'all_windows'}, - varname='p_lcs', + alloced=true, + redraw={'current_window'}, defaults={if_true={vi="eol:$", vim="tab:> ,trail:-,nbsp:+"}} }, { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 2467cf192f..06c21f0e53 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -1451,10 +1451,10 @@ static void win_update(win_T *wp) /* * Display filler lines at the end of the file */ - if (char2cells(fill_diff) > 1) + if (char2cells(wp->w_p_fcs_chars.diff) > 1) i = '-'; else - i = fill_diff; + i = wp->w_p_fcs_chars.diff; if (row + j > wp->w_grid.Rows) { j = wp->w_grid.Rows - row; } @@ -1465,8 +1465,8 @@ static void win_update(win_T *wp) wp->w_botline = lnum; // make sure the rest of the screen is blank - // write the 'fill_eob' character to rows that aren't part of the file. - win_draw_end(wp, fill_eob, ' ', row, wp->w_grid.Rows, HLF_EOB); + // write the 'eob' character to rows that aren't part of the file. + win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', row, wp->w_grid.Rows, HLF_EOB); } if (wp->w_redr_type >= REDRAW_TOP) { @@ -1817,7 +1817,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T txtcol = col; /* remember where text starts */ - // 5. move the text to linebuf_char[off]. Fill up with "fill_fold". + // 5. move the text to linebuf_char[off]. Fill up with "fold". // Right-left text is put in columns 0 - number-col, normal text is put // in columns number-col - window-width. int idx; @@ -1849,7 +1849,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T col -= txtcol; schar_T sc; - schar_from_char(sc, fill_fold); + schar_from_char(sc, wp->w_p_fcs_chars.fold); while (col < wp->w_grid.Columns - (wp->w_p_rl ? txtcol : 0) ) { @@ -2057,10 +2057,10 @@ win_line ( char_u *p_extra_free = NULL; /* p_extra needs to be freed */ int c_extra = NUL; /* extra chars, all the same */ int extra_attr = 0; /* attributes when n_extra != 0 */ - static char_u *at_end_str = (char_u *)""; /* used for p_extra when - displaying lcs_eol at end-of-line */ - int lcs_eol_one = lcs_eol; /* lcs_eol until it's been used */ - int lcs_prec_todo = lcs_prec; /* lcs_prec until it's been used */ + static char_u *at_end_str = (char_u *)""; // used for p_extra when displaying + // curwin->w_p_lcs_chars.eol at end-of-line + int lcs_eol_one = wp->w_p_lcs_chars.eol; // 'eol' until it's been used + int lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used /* saved "extra" items for when draw_state becomes WL_LINE (again) */ int saved_n_extra = 0; @@ -2432,11 +2432,11 @@ win_line ( } if (wp->w_p_list) { - if (lcs_space || lcs_trail) { + if (curwin->w_p_lcs_chars.space || wp->w_p_lcs_chars.trail) { extra_check = true; } // find start of trailing whitespace - if (lcs_trail) { + if (wp->w_p_lcs_chars.trail) { trailcol = (colnr_T)STRLEN(ptr); while (trailcol > (colnr_T)0 && ascii_iswhite(ptr[trailcol - 1])) { trailcol--; @@ -2793,10 +2793,10 @@ win_line ( draw_state = WL_SBR; if (filler_todo > 0) { /* Draw "deleted" diff line(s). */ - if (char2cells(fill_diff) > 1) + if (char2cells(wp->w_p_fcs_chars.diff) > 1) c_extra = '-'; else - c_extra = fill_diff; + c_extra = wp->w_p_fcs_chars.diff; if (wp->w_p_rl) { n_extra = col + 1; } else { @@ -3401,13 +3401,13 @@ win_line ( } } - // 'list': change char 160 to lcs_nbsp and space to lcs_space. + // 'list': change char 160 to 'nbsp' and space to 'space'. if (wp->w_p_list && (((c == 160 || (mb_utf8 && (mb_c == 160 || mb_c == 0x202f))) - && lcs_nbsp) - || (c == ' ' && lcs_space && ptr - line <= trailcol))) { - c = (c == ' ') ? lcs_space : lcs_nbsp; + && curwin->w_p_lcs_chars.nbsp) + || (c == ' ' && curwin->w_p_lcs_chars.space && ptr - line <= trailcol))) { + c = (c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp; n_attr = 1; extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr @@ -3422,7 +3422,7 @@ win_line ( } if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') { - c = lcs_trail; + c = wp->w_p_lcs_chars.trail; n_attr = 1; extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr @@ -3443,7 +3443,7 @@ win_line ( if (!vim_isprintc(c)) { // when getting a character from the file, we may have to // turn it into something else on the way to putting it on the screen. - if (c == TAB && (!wp->w_p_list || lcs_tab1)) { + if (c == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) { int tab_len = 0; long vcol_adjusted = vcol; // removed showbreak length // Only adjust the tab_len, when at the first column after the @@ -3467,26 +3467,26 @@ win_line ( tab_len += vcol_off; } // boguscols before FIX_FOR_BOGUSCOLS macro from above. - if (lcs_tab1 && old_boguscols > 0 && n_extra > tab_len) { + if (wp->w_p_lcs_chars.tab1 && old_boguscols > 0 && n_extra > tab_len) { tab_len += n_extra - tab_len; } /* if n_extra > 0, it gives the number of chars to use for * a tab, else we need to calculate the width for a tab */ - int len = (tab_len * mb_char2len(lcs_tab2)); + int len = (tab_len * mb_char2len(wp->w_p_lcs_chars.tab2)); if (n_extra > 0) { len += n_extra - tab_len; } - c = lcs_tab1; + c = wp->w_p_lcs_chars.tab1; p = xmalloc(len + 1); memset(p, ' ', len); p[len] = NUL; xfree(p_extra_free); p_extra_free = p; for (i = 0; i < tab_len; i++) { - utf_char2bytes(lcs_tab2, p); - p += mb_char2len(lcs_tab2); - n_extra += mb_char2len(lcs_tab2) - (saved_nextra > 0 ? 1: 0); + utf_char2bytes(wp->w_p_lcs_chars.tab2, p); + p += mb_char2len(wp->w_p_lcs_chars.tab2); + n_extra += mb_char2len(wp->w_p_lcs_chars.tab2) - (saved_nextra > 0 ? 1: 0); } p_extra = p_extra_free; @@ -3511,18 +3511,18 @@ win_line ( // Make sure, the highlighting for the tab char will be // correctly set further below (effectively reverts the // FIX_FOR_BOGSUCOLS macro. - if (n_extra == tab_len + vc_saved && wp->w_p_list && lcs_tab1) { + if (n_extra == tab_len + vc_saved && wp->w_p_list && wp->w_p_lcs_chars.tab1) { tab_len += vc_saved; } } mb_utf8 = false; // don't draw as UTF-8 if (wp->w_p_list) { - c = lcs_tab1; + c = wp->w_p_lcs_chars.tab1; if (wp->w_p_lbr) { c_extra = NUL; /* using p_extra from above */ } else { - c_extra = lcs_tab2; + c_extra = wp->w_p_lcs_chars.tab2; } n_attr = tab_len + 1; extra_attr = win_hl_attr(wp, HLF_0); @@ -3563,8 +3563,8 @@ win_line ( c_extra = NUL; } } - if (wp->w_p_list && lcs_eol > 0) { - c = lcs_eol; + if (wp->w_p_list && wp->w_p_lcs_chars.eol > 0) { + c = wp->w_p_lcs_chars.eol; } else { c = ' '; } @@ -3634,8 +3634,8 @@ win_line ( c = match_conc; } else if (syn_get_sub_char() != NUL) { c = syn_get_sub_char(); - } else if (lcs_conceal != NUL) { - c = lcs_conceal; + } else if (wp->w_p_lcs_chars.conceal != NUL) { + c = wp->w_p_lcs_chars.conceal; } else { c = ' '; } @@ -3705,7 +3705,7 @@ win_line ( && filler_todo <= 0 && draw_state > WL_NR && c != NUL) { - c = lcs_prec; + c = wp->w_p_lcs_chars.prec; lcs_prec_todo = NUL; if (has_mbyte && (*mb_char2cells)(mb_c) > 1) { /* Double-width character being overwritten by the "precedes" @@ -3755,7 +3755,7 @@ win_line ( cur = cur->next; } } - if (lcs_eol == lcs_eol_one + if (wp->w_p_lcs_chars.eol == lcs_eol_one && ((area_attr != 0 && vcol == fromcol && (VIsual_mode != Ctrl_V || lnum == VIsual.lnum @@ -3858,7 +3858,7 @@ win_line ( // Make sure alignment is the same regardless // if listchars=eol:X is used or not. - bool delay_virttext = lcs_eol == lcs_eol_one && eol_hl_off == 0; + bool delay_virttext = wp->w_p_lcs_chars.eol == lcs_eol_one && eol_hl_off == 0; if (wp->w_p_cuc) { rightmost_vcol = wp->w_virtcol; @@ -3979,14 +3979,14 @@ win_line ( } /* line continues beyond line end */ - if (lcs_ext + if (wp->w_p_lcs_chars.ext && !wp->w_p_wrap && filler_todo <= 0 && (wp->w_p_rl ? col == 0 : col == grid->Columns - 1) && (*ptr != NUL || (wp->w_p_list && lcs_eol_one > 0) || (n_extra && (c_extra != NUL || *p_extra != NUL)))) { - c = lcs_ext; + c = wp->w_p_lcs_chars.ext; char_attr = win_hl_attr(wp, HLF_AT); mb_c = c; if (enc_utf8 && utf_char2len(c) > 1) { @@ -4164,7 +4164,7 @@ win_line ( if ((wp->w_p_rl ? (col < 0) : (col >= grid->Columns)) && (*ptr != NUL || filler_todo > 0 - || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str) + || (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL && p_extra != at_end_str) || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) ) { bool wrap = wp->w_p_wrap // Wrapping enabled. @@ -4226,7 +4226,7 @@ win_line ( saved_c_extra = c_extra; saved_char_attr = char_attr; n_extra = 0; - lcs_prec_todo = lcs_prec; + lcs_prec_todo = wp->w_p_lcs_chars.prec; if (filler_todo <= 0) need_showbreak = TRUE; --filler_todo; @@ -6849,17 +6849,17 @@ static int fillchar_status(int *attr, win_T *wp) bool is_curwin = (wp == curwin); if (is_curwin) { *attr = win_hl_attr(wp, HLF_S); - fill = fill_stl; + fill = wp->w_p_fcs_chars.stl; } else { *attr = win_hl_attr(wp, HLF_SNC); - fill = fill_stlnc; + fill = wp->w_p_fcs_chars.stlnc; } /* Use fill when there is highlighting, and highlighting of current * window differs, or the fillchars differ, or this is not the * current window */ if (*attr != 0 && ((win_hl_attr(wp, HLF_S) != win_hl_attr(wp, HLF_SNC) || !is_curwin || ONE_WINDOW) - || (fill_stl != fill_stlnc))) { + || (wp->w_p_fcs_chars.stl != wp->w_p_fcs_chars.stlnc))) { return fill; } if (is_curwin) { @@ -6875,7 +6875,7 @@ static int fillchar_status(int *attr, win_T *wp) static int fillchar_vsep(win_T *wp, int *attr) { *attr = win_hl_attr(wp, HLF_C); - return fill_vert; + return wp->w_p_fcs_chars.vert; } /* @@ -7003,7 +7003,7 @@ static void win_redr_ruler(win_T *wp, int always) /* In list mode virtcol needs to be recomputed */ colnr_T virtcol = wp->w_virtcol; - if (wp->w_p_list && lcs_tab1 == NUL) { + if (wp->w_p_list && wp->w_p_lcs_chars.tab1 == NUL) { wp->w_p_list = FALSE; getvvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL); wp->w_p_list = TRUE; |