diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 3bc248c795..f924003e1f 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2393,6 +2393,7 @@ A jump table for the options with a short description can be found at |Q_op|. fold:c '·' or '-' filling 'foldtext' diff:c '-' deleted lines of the 'diff' option msgsep:c ' ' message separator 'display' + eob:c '~' empty lines at the end of a buffer Any one that is omitted will fall back to the default. For "stl" and "stlnc" the space will be used when there is highlighting, '^' or '=' @@ -2415,6 +2416,7 @@ A jump table for the options with a short description can be found at |Q_op|. vert:c VertSplit |hl-VertSplit| fold:c Folded |hl-Folded| diff:c DiffDelete |hl-DiffDelete| + eob:c EndOfBuffer |hl-EndOfBuffer| *'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'* 'fixendofline' 'fixeol' boolean (default on) diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 9dd03079fe..5394414947 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -180,7 +180,8 @@ Options: 'cpoptions' flags: |cpo-_| 'display' flag `msgsep` to minimize scrolling when showing messages 'guicursor' works in the terminal - 'fillchars' flag `msgsep` (see 'display' above) + 'fillchars' flags: `msgsep` (see 'display' above) + and `eob` for |EndOfBuffer| marker 'inccommand' shows interactive results for |:substitute|-like commands 'scrollback' 'statusline' supports unlimited alignment sections diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 20e5353b51..f5ebaa9753 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -908,6 +908,7 @@ 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); diff --git a/src/nvim/option.c b/src/nvim/option.c index a7ee0ef28b..e65798e57a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3386,6 +3386,7 @@ static char_u *set_chars_option(char_u **varp) { &fill_fold, "fold" , 183 }, // · { &fill_diff, "diff" , '-' }, { &fill_msgsep, "msgsep", ' ' }, + { &fill_eob, "eob", '~' }, }; static struct charstab lcstab[] = { { &lcs_eol, "eol", NUL }, @@ -3437,16 +3438,20 @@ static char_u *set_chars_option(char_u **varp) && p[len] == ':' && p[len + 1] != NUL) { s = p + len + 1; - c1 = mb_ptr2char_adv((const char_u **)&s); - if (mb_char2cells(c1) > 1) { + + // TODO(bfredl): use schar_T representation and utfc_ptr2len + int c1len = utf_ptr2len(s); + c1 = mb_cptr2char_adv((const char_u **)&s); + if (mb_char2cells(c1) > 1 || (c1len == 1 && c1 > 127)) { continue; } if (tab[i].cp == &lcs_tab2) { if (*s == NUL) { continue; } - c2 = mb_ptr2char_adv((const char_u **)&s); - if (mb_char2cells(c2) > 1) { + int c2len = utf_ptr2len(s); + c2 = mb_cptr2char_adv((const char_u **)&s); + if (mb_char2cells(c2) > 1 || (c2len == 1 && c2 > 127)) { continue; } } diff --git a/src/nvim/screen.c b/src/nvim/screen.c index cf9a72715b..80f7a32c07 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -1532,9 +1532,9 @@ static void win_update(win_T *wp) } else if (dollar_vcol == -1) wp->w_botline = lnum; - /* make sure the rest of the screen is blank */ - /* put '~'s on rows that aren't part of the file. */ - win_draw_end(wp, '~', ' ', row, wp->w_height, HLF_EOB); + // 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_height, HLF_EOB); } /* Reset the type of redrawing required, the window has been updated. */ diff --git a/test/functional/options/fillchars_spec.lua b/test/functional/options/fillchars_spec.lua new file mode 100644 index 0000000000..ab61935d4c --- /dev/null +++ b/test/functional/options/fillchars_spec.lua @@ -0,0 +1,66 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear, command = helpers.clear, helpers.command +local eval = helpers.eval +local eq = helpers.eq +local exc_exec = helpers.exc_exec + +describe("'fillchars'", function() + local screen + + before_each(function() + clear() + screen = Screen.new(25, 5) + screen:attach() + end) + + after_each(function() + screen:detach() + end) + + local function shouldfail(val,errval) + errval = errval or val + eq('Vim(set):E474: Invalid argument: fillchars='..errval, + exc_exec('set fillchars='..val)) + end + + describe('"eob" flag', function() + it("uses '~' by default", function() + eq('', eval('&fillchars')) + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]]) + end) + it('supports whitespace', function() + command('set fillchars=eob:\\ ') + screen:expect([[ + ^ | + | + | + | + | + ]]) + end) + it('supports multibyte char', function() + command('set fillchars=eob:ñ') + screen:expect([[ + ^ | + ñ | + ñ | + ñ | + | + ]]) + end) + it('handles invalid values', function() + shouldfail('eob:') -- empty string + shouldfail('eob:馬') -- doublewidth char + shouldfail('eob:å̲') -- composing chars + shouldfail('eob:xy') -- two ascii chars + shouldfail('eob:\255', 'eob:') -- invalid UTF-8 + end) + end) +end)