diff options
author | Josh Rahm <rahm@google.com> | 2022-07-18 19:37:18 +0000 |
---|---|---|
committer | Josh Rahm <rahm@google.com> | 2022-07-18 19:37:18 +0000 |
commit | 308e1940dcd64aa6c344c403d4f9e0dda58d9c5c (patch) | |
tree | 35fe43e01755e0f312650667004487a44d6b7941 /test/functional/ui | |
parent | 96a00c7c588b2f38a2424aeeb4ea3581d370bf2d (diff) | |
parent | e8c94697bcbe23a5c7b07c292b90a6b70aadfa87 (diff) | |
download | rneovim-308e1940dcd64aa6c344c403d4f9e0dda58d9c5c.tar.gz rneovim-308e1940dcd64aa6c344c403d4f9e0dda58d9c5c.tar.bz2 rneovim-308e1940dcd64aa6c344c403d4f9e0dda58d9c5c.zip |
Merge remote-tracking branch 'upstream/master' into rahm
Diffstat (limited to 'test/functional/ui')
29 files changed, 6680 insertions, 1481 deletions
diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua index 16ed3b9486..7c0831bd09 100644 --- a/test/functional/ui/bufhl_spec.lua +++ b/test/functional/ui/bufhl_spec.lua @@ -564,6 +564,16 @@ describe('Buffer highlighting', function() ]] clear_namespace(id, 0, -1) + screen:expect{grid=[[ + fooba^r | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} set_extmark(id, 0, 0, { end_line = 0, @@ -755,12 +765,26 @@ describe('Buffer highlighting', function() -- TODO: only a virtual text from the same ns curretly overrides -- an existing virtual text. We might add a prioritation system. set_virtual_text(id1, 0, s1, {}) - eq({{1, 0, 0, { priority = 0, virt_text = s1}}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true})) + eq({{1, 0, 0, { + priority = 0, + virt_text = s1, + -- other details + right_gravity = true, + virt_text_pos = 'eol', + virt_text_hide = false, + }}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true})) -- TODO: is this really valid? shouldn't the max be line_count()-1? local lastline = line_count() set_virtual_text(id1, line_count(), s2, {}) - eq({{3, lastline, 0, { priority = 0, virt_text = s2}}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true})) + eq({{3, lastline, 0, { + priority = 0, + virt_text = s2, + -- other details + right_gravity = true, + virt_text_pos = 'eol', + virt_text_hide = false, + }}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true})) eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {})) end) diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua index 9c746b99bd..384761ab17 100644 --- a/test/functional/ui/cmdline_highlight_spec.lua +++ b/test/functional/ui/cmdline_highlight_spec.lua @@ -33,7 +33,7 @@ before_each(function() let g:NUM_LVLS = 4 function Redraw() mode - return '' + return "\<Ignore>" endfunction let g:id = '' cnoremap <expr> {REDRAW} Redraw() @@ -42,7 +42,7 @@ before_each(function() let Cb = g:Nvim_color_input{g:id} let out = input({'prompt': ':', 'highlight': Cb}) let g:out{id} = out - return (a:do_return ? out : '') + return (a:do_return ? out : "\<Ignore>") endfunction nnoremap <expr> {PROMPT} DoPrompt(0) cnoremap <expr> {PROMPT} DoPrompt(1) @@ -410,7 +410,7 @@ describe('Command-line coloring', function() end) it('stops executing callback after a number of errors', function() set_color_cb('SplittedMultibyteStart') - start_prompt('let x = "«»«»«»«»«»"\n') + start_prompt('let x = "«»«»«»«»«»"') screen:expect([[ {EOB:~ }| {EOB:~ }| @@ -419,7 +419,7 @@ describe('Command-line coloring', function() :let x = " | {ERR:E5405: Chunk 0 start 10 splits multibyte}| {ERR: character} | - ^:let x = "«»«»«»«»«»" | + :let x = "«»«»«»«»«»"^ | ]]) feed('\n') screen:expect([[ @@ -432,6 +432,7 @@ describe('Command-line coloring', function() {EOB:~ }| | ]]) + feed('\n') eq('let x = "«»«»«»«»«»"', meths.get_var('out')) local msg = '\nE5405: Chunk 0 start 10 splits multibyte character' eq(msg:rep(1), funcs.execute('messages')) @@ -474,14 +475,14 @@ describe('Command-line coloring', function() ]]) feed('\n') screen:expect([[ - | + ^ | {EOB:~ }| {EOB:~ }| {EOB:~ }| {EOB:~ }| {EOB:~ }| {EOB:~ }| - ^:echo 42 | + :echo 42 | ]]) feed('\n') eq('echo 42', meths.get_var('out')) diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index ad23402ff9..eb0a14da31 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -4,6 +4,9 @@ local clear, feed = helpers.clear, helpers.feed local source = helpers.source local command = helpers.command local assert_alive = helpers.assert_alive +local uname = helpers.uname +local eval = helpers.eval +local eq = helpers.eq local function new_screen(opt) local screen = Screen.new(25, 5) @@ -16,6 +19,8 @@ local function new_screen(opt) [5] = {bold = true, foreground = Screen.colors.SeaGreen4}, [6] = {foreground = Screen.colors.Magenta}, [7] = {bold = true, foreground = Screen.colors.Brown}, + [8] = {background = Screen.colors.LightGrey}, + [9] = {bold = true}, }) return screen end @@ -824,7 +829,7 @@ describe('cmdline redraw', function() end) it('with <Cmd>', function() - if 'openbsd' == helpers.uname() then + if string.find(uname(), 'bsd') then pending('FIXME #10804') end command('cmap a <Cmd>call sin(0)<CR>') -- no-op @@ -845,6 +850,37 @@ describe('cmdline redraw', function() 456789^ | ]], unchanged=true} end) + + it('after pressing Ctrl-C in cmdwin in Visual mode #18967', function() + screen:try_resize(40, 10) + command('set cmdwinheight=3') + feed('q:iabc<Esc>vhh') + screen:expect([[ + | + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] }| + {1::}^a{8:bc} | + {1:~ }| + {1:~ }| + {3:[Command Line] }| + {9:-- VISUAL --} | + ]]) + feed('<C-C>') + screen:expect([[ + | + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] }| + {1::}a{8:bc} | + {1:~ }| + {1:~ }| + {3:[Command Line] }| + :^abc | + ]]) + end) end) describe("cmdline height", function() @@ -857,3 +893,228 @@ describe("cmdline height", function() assert_alive() end) end) + +describe('cmdheight=0', function() + local screen + before_each(function() + clear() + screen = Screen.new(25, 5) + screen:attach() + end) + + it("with cmdheight=1 noruler laststatus=2", function() + command("set cmdheight=1 noruler laststatus=2") + screen:expect{grid=[[ + ^ | + ~ | + ~ | + [No Name] | + | + ]]} + end) + + it("with cmdheight=0 noruler laststatus=2", function() + command("set cmdheight=0 noruler laststatus=2") + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + [No Name] | + ]]} + end) + + it("with cmdheight=0 ruler laststatus=0", function() + command("set cmdheight=0 ruler laststatus=0") + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + ~ | + ]]} + end) + + it("with cmdheight=0 ruler laststatus=0", function() + command("set cmdheight=0 noruler laststatus=0 showmode") + feed('i') + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + ~ | + ]], showmode={}} + feed('<Esc>') + eq(0, eval('&cmdheight')) + end) + + it("with cmdheight=0 ruler rulerformat laststatus=0", function() + command("set cmdheight=0 noruler laststatus=0 rulerformat=%l,%c%= showmode") + feed('i') + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + ~ | + ]], showmode={}} + feed('<Esc>') + eq(0, eval('&cmdheight')) + end) + + it("with showmode", function() + command("set cmdheight=1 noruler laststatus=0 showmode") + feed('i') + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + -- INSERT -- | + ]]} + feed('<Esc>') + eq(1, eval('&cmdheight')) + end) + + it("when using command line", function() + command("set cmdheight=0 noruler laststatus=0") + feed(':') + screen:expect{grid=[[ + | + ~ | + ~ | + ~ | + :^ | + ]]} + eq(1, eval('&cmdheight')) + feed('<cr>') + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + ~ | + ]], showmode={}} + eq(0, eval('&cmdheight')) + end) + + it("when using input()", function() + command("set cmdheight=0 noruler laststatus=0") + feed(':call input("foo >")<cr>') + screen:expect{grid=[[ + | + ~ | + ~ | + ~ | + foo >^ | + ]]} + eq(1, eval('&cmdheight')) + feed('<cr>') + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + ~ | + ]], showmode={}} + eq(0, eval('&cmdheight')) + end) + + it("with winbar and splits", function() + command("set cmdheight=0 noruler laststatus=3 winbar=foo") + feed(':split<CR>') + screen:expect{grid=[[ + foo | + | + E36: Not enough room | + Press ENTER or type comma| + nd to continue^ | + ]]} + feed('<CR>') + screen:expect{grid=[[ + foo | + ^ | + ~ | + ~ | + [No Name] | + ]]} + feed(':') + screen:expect{grid=[[ + foo | + | + ~ | + [No Name] | + :^ | + ]]} + feed('<Esc>') + screen:expect{grid=[[ + foo | + ^ | + ~ | + ~ | + [No Name] | + ]], showmode={}} + eq(0, eval('&cmdheight')) + + assert_alive() + end) + + it("when macro with lastline", function() + command("set cmdheight=0 display=lastline") + feed('qq') + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + ~ | + ]], showmode={}} + feed('q') + screen:expect{grid=[[ + ^ | + ~ | + ~ | + ~ | + ~ | + ]], showmode={}} + end) + + it("when substitute text", function() + command("set cmdheight=0 noruler laststatus=3") + feed('ifoo<ESC>') + screen:expect{grid=[[ + fo^o | + ~ | + ~ | + ~ | + [No Name] [+] | + ]]} + + feed(':%s/foo/bar/gc<CR>') + screen:expect{grid=[[ + foo | + ~ | + ~ | + [No Name] [+] | + replace wi...q/l/^E/^Y)?^ | + ]]} + + feed('y') + screen:expect{grid=[[ + ^bar | + ~ | + ~ | + ~ | + [No Name] [+] | + ]]} + + assert_alive() + end) + + it("when window resize", function() + command("set cmdheight=0") + feed('<C-w>+') + eq(0, eval('&cmdheight')) + end) +end) diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua index 03cd4bfd06..a1423c98a8 100644 --- a/test/functional/ui/cursor_spec.lua +++ b/test/functional/ui/cursor_spec.lua @@ -215,7 +215,7 @@ describe('ui/cursor', function() m.hl_id = 60 m.attr = {background = Screen.colors.DarkGray} end - if m.id_lm then m.id_lm = 61 end + if m.id_lm then m.id_lm = 65 end end -- Assert the new expectation. diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 1575cab591..9af5d386db 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -30,6 +30,7 @@ describe('decorations providers', function() [11] = {foreground = Screen.colors.Red, background = tonumber('0x005028')}; [12] = {foreground = tonumber('0x990000')}; [13] = {background = Screen.colors.LightBlue}; + [14] = {background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue}; } end) @@ -404,6 +405,50 @@ describe('decorations providers', function() | ]]} end) + + it('can create and remove signs when CursorMoved autocommand validates botline #18661', function() + exec_lua([[ + local lines = {} + for i = 1, 200 do + lines[i] = 'hello' .. tostring(i) + end + vim.api.nvim_buf_set_lines(0, 0, -1, false, lines) + ]]) + setup_provider([[ + local function on_do(kind, winid, bufnr, topline, botline_guess) + if kind == 'win' then + if topline < 100 and botline_guess > 100 then + vim.api.nvim_buf_set_extmark(bufnr, ns1, 99, -1, { sign_text = 'X' }) + else + vim.api.nvim_buf_clear_namespace(bufnr, ns1, 0, -1) + end + end + end + ]]) + command([[autocmd CursorMoved * call line('w$')]]) + meths.win_set_cursor(0, {100, 0}) + screen:expect([[ + {14: }hello97 | + {14: }hello98 | + {14: }hello99 | + X ^hello100 | + {14: }hello101 | + {14: }hello102 | + {14: }hello103 | + | + ]]) + meths.win_set_cursor(0, {1, 0}) + screen:expect([[ + ^hello1 | + hello2 | + hello3 | + hello4 | + hello5 | + hello6 | + hello7 | + | + ]]) + end) end) describe('extmark decorations', function() @@ -437,6 +482,8 @@ describe('extmark decorations', function() [22] = {foreground = tonumber('0xb20000'), background = tonumber('0xf13f3f')}; [23] = {foreground = Screen.colors.Magenta1, background = Screen.colors.LightGrey}; [24] = {bold = true}; + [25] = {background = Screen.colors.LightRed}; + [26] = {background=Screen.colors.DarkGrey, foreground=Screen.colors.LightGrey}; } ns = meths.create_namespace 'test' @@ -456,6 +503,31 @@ for _,item in ipairs(items) do end end]] + it('empty virtual text at eol should not break colorcolumn #17860', function() + insert(example_text) + feed('gg') + command('set colorcolumn=40') + screen:expect([[ + ^for _,item in ipairs(items) do {25: } | + local text, hl_id_cell, count = unp{25:a}ck(item) | + if hl_id_cell ~= nil then {25: } | + hl_id = hl_id_cell {25: } | + end {25: } | + for _ = 1, (count or 1) do {25: } | + local cell = line[colpos] {25: } | + cell.text = text {25: } | + cell.hl_id = hl_id {25: } | + colpos = colpos+1 {25: } | + end {25: } | + end {25: } | + {1:~ }| + {1:~ }| + | + ]]) + meths.buf_set_extmark(0, ns, 4, 0, { virt_text={{''}}, virt_text_pos='eol'}) + screen:expect_unchanged() + end) + it('can have virtual text of overlay position', function() insert(example_text) feed 'gg' @@ -471,7 +543,9 @@ end]] -- can "float" beyond end of line meths.buf_set_extmark(0, ns, 5, 28, { virt_text={{'loopy', 'ErrorMsg'}}, virt_text_pos='overlay'}) -- bound check: right edge of window - meths.buf_set_extmark(0, ns, 2, 26, { virt_text={{'bork bork bork ' }, {'bork bork bork', 'ErrorMsg'}}, virt_text_pos='overlay'}) + meths.buf_set_extmark(0, ns, 2, 26, { virt_text={{'bork bork bork '}, {'bork bork bork', 'ErrorMsg'}}, virt_text_pos='overlay'}) + -- empty virt_text should not change anything + meths.buf_set_extmark(0, ns, 6, 16, { virt_text={{''}}, virt_text_pos='overlay'}) screen:expect{grid=[[ ^for _,item in ipairs(items) do | @@ -621,6 +695,8 @@ end]] meths.buf_set_extmark(0, ns, 2, 10, { virt_text={{'Much', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'}) meths.buf_set_extmark(0, ns, 3, 15, { virt_text={{'Error', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'}) meths.buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_win_col=4, hl_mode='blend'}) + -- empty virt_text should not change anything + meths.buf_set_extmark(0, ns, 8, 0, { virt_text={{''}}, virt_text_win_col=14, hl_mode='blend'}) screen:expect{grid=[[ ^for _,item in ipairs(items) do | @@ -698,7 +774,7 @@ end]] ]]} end) - it('can have virtual text which combines foreground and backround groups', function() + it('can have virtual text which combines foreground and background groups', function() screen:set_default_attr_ids { [1] = {bold=true, foreground=Screen.colors.Blue}; [2] = {background = tonumber('0x123456'), foreground = tonumber('0xbbbbbb')}; @@ -789,6 +865,20 @@ end]] ]]} helpers.assert_alive() end) + + it('conceal #19007', function() + screen:try_resize(50, 5) + insert('foo\n') + command('let &conceallevel=2') + meths.buf_set_extmark(0, ns, 0, 0, {end_col=0, end_row=2, conceal='X'}) + screen:expect([[ + {26:X} | + ^ | + {1:~ }| + {1:~ }| + | + ]]) + end) end) describe('decorations: virtual lines', function() @@ -1111,6 +1201,27 @@ if (h->n_buckets < new_n_buckets) { // expand ]]} end) + it('does not cause syntax ml_get error at the end of a buffer #17816', function() + command([[syntax region foo keepend start='^foo' end='^$']]) + command('syntax sync minlines=100') + insert('foo') + meths.buf_set_extmark(0, ns, 0, 0, {virt_lines = {{{'bar', 'Comment'}}}}) + screen:expect([[ + fo^o | + {6:bar} | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end) + it('works with a block scrolling up', function() screen:try_resize(30, 7) insert("aa\nbb\ncc\ndd\nee\nff\ngg\nhh") @@ -1362,3 +1473,372 @@ if (h->n_buckets < new_n_buckets) { // expand end) end) + +describe('decorations: signs', function() + local screen, ns + before_each(function() + clear() + screen = Screen.new(50, 10) + screen:attach() + screen:set_default_attr_ids { + [1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Grey}; + [2] = {foreground = Screen.colors.Blue1, bold = true}; + [3] = {background = Screen.colors.Yellow1, foreground = Screen.colors.Blue1}; + } + + ns = meths.create_namespace 'test' + meths.win_set_option(0, 'signcolumn', 'auto:9') + end) + + local example_text = [[ +l1 +l2 +l3 +l4 +l5 +]] + + it('can add a single sign (no end row)', function() + insert(example_text) + feed 'gg' + + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S'}) + + screen:expect{grid=[[ + {1: }^l1 | + S l2 | + {1: }l3 | + {1: }l4 | + {1: }l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + + end) + + it('can add a single sign (with end row)', function() + insert(example_text) + feed 'gg' + + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row=1}) + + screen:expect{grid=[[ + {1: }^l1 | + S l2 | + {1: }l3 | + {1: }l4 | + {1: }l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + + end) + + it('can add multiple signs (single extmark)', function() + pending('TODO(lewis6991): Support ranged signs') + insert(example_text) + feed 'gg' + + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row = 2}) + + screen:expect{grid=[[ + {1: }^l1 | + S l2 | + S l3 | + {1: }l4 | + {1: }l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + + end) + + it('can add multiple signs (multiple extmarks)', function() + pending('TODO(lewis6991): Support ranged signs') + insert(example_text) + feed'gg' + + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S1'}) + meths.buf_set_extmark(0, ns, 3, -1, {sign_text='S2', end_row = 4}) + + screen:expect{grid=[[ + {1: }^l1 | + S1l2 | + {1: }l3 | + S2l4 | + S2l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + + end) + + it('can add multiple signs (multiple extmarks) 2', function() + insert(example_text) + feed 'gg' + + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S1'}) + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S2'}) + + screen:expect{grid=[[ + {1: }^l1 | + S2S1l2 | + {1: }l3 | + {1: }l4 | + {1: }l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + + -- TODO(lewis6991): Support ranged signs + -- meths.buf_set_extmark(1, ns, 1, -1, {sign_text='S3', end_row = 2}) + + -- screen:expect{grid=[[ + -- {1: }^l1 | + -- S3S2S1l2 | + -- S3{1: }l3 | + -- {1: }l4 | + -- {1: }l5 | + -- {1: } | + -- {2:~ }| + -- {2:~ }| + -- {2:~ }| + -- | + -- ]]} + + end) + + it('can add multiple signs (multiple extmarks) 3', function() + pending('TODO(lewis6991): Support ranged signs') + + insert(example_text) + feed 'gg' + + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S1', end_row=2}) + meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S2', end_row=3}) + + screen:expect{grid=[[ + {1: }^l1 | + S1{1: }l2 | + S2S1l3 | + S2{1: }l4 | + {1: }l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + end) + + it('can add multiple signs (multiple extmarks) 4', function() + insert(example_text) + feed 'gg' + + meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1', end_row=0}) + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S2', end_row=1}) + + screen:expect{grid=[[ + S1^l1 | + S2l2 | + {1: }l3 | + {1: }l4 | + {1: }l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + end) + + it('works with old signs', function() + insert(example_text) + feed 'gg' + + helpers.command('sign define Oldsign text=x') + helpers.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]]) + + meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1'}) + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S2'}) + meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S4'}) + meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'}) + + screen:expect{grid=[[ + S4S1^l1 | + S2x l2 | + S5{1: }l3 | + {1: }l4 | + {1: }l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + end) + + it('works with old signs (with range)', function() + pending('TODO(lewis6991): Support ranged signs') + insert(example_text) + feed 'gg' + + helpers.command('sign define Oldsign text=x') + helpers.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]]) + + meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1'}) + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S2'}) + meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S3', end_row = 4}) + meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S4'}) + meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'}) + + screen:expect{grid=[[ + S3S4S1^l1 | + S2S3x l2 | + S5S3{1: }l3 | + S3{1: }l4 | + S3{1: }l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + end) + + it('can add a ranged sign (with start out of view)', function() + pending('TODO(lewis6991): Support ranged signs') + + insert(example_text) + command 'set signcolumn=yes:2' + feed 'gg' + feed '2<C-e>' + + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='X', end_row=3}) + + screen:expect{grid=[[ + X {1: }^l3 | + X {1: }l4 | + {1: }l5 | + {1: } | + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]} + + end) + + it('can add lots of signs', function() + screen:try_resize(40, 10) + command 'normal 10oa b c d e f g h' + + for i = 1, 10 do + meths.buf_set_extmark(0, ns, i, 0, { end_col = 1, hl_group='Todo' }) + meths.buf_set_extmark(0, ns, i, 2, { end_col = 3, hl_group='Todo' }) + meths.buf_set_extmark(0, ns, i, 4, { end_col = 5, hl_group='Todo' }) + meths.buf_set_extmark(0, ns, i, 6, { end_col = 7, hl_group='Todo' }) + meths.buf_set_extmark(0, ns, i, 8, { end_col = 9, hl_group='Todo' }) + meths.buf_set_extmark(0, ns, i, 10, { end_col = 11, hl_group='Todo' }) + meths.buf_set_extmark(0, ns, i, 12, { end_col = 13, hl_group='Todo' }) + meths.buf_set_extmark(0, ns, i, 14, { end_col = 15, hl_group='Todo' }) + meths.buf_set_extmark(0, ns, i, -1, { sign_text='W' }) + meths.buf_set_extmark(0, ns, i, -1, { sign_text='X' }) + meths.buf_set_extmark(0, ns, i, -1, { sign_text='Y' }) + meths.buf_set_extmark(0, ns, i, -1, { sign_text='Z' }) + end + + screen:expect{grid=[[ + X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} | + X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} | + X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} | + X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} | + X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} | + X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} | + X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} | + X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} | + X Y Z W {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:^h} | + | + ]]} + end) + +end) + +describe('decorations: virt_text', function() + local screen + + before_each(function() + clear() + screen = Screen.new(50, 10) + screen:attach() + screen:set_default_attr_ids { + [1] = {foreground = Screen.colors.Brown}; + [2] = {foreground = Screen.colors.Fuchsia}; + [3] = {bold = true, foreground = Screen.colors.Blue1}; + } + end) + + it('avoids regression in #17638', function() + exec_lua[[ + vim.wo.number = true + vim.wo.relativenumber = true + ]] + + command 'normal 4ohello' + command 'normal aVIRTUAL' + + local ns = meths.create_namespace('test') + + meths.buf_set_extmark(0, ns, 2, 0, { + virt_text = {{"hello", "String"}}, + virt_text_win_col = 20, + }) + + screen:expect{grid=[[ + {1: 4 } | + {1: 3 }hello | + {1: 2 }hello {2:hello} | + {1: 1 }hello | + {1:5 }helloVIRTUA^L | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]} + + -- Trigger a screen update + feed('k') + + screen:expect{grid=[[ + {1: 3 } | + {1: 2 }hello | + {1: 1 }hello {2:hello} | + {1:4 }hell^o | + {1: 1 }helloVIRTUAL | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]} + end) + +end) diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua index bd2692d19a..5d056cd6c3 100644 --- a/test/functional/ui/diff_spec.lua +++ b/test/functional/ui/diff_spec.lua @@ -6,7 +6,7 @@ local clear = helpers.clear local command = helpers.command local insert = helpers.insert local write_file = helpers.write_file -local source = helpers.source +local exec = helpers.exec describe('Diff mode screen', function() local fname = 'Xtest-functional-diff-screen-1' @@ -57,40 +57,40 @@ describe('Diff mode screen', function() feed(':set diffopt=filler<cr>') screen:expect([[ - {1: }{2:------------------}{3:│}{1: }{4:0 }| - {1: }^1 {3:│}{1: }1 | - {1: }2 {3:│}{1: }2 | - {1: }3 {3:│}{1: }3 | - {1: }4 {3:│}{1: }4 | - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1:+ }{5:+-- 4 lines: 7···}{3:│}{1:+ }{5:+-- 4 lines: 7··}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }{2:------------------}│{1: }{4:0 }| + {1: }^1 │{1: }1 | + {1: }2 │{1: }2 | + {1: }3 │{1: }3 | + {1: }4 │{1: }4 | + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1: }{2:------------------}{3:│}{1: }{4:0 }| - {1: }^1 {3:│}{1: }1 | - {1: }2 {3:│}{1: }2 | - {1: }3 {3:│}{1: }3 | - {1: }4 {3:│}{1: }4 | - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1:+ }{5:+-- 4 lines: 7···}{3:│}{1:+ }{5:+-- 4 lines: 7··}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }{2:------------------}│{1: }{4:0 }| + {1: }^1 │{1: }1 | + {1: }2 │{1: }2 | + {1: }3 │{1: }3 | + {1: }4 │{1: }4 | + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) @@ -103,40 +103,40 @@ describe('Diff mode screen', function() feed(":set diffopt=filler<cr>") screen:expect([[ - {1: }{4:^0 }{3:│}{1: }{2:-----------------}| - {1: }1 {3:│}{1: }1 | - {1: }2 {3:│}{1: }2 | - {1: }3 {3:│}{1: }3 | - {1: }4 {3:│}{1: }4 | - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1:+ }{5:+-- 4 lines: 7···}{3:│}{1:+ }{5:+-- 4 lines: 7··}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }{4:^0 }│{1: }{2:-----------------}| + {1: }1 │{1: }1 | + {1: }2 │{1: }2 | + {1: }3 │{1: }3 | + {1: }4 │{1: }4 | + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(":set diffopt+=internal<cr>") screen:expect([[ - {1: }{4:^0 }{3:│}{1: }{2:-----------------}| - {1: }1 {3:│}{1: }1 | - {1: }2 {3:│}{1: }2 | - {1: }3 {3:│}{1: }3 | - {1: }4 {3:│}{1: }4 | - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1:+ }{5:+-- 4 lines: 7···}{3:│}{1:+ }{5:+-- 4 lines: 7··}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }{4:^0 }│{1: }{2:-----------------}| + {1: }1 │{1: }1 | + {1: }2 │{1: }2 | + {1: }3 │{1: }3 | + {1: }4 │{1: }4 | + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) @@ -149,53 +149,53 @@ describe('Diff mode screen', function() feed(":set diffopt=filler<cr>") screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }{2:------------------}{3:│}{1: }{4:11 }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }{2:------------------}│{1: }{4:11 }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(":set diffopt+=internal<cr>") screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }{2:------------------}{3:│}{1: }{4:11 }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }{2:------------------}│{1: }{4:11 }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) screen:try_resize(40, 9) screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | + {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| | ]]) @@ -208,53 +208,53 @@ describe('Diff mode screen', function() feed(":set diffopt=filler<cr>") screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }{4:11 }{3:│}{1: }{2:-----------------}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }{4:11 }│{1: }{2:-----------------}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(":set diffopt+=internal<cr>") screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }{4:11 }{3:│}{1: }{2:-----------------}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }{4:11 }│{1: }{2:-----------------}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) screen:try_resize(40, 9) screen:expect([[ - {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | + {1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| | ]]) @@ -267,40 +267,40 @@ describe('Diff mode screen', function() feed(':set diffopt=filler<cr>') screen:expect([[ - {1: }^1 {3:│}{1: }1 | - {1: }2 {3:│}{1: }2 | - {1: }3 {3:│}{1: }3 | - {1: }4 {3:│}{1: }4 | - {1: }{2:------------------}{3:│}{1: }{4:4 }| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }{4:11 }{3:│}{1: }{2:-----------------}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^1 │{1: }1 | + {1: }2 │{1: }2 | + {1: }3 │{1: }3 | + {1: }4 │{1: }4 | + {1: }{2:------------------}│{1: }{4:4 }| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }{4:11 }│{1: }{2:-----------------}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1: }^1 {3:│}{1: }1 | - {1: }2 {3:│}{1: }2 | - {1: }3 {3:│}{1: }3 | - {1: }4 {3:│}{1: }4 | - {1: }{2:------------------}{3:│}{1: }{4:4 }| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }{4:11 }{3:│}{1: }{2:-----------------}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^1 │{1: }1 | + {1: }2 │{1: }2 | + {1: }3 │{1: }3 | + {1: }4 │{1: }4 | + {1: }{2:------------------}│{1: }{4:4 }| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }{4:11 }│{1: }{2:-----------------}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) @@ -313,40 +313,40 @@ describe('Diff mode screen', function() feed(':set diffopt=filler<cr>') screen:expect([[ - {1: }^1 {3:│}{1: }1 | - {1: }2 {3:│}{1: }2 | - {1: }3 {3:│}{1: }3 | - {1: }4 {3:│}{1: }4 | - {1: }{4:4 }{3:│}{1: }{2:-----------------}| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }{2:------------------}{3:│}{1: }{4:11 }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^1 │{1: }1 | + {1: }2 │{1: }2 | + {1: }3 │{1: }3 | + {1: }4 │{1: }4 | + {1: }{4:4 }│{1: }{2:-----------------}| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }{2:------------------}│{1: }{4:11 }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1: }^1 {3:│}{1: }1 | - {1: }2 {3:│}{1: }2 | - {1: }3 {3:│}{1: }3 | - {1: }4 {3:│}{1: }4 | - {1: }{4:4 }{3:│}{1: }{2:-----------------}| - {1: }5 {3:│}{1: }5 | - {1: }6 {3:│}{1: }6 | - {1: }7 {3:│}{1: }7 | - {1: }8 {3:│}{1: }8 | - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }{2:------------------}{3:│}{1: }{4:11 }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^1 │{1: }1 | + {1: }2 │{1: }2 | + {1: }3 │{1: }3 | + {1: }4 │{1: }4 | + {1: }{4:4 }│{1: }{2:-----------------}| + {1: }5 │{1: }5 | + {1: }6 │{1: }6 | + {1: }7 │{1: }7 | + {1: }8 │{1: }8 | + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }{2:------------------}│{1: }{4:11 }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) @@ -413,40 +413,40 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler<cr>') screen:expect([[ - {1: }^#include <stdio.h>{3:│}{1: }#include <stdio.h| - {1: } {3:│}{1: } | - {1: }{8:// Frobs foo heart}{3:│}{1: }{8:int fib(int n)}{9: }| - {1: }{4:int frobnitz(int f}{3:│}{1: }{2:-----------------}| - {1: }{ {3:│}{1: }{ | - {1: }{9: i}{8:nt i;}{9: }{3:│}{1: }{9: i}{8:f(n > 2)}{9: }| - {1: }{4: for(i = 0; i <}{3:│}{1: }{2:-----------------}| - {1: } { {3:│}{1: } { | - {1: }{9: }{8:printf("Yo}{3:│}{1: }{9: }{8:return fi}| - {1: }{4: printf("%d}{3:│}{1: }{2:-----------------}| - {1: } } {3:│}{1: } } | - {1: }{2:------------------}{3:│}{1: }{4: return 1; }| - {1: }} {3:│}{1: }} | - {1: } {3:│}{1: } | + {1: }^#include <stdio.h>│{1: }#include <stdio.h| + {1: } │{1: } | + {1: }{8:// Frobs foo heart}│{1: }{8:int fib(int n)}{9: }| + {1: }{4:int frobnitz(int f}│{1: }{2:-----------------}| + {1: }{ │{1: }{ | + {1: }{9: i}{8:nt i;}{9: }│{1: }{9: i}{8:f(n > 2)}{9: }| + {1: }{4: for(i = 0; i <}│{1: }{2:-----------------}| + {1: } { │{1: } { | + {1: }{9: }{8:printf("Yo}│{1: }{9: }{8:return fi}| + {1: }{4: printf("%d}│{1: }{2:-----------------}| + {1: } } │{1: } } | + {1: }{2:------------------}│{1: }{4: return 1; }| + {1: }} │{1: }} | + {1: } │{1: } | {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=internal,filler | ]]) feed('G') screen:expect([[ - {1: }{2:------------------}{3:│}{1: }{4:int frobnitz(int }| - {1: }{ {3:│}{1: }{ | - {1: }{9: i}{8:f(n > 1)}{9: }{3:│}{1: }{9: i}{8:nt i;}{9: }| - {1: }{2:------------------}{3:│}{1: }{4: for(i = 0; i }| - {1: } { {3:│}{1: } { | - {1: }{9: }{8:return fac}{3:│}{1: }{9: }{8:printf("%}| - {1: } } {3:│}{1: } } | - {1: }{4: return 1; }{3:│}{1: }{2:-----------------}| - {1: }} {3:│}{1: }} | - {1: } {3:│}{1: } | - {1: }int main(int argc,{3:│}{1: }int main(int argc| - {1: }{ {3:│}{1: }{ | - {1: }{9: frobnitz(f}{8:act}{9:(}{3:│}{1: }{9: frobnitz(f}{8:ib}{9:(}| - {1: }^} {3:│}{1: }} | + {1: }{2:------------------}│{1: }{4:int frobnitz(int }| + {1: }{ │{1: }{ | + {1: }{9: i}{8:f(n > 1)}{9: }│{1: }{9: i}{8:nt i;}{9: }| + {1: }{2:------------------}│{1: }{4: for(i = 0; i }| + {1: } { │{1: } { | + {1: }{9: }{8:return fac}│{1: }{9: }{8:printf("%}| + {1: } } │{1: } } | + {1: }{4: return 1; }│{1: }{2:-----------------}| + {1: }} │{1: }} | + {1: } │{1: } | + {1: }int main(int argc,│{1: }int main(int argc| + {1: }{ │{1: }{ | + {1: }{9: frobnitz(f}{8:act}{9:(}│{1: }{9: frobnitz(f}{8:ib}{9:(}| + {1: }^} │{1: }} | {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=internal,filler | ]]) @@ -456,40 +456,40 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler,algorithm:patience<cr>') screen:expect([[ - {1: }^#include <stdio.h>{3:│}{1: }#include <stdio.h| - {1: } {3:│}{1: } | - {1: }{2:------------------}{3:│}{1: }{4:int fib(int n) }| - {1: }{2:------------------}{3:│}{1: }{4:{ }| - {1: }{2:------------------}{3:│}{1: }{4: if(n > 2) }| - {1: }{2:------------------}{3:│}{1: }{4: { }| - {1: }{2:------------------}{3:│}{1: }{4: return fi}| - {1: }{2:------------------}{3:│}{1: }{4: } }| - {1: }{2:------------------}{3:│}{1: }{4: return 1; }| - {1: }{2:------------------}{3:│}{1: }{4:} }| - {1: }{2:------------------}{3:│}{1: }{4: }| - {1: }// Frobs foo heart{3:│}{1: }// Frobs foo hear| - {1: }int frobnitz(int f{3:│}{1: }int frobnitz(int | - {1: }{ {3:│}{1: }{ | + {1: }^#include <stdio.h>│{1: }#include <stdio.h| + {1: } │{1: } | + {1: }{2:------------------}│{1: }{4:int fib(int n) }| + {1: }{2:------------------}│{1: }{4:{ }| + {1: }{2:------------------}│{1: }{4: if(n > 2) }| + {1: }{2:------------------}│{1: }{4: { }| + {1: }{2:------------------}│{1: }{4: return fi}| + {1: }{2:------------------}│{1: }{4: } }| + {1: }{2:------------------}│{1: }{4: return 1; }| + {1: }{2:------------------}│{1: }{4:} }| + {1: }{2:------------------}│{1: }{4: }| + {1: }// Frobs foo heart│{1: }// Frobs foo hear| + {1: }int frobnitz(int f│{1: }int frobnitz(int | + {1: }{ │{1: }{ | {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| | ]]) feed('G') screen:expect([[ - {1: } {3:│}{1: } | - {1: }{4:int fact(int n) }{3:│}{1: }{2:-----------------}| - {1: }{4:{ }{3:│}{1: }{2:-----------------}| - {1: }{4: if(n > 1) }{3:│}{1: }{2:-----------------}| - {1: }{4: { }{3:│}{1: }{2:-----------------}| - {1: }{4: return fac}{3:│}{1: }{2:-----------------}| - {1: }{4: } }{3:│}{1: }{2:-----------------}| - {1: }{4: return 1; }{3:│}{1: }{2:-----------------}| - {1: }{4:} }{3:│}{1: }{2:-----------------}| - {1: }{4: }{3:│}{1: }{2:-----------------}| - {1: }int main(int argc,{3:│}{1: }int main(int argc| - {1: }{ {3:│}{1: }{ | - {1: }{9: frobnitz(f}{8:act}{9:(}{3:│}{1: }{9: frobnitz(f}{8:ib}{9:(}| - {1: }^} {3:│}{1: }} | + {1: } │{1: } | + {1: }{4:int fact(int n) }│{1: }{2:-----------------}| + {1: }{4:{ }│{1: }{2:-----------------}| + {1: }{4: if(n > 1) }│{1: }{2:-----------------}| + {1: }{4: { }│{1: }{2:-----------------}| + {1: }{4: return fac}│{1: }{2:-----------------}| + {1: }{4: } }│{1: }{2:-----------------}| + {1: }{4: return 1; }│{1: }{2:-----------------}| + {1: }{4:} }│{1: }{2:-----------------}| + {1: }{4: }│{1: }{2:-----------------}| + {1: }int main(int argc,│{1: }int main(int argc| + {1: }{ │{1: }{ | + {1: }{9: frobnitz(f}{8:act}{9:(}│{1: }{9: frobnitz(f}{8:ib}{9:(}| + {1: }^} │{1: }} | {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| | ]]) @@ -499,40 +499,40 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler,algorithm:histogram<cr>') screen:expect([[ - {1: }^#include <stdio.h>{3:│}{1: }#include <stdio.h| - {1: } {3:│}{1: } | - {1: }{2:------------------}{3:│}{1: }{4:int fib(int n) }| - {1: }{2:------------------}{3:│}{1: }{4:{ }| - {1: }{2:------------------}{3:│}{1: }{4: if(n > 2) }| - {1: }{2:------------------}{3:│}{1: }{4: { }| - {1: }{2:------------------}{3:│}{1: }{4: return fi}| - {1: }{2:------------------}{3:│}{1: }{4: } }| - {1: }{2:------------------}{3:│}{1: }{4: return 1; }| - {1: }{2:------------------}{3:│}{1: }{4:} }| - {1: }{2:------------------}{3:│}{1: }{4: }| - {1: }// Frobs foo heart{3:│}{1: }// Frobs foo hear| - {1: }int frobnitz(int f{3:│}{1: }int frobnitz(int | - {1: }{ {3:│}{1: }{ | + {1: }^#include <stdio.h>│{1: }#include <stdio.h| + {1: } │{1: } | + {1: }{2:------------------}│{1: }{4:int fib(int n) }| + {1: }{2:------------------}│{1: }{4:{ }| + {1: }{2:------------------}│{1: }{4: if(n > 2) }| + {1: }{2:------------------}│{1: }{4: { }| + {1: }{2:------------------}│{1: }{4: return fi}| + {1: }{2:------------------}│{1: }{4: } }| + {1: }{2:------------------}│{1: }{4: return 1; }| + {1: }{2:------------------}│{1: }{4:} }| + {1: }{2:------------------}│{1: }{4: }| + {1: }// Frobs foo heart│{1: }// Frobs foo hear| + {1: }int frobnitz(int f│{1: }int frobnitz(int | + {1: }{ │{1: }{ | {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| | ]]) feed('G') screen:expect([[ - {1: } {3:│}{1: } | - {1: }{4:int fact(int n) }{3:│}{1: }{2:-----------------}| - {1: }{4:{ }{3:│}{1: }{2:-----------------}| - {1: }{4: if(n > 1) }{3:│}{1: }{2:-----------------}| - {1: }{4: { }{3:│}{1: }{2:-----------------}| - {1: }{4: return fac}{3:│}{1: }{2:-----------------}| - {1: }{4: } }{3:│}{1: }{2:-----------------}| - {1: }{4: return 1; }{3:│}{1: }{2:-----------------}| - {1: }{4:} }{3:│}{1: }{2:-----------------}| - {1: }{4: }{3:│}{1: }{2:-----------------}| - {1: }int main(int argc,{3:│}{1: }int main(int argc| - {1: }{ {3:│}{1: }{ | - {1: }{9: frobnitz(f}{8:act}{9:(}{3:│}{1: }{9: frobnitz(f}{8:ib}{9:(}| - {1: }^} {3:│}{1: }} | + {1: } │{1: } | + {1: }{4:int fact(int n) }│{1: }{2:-----------------}| + {1: }{4:{ }│{1: }{2:-----------------}| + {1: }{4: if(n > 1) }│{1: }{2:-----------------}| + {1: }{4: { }│{1: }{2:-----------------}| + {1: }{4: return fac}│{1: }{2:-----------------}| + {1: }{4: } }│{1: }{2:-----------------}| + {1: }{4: return 1; }│{1: }{2:-----------------}| + {1: }{4:} }│{1: }{2:-----------------}| + {1: }{4: }│{1: }{2:-----------------}| + {1: }int main(int argc,│{1: }int main(int argc| + {1: }{ │{1: }{ | + {1: }{9: frobnitz(f}{8:act}{9:(}│{1: }{9: frobnitz(f}{8:ib}{9:(}| + {1: }^} │{1: }} | {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| | ]]) @@ -566,20 +566,20 @@ int main(int argc, char **argv) reread() feed(":set diffopt=internal,filler<cr>") screen:expect([[ - {1: }^def finalize(value{3:│}{1: }def finalize(valu| - {1: } {3:│}{1: } | - {1: } values.each do |{3:│}{1: } values.each do | - {1: }{2:------------------}{3:│}{1: }{4: v.prepare }| - {1: }{2:------------------}{3:│}{1: }{4: end }| - {1: }{2:------------------}{3:│}{1: }{4: }| - {1: }{2:------------------}{3:│}{1: }{4: values.each do }| - {1: } v.finalize {3:│}{1: } v.finalize | - {1: } end {3:│}{1: } end | - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^def finalize(value│{1: }def finalize(valu| + {1: } │{1: } | + {1: } values.each do |│{1: } values.each do | + {1: }{2:------------------}│{1: }{4: v.prepare }| + {1: }{2:------------------}│{1: }{4: end }| + {1: }{2:------------------}│{1: }{4: }| + {1: }{2:------------------}│{1: }{4: values.each do }| + {1: } v.finalize │{1: } v.finalize | + {1: } end │{1: } end | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=internal,filler | ]]) @@ -589,20 +589,20 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler,indent-heuristic<cr>') screen:expect([[ - {1: }^def finalize(value{3:│}{1: }def finalize(valu| - {1: } {3:│}{1: } | - {1: }{2:------------------}{3:│}{1: }{4: values.each do }| - {1: }{2:------------------}{3:│}{1: }{4: v.prepare }| - {1: }{2:------------------}{3:│}{1: }{4: end }| - {1: }{2:------------------}{3:│}{1: }{4: }| - {1: } values.each do |{3:│}{1: } values.each do | - {1: } v.finalize {3:│}{1: } v.finalize | - {1: } end {3:│}{1: } end | - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^def finalize(value│{1: }def finalize(valu| + {1: } │{1: } | + {1: }{2:------------------}│{1: }{4: values.each do }| + {1: }{2:------------------}│{1: }{4: v.prepare }| + {1: }{2:------------------}│{1: }{4: end }| + {1: }{2:------------------}│{1: }{4: }| + {1: } values.each do |│{1: } values.each do | + {1: } v.finalize │{1: } v.finalize | + {1: } end │{1: } end | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| | ]]) @@ -613,20 +613,20 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,indent-heuristic,algorithm:patience<cr>') feed(':<cr>') screen:expect([[ - {1: }^def finalize(value{3:│}{1: }def finalize(valu| - {1: } {3:│}{1: } | - {1: }{2:------------------}{3:│}{1: }{4: values.each do }| - {1: }{2:------------------}{3:│}{1: }{4: v.prepare }| - {1: }{2:------------------}{3:│}{1: }{4: end }| - {1: }{2:------------------}{3:│}{1: }{4: }| - {1: } values.each do |{3:│}{1: } values.each do | - {1: } v.finalize {3:│}{1: } v.finalize | - {1: } end {3:│}{1: } end | - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^def finalize(value│{1: }def finalize(valu| + {1: } │{1: } | + {1: }{2:------------------}│{1: }{4: values.each do }| + {1: }{2:------------------}│{1: }{4: v.prepare }| + {1: }{2:------------------}│{1: }{4: end }| + {1: }{2:------------------}│{1: }{4: }| + {1: } values.each do |│{1: } values.each do | + {1: } v.finalize │{1: } v.finalize | + {1: } end │{1: } end | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| : | ]]) @@ -640,40 +640,40 @@ int main(int argc, char **argv) feed(':set diffopt=filler<cr>') screen:expect([[ - {1:+ }{5:^+-- 10 lines: 1···}{3:│}{1:+ }{5:+-- 10 lines: 1··}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1:+ }{5:^+-- 10 lines: 1···}│{1:+ }{5:+-- 10 lines: 1··}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1:+ }{5:^+-- 10 lines: 1···}{3:│}{1:+ }{5:+-- 10 lines: 1··}| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1:+ }{5:^+-- 10 lines: 1···}│{1:+ }{5:+-- 10 lines: 1··}| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) @@ -686,40 +686,40 @@ int main(int argc, char **argv) feed(':set diffopt=filler<cr>') screen:expect([[ - {1:- }^ {3:│}{1:- } | - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1:- }^ │{1:- } | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1:- }^ {3:│}{1:- } | - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1:- }^ │{1:- } | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) @@ -732,40 +732,40 @@ int main(int argc, char **argv) feed(':set diffopt=filler,icase<cr>') screen:expect([[ - {1: }^a {3:│}{1: }A | - {1: }b {3:│}{1: }b | - {1: }{9:cd }{3:│}{1: }{9:cD}{8:e}{9: }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^a │{1: }A | + {1: }b │{1: }b | + {1: }{9:cd }│{1: }{9:cD}{8:e}{9: }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler,icase | ]]) feed(':set diffopt+=internal<cr>') screen:expect([[ - {1: }^a {3:│}{1: }A | - {1: }b {3:│}{1: }b | - {1: }{9:cd }{3:│}{1: }{9:cD}{8:e}{9: }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^a │{1: }A | + {1: }b │{1: }b | + {1: }{9:cd }│{1: }{9:cD}{8:e}{9: }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt+=internal | ]]) @@ -784,20 +784,20 @@ int main(int argc, char **argv) reread() feed(':set diffopt=filler,iwhite<cr>') screen:expect([[ - {1: }^int main() {3:│}{1: }int main() | - {1: }{ {3:│}{1: }{ | - {1: }{2:------------------}{3:│}{1: }{4: if (0) }| - {1: }{2:------------------}{3:│}{1: }{4: { }| - {1: } printf("Hello, {3:│}{1: } printf("Hel| - {1: } return 0; {3:│}{1: } return 0; | - {1: }{2:------------------}{3:│}{1: }{4: } }| - {1: }} {3:│}{1: }} | - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^int main() │{1: }int main() | + {1: }{ │{1: }{ | + {1: }{2:------------------}│{1: }{4: if (0) }| + {1: }{2:------------------}│{1: }{4: { }| + {1: } printf("Hello, │{1: } printf("Hel| + {1: } return 0; │{1: } return 0; | + {1: }{2:------------------}│{1: }{4: } }| + {1: }} │{1: }} | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler,iwhite | ]]) @@ -807,20 +807,20 @@ int main(int argc, char **argv) reread() feed(':set diffopt=filler,iwhite,internal<cr>') screen:expect([[ - {1: }^int main() {3:│}{1: }int main() | - {1: }{ {3:│}{1: }{ | - {1: }{2:------------------}{3:│}{1: }{4: if (0) }| - {1: }{2:------------------}{3:│}{1: }{4: { }| - {1: } printf("Hello, {3:│}{1: } printf("Hel| - {1: } return 0; {3:│}{1: } return 0; | - {1: }{2:------------------}{3:│}{1: }{4: } }| - {1: }} {3:│}{1: }} | - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^int main() │{1: }int main() | + {1: }{ │{1: }{ | + {1: }{2:------------------}│{1: }{4: if (0) }| + {1: }{2:------------------}│{1: }{4: { }| + {1: } printf("Hello, │{1: } printf("Hel| + {1: } return 0; │{1: } return 0; | + {1: }{2:------------------}│{1: }{4: } }| + {1: }} │{1: }} | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=filler,iwhite,internal | ]]) @@ -838,20 +838,20 @@ int main(int argc, char **argv) reread() feed(':set diffopt=internal,filler,iblank<cr>') screen:expect([[ - {1: }^a {3:│}{1: }a | - {1: }{4: }{3:│}{1: }{2:-----------------}| - {1: }{4: }{3:│}{1: }{2:-----------------}| - {1: }cd {3:│}{1: }cd | - {1: }ef {3:│}{1: } | - {1: }{8:xxx}{9: }{3:│}{1: }ef | - {6:~ }{3:│}{1: }{8:yyy}{9: }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^a │{1: }a | + {1: }{4: }│{1: }{2:-----------------}| + {1: }{4: }│{1: }{2:-----------------}| + {1: }cd │{1: }cd | + {1: }ef │{1: } | + {1: }{8:xxx}{9: }│{1: }ef | + {6:~ }│{1: }{8:yyy}{9: }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| :set diffopt=internal,filler,iblank | ]]) @@ -862,20 +862,20 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iblank,iwhite<cr>') feed(':<cr>') screen:expect([[ - {1: }^a {3:│}{1: }a | - {1: } {3:│}{1: }cd | - {1: } {3:│}{1: } | - {1: }cd {3:│}{1: }ef | - {1: }ef {3:│}{1: }{8:yyy}{9: }| - {1: }{8:xxx}{9: }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^a │{1: }a | + {1: } │{1: }cd | + {1: } │{1: } | + {1: }cd │{1: }ef | + {1: }ef │{1: }{8:yyy}{9: }| + {1: }{8:xxx}{9: }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| : | ]]) @@ -886,20 +886,20 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iblank,iwhiteall<cr>') feed(':<cr>') screen:expect([[ - {1: }^a {3:│}{1: }a | - {1: } {3:│}{1: }cd | - {1: } {3:│}{1: } | - {1: }cd {3:│}{1: }ef | - {1: }ef {3:│}{1: }{8:yyy}{9: }| - {1: }{8:xxx}{9: }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^a │{1: }a | + {1: } │{1: }cd | + {1: } │{1: } | + {1: }cd │{1: }ef | + {1: }ef │{1: }{8:yyy}{9: }| + {1: }{8:xxx}{9: }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| : | ]]) @@ -910,20 +910,20 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iblank,iwhiteeol<cr>') feed(':<cr>') screen:expect([[ - {1: }^a {3:│}{1: }a | - {1: } {3:│}{1: }cd | - {1: } {3:│}{1: } | - {1: }cd {3:│}{1: }ef | - {1: }ef {3:│}{1: }{8:yyy}{9: }| - {1: }{8:xxx}{9: }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^a │{1: }a | + {1: } │{1: }cd | + {1: } │{1: } | + {1: }cd │{1: }ef | + {1: }ef │{1: }{8:yyy}{9: }| + {1: }{8:xxx}{9: }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| : | ]]) @@ -942,20 +942,20 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iwhiteeol<cr>') feed(':<cr>') screen:expect([[ - {1: }^a {3:│}{1: }a | - {1: }x {3:│}{1: }x | - {1: }{9:cd }{3:│}{1: }{9:c}{8: }{9:d }| - {1: }{9:ef }{3:│}{1: }{8: }{9:ef }| - {1: }{9:xx }{8: }{9:xx }{3:│}{1: }{9:xx xx }| - {1: }foo {3:│}{1: }foo | - {1: }{2:------------------}{3:│}{1: }{4: }| - {1: }bar {3:│}{1: }bar | - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^a │{1: }a | + {1: }x │{1: }x | + {1: }{9:cd }│{1: }{9:c}{8: }{9:d }| + {1: }{9:ef }│{1: }{8: }{9:ef }| + {1: }{9:xx }{8: }{9:xx }│{1: }{9:xx xx }| + {1: }foo │{1: }foo | + {1: }{2:------------------}│{1: }{4: }| + {1: }bar │{1: }bar | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| : | ]]) @@ -966,20 +966,20 @@ int main(int argc, char **argv) feed(':set diffopt=internal,filler,iwhiteall<cr>') feed(':<cr>') screen:expect([[ - {1: }^a {3:│}{1: }a | - {1: }x {3:│}{1: }x | - {1: }cd {3:│}{1: }c d | - {1: }ef {3:│}{1: } ef | - {1: }xx xx {3:│}{1: }xx xx | - {1: }foo {3:│}{1: }foo | - {1: }{2:------------------}{3:│}{1: }{4: }| - {1: }bar {3:│}{1: }bar | - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| - {6:~ }{3:│}{6:~ }| + {1: }^a │{1: }a | + {1: }x │{1: }x | + {1: }cd │{1: }c d | + {1: }ef │{1: } ef | + {1: }xx xx │{1: }xx xx | + {1: }foo │{1: }foo | + {1: }{2:------------------}│{1: }{4: }| + {1: }bar │{1: }bar | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| : | ]]) @@ -1029,14 +1029,14 @@ it('win_update redraws lines properly', function() command("windo diffthis") command("windo 1") screen:expect{grid=[[ - {13: }{16:-----------------------}{14:│}{13: }{15:^1 }| - {13: }{16:-----------------------}{14:│}{13: }{15: }| - {13: }{16:-----------------------}{14:│}{13: }{15: }| - {13: }2 {14:│}{13: }2 | - {13: }{17:2}{18:a }{14:│}{13: }{17:1}{18:a }| - {13: }{15:2b }{14:│}{13: }{16:----------------------}| - {13: } {14:│}{13: } | - {1:~ }{14:│}{1:~ }| + {13: }{16:-----------------------}│{13: }{15:^1 }| + {13: }{16:-----------------------}│{13: }{15: }| + {13: }{16:-----------------------}│{13: }{15: }| + {13: }2 │{13: }2 | + {13: }{17:2}{18:a }│{13: }{17:1}{18:a }| + {13: }{15:2b }│{13: }{16:----------------------}| + {13: } │{13: } | + {1:~ }│{1:~ }| {14:left [+] }{12:[No Name] [+] }| | ]]} @@ -1046,14 +1046,14 @@ it('win_update redraws lines properly', function() feed('<C-y>') feed('<C-y>') screen:expect{grid=[[ - {13: }{16:-----------------------}{14:│}{13: }{15:1 }| - {13: }{16:-----------------------}{14:│}{13: }{15: }| - {13: }{16:-----------------------}{14:│}{13: }{15:^ }| - {13: }2 {14:│}{13: }2 | - {13: }{17:2}{18:a }{14:│}{13: }{17:1}{18:a }| - {13: }{15:2b }{14:│}{13: }{16:----------------------}| - {13: } {14:│}{13: } | - {1:~ }{14:│}{1:~ }| + {13: }{16:-----------------------}│{13: }{15:1 }| + {13: }{16:-----------------------}│{13: }{15: }| + {13: }{16:-----------------------}│{13: }{15:^ }| + {13: }2 │{13: }2 | + {13: }{17:2}{18:a }│{13: }{17:1}{18:a }| + {13: }{15:2b }│{13: }{16:----------------------}| + {13: } │{13: } | + {1:~ }│{1:~ }| {14:left [+] }{12:[No Name] [+] }| | ]]} @@ -1075,10 +1075,8 @@ it('diff updates line numbers below filler lines', function() [9] = {background = Screen.colors.LightMagenta}, [10] = {bold = true, foreground = Screen.colors.Brown}, [11] = {foreground = Screen.colors.Brown}, - [12] = {foreground = Screen.colors.Brown, bold = true, background = Screen.colors.Red}; - [13] = {background = Screen.colors.Gray90}; }) - source([[ + exec([[ call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b']) vnew call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b']) @@ -1086,73 +1084,55 @@ it('diff updates line numbers below filler lines', function() setlocal number rnu cursorline cursorlineopt=number foldcolumn=0 ]]) screen:expect([[ - {1: }a {3:│}{10:1 }^a | - {1: }a {3:│}{11: 1 }a | - {1: }a {3:│}{11: 2 }a | - {1: }{8:x}{9: }{3:│}{11: 3 }{8:y}{9: }| - {1: }{4:x }{3:│}{11: }{2:----------------}| - {1: }{4:x }{3:│}{11: }{2:----------------}| - {1: }b {3:│}{11: 4 }b | - {1: }b {3:│}{11: 5 }b | - {1: }b {3:│}{11: 6 }b | - {1: }b {3:│}{11: 7 }b | - {1: }b {3:│}{11: 8 }b | - {6:~ }{3:│}{6:~ }| + {1: }a │{10:1 }^a | + {1: }a │{11: 1 }a | + {1: }a │{11: 2 }a | + {1: }{8:x}{9: }│{11: 3 }{8:y}{9: }| + {1: }{4:x }│{11: }{2:----------------}| + {1: }{4:x }│{11: }{2:----------------}| + {1: }b │{11: 4 }b | + {1: }b │{11: 5 }b | + {1: }b │{11: 6 }b | + {1: }b │{11: 7 }b | + {1: }b │{11: 8 }b | + {6:~ }│{6:~ }| {3:[No Name] [+] }{7:[No Name] [+] }| | ]]) feed('j') screen:expect([[ - {1: }a {3:│}{11: 1 }a | - {1: }a {3:│}{10:2 }^a | - {1: }a {3:│}{11: 1 }a | - {1: }{8:x}{9: }{3:│}{11: 2 }{8:y}{9: }| - {1: }{4:x }{3:│}{11: }{2:----------------}| - {1: }{4:x }{3:│}{11: }{2:----------------}| - {1: }b {3:│}{11: 3 }b | - {1: }b {3:│}{11: 4 }b | - {1: }b {3:│}{11: 5 }b | - {1: }b {3:│}{11: 6 }b | - {1: }b {3:│}{11: 7 }b | - {6:~ }{3:│}{6:~ }| + {1: }a │{11: 1 }a | + {1: }a │{10:2 }^a | + {1: }a │{11: 1 }a | + {1: }{8:x}{9: }│{11: 2 }{8:y}{9: }| + {1: }{4:x }│{11: }{2:----------------}| + {1: }{4:x }│{11: }{2:----------------}| + {1: }b │{11: 3 }b | + {1: }b │{11: 4 }b | + {1: }b │{11: 5 }b | + {1: }b │{11: 6 }b | + {1: }b │{11: 7 }b | + {6:~ }│{6:~ }| {3:[No Name] [+] }{7:[No Name] [+] }| | ]]) feed('j') screen:expect([[ - {1: }a {3:│}{11: 2 }a | - {1: }a {3:│}{11: 1 }a | - {1: }a {3:│}{10:3 }^a | - {1: }{8:x}{9: }{3:│}{11: 1 }{8:y}{9: }| - {1: }{4:x }{3:│}{11: }{2:----------------}| - {1: }{4:x }{3:│}{11: }{2:----------------}| - {1: }b {3:│}{11: 2 }b | - {1: }b {3:│}{11: 3 }b | - {1: }b {3:│}{11: 4 }b | - {1: }b {3:│}{11: 5 }b | - {1: }b {3:│}{11: 6 }b | - {6:~ }{3:│}{6:~ }| + {1: }a │{11: 2 }a | + {1: }a │{11: 1 }a | + {1: }a │{10:3 }^a | + {1: }{8:x}{9: }│{11: 1 }{8:y}{9: }| + {1: }{4:x }│{11: }{2:----------------}| + {1: }{4:x }│{11: }{2:----------------}| + {1: }b │{11: 2 }b | + {1: }b │{11: 3 }b | + {1: }b │{11: 4 }b | + {1: }b │{11: 5 }b | + {1: }b │{11: 6 }b | + {6:~ }│{6:~ }| {3:[No Name] [+] }{7:[No Name] [+] }| | ]]) - command("set signcolumn number tgc cursorline cursorlineopt=number,line") - command("hi CursorLineNr guibg=red") - screen:expect{grid=[[ - {1: }a {3:│}{11: 2 }a | - {1: }a {3:│}{11: 1 }a | - {1: }a {3:│}{12:3 }{13:^a }| - {1: }{8:x}{9: }{3:│}{11: 1 }{8:y}{9: }| - {1: }{4:x }{3:│}{11: }{2:----------------}| - {1: }{4:x }{3:│}{11: }{2:----------------}| - {1: }b {3:│}{11: 2 }b | - {1: }b {3:│}{11: 3 }b | - {1: }b {3:│}{11: 4 }b | - {1: }b {3:│}{11: 5 }b | - {1: }b {3:│}{11: 6 }b | - {6:~ }{3:│}{6:~ }| - {3:[No Name] [+] }{7:[No Name] [+] }| - signcolumn=auto | - ]]} end) it('Align the filler lines when changing text in diff mode', function() @@ -1169,7 +1149,7 @@ it('Align the filler lines when changing text in diff mode', function() [7] = {foreground = Screen.colors.Blue1, bold = true}; [8] = {reverse = true, bold = true}; }) - source([[ + exec([[ call setline(1, range(1, 15)) vnew call setline(1, range(9, 15)) @@ -1178,71 +1158,198 @@ it('Align the filler lines when changing text in diff mode', function() exe "normal Gl5\<C-E>" ]]) screen:expect{grid=[[ - {1: }{2:------------------}{3:│}{1: }{4:6 }| - {1: }{2:------------------}{3:│}{1: }{4:7 }| - {1: }{2:------------------}{3:│}{1: }{4:8 }| - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }11 {3:│}{1: }11 | - {1: }12 {3:│}{1: }12 | - {1: }13 {3:│}{1: }13 | - {1: }14 {3:│}{1: }14 | - {1:- }1^5 {3:│}{1:- }15 | - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| + {1: }{2:------------------}│{1: }{4:6 }| + {1: }{2:------------------}│{1: }{4:7 }| + {1: }{2:------------------}│{1: }{4:8 }| + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }11 │{1: }11 | + {1: }12 │{1: }12 | + {1: }13 │{1: }13 | + {1: }14 │{1: }14 | + {1:- }1^5 │{1:- }15 | + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| {8:[No Name] [+] }{3:[No Name] [+] }| | ]]} feed('ax<Esc>') screen:expect{grid=[[ - {1: }{2:------------------}{3:│}{1: }{4:6 }| - {1: }{2:------------------}{3:│}{1: }{4:7 }| - {1: }{2:------------------}{3:│}{1: }{4:8 }| - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }11 {3:│}{1: }11 | - {1: }12 {3:│}{1: }12 | - {1: }13 {3:│}{1: }13 | - {1: }14 {3:│}{1: }14 | - {1: }{5:15}{6:^x}{5: }{3:│}{1: }{5:15 }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| + {1: }{2:------------------}│{1: }{4:6 }| + {1: }{2:------------------}│{1: }{4:7 }| + {1: }{2:------------------}│{1: }{4:8 }| + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }11 │{1: }11 | + {1: }12 │{1: }12 | + {1: }13 │{1: }13 | + {1: }14 │{1: }14 | + {1: }{5:15}{6:^x}{5: }│{1: }{5:15 }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| {8:[No Name] [+] }{3:[No Name] [+] }| | ]]} feed('<C-W>lay<Esc>') screen:expect{grid=[[ - {1: }{2:-----------------}{3:│}{1: }{4:6 }| - {1: }{2:-----------------}{3:│}{1: }{4:7 }| - {1: }{2:-----------------}{3:│}{1: }{4:8 }| - {1: }9 {3:│}{1: }9 | - {1: }10 {3:│}{1: }10 | - {1: }11 {3:│}{1: }11 | - {1: }12 {3:│}{1: }12 | - {1: }13 {3:│}{1: }13 | - {1: }14 {3:│}{1: }14 | - {1: }{5:15}{6:x}{5: }{3:│}{1: }{5:15}{6:^y}{5: }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| - {7:~ }{3:│}{7:~ }| + {1: }{2:-----------------}│{1: }{4:6 }| + {1: }{2:-----------------}│{1: }{4:7 }| + {1: }{2:-----------------}│{1: }{4:8 }| + {1: }9 │{1: }9 | + {1: }10 │{1: }10 | + {1: }11 │{1: }11 | + {1: }12 │{1: }12 | + {1: }13 │{1: }13 | + {1: }14 │{1: }14 | + {1: }{5:15}{6:x}{5: }│{1: }{5:15}{6:^y}{5: }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| {3:[No Name] [+] }{8:[No Name] [+] }| | ]]} end) + +it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', function() + clear() + local screen = Screen.new(40, 20) + screen:set_default_attr_ids({ + [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray}; + [2] = {reverse = true}; + [3] = {background = Screen.colors.LightBlue}; + [4] = {background = Screen.colors.LightMagenta}; + [5] = {background = Screen.colors.Red, bold = true}; + [6] = {foreground = Screen.colors.Blue, bold = true}; + [7] = {background = Screen.colors.Red, foreground = Screen.colors.Blue, bold = true}; + [8] = {reverse = true, bold = true}; + }) + screen:attach() + exec([[ + call setline(1, ['a', 'b', "c\n", 'd', 'e', 'f', 'g']) + vnew + call setline(1, ['A', 'b', 'c', 'd', 'E', 'f', 'g']) + windo diffthis + wincmd p + norm! gg0 + redraw! + ]]) + + -- Test using internal diff + screen:expect([[ + {1: }{5:^A}{4: }│{1: }{5:a}{4: }| + {1: }b │{1: }b | + {1: }{4:c }│{1: }{4:c}{7:^@}{4: }| + {1: }d │{1: }d | + {1: }{5:E}{4: }│{1: }{5:e}{4: }| + {1: }f │{1: }f | + {1: }g │{1: }g | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {8:[No Name] [+] }{2:[No Name] [+] }| + | + ]]) + + -- Test using internal diff and case folding + command('set diffopt+=icase') + feed('<C-L>') + screen:expect([[ + {1: }^A │{1: }a | + {1: }b │{1: }b | + {1: }{4:c }│{1: }{4:c}{7:^@}{4: }| + {1: }d │{1: }d | + {1: }E │{1: }e | + {1: }f │{1: }f | + {1: }g │{1: }g | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {8:[No Name] [+] }{2:[No Name] [+] }| + | + ]]) + + -- Test using external diff + command('set diffopt=filler') + feed('<C-L>') + screen:expect([[ + {1: }{5:^A}{4: }│{1: }{5:a}{4: }| + {1: }b │{1: }b | + {1: }{4:c }│{1: }{4:c}{7:^@}{4: }| + {1: }d │{1: }d | + {1: }{5:E}{4: }│{1: }{5:e}{4: }| + {1: }f │{1: }f | + {1: }g │{1: }g | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {8:[No Name] [+] }{2:[No Name] [+] }| + | + ]]) + + -- Test using external diff and case folding + command('set diffopt+=filler,icase') + feed('<C-L>') + screen:expect([[ + {1: }^A │{1: }a | + {1: }b │{1: }b | + {1: }{4:c }│{1: }{4:c}{7:^@}{4: }| + {1: }d │{1: }d | + {1: }E │{1: }e | + {1: }f │{1: }f | + {1: }g │{1: }g | + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {6:~ }│{6:~ }| + {8:[No Name] [+] }{2:[No Name] [+] }| + | + ]]) +end) diff --git a/test/functional/ui/embed_spec.lua b/test/functional/ui/embed_spec.lua index 8218c8e12d..92f5beebf5 100644 --- a/test/functional/ui/embed_spec.lua +++ b/test/functional/ui/embed_spec.lua @@ -1,3 +1,5 @@ +local uv = require'luv' + local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') @@ -98,3 +100,49 @@ end describe('--embed UI on startup (ext_linegrid=true)', function() test_embed(true) end) describe('--embed UI on startup (ext_linegrid=false)', function() test_embed(false) end) + +describe('--embed UI', function() + it('can pass stdin', function() + local pipe = assert(uv.pipe()) + + local writer = assert(uv.new_pipe(false)) + writer:open(pipe.write) + + clear {args_rm={'--headless'}, io_extra=pipe.read} + + -- attach immediately after startup, for early UI + local screen = Screen.new(40, 8) + screen:attach {stdin_fd=3} + screen:set_default_attr_ids { + [1] = {bold = true, foreground = Screen.colors.Blue1}; + [2] = {bold = true}; + } + + writer:write "hello nvim\nfrom external input\n" + writer:shutdown(function() writer:close() end) + + screen:expect{grid=[[ + ^hello nvim | + from external input | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + + -- stdin (rpc input) still works + feed 'o' + screen:expect{grid=[[ + hello nvim | + ^ | + from external input | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:-- INSERT --} | + ]]} + end) +end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 5f29261b17..50247ed214 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -8,6 +8,7 @@ local command, feed_command = helpers.command, helpers.feed_command local eval = helpers.eval local eq = helpers.eq local neq = helpers.neq +local expect = helpers.expect local exec_lua = helpers.exec_lua local insert = helpers.insert local meths = helpers.meths @@ -16,10 +17,12 @@ local funcs = helpers.funcs local run = helpers.run local pcall_err = helpers.pcall_err local tbl_contains = global_helpers.tbl_contains +local curbuf, curwin, curtab = helpers.curbuf, helpers.curwin, helpers.curtab describe('float window', function() before_each(function() clear() + command('hi VertSplit gui=reverse') end) local attrs = { [0] = {bold=true, foreground=Screen.colors.Blue}, @@ -83,8 +86,8 @@ describe('float window', function() local buf = meths.create_buf(false, false) meths.buf_set_lines(buf, 0, -1, true, {'the floatwin'}) local win = meths.open_win(buf, true, {relative='win', width=16, height=1, row=0, col=10}) - eq(pcall_err(funcs.win_execute, win, 'close'), 'Vim(close):E37: No write since last change (add ! to override)') - eq(pcall_err(funcs.win_execute, win, 'bdelete'), 'Vim(bdelete):E89: No write since last change for buffer 2 (add ! to override)') + eq('Vim(close):E37: No write since last change (add ! to override)', pcall_err(funcs.win_execute, win, 'close')) + eq('Vim(bdelete):E89: No write since last change for buffer 2 (add ! to override)', pcall_err(funcs.win_execute, win, 'bdelete')) funcs.win_execute(win, 'bwipe!') end) @@ -365,7 +368,7 @@ describe('float window', function() return vim.api.nvim_open_win(bufnr, false, opts) ]]) command('windo echo') - neq(eval('win_getid()'), winid) + neq(winid, eval('win_getid()')) end) it('is active after windo when focusable', function() @@ -382,7 +385,7 @@ describe('float window', function() return vim.api.nvim_open_win(bufnr, false, opts) ]]) command('windo echo') - eq(eval('win_getid()'), winid) + eq(winid, eval('win_getid()')) end) it('supports windo with focusable and non-focusable floats', function() @@ -417,6 +420,287 @@ describe('float window', function() eq(winids, eval('winids')) end) + describe('with only one tabpage,', function() + local float_opts = {relative = 'editor', row = 1, col = 1, width = 1, height = 1} + local old_buf, old_win + before_each(function() + insert('foo') + old_buf = curbuf().id + old_win = curwin().id + end) + describe('closing the last non-floating window gives E444', function() + before_each(function() + meths.open_win(old_buf, true, float_opts) + end) + it('if called from non-floating window', function() + meths.set_current_win(old_win) + eq('Vim:E444: Cannot close last window', + pcall_err(meths.win_close, old_win, false)) + end) + it('if called from floating window', function() + eq('Vim:E444: Cannot close last window', + pcall_err(meths.win_close, old_win, false)) + end) + end) + describe("deleting the last non-floating window's buffer", function() + describe('leaves one window with an empty buffer when there is only one buffer', function() + local same_buf_float + before_each(function() + same_buf_float = meths.open_win(old_buf, false, float_opts).id + end) + after_each(function() + eq(old_win, curwin().id) + expect('') + eq(1, #meths.list_wins()) + end) + it('if called from non-floating window', function() + meths.buf_delete(old_buf, {force = true}) + end) + it('if called from floating window', function() + meths.set_current_win(same_buf_float) + command('autocmd WinLeave * let g:win_leave = nvim_get_current_win()') + command('autocmd WinEnter * let g:win_enter = nvim_get_current_win()') + meths.buf_delete(old_buf, {force = true}) + eq(same_buf_float, eval('g:win_leave')) + eq(old_win, eval('g:win_enter')) + end) + end) + describe('closes other windows with that buffer when there are other buffers', function() + local same_buf_float, other_buf, other_buf_float + before_each(function() + same_buf_float = meths.open_win(old_buf, false, float_opts).id + other_buf = meths.create_buf(true, false).id + other_buf_float = meths.open_win(other_buf, true, float_opts).id + insert('bar') + meths.set_current_win(old_win) + end) + after_each(function() + eq(other_buf, curbuf().id) + expect('bar') + eq(2, #meths.list_wins()) + end) + it('if called from non-floating window', function() + meths.buf_delete(old_buf, {force = true}) + eq(old_win, curwin().id) + end) + it('if called from floating window with the same buffer', function() + meths.set_current_win(same_buf_float) + command('autocmd WinLeave * let g:win_leave = nvim_get_current_win()') + command('autocmd WinEnter * let g:win_enter = nvim_get_current_win()') + meths.buf_delete(old_buf, {force = true}) + eq(same_buf_float, eval('g:win_leave')) + eq(old_win, eval('g:win_enter')) + eq(old_win, curwin().id) + end) + -- TODO: this case is too hard to deal with + pending('if called from floating window with another buffer', function() + meths.set_current_win(other_buf_float) + meths.buf_delete(old_buf, {force = true}) + end) + end) + describe('creates an empty buffer when there is only one listed buffer', function() + local same_buf_float, unlisted_buf_float + before_each(function() + same_buf_float = meths.open_win(old_buf, false, float_opts).id + local unlisted_buf = meths.create_buf(true, false).id + unlisted_buf_float = meths.open_win(unlisted_buf, true, float_opts).id + insert('unlisted') + command('set nobuflisted') + meths.set_current_win(old_win) + end) + after_each(function() + expect('') + eq(2, #meths.list_wins()) + end) + it('if called from non-floating window', function() + meths.buf_delete(old_buf, {force = true}) + eq(old_win, curwin().id) + end) + it('if called from floating window with the same buffer', function() + meths.set_current_win(same_buf_float) + command('autocmd WinLeave * let g:win_leave = nvim_get_current_win()') + command('autocmd WinEnter * let g:win_enter = nvim_get_current_win()') + meths.buf_delete(old_buf, {force = true}) + eq(same_buf_float, eval('g:win_leave')) + eq(old_win, eval('g:win_enter')) + eq(old_win, curwin().id) + end) + -- TODO: this case is too hard to deal with + pending('if called from floating window with an unlisted buffer', function() + meths.set_current_win(unlisted_buf_float) + meths.buf_delete(old_buf, {force = true}) + end) + end) + end) + describe('with splits, deleting the last listed buffer creates an empty buffer', function() + describe('when a non-floating window has an unlisted buffer', function() + local same_buf_float + before_each(function() + command('botright vnew') + insert('unlisted') + command('set nobuflisted') + meths.set_current_win(old_win) + same_buf_float = meths.open_win(old_buf, false, float_opts).id + end) + after_each(function() + expect('') + eq(2, #meths.list_wins()) + end) + it('if called from non-floating window with the deleted buffer', function() + meths.buf_delete(old_buf, {force = true}) + eq(old_win, curwin().id) + end) + it('if called from floating window with the deleted buffer', function() + meths.set_current_win(same_buf_float) + meths.buf_delete(old_buf, {force = true}) + eq(same_buf_float, curwin().id) + end) + end) + end) + end) + + describe('with mulitple tabpages but only one listed buffer,', function() + local float_opts = {relative = 'editor', row = 1, col = 1, width = 1, height = 1} + local unlisted_buf, old_buf, old_win + before_each(function() + insert('unlisted') + command('set nobuflisted') + unlisted_buf = curbuf().id + command('tabnew') + insert('foo') + old_buf = curbuf().id + old_win = curwin().id + end) + describe('without splits, deleting the last listed buffer creates an empty buffer', function() + local same_buf_float + before_each(function() + meths.set_current_win(old_win) + same_buf_float = meths.open_win(old_buf, false, float_opts).id + end) + after_each(function() + expect('') + eq(2, #meths.list_wins()) + eq(2, #meths.list_tabpages()) + end) + it('if called from non-floating window', function() + meths.buf_delete(old_buf, {force = true}) + eq(old_win, curwin().id) + end) + it('if called from floating window with the same buffer', function() + meths.set_current_win(same_buf_float) + command('autocmd WinLeave * let g:win_leave = nvim_get_current_win()') + command('autocmd WinEnter * let g:win_enter = nvim_get_current_win()') + meths.buf_delete(old_buf, {force = true}) + eq(same_buf_float, eval('g:win_leave')) + eq(old_win, eval('g:win_enter')) + eq(old_win, curwin().id) + end) + end) + describe('with splits, deleting the last listed buffer creates an empty buffer', function() + local same_buf_float + before_each(function() + command('botright vsplit') + meths.set_current_buf(unlisted_buf) + meths.set_current_win(old_win) + same_buf_float = meths.open_win(old_buf, false, float_opts).id + end) + after_each(function() + expect('') + eq(3, #meths.list_wins()) + eq(2, #meths.list_tabpages()) + end) + it('if called from non-floating window with the deleted buffer', function() + meths.buf_delete(old_buf, {force = true}) + eq(old_win, curwin().id) + end) + it('if called from floating window with the deleted buffer', function() + meths.set_current_win(same_buf_float) + meths.buf_delete(old_buf, {force = true}) + eq(same_buf_float, curwin().id) + end) + end) + end) + + describe('with multiple tabpages and multiple listed buffers,', function() + local float_opts = {relative = 'editor', row = 1, col = 1, width = 1, height = 1} + local old_tabpage, old_buf, old_win + before_each(function() + old_tabpage = curtab().id + insert('oldtab') + command('tabnew') + old_buf = curbuf().id + old_win = curwin().id + end) + describe('closing the last non-floating window', function() + describe('closes the tabpage when all floating windows are closeable', function() + local same_buf_float + before_each(function() + same_buf_float = meths.open_win(old_buf, false, float_opts).id + end) + after_each(function() + eq(old_tabpage, curtab().id) + expect('oldtab') + eq(1, #meths.list_tabpages()) + end) + it('if called from non-floating window', function() + meths.win_close(old_win, false) + end) + it('if called from floating window', function() + meths.set_current_win(same_buf_float) + meths.win_close(old_win, false) + end) + end) + describe('gives E5601 when there are non-closeable floating windows', function() + local other_buf_float + before_each(function() + command('set nohidden') + local other_buf = meths.create_buf(true, false).id + other_buf_float = meths.open_win(other_buf, true, float_opts).id + insert('foo') + meths.set_current_win(old_win) + end) + it('if called from non-floating window', function() + eq('Vim:E5601: Cannot close window, only floating window would remain', + pcall_err(meths.win_close, old_win, false)) + end) + it('if called from floating window', function() + meths.set_current_win(other_buf_float) + eq('Vim:E5601: Cannot close window, only floating window would remain', + pcall_err(meths.win_close, old_win, false)) + end) + end) + end) + describe("deleting the last non-floating window's buffer", function() + describe('closes the tabpage when all floating windows are closeable', function() + local same_buf_float, other_buf, other_buf_float + before_each(function() + same_buf_float = meths.open_win(old_buf, false, float_opts).id + other_buf = meths.create_buf(true, false).id + other_buf_float = meths.open_win(other_buf, true, float_opts).id + meths.set_current_win(old_win) + end) + after_each(function() + eq(old_tabpage, curtab().id) + expect('oldtab') + eq(1, #meths.list_tabpages()) + end) + it('if called from non-floating window', function() + meths.buf_delete(old_buf, {force = false}) + end) + it('if called from floating window with the same buffer', function() + meths.set_current_win(same_buf_float) + meths.buf_delete(old_buf, {force = false}) + end) + -- TODO: this case is too hard to deal with + pending('if called from floating window with another buffer', function() + meths.set_current_win(other_buf_float) + meths.buf_delete(old_buf, {force = false}) + end) + end) + -- TODO: what to do when there are non-closeable floating windows? + end) + end) + local function with_ext_multigrid(multigrid) local screen before_each(function() @@ -3376,10 +3660,10 @@ describe('float window', function() screen:expect{grid=[[ ## grid 1 [2:----------------------------------------]| - {5:[No Name] }| - [5:----------------------------------------]| - [5:----------------------------------------]| - [5:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| {5:[Preview] }| [3:----------------------------------------]| ## grid 2 @@ -3390,10 +3674,6 @@ describe('float window', function() {17:f}{1:oo }| {17:b}{1:ar }| {1: }| - ## grid 5 - |1| {17:f}oo | - |2| {17:b}ar | - {0:~ }| ]], float_pos=expected_pos} else screen:expect([[ @@ -4169,7 +4449,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x | @@ -4207,7 +4487,7 @@ describe('float window', function() ## grid 4 {1:^y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -4243,7 +4523,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x | @@ -4283,7 +4563,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x | @@ -4319,7 +4599,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x | @@ -4357,7 +4637,7 @@ describe('float window', function() ## grid 4 {1:^y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -4393,7 +4673,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x | @@ -4431,7 +4711,7 @@ describe('float window', function() ## grid 4 {1:^y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else meths.input_mouse('left', 'press', '', 0, 2, 5) screen:expect([[ @@ -4468,7 +4748,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else meths.input_mouse('left', 'press', '', 0, 0, 0) screen:expect([[ @@ -4510,7 +4790,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else meths.input_mouse('left', 'press', '', 0, 2, 5) screen:expect([[ @@ -4547,7 +4827,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos, unchanged=true} + ]], float_pos=expected_pos, unchanged=true} else meths.input_mouse('left', 'press', '', 0, 0, 0) screen:expect([[ @@ -4562,7 +4842,6 @@ describe('float window', function() end end) - it("j", function() feed("<c-w>ji") -- INSERT to trigger screen change if multigrid then @@ -4587,7 +4866,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x | @@ -4623,7 +4902,7 @@ describe('float window', function() ## grid 4 {1:^y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -4659,7 +4938,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x | @@ -4698,7 +4977,7 @@ describe('float window', function() ## grid 4 {1:^y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -4886,7 +5165,7 @@ describe('float window', function() ## grid 4 {1:^y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -5067,7 +5346,7 @@ describe('float window', function() ## grid 5 ^x | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x | @@ -5102,7 +5381,7 @@ describe('float window', function() ## grid 5 x | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -5137,7 +5416,7 @@ describe('float window', function() ## grid 5 x | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -5173,7 +5452,7 @@ describe('float window', function() ## grid 5 ^x | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x | @@ -5210,7 +5489,7 @@ describe('float window', function() ## grid 5 ^y | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^y | @@ -5245,7 +5524,7 @@ describe('float window', function() ## grid 5 y | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ y | @@ -5280,7 +5559,7 @@ describe('float window', function() ## grid 5 y | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ y | @@ -5317,7 +5596,7 @@ describe('float window', function() ## grid 5 ^ | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^ | @@ -5354,7 +5633,7 @@ describe('float window', function() ## grid 5 ^ | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^ | @@ -5397,7 +5676,7 @@ describe('float window', function() {0:~ }| {0:~ }| {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^x {5:│}x | @@ -5440,17 +5719,17 @@ describe('float window', function() {0:~ }| {0:~ }| {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else - screen:expect([[ - ^ {5:│}x | - {0:~ }{5:│}{0:~ }| - {0:~ }{1:y }{0: }| - {0:~ }{2:~ }{0: }| - {0:~ }{5:│}{0:~ }| - {4:[No Name] }{5:[No Name] [+] }| - :vnew | - ]]) + screen:expect([[ + ^ {5:│}x | + {0:~ }{5:│}{0:~ }| + {0:~ }{1:y }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }{5:│}{0:~ }| + {4:[No Name] }{5:[No Name] [+] }| + :vnew | + ]]) end end) @@ -5483,7 +5762,7 @@ describe('float window', function() {0:~ }| {0:~ }| {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ ^ {5:│}x | @@ -5553,7 +5832,7 @@ describe('float window', function() [4] = {{id = 1001}, "NW", 1, 2, 5, true}, [5] = {{id = 1002}, "NW", 1, 4, 8, true} }} - else + else screen:expect([[ x | {0:~ }| @@ -5574,7 +5853,7 @@ describe('float window', function() [2:----------------------------------------]| [2:----------------------------------------]| [2:----------------------------------------]| - {5:[No Name] [+] }| + [2:----------------------------------------]| [3:----------------------------------------]| ## grid 2 x | @@ -5582,6 +5861,7 @@ describe('float window', function() {0:~ }| {0:~ }| {0:~ }| + {0:~ }| ## grid 3 :quit | ## grid 4 @@ -5590,14 +5870,14 @@ describe('float window', function() ]], float_pos={ [4] = {{id = 1001}, "NW", 1, 2, 5, true}, }} - else + else screen:expect([[ x | {0:~ }| {0:~ }{1:^y }{0: }| {0:~ }{2:~ }{0: }| {0:~ }| - {5:[No Name] [+] }| + {0:~ }| :quit | ]]) end @@ -5659,7 +5939,7 @@ describe('float window', function() {0:~ }| ## grid 3 | - ]]} + ]]} else screen:expect([[ ^x | @@ -5699,7 +5979,7 @@ describe('float window', function() ## grid 4 {1:y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -5736,7 +6016,7 @@ describe('float window', function() ## grid 4 {1:^y }| {2:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -5806,7 +6086,7 @@ describe('float window', function() {0:~ }| {0:~ }| {0:~ }| - ]]} + ]]} else screen:expect([[ ^x | @@ -5843,7 +6123,7 @@ describe('float window', function() ## grid 5 x | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -5880,7 +6160,7 @@ describe('float window', function() ## grid 5 x | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else screen:expect([[ x | @@ -5914,7 +6194,7 @@ describe('float window', function() ## grid 4 ^y | {0:~ }| - ]]} + ]]} else screen:expect([[ x | @@ -5950,7 +6230,7 @@ describe('float window', function() ## grid 4 ^y | {0:~ }| - ]], float_pos=expected_pos} + ]], float_pos=expected_pos} else eq("UI doesn't support external windows", pcall_err(meths.win_set_config, 0, {external=true, width=30, height=2})) @@ -5980,6 +6260,78 @@ describe('float window', function() end end) + it('J (float with border)', function() + meths.win_set_config(win, {relative='editor', width=20, height=2, row=2, col=5, border='single'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^x | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + {5:┌────────────────────┐}| + {5:│}{1:y }{5:│}| + {5:│}{2:~ }{5:│}| + {5:└────────────────────┘}| + ]], float_pos=expected_pos} + else + screen:expect([[ + ^x | + {0:~ }| + {0:~ }{5:┌────────────────────┐}{0: }| + {0:~ }{5:│}{1:y }{5:│}{0: }| + {0:~ }{5:│}{2:~ }{5:│}{0: }| + {0:~ }{5:└────────────────────┘}{0: }| + | + ]]) + end + + feed("<c-w>w<c-w>J") + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + {5:[No Name] [+] }| + [4:----------------------------------------]| + [4:----------------------------------------]| + {4:[No Name] [+] }| + [3:----------------------------------------]| + ## grid 2 + x | + {0:~ }| + ## grid 3 + | + ## grid 4 + ^y | + {0:~ }| + ]]} + else + screen:expect([[ + x | + {0:~ }| + {5:[No Name] [+] }| + ^y | + {0:~ }| + {4:[No Name] [+] }| + | + ]]) + end + end) + it('movements with nested split layout', function() command("set hidden") feed("<c-w>s<c-w>v<c-w>b<c-w>v") @@ -6342,7 +6694,7 @@ describe('float window', function() it("left drag changes visual selection in float window", function() local buf = meths.create_buf(false,false) - meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar'}) + meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'}) meths.open_win(buf, false, {relative='editor', width=20, height=3, row=2, col=5}) if multigrid then screen:expect{grid=[[ @@ -6366,13 +6718,14 @@ describe('float window', function() ## grid 5 {1:foo }| {1:bar }| - {2:~ }| + {1:baz }| ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50}; }, win_viewport={ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 2}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; }} + meths.input_mouse('left', 'press', '', 5, 0, 0) screen:expect{grid=[[ ## grid 1 @@ -6395,13 +6748,14 @@ describe('float window', function() ## grid 5 {1:^foo }| {1:bar }| - {2:~ }| + {1:baz }| ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50}; }, win_viewport={ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 2}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; }} + meths.input_mouse('left', 'drag', '', 5, 1, 2) screen:expect{grid=[[ ## grid 1 @@ -6424,12 +6778,12 @@ describe('float window', function() ## grid 5 {27:foo}{1: }| {27:ba}{1:^r }| - {2:~ }| + {1:baz }| ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50}; }, win_viewport={ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 2}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3}; }} else screen:expect{grid=[[ @@ -6437,7 +6791,7 @@ describe('float window', function() {0:~ }| {0:~ }{1:foo }{0: }| {0:~ }{1:bar }{0: }| - {0:~ }{2:~ }{0: }| + {0:~ }{1:baz }{0: }| {0:~ }| | ]]} @@ -6448,7 +6802,7 @@ describe('float window', function() {0:~ }| {0:~ }{1:^foo }{0: }| {0:~ }{1:bar }{0: }| - {0:~ }{2:~ }{0: }| + {0:~ }{1:baz }{0: }| {0:~ }| | ]]} @@ -6459,13 +6813,396 @@ describe('float window', function() {0:~ }| {0:~ }{27:foo}{1: }{0: }| {0:~ }{27:ba}{1:^r }{0: }| - {0:~ }{2:~ }{0: }| + {0:~ }{1:baz }{0: }| {0:~ }| {3:-- VISUAL --} | ]]} end end) + it("left drag changes visual selection in float window with border", function() + local buf = meths.create_buf(false,false) + meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'}) + meths.open_win(buf, false, {relative='editor', width=20, height=3, row=0, col=5, border='single'}) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {5:┌────────────────────┐}| + {5:│}{1:foo }{5:│}| + {5:│}{1:bar }{5:│}| + {5:│}{1:baz }{5:│}| + {5:└────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "NW", 1, 0, 5, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + }} + + meths.input_mouse('left', 'press', '', 5, 1, 1) + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {5:┌────────────────────┐}| + {5:│}{1:^foo }{5:│}| + {5:│}{1:bar }{5:│}| + {5:│}{1:baz }{5:│}| + {5:└────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "NW", 1, 0, 5, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + }} + + meths.input_mouse('left', 'drag', '', 5, 2, 3) + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {3:-- VISUAL --} | + ## grid 5 + {5:┌────────────────────┐}| + {5:│}{27:foo}{1: }{5:│}| + {5:│}{27:ba}{1:^r }{5:│}| + {5:│}{1:baz }{5:│}| + {5:└────────────────────┘}| + ]], float_pos={ + [5] = {{id = 1002}, "NW", 1, 0, 5, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3}; + }} + else + screen:expect{grid=[[ + ^ {5:┌────────────────────┐} | + {0:~ }{5:│}{1:foo }{5:│}{0: }| + {0:~ }{5:│}{1:bar }{5:│}{0: }| + {0:~ }{5:│}{1:baz }{5:│}{0: }| + {0:~ }{5:└────────────────────┘}{0: }| + {0:~ }| + | + ]]} + + meths.input_mouse('left', 'press', '', 0, 1, 6) + screen:expect{grid=[[ + {5:┌────────────────────┐} | + {0:~ }{5:│}{1:^foo }{5:│}{0: }| + {0:~ }{5:│}{1:bar }{5:│}{0: }| + {0:~ }{5:│}{1:baz }{5:│}{0: }| + {0:~ }{5:└────────────────────┘}{0: }| + {0:~ }| + | + ]]} + + meths.input_mouse('left', 'drag', '', 0, 2, 8) + screen:expect{grid=[[ + {5:┌────────────────────┐} | + {0:~ }{5:│}{27:foo}{1: }{5:│}{0: }| + {0:~ }{5:│}{27:ba}{1:^r }{5:│}{0: }| + {0:~ }{5:│}{1:baz }{5:│}{0: }| + {0:~ }{5:└────────────────────┘}{0: }| + {0:~ }| + {3:-- VISUAL --} | + ]]} + end + end) + + it("left drag changes visual selection in float window with winbar", function() + local buf = meths.create_buf(false,false) + meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'}) + local float_win = meths.open_win(buf, false, {relative='editor', width=20, height=4, row=1, col=5}) + meths.win_set_option(float_win, 'winbar', 'floaty bar') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {3:floaty bar }| + {1:foo }| + {1:bar }| + {1:baz }| + ]], float_pos={ + [5] = {{id = 1002}, "NW", 1, 1, 5, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + }} + + meths.input_mouse('left', 'press', '', 5, 1, 0) + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + {3:floaty bar }| + {1:^foo }| + {1:bar }| + {1:baz }| + ]], float_pos={ + [5] = {{id = 1002}, "NW", 1, 1, 5, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + }} + + meths.input_mouse('left', 'drag', '', 5, 2, 2) + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {3:-- VISUAL --} | + ## grid 5 + {3:floaty bar }| + {27:foo}{1: }| + {27:ba}{1:^r }| + {1:baz }| + ]], float_pos={ + [5] = {{id = 1002}, "NW", 1, 1, 5, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }{3:floaty bar }{0: }| + {0:~ }{1:foo }{0: }| + {0:~ }{1:bar }{0: }| + {0:~ }{1:baz }{0: }| + {0:~ }| + | + ]]} + + meths.input_mouse('left', 'press', '', 0, 2, 5) + screen:expect{grid=[[ + | + {0:~ }{3:floaty bar }{0: }| + {0:~ }{1:^foo }{0: }| + {0:~ }{1:bar }{0: }| + {0:~ }{1:baz }{0: }| + {0:~ }| + | + ]]} + + meths.input_mouse('left', 'drag', '', 0, 3, 7) + screen:expect{grid=[[ + | + {0:~ }{3:floaty bar }{0: }| + {0:~ }{27:foo}{1: }{0: }| + {0:~ }{27:ba}{1:^r }{0: }| + {0:~ }{1:baz }{0: }| + {0:~ }| + {3:-- VISUAL --} | + ]]} + end + end) + + it('left drag changes visual selection if float window is turned into a split', function() + local buf = meths.create_buf(false,false) + meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'}) + meths.open_win(buf, true, {relative='editor', width=20, height=3, row=2, col=5}) + command('wincmd L') + if multigrid then + screen:expect([[ + ## grid 1 + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + {5:[No Name] }{4:[No Name] [+] }| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + ^foo | + bar | + baz | + {0:~ }| + {0:~ }| + ]]) + + meths.input_mouse('left', 'press', '', 5, 2, 2) + screen:expect([[ + ## grid 1 + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + {5:[No Name] }{4:[No Name] [+] }| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + foo | + bar | + ba^z | + {0:~ }| + {0:~ }| + ]]) + + meths.input_mouse('left', 'drag', '', 5, 1, 1) + screen:expect([[ + ## grid 1 + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + [2:-------------------]{5:│}[5:--------------------]| + {5:[No Name] }{4:[No Name] [+] }| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + {3:-- VISUAL --} | + ## grid 5 + foo | + b^a{27:r} | + {27:baz} | + {0:~ }| + {0:~ }| + ]]) + else + screen:expect([[ + {5:│}^foo | + {0:~ }{5:│}bar | + {0:~ }{5:│}baz | + {0:~ }{5:│}{0:~ }| + {0:~ }{5:│}{0:~ }| + {5:[No Name] }{4:[No Name] [+] }| + | + ]]) + + meths.input_mouse('left', 'press', '', 0, 2, 22) + screen:expect([[ + {5:│}foo | + {0:~ }{5:│}bar | + {0:~ }{5:│}ba^z | + {0:~ }{5:│}{0:~ }| + {0:~ }{5:│}{0:~ }| + {5:[No Name] }{4:[No Name] [+] }| + | + ]]) + + meths.input_mouse('left', 'drag', '', 0, 1, 21) + screen:expect([[ + {5:│}foo | + {0:~ }{5:│}b^a{27:r} | + {0:~ }{5:│}{27:baz} | + {0:~ }{5:│}{0:~ }| + {0:~ }{5:│}{0:~ }| + {5:[No Name] }{4:[No Name] [+] }| + {3:-- VISUAL --} | + ]]) + end + end) + it("'winblend' option", function() screen:try_resize(50,9) screen:set_default_attr_ids({ @@ -7306,6 +8043,100 @@ describe('float window', function() ]]} end end) + + it('can use winbar', function() + local buf = meths.create_buf(false,false) + local win1 = meths.open_win(buf, false, {relative='editor', width=15, height=3, row=1, col=5}) + meths.win_set_option(win1, 'winbar', 'floaty bar') + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + {3:floaty bar }| + {1: }| + {2:~ }| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 1, 5, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }{3:floaty bar }{0: }| + {0:~ }{1: }{0: }| + {0:~ }{2:~ }{0: }| + {0:~ }| + {0:~ }| + | + ]]} + end + + -- resize and add a border + meths.win_set_config(win1, {relative='editor', width=15, height=4, row=0, col=4, border = 'single'}) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + {5:┌───────────────┐}| + {5:│}{3:floaty bar }{5:│}| + {5:│}{1: }{5:│}| + {5:│}{2:~ }{5:│}| + {5:│}{2:~ }{5:│}| + {5:└───────────────┘}| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 0, 4, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + else + screen:expect{grid=[[ + ^ {5:┌───────────────┐} | + {0:~ }{5:│}{3:floaty bar }{5:│}{0: }| + {0:~ }{5:│}{1: }{5:│}{0: }| + {0:~ }{5:│}{2:~ }{5:│}{0: }| + {0:~ }{5:│}{2:~ }{5:│}{0: }| + {0:~ }{5:└───────────────┘}{0: }| + | + ]]} + end + end) end describe('with ext_multigrid', function() diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index 3e0e15c2b7..394f2f5f49 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -21,12 +21,14 @@ local content1 = [[ describe("folded lines", function() before_each(function() clear() + command('hi VertSplit gui=reverse') end) local function with_ext_multigrid(multigrid) local screen before_each(function() clear() + command('hi VertSplit gui=reverse') screen = Screen.new(45, 8) screen:attach({rgb=true, ext_multigrid=multigrid}) screen:set_default_attr_ids({ @@ -1672,7 +1674,7 @@ describe("folded lines", function() end -- relax the maximum fdc thus fdc should expand to - -- accomodate the current number of folds + -- accommodate the current number of folds command("set foldcolumn=auto:4") if multigrid then screen:expect([[ @@ -1755,6 +1757,67 @@ describe("folded lines", function() end assert_alive() end) + + it('work correctly with :move #18668', function() + screen:try_resize(45, 12) + source([[ + set foldmethod=expr foldexpr=indent(v:lnum) + let content = ['', '', 'Line1', ' Line2', ' Line3', + \ 'Line4', ' Line5', ' Line6', + \ 'Line7', ' Line8', ' Line9'] + call append(0, content) + normal! zM + call cursor(4, 1) + move 2 + move 1 + ]]) + if multigrid then + screen:expect([[ + ## grid 1 + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [2:---------------------------------------------]| + [3:---------------------------------------------]| + ## grid 2 + | + {5:^+-- 2 lines: Line2··························}| + | + Line1 | + Line4 | + {5:+-- 2 lines: Line5··························}| + Line7 | + {5:+-- 2 lines: Line8··························}| + | + {1:~ }| + {1:~ }| + ## grid 3 + | + ]]) + else + screen:expect([[ + | + {5:^+-- 2 lines: Line2··························}| + | + Line1 | + Line4 | + {5:+-- 2 lines: Line5··························}| + Line7 | + {5:+-- 2 lines: Line8··························}| + | + {1:~ }| + {1:~ }| + | + ]]) + end + end) end describe("with ext_multigrid", function() diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 255180bba8..946129b082 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local os = require('os') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command = helpers.command +local command, exec = helpers.command, helpers.exec local eval, exc_exec = helpers.eval, helpers.exc_exec local feed_command, eq = helpers.feed_command, helpers.eq local curbufmeths = helpers.curbufmeths @@ -104,12 +104,12 @@ describe('highlight defaults', function() }) feed_command('sp', 'vsp', 'vsp') screen:expect([[ - ^ {2:│} {2:│} | - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| + ^ │ │ | + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| {1:[No Name] }{2:[No Name] [No Name] }| | {0:~ }| @@ -122,12 +122,12 @@ describe('highlight defaults', function() -- navigate to verify that the attributes are properly moved feed('<c-w>j') screen:expect([[ - {2:│} {2:│} | - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| + │ │ | + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| {2:[No Name] [No Name] [No Name] }| ^ | {0:~ }| @@ -142,12 +142,12 @@ describe('highlight defaults', function() -- (upstream vim has the same behavior) feed('<c-w>k<c-w>l') screen:expect([[ - {2:│}^ {2:│} | - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| + │^ │ | + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| {2:[No Name] }{1:[No Name] }{2:[No Name] }| | {0:~ }| @@ -159,12 +159,12 @@ describe('highlight defaults', function() ]]) feed('<c-w>l') screen:expect([[ - {2:│} {2:│}^ | - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| + │ │^ | + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| {2:[No Name] [No Name] }{1:[No Name] }| | {0:~ }| @@ -176,12 +176,12 @@ describe('highlight defaults', function() ]]) feed('<c-w>h<c-w>h') screen:expect([[ - ^ {2:│} {2:│} | - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| - {0:~ }{2:│}{0:~ }{2:│}{0:~ }| + ^ │ │ | + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| {1:[No Name] }{2:[No Name] [No Name] }| | {0:~ }| @@ -840,7 +840,7 @@ describe("'listchars' highlight", function() end) end) -describe('CursorLine highlight', function() +describe('CursorLine and CursorLineNr highlights', function() before_each(clear) it('overridden by Error, ColorColumn if fg not set', function() @@ -938,17 +938,18 @@ describe('CursorLine highlight', function() [2] = {foreground = Screen.colors.Yellow}; [3] = {foreground = Screen.colors.Red, background = Screen.colors.Green}; [4] = {foreground = Screen.colors.Green, background = Screen.colors.Red}; + [5] = {bold = true}, -- ModeMsg }) screen:attach() - feed_command('set wrap cursorline cursorlineopt=screenline') - feed_command('set showbreak=>>>') - feed_command('highlight clear NonText') - feed_command('highlight clear CursorLine') - feed_command('highlight NonText guifg=Yellow gui=NONE') - feed_command('highlight LineNr guifg=Red guibg=Green gui=NONE') - feed_command('highlight CursorLine guifg=Black guibg=White gui=NONE') - feed_command('highlight CursorLineNr guifg=Green guibg=Red gui=NONE') + command('set wrap cursorline cursorlineopt=screenline') + command('set showbreak=>>>') + command('highlight clear NonText') + command('highlight clear CursorLine') + command('highlight NonText guifg=Yellow gui=NONE') + command('highlight LineNr guifg=Red guibg=Green gui=NONE') + command('highlight CursorLine guifg=Black guibg=White gui=NONE') + command('highlight CursorLineNr guifg=Green guibg=Red gui=NONE') feed('30iø<esc>o<esc>30ia<esc>') @@ -978,7 +979,7 @@ describe('CursorLine highlight', function() ]]) -- CursorLineNr should not apply to line number when 'cursorlineopt' does not contain "number" - feed_command('set relativenumber numberwidth=2') + command('set relativenumber numberwidth=2') screen:expect([[ {3:0 }{1:øøøøøøøøøøøø^øøøøøø}| {3: }{2:>>>}øøøøøøøøøøøø | @@ -988,7 +989,7 @@ describe('CursorLine highlight', function() ]]) -- CursorLineNr should apply to line number when 'cursorlineopt' contains "number" - feed_command('set cursorlineopt+=number') + command('set cursorlineopt+=number') screen:expect([[ {4:0 }{1:øøøøøøøøøøøø^øøøøøø}| {3: }{2:>>>}øøøøøøøøøøøø | @@ -1020,6 +1021,44 @@ describe('CursorLine highlight', function() {3: }{2:>>>}{1:aaaaaaaaa^aaa }| | ]]) + + -- updated in Insert mode + feed('I') + screen:expect([[ + {3:1 }øøøøøøøøøøøøøøøøøø| + {3: }{2:>>>}øøøøøøøøøøøø | + {4:0 }{1:^aaaaaaaaaaaaaaaaaa}| + {3: }{2:>>>}aaaaaaaaaaaa | + {5:-- INSERT --} | + ]]) + + feed('<Esc>gg') + screen:expect([[ + {4:0 }{1:^øøøøøøøøøøøøøøøøøø}| + {3: }{2:>>>}øøøøøøøøøøøø | + {3:1 }aaaaaaaaaaaaaaaaaa| + {3: }{2:>>>}aaaaaaaaaaaa | + | + ]]) + + command('inoremap <F2> <Cmd>call cursor(1, 1)<CR>') + feed('A') + screen:expect([[ + {4:0 }øøøøøøøøøøøøøøøøøø| + {3: }{2:>>>}{1:øøøøøøøøøøøø^ }| + {3:1 }aaaaaaaaaaaaaaaaaa| + {3: }{2:>>>}aaaaaaaaaaaa | + {5:-- INSERT --} | + ]]) + + feed('<F2>') + screen:expect([[ + {4:0 }{1:^øøøøøøøøøøøøøøøøøø}| + {3: }{2:>>>}øøøøøøøøøøøø | + {3:1 }aaaaaaaaaaaaaaaaaa| + {3: }{2:>>>}aaaaaaaaaaaa | + {5:-- INSERT --} | + ]]) end) it('always updated. vim-patch:8.1.0849', function() @@ -1082,7 +1121,47 @@ describe('CursorLine highlight', function() ]]) end) - it('with split-windows in diff-mode', function() + it('is updated if cursor is moved up from timer vim-patch:8.2.4591', function() + local screen = Screen.new(50, 8) + screen:set_default_attr_ids({ + [1] = {background = Screen.colors.Gray90}, -- CursorLine + [2] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText + }) + screen:attach() + exec([[ + call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd']) + set cursorline + call cursor(4, 1) + + func Func(timer) + call cursor(2, 1) + endfunc + + call timer_start(300, 'Func') + ]]) + screen:expect({grid = [[ + aaaaa | + bbbbb | + ccccc | + {1:^ddddd }| + {2:~ }| + {2:~ }| + {2:~ }| + | + ]], timeout = 100}) + screen:expect({grid = [[ + aaaaa | + {1:^bbbbb }| + ccccc | + ddddd | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]}) + end) + + it('with split windows in diff mode', function() local screen = Screen.new(50,12) screen:set_default_attr_ids({ [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray}, @@ -1094,7 +1173,6 @@ describe('CursorLine highlight', function() [7] = {background = Screen.colors.Red, foreground = Screen.colors.White}, [8] = {bold = true, foreground = Screen.colors.Blue1}, [9] = {bold = true, reverse = true}, - [10] = {bold = true}, }) screen:attach() @@ -1108,31 +1186,31 @@ describe('CursorLine highlight', function() feed('<esc>gg') command('windo diffthis') screen:expect([[ - {1: }{7:line 1 some text }{4:│}{1: }{7:^line 1 some text }| - {1: }{3:line 2 mo}{2:Re text!}{3: }{4:│}{1: }{3:line 2 mo}{2:re text}{3: }| - {1: }{5:extra line! }{4:│}{1: }{6:----------------------}| - {1: }extra line! {4:│}{1: }extra line! | - {1: }extra line! {4:│}{1: }extra line! | - {1: }last line ... {4:│}{1: }last line ... | - {1: } {4:│}{1: } | - {8:~ }{4:│}{8:~ }| - {8:~ }{4:│}{8:~ }| - {8:~ }{4:│}{8:~ }| + {1: }{7:line 1 some text }│{1: }{7:^line 1 some text }| + {1: }{3:line 2 mo}{2:Re text!}{3: }│{1: }{3:line 2 mo}{2:re text}{3: }| + {1: }{5:extra line! }│{1: }{6:----------------------}| + {1: }extra line! │{1: }extra line! | + {1: }extra line! │{1: }extra line! | + {1: }last line ... │{1: }last line ... | + {1: } │{1: } | + {8:~ }│{8:~ }| + {8:~ }│{8:~ }| + {8:~ }│{8:~ }| {4:[No Name] [+] }{9:[No Name] [+] }| | ]]) feed('jjjjj') screen:expect([[ - {1: }line 1 some text {4:│}{1: }line 1 some text | - {1: }{3:line 2 mo}{2:Re text!}{3: }{4:│}{1: }{3:line 2 mo}{2:re text}{3: }| - {1: }{5:extra line! }{4:│}{1: }{6:----------------------}| - {1: }extra line! {4:│}{1: }extra line! | - {1: }extra line! {4:│}{1: }extra line! | - {1: }last line ... {4:│}{1: }last line ... | - {1: }{7: }{4:│}{1: }{7:^ }| - {8:~ }{4:│}{8:~ }| - {8:~ }{4:│}{8:~ }| - {8:~ }{4:│}{8:~ }| + {1: }line 1 some text │{1: }line 1 some text | + {1: }{3:line 2 mo}{2:Re text!}{3: }│{1: }{3:line 2 mo}{2:re text}{3: }| + {1: }{5:extra line! }│{1: }{6:----------------------}| + {1: }extra line! │{1: }extra line! | + {1: }extra line! │{1: }extra line! | + {1: }last line ... │{1: }last line ... | + {1: }{7: }│{1: }{7:^ }| + {8:~ }│{8:~ }| + {8:~ }│{8:~ }| + {8:~ }│{8:~ }| {4:[No Name] [+] }{9:[No Name] [+] }| | ]]) @@ -1142,16 +1220,16 @@ describe('CursorLine highlight', function() command('hi CursorLine ctermbg=red ctermfg=NONE guibg=red guifg=NONE') feed('kkkk') screen:expect([[ - {1: }line 1 some text {4:│}{1: }line 1 some text | - {1: }{11:line 2 mo}{12:Re text!}{11: }{4:│}{1: }{11:^line 2 mo}{12:re text}{11: }| - {1: }{5:extra line! }{4:│}{1: }{6:----------------------}| - {1: }extra line! {4:│}{1: }extra line! | - {1: }extra line! {4:│}{1: }extra line! | - {1: }last line ... {4:│}{1: }last line ... | - {1: } {4:│}{1: } | - {8:~ }{4:│}{8:~ }| - {8:~ }{4:│}{8:~ }| - {8:~ }{4:│}{8:~ }| + {1: }line 1 some text │{1: }line 1 some text | + {1: }{11:line 2 mo}{12:Re text!}{11: }│{1: }{11:^line 2 mo}{12:re text}{11: }| + {1: }{5:extra line! }│{1: }{6:----------------------}| + {1: }extra line! │{1: }extra line! | + {1: }extra line! │{1: }extra line! | + {1: }last line ... │{1: }last line ... | + {1: } │{1: } | + {8:~ }│{8:~ }| + {8:~ }│{8:~ }| + {8:~ }│{8:~ }| {4:[No Name] [+] }{9:[No Name] [+] }| | ]], { @@ -1171,8 +1249,261 @@ describe('CursorLine highlight', function() background = Screen.colors.Red}, }) end) + + it('CursorLineNr shows correctly just below filler lines', function() + local screen = Screen.new(50,12) + screen:set_default_attr_ids({ + [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray}, + [2] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1}, + [3] = {reverse = true}, + [4] = {background = Screen.colors.LightBlue}, + [5] = {background = Screen.colors.Red, foreground = Screen.colors.White}, + [6] = {background = Screen.colors.White, bold = true, foreground = Screen.colors.Black}, + [7] = {bold = true, foreground = Screen.colors.Blue1}, + [8] = {bold = true, reverse = true}, + [9] = {foreground = Screen.colors.Brown}, + }) + screen:attach() + + command('hi CursorLine guibg=red guifg=white') + command('hi CursorLineNr guibg=white guifg=black gui=bold') + command('set cursorline number') + command('call setline(1, ["baz", "foo", "foo", "bar"])') + feed('2gg0') + command('vnew') + command('call setline(1, ["foo", "foo", "bar"])') + command('windo diffthis') + command('1wincmd w') + screen:expect([[ + {1: }{9: }{2:-------------------}│{1: }{9: 1 }{4:baz }| + {1: }{6: 1 }{5:^foo }│{1: }{6: 2 }{5:foo }| + {1: }{9: 2 }foo │{1: }{9: 3 }foo | + {1: }{9: 3 }bar │{1: }{9: 4 }bar | + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {8:[No Name] [+] }{3:[No Name] [+] }| + | + ]]) + command('set cursorlineopt=number') + screen:expect([[ + {1: }{9: }{2:-------------------}│{1: }{9: 1 }{4:baz }| + {1: }{6: 1 }^foo │{1: }{6: 2 }{5:foo }| + {1: }{9: 2 }foo │{1: }{9: 3 }foo | + {1: }{9: 3 }bar │{1: }{9: 4 }bar | + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {7:~ }│{7:~ }| + {8:[No Name] [+] }{3:[No Name] [+] }| + | + ]]) + end) +end) + +describe('CursorColumn highlight', function() + local screen + before_each(function() + clear() + screen = Screen.new(50, 8) + screen:set_default_attr_ids({ + [1] = {background = Screen.colors.Gray90}, -- CursorColumn + [2] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText + [3] = {bold = true}, -- ModeMsg + }) + screen:attach() + end) + + it('is updated when pressing "i" on a TAB character', function() + exec([[ + call setline(1, ['123456789', "a\tb"]) + set cursorcolumn + call cursor(2, 2) + ]]) + screen:expect([[ + 1234567{1:8}9 | + a ^ b | + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]) + feed('i') + screen:expect([[ + 1{1:2}3456789 | + a^ b | + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {3:-- INSERT --} | + ]]) + feed('<C-O>') + screen:expect([[ + 1234567{1:8}9 | + a ^ b | + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {3:-- (insert) --} | + ]]) + feed('i') + screen:expect([[ + 1{1:2}3456789 | + a^ b | + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {3:-- INSERT --} | + ]]) + end) + + it('is updated if cursor is moved from timer', function() + exec([[ + call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd']) + set cursorcolumn + call cursor(4, 5) + + func Func(timer) + call cursor(1, 1) + endfunc + + call timer_start(300, 'Func') + ]]) + screen:expect({grid = [[ + aaaa{1:a} | + bbbb{1:b} | + cccc{1:c} | + dddd^d | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]], timeout = 100}) + screen:expect({grid = [[ + ^aaaaa | + {1:b}bbbb | + {1:c}cccc | + {1:d}dddd | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]}) + end) end) +describe('ColorColumn highlight', function() + local screen + + before_each(function() + clear() + screen = Screen.new(40, 15) + Screen:set_default_attr_ids({ + [1] = {background = Screen.colors.LightRed}, -- ColorColumn + [2] = {background = Screen.colors.Grey90}, -- CursorLine + [3] = {foreground = Screen.colors.Brown}, -- LineNr + [4] = {foreground = Screen.colors.Brown, bold = true}, -- CursorLineNr + [5] = {foreground = Screen.colors.Blue, bold = true}, -- NonText + -- NonText and ColorColumn + [6] = {foreground = Screen.colors.Blue, background = Screen.colors.LightRed, bold = true}, + [7] = {reverse = true, bold = true}, -- StatusLine + [8] = {reverse = true}, -- StatusLineNC + }) + screen:attach() + end) + + it('when entering a buffer vim-patch:8.1.2073', function() + exec([[ + set nohidden + split + edit X + call setline(1, ["1111111111","22222222222","3333333333"]) + set nomodified + set colorcolumn=3,9 + set number cursorline cursorlineopt=number + wincmd w + buf X + ]]) + screen:expect([[ + {4: 1 }11{1:1}11111{1:1}1 | + {3: 2 }22{1:2}22222{1:2}22 | + {3: 3 }33{1:3}33333{1:3}3 | + {5:~ }| + {5:~ }| + {5:~ }| + {8:X }| + {4: 1 }^11{1:1}11111{1:1}1 | + {3: 2 }22{1:2}22222{1:2}22 | + {3: 3 }33{1:3}33333{1:3}3 | + {5:~ }| + {5:~ }| + {5:~ }| + {7:X }| + | + ]]) + end) + + it("in 'breakindent' vim-patch:8.2.1689", function() + exec([[ + call setline(1, 'The quick brown fox jumped over the lazy dogs') + set co=40 linebreak bri briopt=shift:2 cc=40,41,43 + ]]) + screen:expect([[ + ^The quick brown fox jumped over the {1: }| + {1: } {1:l}azy dogs | + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + | + ]]) + end) + + it("in 'showbreak' vim-patch:8.2.1689", function() + exec([[ + call setline(1, 'The quick brown fox jumped over the lazy dogs') + set co=40 showbreak=+++>\\ cc=40,41,43 + ]]) + screen:expect([[ + ^The quick brown fox jumped over the laz{1:y}| + {6:+}{5:+}{6:+}{5:>\} dogs | + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + | + ]]) + end) +end) describe("MsgSeparator highlight and msgsep fillchar", function() local screen @@ -1378,6 +1709,46 @@ describe("'number' and 'relativenumber' highlight", function() | ]]) end) + + it('relative number highlight is updated if cursor is moved from timer', function() + local screen = Screen.new(50, 8) + screen:set_default_attr_ids({ + [1] = {foreground = Screen.colors.Brown}, -- LineNr + [2] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText + }) + screen:attach() + exec([[ + call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd']) + set relativenumber + call cursor(4, 1) + + func Func(timer) + call cursor(1, 1) + endfunc + + call timer_start(300, 'Func') + ]]) + screen:expect({grid = [[ + {1: 3 }aaaaa | + {1: 2 }bbbbb | + {1: 1 }ccccc | + {1: 0 }^ddddd | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]], timeout = 100}) + screen:expect({grid = [[ + {1: 0 }^aaaaa | + {1: 1 }bbbbb | + {1: 2 }ccccc | + {1: 3 }ddddd | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]}) + end) end) describe("'winhighlight' highlight", function() @@ -1478,8 +1849,7 @@ describe("'winhighlight' highlight", function() ]], unchanged=true} end) - - it('works local to the buffer', function() + it('works local to the window', function() insert("aa") command("split") command("setlocal winhl=Normal:Background1") @@ -1870,4 +2240,35 @@ describe("'winhighlight' highlight", function() | ]]} end) + + it('can override StatusLine and StatusLineNC', function() + command('set winhighlight=StatusLine:Background1,StatusLineNC:Background2') + command('split') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {1:[No Name] }| + | + {0:~ }| + {5:[No Name] }| + | + ]]) + end) + + it('can override WinBar and WinBarNC #19345', function() + command('setlocal winbar=foobar') + command('set winhighlight=WinBar:Background1,WinBarNC:Background2') + command('split') + screen:expect([[ + {1:foobar }| + ^ | + {0:~ }| + {3:[No Name] }| + {5:foobar }| + | + {4:[No Name] }| + | + ]]) + end) end) diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua index 2a567b28ee..df7f34aa7f 100644 --- a/test/functional/ui/hlstate_spec.lua +++ b/test/functional/ui/hlstate_spec.lua @@ -5,7 +5,7 @@ local clear, insert = helpers.clear, helpers.insert local command = helpers.command local meths = helpers.meths local iswin = helpers.iswin -local nvim_dir = helpers.nvim_dir +local testprg = helpers.testprg local thelpers = require('test.functional.terminal.helpers') describe('ext_hlstate detailed highlights', function() @@ -14,6 +14,7 @@ describe('ext_hlstate detailed highlights', function() before_each(function() clear() command('syntax on') + command('hi VertSplit gui=reverse') screen = Screen.new(40, 8) screen:attach({ext_hlstate=true}) end) @@ -59,7 +60,7 @@ describe('ext_hlstate detailed highlights', function() it('work with cleared UI highlights', function() screen:set_default_attr_ids({ - [1] = {{}, {{hi_name = "VertSplit", ui_name = "VertSplit", kind = "ui"}}}, + [1] = {{}, {{hi_name = "Normal", ui_name = "WinSeparator", kind = "ui"}}}, [2] = {{bold = true, foreground = Screen.colors.Blue1}, {{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}}, [3] = {{bold = true, reverse = true}, @@ -179,6 +180,8 @@ describe('ext_hlstate detailed highlights', function() end) it("work with :terminal", function() + if helpers.pending_win32(pending) then return end + screen:set_default_attr_ids({ [1] = {{}, {{hi_name = "TermCursorNC", ui_name = "TermCursorNC", kind = "ui"}}}, [2] = {{foreground = tonumber('0x00ccff'), fg_indexed=true}, {{kind = "term"}}}, @@ -188,7 +191,7 @@ describe('ext_hlstate detailed highlights', function() [6] = {{foreground = tonumber('0x40ffff'), fg_indexed=true}, {5, 1}}, [7] = {{}, {{hi_name = "MsgArea", ui_name = "MsgArea", kind = "ui"}}}, }) - command('enew | call termopen(["'..nvim_dir..'/tty-test"])') + command(("enew | call termopen(['%s'])"):format(testprg('tty-test'))) screen:expect([[ ^tty ready | {1: } | diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index b6e2f2311f..d8dd546a8d 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -17,7 +17,7 @@ local source = helpers.source local poke_eventloop = helpers.poke_eventloop local nvim = helpers.nvim local sleep = helpers.sleep -local nvim_dir = helpers.nvim_dir +local testprg = helpers.testprg local assert_alive = helpers.assert_alive local default_text = [[ @@ -123,13 +123,11 @@ describe(":substitute, inccommand=split interactivity", function() it("no preview if invoked by feedkeys()", function() -- in a script... source([[:call feedkeys(":%s/tw/MO/g\<CR>")]]) - poke_eventloop() -- or interactively... - feed([[:call feedkeys(":%s/tw/MO/g\<CR>")<CR>]]) - poke_eventloop() + feed([[:call feedkeys(":%s/bs/BUU/g\<lt>CR>")<CR>]]) eq(1, eval("bufnr('$')")) -- sanity check: assert the buffer state - expect(default_text:gsub("tw", "MO")) + expect(default_text:gsub("tw", "MO"):gsub("bs", "BUU")) end) end) @@ -257,42 +255,70 @@ describe(":substitute, 'inccommand' preserves", function() end) end - for _, case in pairs{"", "split", "nosplit"} do - it("visual selection for non-previewable command (inccommand="..case..") #5888", function() + for _, case in ipairs({'', 'split', 'nosplit'}) do + it('previous substitute string ~ (inccommand='..case..') #12109', function() local screen = Screen.new(30,10) common_setup(screen, case, default_text) - feed('1G2V') - feed(':s') - screen:expect([[ - {vis:Inc substitution on} | - t{vis:wo lines} | - | - {15:~ }| - {15:~ }| - {15:~ }| - {15:~ }| - {15:~ }| - {15:~ }| - :'<,'>s^ | - ]]) + feed(':%s/Inc/SUB<CR>') + expect([[ + SUB substitution on + two lines + ]]) - feed('o') - screen:expect([[ - {vis:Inc substitution on} | - t{vis:wo lines} | - | - {15:~ }| - {15:~ }| - {15:~ }| - {15:~ }| - {15:~ }| - {15:~ }| - :'<,'>so^ | - ]]) + feed(':%s/line/') + poke_eventloop() + feed('~') + poke_eventloop() + feed('<CR>') + expect([[ + SUB substitution on + two SUBs + ]]) + + feed(':%s/sti/') + poke_eventloop() + feed('~') + poke_eventloop() + feed('B') + poke_eventloop() + feed('<CR>') + expect([[ + SUB subSUBBtution on + two SUBs + ]]) + + feed(':%s/ion/NEW<CR>') + expect([[ + SUB subSUBBtutNEW on + two SUBs + ]]) + + feed(':%s/two/') + poke_eventloop() + feed('N') + poke_eventloop() + feed('~') + poke_eventloop() + feed('<CR>') + expect([[ + SUB subSUBBtutNEW on + NNEW SUBs + ]]) + + feed(':%s/bS/') + poke_eventloop() + feed('~') + poke_eventloop() + feed('W') + poke_eventloop() + feed('<CR>') + expect([[ + SUB suNNEWWUBBtutNEW on + NNEW SUBs + ]]) end) end - end) describe(":substitute, 'inccommand' preserves undo", function() @@ -317,7 +343,7 @@ describe(":substitute, 'inccommand' preserves undo", function() } local function test_sub(substring, split, redoable) - clear() + command('bwipe!') feed_command("set inccommand=" .. split) insert("1") @@ -343,7 +369,7 @@ describe(":substitute, 'inccommand' preserves undo", function() end local function test_notsub(substring, split, redoable) - clear() + command('bwipe!') feed_command("set inccommand=" .. split) insert("1") @@ -377,7 +403,7 @@ describe(":substitute, 'inccommand' preserves undo", function() local function test_threetree(substring, split) - clear() + command('bwipe!') feed_command("set inccommand=" .. split) insert("1") @@ -429,6 +455,8 @@ describe(":substitute, 'inccommand' preserves undo", function() 2]]) end + before_each(clear) + it("at a non-leaf of the undo tree", function() for _, case in pairs(cases) do for _, str in pairs(substrings) do @@ -1279,6 +1307,108 @@ describe(":substitute, inccommand=split", function() ]]) end) + it([[preview changes correctly with c_CTRL-R_= and c_CTRL-\_e]], function() + feed('gg') + feed(":1,2s/t/X") + screen:expect([[ + Inc subs{12:X}itution on | + {12:X}wo lines | + Inc substitution on | + two lines | + | + {11:[No Name] [+] }| + |1| Inc subs{12:X}itution on | + |2| {12:X}wo lines | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :1,2s/t/X^ | + ]]) + + feed([[<C-R>='Y']]) + -- preview should be unchanged during c_CTRL-R_= editing + screen:expect([[ + Inc subs{12:X}itution on | + {12:X}wo lines | + Inc substitution on | + two lines | + | + {11:[No Name] [+] }| + |1| Inc subs{12:X}itution on | + |2| {12:X}wo lines | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + ={1:'Y'}^ | + ]]) + + feed('<CR>') + -- preview should be changed by the result of the expression + screen:expect([[ + Inc subs{12:XY}itution on | + {12:XY}wo lines | + Inc substitution on | + two lines | + | + {11:[No Name] [+] }| + |1| Inc subs{12:XY}itution on | + |2| {12:XY}wo lines | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :1,2s/t/XY^ | + ]]) + + feed([[<C-\>e'echo']]) + -- preview should be unchanged during c_CTRL-\_e editing + screen:expect([[ + Inc subs{12:XY}itution on | + {12:XY}wo lines | + Inc substitution on | + two lines | + | + {11:[No Name] [+] }| + |1| Inc subs{12:XY}itution on | + |2| {12:XY}wo lines | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + ={1:'echo'}^ | + ]]) + + feed('<CR>') + -- preview should be cleared if command is changed to a non-previewable one + screen:expect([[ + Inc substitution on | + two lines | + Inc substitution on | + two lines | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :echo^ | + ]]) + end) + end) describe("inccommand=nosplit", function() @@ -1582,10 +1712,12 @@ end) describe("'inccommand' and :cnoremap", function() local cases = { "", "split", "nosplit" } + local screen - local function refresh(case) + local function refresh(case, visual) clear() - common_setup(nil, case, default_text) + screen = visual and Screen.new(50,10) or nil + common_setup(screen, case, default_text) end it('work with remapped characters', function() @@ -1642,13 +1774,15 @@ describe("'inccommand' and :cnoremap", function() it('still works with a broken mapping', function() for _, case in pairs(cases) do - refresh(case) + refresh(case, true) feed_command("cnoremap <expr> x execute('bwipeout!')[-1].'x'") feed(":%s/tw/tox<enter>") + screen:expect{any=[[{14:^E565:]]} + feed('<c-c>') -- error thrown b/c of the mapping - neq(nil, eval('v:errmsg'):find('^E523:')) + neq(nil, eval('v:errmsg'):find('^E565:')) expect([[ Inc substitution on toxo lines @@ -1794,26 +1928,26 @@ describe("'inccommand' split windows", function() feed_command("split") feed(":%s/tw") screen:expect([[ - Inc substitution on {10:│}Inc substitution on| - {12:tw}o lines {10:│}{12:tw}o lines | - {10:│} | - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {11:[No Name] [+] }{10:│}{15:~ }| - Inc substitution on {10:│}{15:~ }| - {12:tw}o lines {10:│}{15:~ }| - {10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| + Inc substitution on │Inc substitution on| + {12:tw}o lines │{12:tw}o lines | + │ | + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {11:[No Name] [+] }│{15:~ }| + Inc substitution on │{15:~ }| + {12:tw}o lines │{15:~ }| + │{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| {10:[No Name] [+] [No Name] [+] }| |2| {12:tw}o lines | {15:~ }| @@ -1833,20 +1967,20 @@ describe("'inccommand' split windows", function() feed(":%s/tw") screen:expect([[ - Inc substitution on {10:│}Inc substitution on| - {12:tw}o lines {10:│}{12:tw}o lines | - {10:│} | - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| - {15:~ }{10:│}{15:~ }| + Inc substitution on │Inc substitution on| + {12:tw}o lines │{12:tw}o lines | + │ | + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| + {15:~ }│{15:~ }| {11:[No Name] [+] }{10:[No Name] [+] }| Inc substitution on | {12:tw}o lines | @@ -1917,6 +2051,16 @@ describe("'inccommand' split windows", function() end end) + it("don't open if there's not enough room", function() + refresh() + screen:try_resize(40, 3) + feed("gg:%s/tw") + screen:expect([[ + Inc substitution on | + {12:tw}o lines | + :%s/tw^ | + ]]) + end) end) describe("'inccommand' with 'gdefault'", function() @@ -2731,7 +2875,7 @@ it(':substitute with inccommand during :terminal activity', function() clear() command("set cmdwinheight=3") - feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 5000 xxx<cr>]]) + feed(([[:terminal "%s" REP 5000 xxx<cr>]]):format(testprg('shell-test'))) command('file term') feed('G') -- Follow :terminal output. command('new') @@ -2773,6 +2917,62 @@ it(':substitute with inccommand, timer-induced :redraw #9777', function() ]]) end) +it(':substitute with inccommand, allows :redraw before first separator is typed #18857', function() + local screen = Screen.new(30,6) + clear() + common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz') + command('hi! link NormalFloat CursorLine') + local float_buf = meths.create_buf(false, true) + meths.open_win(float_buf, false, { + relative = 'editor', height = 1, width = 5, row = 3, col = 0, focusable = false, + }) + feed(':%s') + screen:expect([[ + foo bar baz | + bar baz fox | + bar foo baz | + {16: }{15: }| + {15:~ }| + :%s^ | + ]]) + meths.buf_set_lines(float_buf, 0, -1, true, {'foo'}) + command('redraw') + screen:expect([[ + foo bar baz | + bar baz fox | + bar foo baz | + {16:foo }{15: }| + {15:~ }| + :%s^ | + ]]) +end) + +it(':substitute with inccommand, does not crash if range contains invalid marks', function() + local screen = Screen.new(30, 6) + clear() + common_setup(screen, 'split', 'test') + feed([[:'a,'bs]]) + screen:expect([[ + test | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :'a,'bs^ | + ]]) + -- v:errmsg shouldn't be set either before the first separator is typed + eq('', eval('v:errmsg')) + feed('/') + screen:expect([[ + test | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + :'a,'bs/^ | + ]]) +end) + it(":substitute doesn't crash with inccommand, if undo is empty #12932", function() local screen = Screen.new(10,5) clear() @@ -2808,3 +3008,16 @@ it('long :%s/ with inccommand does not collapse cmdline', function() AAAAAAA^ | ]]) end) + +it("with 'inccommand' typing :filter doesn't segfault or leak memory #19057", function() + clear() + common_setup(nil, 'nosplit') + feed(':filter s') + assert_alive() + feed(' ') + assert_alive() + feed('h') + assert_alive() + feed('i') + assert_alive() +end) diff --git a/test/functional/ui/inccommand_user_spec.lua b/test/functional/ui/inccommand_user_spec.lua new file mode 100644 index 0000000000..b5816f6fe6 --- /dev/null +++ b/test/functional/ui/inccommand_user_spec.lua @@ -0,0 +1,356 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear = helpers.clear +local exec_lua = helpers.exec_lua +local insert = helpers.insert +local feed = helpers.feed +local command = helpers.command +local assert_alive = helpers.assert_alive + +-- Implements a :Replace command that works like :substitute. +local setup_replace_cmd = [[ + local function show_replace_preview(buf, use_preview_win, preview_ns, preview_buf, matches) + -- Find the width taken by the largest line number, used for padding the line numbers + local highest_lnum = math.max(matches[#matches][1], 1) + local highest_lnum_width = math.floor(math.log10(highest_lnum)) + local preview_buf_line = 0 + + vim.g.prevns = preview_ns + vim.g.prevbuf = preview_buf + + for _, match in ipairs(matches) do + local lnum = match[1] + local line_matches = match[2] + local prefix + + if use_preview_win then + prefix = string.format( + '|%s%d| ', + string.rep(' ', highest_lnum_width - math.floor(math.log10(lnum))), + lnum + ) + + vim.api.nvim_buf_set_lines( + preview_buf, + preview_buf_line, + preview_buf_line, + 0, + { prefix .. vim.api.nvim_buf_get_lines(buf, lnum - 1, lnum, false)[1] } + ) + end + + for _, line_match in ipairs(line_matches) do + vim.api.nvim_buf_add_highlight( + buf, + preview_ns, + 'Substitute', + lnum - 1, + line_match[1], + line_match[2] + ) + + if use_preview_win then + vim.api.nvim_buf_add_highlight( + preview_buf, + preview_ns, + 'Substitute', + preview_buf_line, + #prefix + line_match[1], + #prefix + line_match[2] + ) + end + end + + preview_buf_line = preview_buf_line + 1 + end + + if use_preview_win then + return 2 + else + return 1 + end + end + + local function do_replace(opts, preview, preview_ns, preview_buf) + local pat1 = opts.fargs[1] or '' + local pat2 = opts.fargs[2] or '' + local line1 = opts.line1 + local line2 = opts.line2 + + local buf = vim.api.nvim_get_current_buf() + local lines = vim.api.nvim_buf_get_lines(buf, line1 - 1, line2, 0) + local matches = {} + + for i, line in ipairs(lines) do + local startidx, endidx = 0, 0 + local line_matches = {} + local num = 1 + + while startidx ~= -1 do + local match = vim.fn.matchstrpos(line, pat1, 0, num) + startidx, endidx = match[2], match[3] + + if startidx ~= -1 then + line_matches[#line_matches+1] = { startidx, endidx } + end + + num = num + 1 + end + + if #line_matches > 0 then + matches[#matches+1] = { line1 + i - 1, line_matches } + end + end + + local new_lines = {} + + for _, match in ipairs(matches) do + local lnum = match[1] + local line_matches = match[2] + local line = lines[lnum - line1 + 1] + local pat_width_differences = {} + + -- If previewing, only replace the text in current buffer if pat2 isn't empty + -- Otherwise, always replace the text + if pat2 ~= '' or not preview then + if preview then + for _, line_match in ipairs(line_matches) do + local startidx, endidx = unpack(line_match) + local pat_match = line:sub(startidx + 1, endidx) + + pat_width_differences[#pat_width_differences+1] = + #vim.fn.substitute(pat_match, pat1, pat2, 'g') - #pat_match + end + end + + new_lines[lnum] = vim.fn.substitute(line, pat1, pat2, 'g') + end + + -- Highlight the matches if previewing + if preview then + local idx_offset = 0 + for i, line_match in ipairs(line_matches) do + local startidx, endidx = unpack(line_match) + -- Starting index of replacement text + local repl_startidx = startidx + idx_offset + -- Ending index of the replacement text (if pat2 isn't empty) + local repl_endidx + + if pat2 ~= '' then + repl_endidx = endidx + idx_offset + pat_width_differences[i] + else + repl_endidx = endidx + idx_offset + end + + if pat2 ~= '' then + idx_offset = idx_offset + pat_width_differences[i] + end + + line_matches[i] = { repl_startidx, repl_endidx } + end + end + end + + for lnum, line in pairs(new_lines) do + vim.api.nvim_buf_set_lines(buf, lnum - 1, lnum, false, { line }) + end + + if preview then + local lnum = vim.api.nvim_win_get_cursor(0)[1] + -- Use preview window only if preview buffer is provided and range isn't just the current line + local use_preview_win = (preview_buf ~= nil) and (line1 ~= lnum or line2 ~= lnum) + return show_replace_preview(buf, use_preview_win, preview_ns, preview_buf, matches) + end + end + + local function replace(opts) + do_replace(opts, false) + end + + local function replace_preview(opts, preview_ns, preview_buf) + return do_replace(opts, true, preview_ns, preview_buf) + end + + -- ":<range>Replace <pat1> <pat2>" + -- Replaces all occurences of <pat1> in <range> with <pat2> + vim.api.nvim_create_user_command( + 'Replace', + replace, + { nargs = '*', range = '%', addr = 'lines', + preview = replace_preview } + ) +]] + +describe("'inccommand' for user commands", function() + local screen + + before_each(function() + clear() + screen = Screen.new(40, 17) + screen:set_default_attr_ids({ + [1] = {background = Screen.colors.Yellow1}, + [2] = {foreground = Screen.colors.Blue1, bold = true}, + [3] = {reverse = true}, + [4] = {reverse = true, bold = true} + }) + screen:attach() + exec_lua(setup_replace_cmd) + command('set cmdwinheight=5') + insert[[ + text on line 1 + more text on line 2 + oh no, even more text + will the text ever stop + oh well + did the text stop + why won't it stop + make the text stop + ]] + end) + + it('works with inccommand=nosplit', function() + command('set inccommand=nosplit') + feed(':Replace text cats') + screen:expect([[ + {1:cats} on line 1 | + more {1:cats} on line 2 | + oh no, even more {1:cats} | + will the {1:cats} ever stop | + oh well | + did the {1:cats} stop | + why won't it stop | + make the {1:cats} stop | + | + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + :Replace text cats^ | + ]]) + end) + + it('works with inccommand=split', function() + command('set inccommand=split') + feed(':Replace text cats') + screen:expect([[ + {1:cats} on line 1 | + more {1:cats} on line 2 | + oh no, even more {1:cats} | + will the {1:cats} ever stop | + oh well | + did the {1:cats} stop | + why won't it stop | + make the {1:cats} stop | + | + {4:[No Name] [+] }| + |1| {1:cats} on line 1 | + |2| more {1:cats} on line 2 | + |3| oh no, even more {1:cats} | + |4| will the {1:cats} ever stop | + |6| did the {1:cats} stop | + {3:[Preview] }| + :Replace text cats^ | + ]]) + end) + + it('properly closes preview when inccommand=split', function() + command('set inccommand=split') + feed(':Replace text cats<Esc>') + screen:expect([[ + text on line 1 | + more text on line 2 | + oh no, even more text | + will the text ever stop | + oh well | + did the text stop | + why won't it stop | + make the text stop | + ^ | + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + | + ]]) + end) + + it('properly executes command when inccommand=split', function() + command('set inccommand=split') + feed(':Replace text cats<CR>') + screen:expect([[ + cats on line 1 | + more cats on line 2 | + oh no, even more cats | + will the cats ever stop | + oh well | + did the cats stop | + why won't it stop | + make the cats stop | + ^ | + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + :Replace text cats | + ]]) + end) + + it('shows preview window only when range is not current line', function() + command('set inccommand=split') + feed('gg:.Replace text cats') + screen:expect([[ + {1:cats} on line 1 | + more text on line 2 | + oh no, even more text | + will the text ever stop | + oh well | + did the text stop | + why won't it stop | + make the text stop | + | + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + {2:~ }| + :.Replace text cats^ | + ]]) + end) + + it('does not crash on ambiguous command #18825', function() + command('set inccommand=split') + command('command Reply echo 1') + feed(':R') + assert_alive() + feed('e') + assert_alive() + end) + + it('no crash if preview callback changes inccommand option', function() + command('set inccommand=nosplit') + exec_lua([[ + vim.api.nvim_create_user_command('Replace', function() end, { + nargs = '*', + preview = function() + vim.api.nvim_set_option('inccommand', 'split') + return 2 + end, + }) + ]]) + feed(':R') + assert_alive() + feed('e') + assert_alive() + end) +end) diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua index ea8968a653..0f4e97088c 100644 --- a/test/functional/ui/input_spec.lua +++ b/test/functional/ui/input_spec.lua @@ -3,9 +3,12 @@ local clear, feed_command = helpers.clear, helpers.feed_command local feed, next_msg, eq = helpers.feed, helpers.next_msg, helpers.eq local command = helpers.command local expect = helpers.expect +local curbuf_contents = helpers.curbuf_contents local meths = helpers.meths local exec_lua = helpers.exec_lua local write_file = helpers.write_file +local funcs = helpers.funcs +local eval = helpers.eval local Screen = require('test.functional.ui.screen') before_each(clear) @@ -50,6 +53,8 @@ describe('mappings', function() add_mapping('<kenter>','<kenter>') add_mapping('<kcomma>','<kcomma>') add_mapping('<kequal>','<kequal>') + add_mapping('<f38>','<f38>') + add_mapping('<f63>','<f63>') end) it('ok', function() @@ -106,6 +111,8 @@ describe('mappings', function() check_mapping('<KPComma>','<kcomma>') check_mapping('<kequal>','<kequal>') check_mapping('<KPEquals>','<kequal>') + check_mapping('<f38>','<f38>') + check_mapping('<f63>','<f63>') end) it('support meta + multibyte char mapping', function() @@ -114,11 +121,196 @@ describe('mappings', function() end) end) -describe('input utf sequences that contain CSI/K_SPECIAL', function() +describe('input utf sequences that contain K_SPECIAL (0x80)', function() it('ok', function() feed('i…<esc>') expect('…') end) + + it('can be mapped', function() + command('inoremap … E280A6') + feed('i…<esc>') + expect('E280A6') + end) +end) + +describe('input utf sequences that contain CSI (0x9B)', function() + it('ok', function() + feed('iě<esc>') + expect('ě') + end) + + it('can be mapped', function() + command('inoremap ě C49B') + feed('iě<esc>') + expect('C49B') + end) +end) + +describe('input split utf sequences', function() + it('ok', function() + local str = '►' + feed('i' .. str:sub(1, 1)) + helpers.sleep(10) + feed(str:sub(2, 3)) + expect('►') + end) + + it('can be mapped', function() + command('inoremap ► E296BA') + local str = '►' + feed('i' .. str:sub(1, 1)) + helpers.sleep(10) + feed(str:sub(2, 3)) + expect('E296BA') + end) +end) + +describe('input pairs', function() + describe('<tab> / <c-i>', function() + it('ok', function() + feed('i<tab><c-i><esc>') + eq('\t\t', curbuf_contents()) + end) + + describe('can be mapped separately', function() + it('if <tab> is mapped after <c-i>', function() + command('inoremap <c-i> CTRL-I!') + command('inoremap <tab> TAB!') + feed('i<tab><c-i><esc>') + eq('TAB!CTRL-I!', curbuf_contents()) + end) + + it('if <tab> is mapped before <c-i>', function() + command('inoremap <tab> TAB!') + command('inoremap <c-i> CTRL-I!') + feed('i<tab><c-i><esc>') + eq('TAB!CTRL-I!', curbuf_contents()) + end) + end) + end) + + describe('<cr> / <c-m>', function() + it('ok', function() + feed('iunos<c-m>dos<cr>tres<esc>') + eq('unos\ndos\ntres', curbuf_contents()) + end) + + describe('can be mapped separately', function() + it('if <cr> is mapped after <c-m>', function() + command('inoremap <c-m> SNIPPET!') + command('inoremap <cr> , and then<cr>') + feed('iunos<c-m>dos<cr>tres<esc>') + eq('unosSNIPPET!dos, and then\ntres', curbuf_contents()) + end) + + it('if <cr> is mapped before <c-m>', function() + command('inoremap <cr> , and then<cr>') + command('inoremap <c-m> SNIPPET!') + feed('iunos<c-m>dos<cr>tres<esc>') + eq('unosSNIPPET!dos, and then\ntres', curbuf_contents()) + end) + end) + end) + + describe('<esc> / <c-[>', function() + it('ok', function() + feed('2adouble<c-[>asingle<esc>') + eq('doubledoublesingle', curbuf_contents()) + end) + + describe('can be mapped separately', function() + it('if <esc> is mapped after <c-[>', function() + command('inoremap <c-[> HALLOJ!') + command('inoremap <esc> ,<esc>') + feed('2adubbel<c-[>upp<esc>') + eq('dubbelHALLOJ!upp,dubbelHALLOJ!upp,', curbuf_contents()) + end) + + it('if <esc> is mapped before <c-[>', function() + command('inoremap <esc> ,<esc>') + command('inoremap <c-[> HALLOJ!') + feed('2adubbel<c-[>upp<esc>') + eq('dubbelHALLOJ!upp,dubbelHALLOJ!upp,', curbuf_contents()) + end) + end) + end) +end) + +it('Ctrl-6 is Ctrl-^ vim-patch:8.1.2333', function() + command('split aaa') + command('edit bbb') + feed('<C-6>') + eq('aaa', funcs.bufname()) +end) + +it('c_CTRL-R_CTRL-R, i_CTRL-R_CTRL-R, i_CTRL-G_CTRL-K work properly vim-patch:8.1.2346', function() + command('set timeoutlen=10') + + command([[let @a = 'aaa']]) + feed([[:let x = '<C-R><C-R>a'<CR>]]) + eq([[let x = 'aaa']], eval('@:')) + + feed('a<C-R><C-R>a<Esc>') + expect('aaa') + command('bwipe!') + + feed('axx<CR>yy<C-G><C-K>a<Esc>') + expect([[ + axx + yy]]) +end) + +it('typing a simplifiable key at hit-enter prompt triggers mapping vim-patch:8.2.0839', function() + local screen = Screen.new(60,8) + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + [2] = {bold = true, reverse = true}, -- MsgSeparator + [3] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg + }) + screen:attach() + command([[nnoremap <C-6> <Cmd>echo 'hit ctrl-6'<CR>]]) + feed_command('ls') + screen:expect([[ + | + {1:~ }| + {1:~ }| + {1:~ }| + {2: }| + :ls | + 1 %a "[No Name]" line 1 | + {3:Press ENTER or type command to continue}^ | + ]]) + feed('<C-6>') + screen:expect([[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + hit ctrl-6 | + ]]) +end) + +it('mixing simplified and unsimplified keys can trigger mapping vim-patch:8.2.0916', function() + command('set timeoutlen=10') + command([[imap ' <C-W>]]) + command('imap <C-W><C-A> c-a') + feed([[a'<C-A>]]) + expect('c-a') +end) + +it('unsimplified mapping works when there was a partial match vim-patch:8.2.4504', function() + command('set timeoutlen=10') + command('nnoremap <C-J> a') + command('nnoremap <NL> x') + command('nnoremap <C-J>x <Nop>') + funcs.setline(1, 'x') + -- CTRL-J b should have trigger the <C-J> mapping and then insert "b" + feed('<C-J>b<Esc>') + expect('xb') end) describe('input non-printable chars', function() @@ -146,7 +338,7 @@ describe('input non-printable chars', function() {1:~ }| {1:~ }| {1:~ }| - "Xtest-overwrite" [noeol] 1L, 6C | + "Xtest-overwrite" [noeol] 1L, 6B | ]]) -- The timestamp is in second resolution, wait two seconds to be sure. @@ -237,3 +429,47 @@ describe("event processing and input", function() eq({'notification', 'stop', {}}, next_msg()) end) end) + +describe('display is updated', function() + local screen + before_each(function() + screen = Screen.new(60, 8) + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText + [2] = {bold = true}, -- ModeMsg + }) + screen:attach() + end) + + it('in Insert mode after <Nop> mapping #17911', function() + command('imap <Plug>test <Nop>') + command('imap <F2> abc<CR><Plug>test') + feed('i<F2>') + screen:expect([[ + abc | + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:-- INSERT --} | + ]]) + end) + + it('in Insert mode after empty string <expr> mapping #17911', function() + command('imap <expr> <Plug>test ""') + command('imap <F2> abc<CR><Plug>test') + feed('i<F2>') + screen:expect([[ + abc | + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:-- INSERT --} | + ]]) + end) +end) diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index f038348253..00f126a1f2 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -12,6 +12,7 @@ local nvim_prog = helpers.nvim_prog local iswin = helpers.iswin local exc_exec = helpers.exc_exec local exec_lua = helpers.exec_lua +local poke_eventloop = helpers.poke_eventloop describe('ui/ext_messages', function() local screen @@ -30,6 +31,7 @@ describe('ui/ext_messages', function() [7] = {background = Screen.colors.Yellow}, [8] = {foreground = Screen.colors.Red}, [9] = {special = Screen.colors.Red, undercurl = true}, + [10] = {foreground = Screen.colors.Brown}; }) end) after_each(function() @@ -303,13 +305,25 @@ describe('ui/ext_messages', function() {1:~ }| {1:~ }| {1:~ }| - ]], messages={ + ]], msg_history={ {kind="echoerr", content={{"raa", 2}}}, {kind="echoerr", content={{"bork", 2}}}, {kind="echoerr", content={{"fail", 2}}}, {kind="echoerr", content={{"extrafail", 2}}}, {kind="echoerr", content={{"problem", 2}}} - }} + }, messages={{ + content = {{ "Press ENTER or type command to continue", 4 }}, + kind = "return_prompt" + }}} + + feed '<cr>' + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} end) it('shortmess-=S', function() @@ -454,11 +468,14 @@ describe('ui/ext_messages', function() alphpabe^t | {1:~ }| {1:~ }| - ]], messages={ - {kind="echomsg", content={{"stuff"}}}, - }, showmode={ - { "-- INSERT --", 3 } - }} + ]], msg_history={{ + content = {{ "stuff" }}, + kind = "echomsg", + }}, showmode={{ "-- INSERT --", 3 }}, + messages={{ + content = {{ "Press ENTER or type command to continue", 4}}, + kind = "return_prompt" + }}} end) it('&showmode with macro-recording message', function() @@ -684,12 +701,15 @@ describe('ui/ext_messages', function() {1:~ }| {1:~ }| {1:~ }| - ]], messages={ + ]], msg_history={ {kind="echomsg", content={{"howdy"}}}, {kind="", content={{"Type :qa and press <Enter> to exit Nvim"}}}, {kind="echoerr", content={{"bork", 2}}}, {kind="emsg", content={{"E117: Unknown function: nosuchfunction", 2}}} - }} + }, messages={{ + content = {{ "Press ENTER or type command to continue", 4}}, + kind = "return_prompt" + }}} end) it('implies ext_cmdline and ignores cmdheight', function() @@ -717,7 +737,6 @@ describe('ui/ext_messages', function() ]]) eq(0, eval('&cmdheight')) - -- normally this would be an error feed(':set cmdheight=0') screen:expect{grid=[[ ^ | @@ -839,9 +858,53 @@ stack traceback: {1:~ }| {1:~ }| ]]} - end) + it('supports nvim_echo messages with multiple attrs', function() + async_meths.echo({{'wow, ',"Search"}, {"such\n\nvery ", "ErrorMsg"}, {"color", "LineNr"}}, true, {}) + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]], messages={ + { content = { { "wow, ", 7 }, { "such\n\nvery ", 2 }, { "color", 10 } }, kind = "" } + }} + + feed ':ls<cr>' + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]], messages={ + { content = { { '\n 1 %a "[No Name]" line 1' } }, kind = "echomsg" } + }} + + feed ':messages<cr>' + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]], messages={ + { content = { { "Press ENTER or type command to continue", 4 } }, kind = "return_prompt" } + }, msg_history={ + { content = { { "wow, ", 7 }, { "such\n\nvery ", 2 }, { "color", 10 } }, kind = "echomsg" } + }} + + feed '<cr>' + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} + end) end) describe('ui/builtin messages', function() @@ -850,17 +913,19 @@ describe('ui/builtin messages', function() clear() screen = Screen.new(60, 7) screen:attach({rgb=true, ext_popupmenu=true}) - screen:set_default_attr_ids({ - [1] = {bold = true, foreground = Screen.colors.Blue1}, - [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, - [3] = {bold = true, reverse = true}, - [4] = {bold = true, foreground = Screen.colors.SeaGreen4}, - [5] = {foreground = Screen.colors.Blue1}, - [6] = {bold = true, foreground = Screen.colors.Magenta}, - [7] = {background = Screen.colors.Grey20}, - [8] = {reverse = true}, - [9] = {background = Screen.colors.LightRed} - }) + screen:set_default_attr_ids { + [1] = {bold = true, foreground = Screen.colors.Blue1}; + [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}; + [3] = {bold = true, reverse = true}; + [4] = {bold = true, foreground = Screen.colors.SeaGreen4}; + [5] = {foreground = Screen.colors.Blue1}; + [6] = {bold = true, foreground = Screen.colors.Magenta}; + [7] = {background = Screen.colors.Grey20}; + [8] = {reverse = true}; + [9] = {background = Screen.colors.LightRed}; + [10] = {background = Screen.colors.Yellow}; + [11] = {foreground = Screen.colors.Brown}; + } end) it('supports multiline messages from rpc', function() @@ -1013,7 +1078,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim end) it('redraws NOT_VALID correctly after message', function() - -- edge case: only one window was set NOT_VALID. Orginal report + -- edge case: only one window was set NOT_VALID. Original report -- used :make, but fake it using one command to set the current -- window NOT_VALID and another to show a long message. command("set more") @@ -1096,6 +1161,88 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim {4:Press ENTER or type command to continue}^ | ]]} end) + + it('supports nvim_echo messages with multiple attrs', function() + async_meths.echo({{'wow, ',"Search"}, {"such\n\nvery ", "ErrorMsg"}, {"color", "LineNr"}}, true, {}) + screen:expect{grid=[[ + | + {1:~ }| + {3: }| + {10:wow, }{2:such} | + | + {2:very }{11:color} | + {4:Press ENTER or type command to continue}^ | + ]]} + + feed '<cr>' + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + + feed ':messages<cr>' + screen:expect{grid=[[ + | + {1:~ }| + {3: }| + {10:wow, }{2:such} | + | + {2:very }{11:color} | + {4:Press ENTER or type command to continue}^ | + ]]} + end) + + it('prints lines in Ex mode correctly with a burst of carriage returns #19341', function() + command('set number') + meths.buf_set_lines(0, 0, 0, true, {'aaa', 'bbb', 'ccc'}) + command('set display-=msgsep') + feed('gggQ<CR><CR>1<CR><CR>vi') + screen:expect([[ + Entering Ex mode. Type "visual" to go to Normal mode. | + {11: 2 }bbb | + {11: 3 }ccc | + :1 | + {11: 1 }aaa | + {11: 2 }bbb | + :vi^ | + ]]) + feed('<CR>') + screen:expect([[ + {11: 1 }aaa | + {11: 2 }^bbb | + {11: 3 }ccc | + {11: 4 } | + {1:~ }| + {1:~ }| + | + ]]) + command('set display+=msgsep') + feed('gggQ<CR><CR>1<CR><CR>vi') + screen:expect([[ + Entering Ex mode. Type "visual" to go to Normal mode. | + {11: 2 }bbb | + {11: 3 }ccc | + :1 | + {11: 1 }aaa | + {11: 2 }bbb | + :vi^ | + ]]) + feed('<CR>') + screen:expect([[ + {11: 1 }aaa | + {11: 2 }^bbb | + {11: 3 }ccc | + {11: 4 } | + {1:~ }| + {1:~ }| + | + ]]) + end) end) describe('ui/ext_messages', function() @@ -1111,6 +1258,8 @@ describe('ui/ext_messages', function() [3] = {bold = true}, [4] = {bold = true, foreground = Screen.colors.SeaGreen4}, [5] = {foreground = Screen.colors.Blue1}, + [6] = {reverse = true}, + [7] = {bold = true, reverse = true}, }) end) @@ -1202,6 +1351,107 @@ describe('ui/ext_messages', function() {content = { { "Press ENTER or type command to continue", 4 } }, kind = "return_prompt" } }} end) + + it('supports global statusline', function() + feed(":set laststatus=3<cr>") + feed(":sp<cr>") + feed(":set cmdheight<cr>") + screen:expect({grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ────────────────────────────────────────────────────────────────────────────────| + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {7:[No Name] }| + ]], messages={ + {content = { { " cmdheight=0" } }, kind = "" } + }}) + + feed("<c-w>+") + feed(":set laststatus<cr>") + screen:expect({grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ────────────────────────────────────────────────────────────────────────────────| + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {7:[No Name] }| + ]], messages={ + {content = { { " laststatus=3" } }, kind = "" } + }}) + + feed(":set mouse=a<cr>") + meths.input_mouse('left', 'press', '', 0, 12, 10) + poke_eventloop() + meths.input_mouse('left', 'drag', '', 0, 12, 10) + meths.input_mouse('left', 'drag', '', 0, 11, 10) + feed("<c-l>") + feed(":set cmdheight<cr>") + screen:expect({grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ────────────────────────────────────────────────────────────────────────────────| + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {7:[No Name] }| + ]], messages={ + {content = { { " cmdheight=0" } }, kind = "" } + }}) + end) end) describe('ui/msg_puts_printf', function() @@ -1226,7 +1476,7 @@ describe('ui/msg_puts_printf', function() pending('Locale ja_JP.UTF-8 not supported', function() end) return elseif helpers.isCI() then - -- Fails non--Windows CI. Message catalog direcotry issue? + -- Fails non--Windows CI. Message catalog directory issue? pending('fails on unix CI', function() end) return end @@ -1281,7 +1531,7 @@ ullamco laboris nisi ut aliquip ex ea commodo consequat.]]) end) - it('can be quit', function() + it('can be quit with echon', function() screen:try_resize(25,5) feed(':echon join(map(range(0, &lines*10), "v:val"), "\\n")<cr>') screen:expect{grid=[[ @@ -1301,6 +1551,45 @@ aliquip ex ea commodo consequat.]]) ]]} end) + it('can be quit with Lua #11224 #16537', function() + -- NOTE: adds "4" to message history, although not displayed initially + -- (triggered the more prompt). + screen:try_resize(40,5) + feed(':lua for i=0,10 do print(i) end<cr>') + screen:expect{grid=[[ + 0 | + 1 | + 2 | + 3 | + {4:-- More --}^ | + ]]} + feed('q') + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + feed(':mess<cr>') + screen:expect{grid=[[ + 0 | + 1 | + 2 | + 3 | + {4:-- More --}^ | + ]]} + feed('j') + screen:expect{grid=[[ + 1 | + 2 | + 3 | + 4 | + {4:Press ENTER or type command to continue}^ | + ]]} + feed('<cr>') + end) + it('handles wrapped lines with line scroll', function() feed(':lua error(_G.x)<cr>') screen:expect{grid=[[ diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index baacef358f..69b0d1ecec 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -32,7 +32,7 @@ describe('ui/mouse/input', function() [6] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, [7] = {bold = true, foreground = Screen.colors.SeaGreen4}, }) - command("set display-=msgsep") + command("set display-=msgsep mousemodel=extend") feed('itesting<cr>mouse<cr>support and selection<esc>') screen:expect([[ testing | @@ -595,54 +595,54 @@ describe('ui/mouse/input', function() feed('ifoo\nbar<esc>') screen:expect{grid=[[ - testing {4:│}testing | - mouse {4:│}mouse | - support and selection {4:│}support and selection | - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│[No Name] [+] }| - {0:~ }{4:│}foo{0:$} | - {0:~ }{4:│}ba^r{0:$} | - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| + testing │testing | + mouse │mouse | + support and selection │support and selection | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{4:[No Name] [+] }| + {0:~ }│foo{0:$} | + {0:~ }│ba^r{0:$} | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| {4:[No Name] [+] }{5:[No Name] [+] }| | ]]} meths.input_mouse('left', 'press', '', 0, 6, 27) screen:expect{grid=[[ - testing {4:│}testing | - mouse {4:│}mouse | - support and selection {4:│}support and selection | - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│[No Name] [+] }| - {0:~ }{4:│}^foo{0:$} | - {0:~ }{4:│}bar{0:$} | - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| + testing │testing | + mouse │mouse | + support and selection │support and selection | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{4:[No Name] [+] }| + {0:~ }│^foo{0:$} | + {0:~ }│bar{0:$} | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| {4:[No Name] [+] }{5:[No Name] [+] }| | ]]} meths.input_mouse('left', 'drag', '', 0, 7, 30) screen:expect{grid=[[ - testing {4:│}testing | - mouse {4:│}mouse | - support and selection {4:│}support and selection | - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│[No Name] [+] }| - {0:~ }{4:│}{1:foo}{3:$} | - {0:~ }{4:│}{1:bar}{0:^$} | - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| - {0:~ }{4:│}{0:~ }| + testing │testing | + mouse │mouse | + support and selection │support and selection | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{4:[No Name] [+] }| + {0:~ }│{1:foo}{3:$} | + {0:~ }│{1:bar}{0:^$} | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| {4:[No Name] [+] }{5:[No Name] [+] }| {2:-- VISUAL --} | ]]} @@ -729,12 +729,12 @@ describe('ui/mouse/input', function() feed('k') feed_command('sp', 'vsp') screen:expect([[ - lines {4:│}lines | - to {4:│}to | - test {4:│}test | - ^mouse scrolling {4:│}mouse scrolling | - {4:│} | - {0:~ }{4:│}{0:~ }| + lines │lines | + to │to | + test │test | + ^mouse scrolling │mouse scrolling | + │ | + {0:~ }│{0:~ }| {5:[No Name] [+] }{4:[No Name] [+] }| to | test | @@ -750,12 +750,12 @@ describe('ui/mouse/input', function() feed('<ScrollWheelDown><0,0>') end screen:expect([[ - ^mouse scrolling {4:│}lines | - {4:│}to | - {0:~ }{4:│}test | - {0:~ }{4:│}mouse scrolling | - {0:~ }{4:│} | - {0:~ }{4:│}{0:~ }| + ^mouse scrolling │lines | + │to | + {0:~ }│test | + {0:~ }│mouse scrolling | + {0:~ }│ | + {0:~ }│{0:~ }| {5:[No Name] [+] }{4:[No Name] [+] }| to | test | @@ -771,12 +771,12 @@ describe('ui/mouse/input', function() feed('<ScrollWheelUp><27,0>') end screen:expect([[ - ^mouse scrolling {4:│}text | - {4:│}with | - {0:~ }{4:│}many | - {0:~ }{4:│}lines | - {0:~ }{4:│}to | - {0:~ }{4:│}test | + ^mouse scrolling │text | + │with | + {0:~ }│many | + {0:~ }│lines | + {0:~ }│to | + {0:~ }│test | {5:[No Name] [+] }{4:[No Name] [+] }| to | test | @@ -793,12 +793,12 @@ describe('ui/mouse/input', function() feed('<ScrollWheelUp><27,7><ScrollWheelUp>') end screen:expect([[ - ^mouse scrolling {4:│}text | - {4:│}with | - {0:~ }{4:│}many | - {0:~ }{4:│}lines | - {0:~ }{4:│}to | - {0:~ }{4:│}test | + ^mouse scrolling │text | + │with | + {0:~ }│many | + {0:~ }│lines | + {0:~ }│to | + {0:~ }│test | {5:[No Name] [+] }{4:[No Name] [+] }| Inserting | text | @@ -1571,4 +1571,23 @@ describe('ui/mouse/input', function() meths.set_option('winwidth', winwidth) meths.input_mouse('left', 'release', '', 0, 0, 0) end) + + it('scroll keys are not translated into multiclicks #6211 #6989', function() + meths.set_var('mouse_up', 0) + meths.set_var('mouse_up2', 0) + meths.set_var('mouse_up3', 0) + meths.set_var('mouse_up4', 0) + command('nnoremap <ScrollWheelUp> <Cmd>let g:mouse_up += 1<CR>') + command('nnoremap <2-ScrollWheelUp> <Cmd>let g:mouse_up2 += 1<CR>') + command('nnoremap <3-ScrollWheelUp> <Cmd>let g:mouse_up3 += 1<CR>') + command('nnoremap <4-ScrollWheelUp> <Cmd>let g:mouse_up4 += 1<CR>') + meths.input_mouse('wheel', 'up', '', 0, 0, 0) + meths.input_mouse('wheel', 'up', '', 0, 0, 0) + meths.input_mouse('wheel', 'up', '', 0, 0, 0) + meths.input_mouse('wheel', 'up', '', 0, 0, 0) + eq(4, meths.get_var('mouse_up')) + eq(0, meths.get_var('mouse_up2')) + eq(0, meths.get_var('mouse_up3')) + eq(0, meths.get_var('mouse_up4')) + end) end) diff --git a/test/functional/ui/multibyte_spec.lua b/test/functional/ui/multibyte_spec.lua index e6a79feadc..d4e237bcb4 100644 --- a/test/functional/ui/multibyte_spec.lua +++ b/test/functional/ui/multibyte_spec.lua @@ -6,6 +6,9 @@ local feed = helpers.feed local feed_command = helpers.feed_command local insert = helpers.insert local funcs = helpers.funcs +local meths = helpers.meths +local split = helpers.split +local dedent = helpers.dedent describe("multibyte rendering", function() local screen @@ -26,7 +29,7 @@ describe("multibyte rendering", function() ̊ x]]) feed("gg") - -- verify the modifier infact is alone + -- verify the modifier in fact is alone feed_command("ascii") screen:expect([[ ^ ̊ | @@ -115,6 +118,35 @@ describe("multibyte rendering", function() {4:-- INSERT --} | ]]) end) + + it('works with a lot of unicode (zalgo) text', function() + screen:try_resize(65, 10) + meths.buf_set_lines(0,0,-1,true, split(dedent [[ + L̓̉̑̒̌̚ơ̗̌̒̄̀ŕ̈̈̎̐̕è̇̅̄̄̐m̖̟̟̅̄̚ ̛̓̑̆̇̍i̗̟̞̜̅̐p̗̞̜̉̆̕s̟̜̘̍̑̏ū̟̞̎̃̉ḿ̘̙́́̐ ̖̍̌̇̉̚d̞̄̃̒̉̎ò́̌̌̂̐l̞̀̄̆̌̚ȯ̖̞̋̀̐r̓̇̌̃̃̚ ̗̘̀̏̍́s̜̀̎̎̑̕i̟̗̐̄̄̚t̝̎̆̓̐̒ ̘̇̔̓̊̚ȃ̛̟̗̏̅m̜̟̙̞̈̓é̘̞̟̔̆t̝̂̂̈̑̔,̜̜̖̅̄̍ ̛̗̊̓̆̚c̟̍̆̍̈̔ȯ̖̖̝̑̀n̜̟̎̊̃̚s̟̏̇̎̒̚e̙̐̈̓̌̚c̙̍̈̏̅̕ť̇̄̇̆̓e̛̓̌̈̓̈t̟̍̀̉̆̅u̝̞̎̂̄̚r̘̀̅̈̅̐ ̝̞̓́̇̉ã̏̀̆̅̕d̛̆̐̉̆̋ȉ̞̟̍̃̚p̛̜̊̍̂̓ȋ̏̅̃̋̚ṥ̛̏̃̕č̛̞̝̀̂í̗̘̌́̎n̔̎́̒̂̕ǧ̗̜̋̇̂ ̛̜̔̄̎̃ê̛̔̆̇̕l̘̝̏̐̊̏ĩ̛̍̏̏̄t̟̐́̀̐̎,̙̘̍̆̉̐ ̋̂̏̄̌̅s̙̓̌̈́̇e̛̗̋̒̎̏d̜̗̊̍̊̚ + ď̘̋̌̌̕ǒ̝̗̔̇̕ ̙̍́̄̄̉è̛̛̞̌̌i̜̖̐̈̆̚ȕ̇̈̓̃̓ŝ̛̞̙̉̋m̜̐̂̄̋̂ȯ̈̎̎̅̕d̜̙̓̔̋̑ ̞̗̄̂̂̚t̝̊́̃́̄e̛̘̜̞̓̑m̊̅̏̉̌̕p̛̈̂̇̀̐ỏ̙̘̈̉̔r̘̞̋̍̃̚ ̝̄̀̇̅̇ỉ̛̖̍̓̈n̛̛̝̎̕̕c̛̛̊̅́̐ĭ̗̓̀̍̐d̞̜̋̐̅̚i̟̙̇̄̊̄d̞̊̂̀̇̚ủ̝̉̑̃̕n̜̏̇̄̐̋ť̗̜̞̋̉ ̝̒̓̌̓̚ȕ̖̙̀̚̕t̖̘̎̉̂̌ ̛̝̄̍̌̂l̛̟̝̃̑̋á̛̝̝̔̅b̝̙̜̗̅̒ơ̖̌̒̄̆r̒̇̓̎̈̄e̛̛̖̅̏̇ ̖̗̜̝̃́e̛̛̘̅̔̌ẗ̛̙̗̐̕ ̖̟̇̋̌̈d̞̙̀̉̑̕ŏ̝̂́̐̑l̞̟̗̓̓̀ơ̘̎̃̄̂r̗̗̖̔̆̍ẻ̖̝̞̋̅ ̜̌̇̍̈̊m̈̉̇̄̒̀a̜̞̘̔̅̆g̗̖̈̃̈̉n̙̖̄̈̉̄â̛̝̜̄̃ ̛́̎̕̕̚ā̊́́̆̌l̟̙̞̃̒́i̖̇̎̃̀̋q̟̇̒̆́̊ủ́̌̇̑̚ã̛̘̉̐̚.̛́̏̐̍̊ + U̝̙̎̈̐̆t̜̍̌̀̔̏ ̞̉̍̇̈̃e̟̟̊̄̕̕n̝̜̒̓̆̕i̖̒̌̅̇̚m̞̊̃̔̊̂ ̛̜̊̎̄̂a̘̜̋̒̚̚d̟̊̎̇̂̍ ̜̖̏̑̉̕m̜̒̎̅̄̚i̝̖̓̂̍̕n̙̉̒̑̀̔ỉ̖̝̌̒́m̛̖̘̅̆̎ ̖̉̎̒̌̕v̖̞̀̔́̎e̖̙̗̒̎̉n̛̗̝̎̀̂ȉ̞̗̒̕̚ȧ̟̜̝̅̚m̆̉̐̐̇̈,̏̐̎́̍́ ̜̞̙̘̏̆q̙̖̙̅̓̂ủ̇́̀̔̚í̙̟̟̏̐s̖̝̍̏̂̇ ̛̘̋̈̕̕ń̛̞̜̜̎o̗̜̔̔̈̆s̞̘̘̄̒̋t̛̅̋́̔̈ȓ̓̒́̇̅ủ̜̄̃̒̍d̙̝̘̊̏̚ ̛̟̞̄́̔e̛̗̝̍̃̀x̞̖̃̄̂̅e̖̅̇̐̔̃r̗̞̖̔̎̚c̘̜̖̆̊̏ï̙̝̙̂̕t̖̏́̓̋̂ă̖̄̆̑̒t̜̟̍̉̑̏i̛̞̞̘̒̑ǒ̜̆̅̃̉ṅ̖̜̒̎̚ + u̗̞̓̔̈̏ĺ̟̝́̎̚l̛̜̅̌̎̆a̒̑̆̔̇̃m̜̗̈̊̎̚ċ̘̋̇̂̚ơ̟̖̊́̕ ̖̟̍̉̏̚l̙̔̓̀̅̏ä̞̗̘̙̅ḃ̟̎̄̃̕o̞̎̓̓̓̚r̗̜̊̓̈̒ï̗̜̃̃̅s̀̒̌̂̎̂ ̖̗̗̋̎̐n̝̟̝̘̄̚i̜̒̀̒̐̕s̘̘̄̊̃̀ī̘̜̏̌̕ ̗̖̞̐̈̒ư̙̞̄́̌t̟̘̖̙̊̚ ̌̅̋̆̚̚ä̇̊̇̕̕l̝̞̘̋̔̅i̍̋́̆̑̈q̛̆̐̈̐̚ư̏̆̊́̚î̜̝̑́̊p̗̓̅̑̆̏ ̆́̓̔̋̋e̟̊̋̏̓̚x̗̍̑̊̎̈ ̟̞̆̄̂̍ë̄̎̄̃̅a̛̜̅́̃̈ ̔̋̀̎̐̀c̖̖̍̀̒̂ơ̛̙̖̄̒m̘̔̍̏̆̕ḿ̖̙̝̏̂ȍ̓̋̈̀̕d̆̂̊̅̓̚o̖̔̌̑̚̕ ̙̆́̔̊̒c̖̘̖̀̄̍o̓̄̑̐̓̒ñ̞̒̎̈̚s̞̜̘̈̄̄e̙̊̀̇̌̋q̐̒̓́̔̃ư̗̟̔̔̚å̖̙̞̄̏t̛̙̟̒̇̏.̙̗̓̃̓̎ + D̜̖̆̏̌̌ư̑̃̌̍̕i̝̊̊̊̊̄s̛̙̒́̌̇ ̛̃̔̄̆̌ă̘̔̅̅̀ú̟̟̟̃̃t̟̂̄̈̈̃e̘̅̌̒̂̆ ̖̟̐̉̉̌î̟̟̙̜̇r̛̙̞̗̄̌ú̗̗̃̌̎r̛̙̘̉̊̕e̒̐̔̃̓̋ ̊̊̍̋̑̉d̛̝̙̉̀̓o̘̜̐̐̓̐l̞̋̌̆̍́o̊̊̐̃̃̚ṙ̛̖̘̃̕ ̞̊̀̍̒̕ȉ́̑̐̇̅ǹ̜̗̜̞̏ ̛̜̐̄̄̚r̜̖̈̇̅̋ĕ̗̉̃̔̚p̟̝̀̓̔̆r̜̈̆̇̃̃e̘̔̔̏̎̓h̗̒̉̑̆̚ė̛̘̘̈̐n̘̂̀̒̕̕d̗̅̂̋̅́ê̗̜̜̜̕r̟̋̄̐̅̂i̛̔̌̒̂̕t̛̗̓̎̀̎ ̙̗̀̉̂̚ȉ̟̗̐̓̚n̙̂̍̏̓̉ ̙̘̊̋̍̕v̜̖̀̎̆̐ő̜̆̉̃̎l̑̋̒̉̔̆ư̙̓̓́̚p̝̘̖̎̏̒t̛̘̝̞̂̓ȁ̘̆̔́̊t̖̝̉̒̐̎e̞̟̋̀̅̄ ̆̌̃̀̑̔v̝̘̝̍̀̇ȅ̝̊̄̓̕l̞̝̑̔̂̋ĭ̝̄̅̆̍t̝̜̉̂̈̇ + ē̟̊̇̕̚s̖̘̘̒̄̑s̛̘̀̊̆̇e̛̝̘̒̏̚ ̉̅̑̂̐̎c̛̟̙̎̋̓i̜̇̒̏̆̆l̟̄́̆̊̌l̍̊̋̃̆̌ủ̗̙̒̔̚m̛̘̘̖̅̍ ̖̙̈̎̂̕d̞̟̏̋̈̔ơ̟̝̌̃̄l̗̙̝̂̉̒õ̒̃̄̄̚ŕ̗̏̏̊̍ê̞̝̞̋̈ ̜̔̒̎̃̚e̞̟̞̒̃̄ư̖̏̄̑̃ ̛̗̜̄̓̎f̛̖̞̅̓̃ü̞̏̆̋̕g̜̝̞̑̑̆i̛̘̐̐̅̚à̜̖̌̆̎t̙̙̎̉̂̍ ̋̔̈̎̎̉n̞̓́̔̊̕ư̘̅̋̔̚l̗̍̒̄̀̚l̞̗̘̙̓̍â̘̔̒̎̚ ̖̓̋̉̃̆p̛̛̘̋̌̀ä̙̔́̒̕r̟̟̖̋̐̋ì̗̙̎̓̓ȃ̔̋̑̚̕t̄́̎̓̂̋ư̏̈̂̑̃r̖̓̋̊̚̚.̒̆̑̆̊̎ ̘̜̍̐̂̚E̞̅̐̇́̂x̄́̈̌̉̕ć̘̃̉̃̕è̘̂̑̏̑p̝̘̑̂̌̆t̔̐̅̍̌̂ȇ̞̈̐̚̕ű̝̞̜́̚ŕ̗̝̉̆́ + š̟́̔̏̀ȉ̝̟̝̏̅n̑̆̇̒̆̚t̝̒́̅̋̏ ̗̑̌̋̇̚ơ̙̗̟̆̅c̙̞̙̎̊̎c̘̟̍̔̊̊a̛̒̓̉́̐e̜̘̙̒̅̇ć̝̝̂̇̕ả̓̍̎̂̚t̗̗̗̟̒̃ ̘̒̓̐̇́c̟̞̉̐̓̄ȕ̙̗̅́̏p̛̍̋̈́̅i̖̓̒̍̈̄d̞̃̈̌̆̐a̛̗̝̎̋̉t̞̙̀̊̆̇a̛̙̒̆̉̚t̜̟̘̉̓̚ ̝̘̗̐̇̕n̛̘̑̏̂́ō̑̋̉̏́ň̞̊̆̄̃ ̙̙̙̜̄̏p̒̆̋̋̓̏r̖̖̅̉́̚ơ̜̆̑̈̚i̟̒̀̃̂̌d̛̏̃̍̋̚ë̖̞̙̗̓n̛̘̓̒̅̎t̟̗̙̊̆̚,̘̙̔̊̚̕ ̟̗̘̜̑̔s̜̝̍̀̓̌û̞̙̅̇́n̘̗̝̒̃̎t̗̅̀̅̊̈ ̗̖̅̅̀̄i̛̖̍̅̋̂n̙̝̓̓̎̚ ̞̋̅̋̃̚c̗̒̀̆̌̎ū̞̂̑̌̓ĺ̛̐̍̑́p̝̆̌̎̈̚a̖̙̒̅̈̌ ̝̝̜̂̈̀q̝̖̔̍̒̚ư̔̐̂̎̊ǐ̛̟̖̘̕ + o̖̜̔̋̅̚f̛̊̀̉́̕f̏̉̀̔̃̃i̘̍̎̐̔̎c̙̅̑̂̐̅ȋ̛̜̀̒̚a̋̍̇̏̀̋ ̖̘̒̅̃̒d̗̘̓̈̇̋é̝́̎̒̄š̙̒̊̉̋e̖̓̐̀̍̕r̗̞̂̅̇̄ù̘̇̐̉̀n̐̑̀̄̍̐t̟̀̂̊̄̚ ̟̝̂̍̏́m̜̗̈̂̏̚ő̞̊̑̇̒l̘̑̏́̔̄l̛̛̇̃̋̊i̓̋̒̃̉̌t̛̗̜̏̀̋ ̙̟̒̂̌̐a̙̝̔̆̏̅n̝̙̙̗̆̅i̍̔́̊̃̕m̖̝̟̒̍̚ ̛̃̃̑̌́ǐ̘̉̔̅̚d̝̗̀̌̏̒ ̖̝̓̑̊̚ȇ̞̟̖̌̕š̙̙̈̔̀t̂̉̒̍̄̄ ̝̗̊̋̌̄l̛̞̜̙̘̔å̝̍̂̍̅b̜̆̇̈̉̌ǒ̜̙̎̃̆r̝̀̄̍́̕ư̋̊́̊̕m̜̗̒̐̕̚.̟̘̀̒̌̚]], + '\n')) + + -- tests that we can handle overflow of the buffer + -- for redraw events (4096 bytes) gracefully + screen:expect{grid=[[ + ^L̓̉̑̒̌̚ơ̗̌̒̄̀ŕ̈̈̎̐̕è̇̅̄̄̐m̖̟̟̅̄̚ ̛̓̑̆̇̍i̗̟̞̜̅̐p̗̞̜̉̆̕s̟̜̘̍̑̏ū̟̞̎̃̉ḿ̘̙́́̐ ̖̍̌̇̉̚d̞̄̃̒̉̎ò́̌̌̂̐l̞̀̄̆̌̚ȯ̖̞̋̀̐r̓̇̌̃̃̚ ̗̘̀̏̍́s̜̀̎̎̑̕i̟̗̐̄̄̚t̝̎̆̓̐̒ ̘̇̔̓̊̚ȃ̛̟̗̏̅m̜̟̙̞̈̓é̘̞̟̔̆t̝̂̂̈̑̔,̜̜̖̅̄̍ ̛̗̊̓̆̚c̟̍̆̍̈̔ȯ̖̖̝̑̀n̜̟̎̊̃̚s̟̏̇̎̒̚e̙̐̈̓̌̚c̙̍̈̏̅̕ť̇̄̇̆̓e̛̓̌̈̓̈t̟̍̀̉̆̅u̝̞̎̂̄̚r̘̀̅̈̅̐ ̝̞̓́̇̉ã̏̀̆̅̕d̛̆̐̉̆̋ȉ̞̟̍̃̚p̛̜̊̍̂̓ȋ̏̅̃̋̚ṥ̛̏̃̕č̛̞̝̀̂í̗̘̌́̎n̔̎́̒̂̕ǧ̗̜̋̇̂ ̛̜̔̄̎̃ê̛̔̆̇̕l̘̝̏̐̊̏ĩ̛̍̏̏̄t̟̐́̀̐̎,̙̘̍̆̉̐ ̋̂̏̄̌̅s̙̓̌̈́̇e̛̗̋̒̎̏d̜̗̊̍̊̚ | + ď̘̋̌̌̕ǒ̝̗̔̇̕ ̙̍́̄̄̉è̛̛̞̌̌i̜̖̐̈̆̚ȕ̇̈̓̃̓ŝ̛̞̙̉̋m̜̐̂̄̋̂ȯ̈̎̎̅̕d̜̙̓̔̋̑ ̞̗̄̂̂̚t̝̊́̃́̄e̛̘̜̞̓̑m̊̅̏̉̌̕p̛̈̂̇̀̐ỏ̙̘̈̉̔r̘̞̋̍̃̚ ̝̄̀̇̅̇ỉ̛̖̍̓̈n̛̛̝̎̕̕c̛̛̊̅́̐ĭ̗̓̀̍̐d̞̜̋̐̅̚i̟̙̇̄̊̄d̞̊̂̀̇̚ủ̝̉̑̃̕n̜̏̇̄̐̋ť̗̜̞̋̉ ̝̒̓̌̓̚ȕ̖̙̀̚̕t̖̘̎̉̂̌ ̛̝̄̍̌̂l̛̟̝̃̑̋á̛̝̝̔̅b̝̙̜̗̅̒ơ̖̌̒̄̆r̒̇̓̎̈̄e̛̛̖̅̏̇ ̖̗̜̝̃́e̛̛̘̅̔̌ẗ̛̙̗̐̕ ̖̟̇̋̌̈d̞̙̀̉̑̕ŏ̝̂́̐̑l̞̟̗̓̓̀ơ̘̎̃̄̂r̗̗̖̔̆̍ẻ̖̝̞̋̅ ̜̌̇̍̈̊m̈̉̇̄̒̀a̜̞̘̔̅̆g̗̖̈̃̈̉n̙̖̄̈̉̄â̛̝̜̄̃ ̛́̎̕̕̚ā̊́́̆̌l̟̙̞̃̒́i̖̇̎̃̀̋q̟̇̒̆́̊ủ́̌̇̑̚ã̛̘̉̐̚.̛́̏̐̍̊ | + U̝̙̎̈̐̆t̜̍̌̀̔̏ ̞̉̍̇̈̃e̟̟̊̄̕̕n̝̜̒̓̆̕i̖̒̌̅̇̚m̞̊̃̔̊̂ ̛̜̊̎̄̂a̘̜̋̒̚̚d̟̊̎̇̂̍ ̜̖̏̑̉̕m̜̒̎̅̄̚i̝̖̓̂̍̕n̙̉̒̑̀̔ỉ̖̝̌̒́m̛̖̘̅̆̎ ̖̉̎̒̌̕v̖̞̀̔́̎e̖̙̗̒̎̉n̛̗̝̎̀̂ȉ̞̗̒̕̚ȧ̟̜̝̅̚m̆̉̐̐̇̈,̏̐̎́̍́ ̜̞̙̘̏̆q̙̖̙̅̓̂ủ̇́̀̔̚í̙̟̟̏̐s̖̝̍̏̂̇ ̛̘̋̈̕̕ń̛̞̜̜̎o̗̜̔̔̈̆s̞̘̘̄̒̋t̛̅̋́̔̈ȓ̓̒́̇̅ủ̜̄̃̒̍d̙̝̘̊̏̚ ̛̟̞̄́̔e̛̗̝̍̃̀x̞̖̃̄̂̅e̖̅̇̐̔̃r̗̞̖̔̎̚c̘̜̖̆̊̏ï̙̝̙̂̕t̖̏́̓̋̂ă̖̄̆̑̒t̜̟̍̉̑̏i̛̞̞̘̒̑ǒ̜̆̅̃̉ṅ̖̜̒̎̚ | + u̗̞̓̔̈̏ĺ̟̝́̎̚l̛̜̅̌̎̆a̒̑̆̔̇̃m̜̗̈̊̎̚ċ̘̋̇̂̚ơ̟̖̊́̕ ̖̟̍̉̏̚l̙̔̓̀̅̏ä̞̗̘̙̅ḃ̟̎̄̃̕o̞̎̓̓̓̚r̗̜̊̓̈̒ï̗̜̃̃̅s̀̒̌̂̎̂ ̖̗̗̋̎̐n̝̟̝̘̄̚i̜̒̀̒̐̕s̘̘̄̊̃̀ī̘̜̏̌̕ ̗̖̞̐̈̒ư̙̞̄́̌t̟̘̖̙̊̚ ̌̅̋̆̚̚ä̇̊̇̕̕l̝̞̘̋̔̅i̍̋́̆̑̈q̛̆̐̈̐̚ư̏̆̊́̚î̜̝̑́̊p̗̓̅̑̆̏ ̆́̓̔̋̋e̟̊̋̏̓̚x̗̍̑̊̎̈ ̟̞̆̄̂̍ë̄̎̄̃̅a̛̜̅́̃̈ ̔̋̀̎̐̀c̖̖̍̀̒̂ơ̛̙̖̄̒m̘̔̍̏̆̕ḿ̖̙̝̏̂ȍ̓̋̈̀̕d̆̂̊̅̓̚o̖̔̌̑̚̕ ̙̆́̔̊̒c̖̘̖̀̄̍o̓̄̑̐̓̒ñ̞̒̎̈̚s̞̜̘̈̄̄e̙̊̀̇̌̋q̐̒̓́̔̃ư̗̟̔̔̚å̖̙̞̄̏t̛̙̟̒̇̏.̙̗̓̃̓̎ | + D̜̖̆̏̌̌ư̑̃̌̍̕i̝̊̊̊̊̄s̛̙̒́̌̇ ̛̃̔̄̆̌ă̘̔̅̅̀ú̟̟̟̃̃t̟̂̄̈̈̃e̘̅̌̒̂̆ ̖̟̐̉̉̌î̟̟̙̜̇r̛̙̞̗̄̌ú̗̗̃̌̎r̛̙̘̉̊̕e̒̐̔̃̓̋ ̊̊̍̋̑̉d̛̝̙̉̀̓o̘̜̐̐̓̐l̞̋̌̆̍́o̊̊̐̃̃̚ṙ̛̖̘̃̕ ̞̊̀̍̒̕ȉ́̑̐̇̅ǹ̜̗̜̞̏ ̛̜̐̄̄̚r̜̖̈̇̅̋ĕ̗̉̃̔̚p̟̝̀̓̔̆r̜̈̆̇̃̃e̘̔̔̏̎̓h̗̒̉̑̆̚ė̛̘̘̈̐n̘̂̀̒̕̕d̗̅̂̋̅́ê̗̜̜̜̕r̟̋̄̐̅̂i̛̔̌̒̂̕t̛̗̓̎̀̎ ̙̗̀̉̂̚ȉ̟̗̐̓̚n̙̂̍̏̓̉ ̙̘̊̋̍̕v̜̖̀̎̆̐ő̜̆̉̃̎l̑̋̒̉̔̆ư̙̓̓́̚p̝̘̖̎̏̒t̛̘̝̞̂̓ȁ̘̆̔́̊t̖̝̉̒̐̎e̞̟̋̀̅̄ ̆̌̃̀̑̔v̝̘̝̍̀̇ȅ̝̊̄̓̕l̞̝̑̔̂̋ĭ̝̄̅̆̍t̝̜̉̂̈̇ | + ē̟̊̇̕̚s̖̘̘̒̄̑s̛̘̀̊̆̇e̛̝̘̒̏̚ ̉̅̑̂̐̎c̛̟̙̎̋̓i̜̇̒̏̆̆l̟̄́̆̊̌l̍̊̋̃̆̌ủ̗̙̒̔̚m̛̘̘̖̅̍ ̖̙̈̎̂̕d̞̟̏̋̈̔ơ̟̝̌̃̄l̗̙̝̂̉̒õ̒̃̄̄̚ŕ̗̏̏̊̍ê̞̝̞̋̈ ̜̔̒̎̃̚e̞̟̞̒̃̄ư̖̏̄̑̃ ̛̗̜̄̓̎f̛̖̞̅̓̃ü̞̏̆̋̕g̜̝̞̑̑̆i̛̘̐̐̅̚à̜̖̌̆̎t̙̙̎̉̂̍ ̋̔̈̎̎̉n̞̓́̔̊̕ư̘̅̋̔̚l̗̍̒̄̀̚l̞̗̘̙̓̍â̘̔̒̎̚ ̖̓̋̉̃̆p̛̛̘̋̌̀ä̙̔́̒̕r̟̟̖̋̐̋ì̗̙̎̓̓ȃ̔̋̑̚̕t̄́̎̓̂̋ư̏̈̂̑̃r̖̓̋̊̚̚.̒̆̑̆̊̎ ̘̜̍̐̂̚E̞̅̐̇́̂x̄́̈̌̉̕ć̘̃̉̃̕è̘̂̑̏̑p̝̘̑̂̌̆t̔̐̅̍̌̂ȇ̞̈̐̚̕ű̝̞̜́̚ŕ̗̝̉̆́ | + š̟́̔̏̀ȉ̝̟̝̏̅n̑̆̇̒̆̚t̝̒́̅̋̏ ̗̑̌̋̇̚ơ̙̗̟̆̅c̙̞̙̎̊̎c̘̟̍̔̊̊a̛̒̓̉́̐e̜̘̙̒̅̇ć̝̝̂̇̕ả̓̍̎̂̚t̗̗̗̟̒̃ ̘̒̓̐̇́c̟̞̉̐̓̄ȕ̙̗̅́̏p̛̍̋̈́̅i̖̓̒̍̈̄d̞̃̈̌̆̐a̛̗̝̎̋̉t̞̙̀̊̆̇a̛̙̒̆̉̚t̜̟̘̉̓̚ ̝̘̗̐̇̕n̛̘̑̏̂́ō̑̋̉̏́ň̞̊̆̄̃ ̙̙̙̜̄̏p̒̆̋̋̓̏r̖̖̅̉́̚ơ̜̆̑̈̚i̟̒̀̃̂̌d̛̏̃̍̋̚ë̖̞̙̗̓n̛̘̓̒̅̎t̟̗̙̊̆̚,̘̙̔̊̚̕ ̟̗̘̜̑̔s̜̝̍̀̓̌û̞̙̅̇́n̘̗̝̒̃̎t̗̅̀̅̊̈ ̗̖̅̅̀̄i̛̖̍̅̋̂n̙̝̓̓̎̚ ̞̋̅̋̃̚c̗̒̀̆̌̎ū̞̂̑̌̓ĺ̛̐̍̑́p̝̆̌̎̈̚a̖̙̒̅̈̌ ̝̝̜̂̈̀q̝̖̔̍̒̚ư̔̐̂̎̊ǐ̛̟̖̘̕ | + o̖̜̔̋̅̚f̛̊̀̉́̕f̏̉̀̔̃̃i̘̍̎̐̔̎c̙̅̑̂̐̅ȋ̛̜̀̒̚a̋̍̇̏̀̋ ̖̘̒̅̃̒d̗̘̓̈̇̋é̝́̎̒̄š̙̒̊̉̋e̖̓̐̀̍̕r̗̞̂̅̇̄ù̘̇̐̉̀n̐̑̀̄̍̐t̟̀̂̊̄̚ ̟̝̂̍̏́m̜̗̈̂̏̚ő̞̊̑̇̒l̘̑̏́̔̄l̛̛̇̃̋̊i̓̋̒̃̉̌t̛̗̜̏̀̋ ̙̟̒̂̌̐a̙̝̔̆̏̅n̝̙̙̗̆̅i̍̔́̊̃̕m̖̝̟̒̍̚ ̛̃̃̑̌́ǐ̘̉̔̅̚d̝̗̀̌̏̒ ̖̝̓̑̊̚ȇ̞̟̖̌̕š̙̙̈̔̀t̂̉̒̍̄̄ ̝̗̊̋̌̄l̛̞̜̙̘̔å̝̍̂̍̅b̜̆̇̈̉̌ǒ̜̙̎̃̆r̝̀̄̍́̕ư̋̊́̊̕m̜̗̒̐̕̚.̟̘̀̒̌̚ | + {1:~ }| + | + ]]} + end) end) describe('multibyte rendering: statusline', function() diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua index 4e5e9c3a71..b30aa67fd3 100644 --- a/test/functional/ui/multigrid_spec.lua +++ b/test/functional/ui/multigrid_spec.lua @@ -77,18 +77,18 @@ describe('ext_multigrid', function() command('vsplit') screen:expect{grid=[[ ## grid 1 - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {11:[No Name] }{12:[No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -129,18 +129,18 @@ describe('ext_multigrid', function() command('split') screen:expect{grid=[[ ## grid 1 - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}{11:[No Name] }| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│{11:[No Name] }| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {12:[No Name] [No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -300,12 +300,12 @@ describe('ext_multigrid', function() command('vsp') screen:expect{grid=[[ ## grid 1 - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| {11:[No Name] }{12:[No Name] [No Name] }| [2:-----------------------------------------------------]| [2:-----------------------------------------------------]| @@ -347,12 +347,12 @@ describe('ext_multigrid', function() insert('hello') screen:expect{grid=[[ ## grid 1 - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| - [6:--------------------]{12:│}[5:----------------]{12:│}[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| + [6:--------------------]│[5:----------------]│[4:---------------]| {11:[No Name] [+] }{12:[No Name] [+] [No Name] [+] }| [2:-----------------------------------------------------]| [2:-----------------------------------------------------]| @@ -467,18 +467,18 @@ describe('ext_multigrid', function() command('vsp') screen:expect{grid=[[ ## grid 1 - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {11:[No Name] }{12:[No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -516,18 +516,18 @@ describe('ext_multigrid', function() command('vertical resize 10') screen:expect{grid=[[ ## grid 1 - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| - [4:----------]{12:│}[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| + [4:----------]│[2:------------------------------------------]| {11:<No Name] }{12:[No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -565,18 +565,18 @@ describe('ext_multigrid', function() command('sp') screen:expect{grid=[[ ## grid 1 - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - {11:[No Name] }{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + {11:[No Name] }│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {12:[No Name] [No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -611,18 +611,18 @@ describe('ext_multigrid', function() insert('hello') screen:expect{grid=[[ ## grid 1 - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - {11:[No Name] [+] }{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + {11:[No Name] [+] }│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {12:[No Name] [+] [No Name] [+] }| [3:-----------------------------------------------------]| ## grid 2 @@ -659,18 +659,18 @@ describe('ext_multigrid', function() command('vsp') screen:expect{grid=[[ ## grid 1 - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {11:[No Name] }{12:[No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -1056,12 +1056,12 @@ describe('ext_multigrid', function() command('vsp') screen:expect{grid=[[ ## grid 1 - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| {11:[No Name] }{12:[No Name] }| [2:-----------------------------------------------------]| [2:-----------------------------------------------------]| @@ -1097,12 +1097,12 @@ describe('ext_multigrid', function() feed(":echoerr 'very' | echoerr 'much' | echoerr 'fail'<cr>") screen:expect{grid=[[ ## grid 1 - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| {11:[No Name] }{12:[No Name] }| [2:-----------------------------------------------------]| [2:-----------------------------------------------------]| @@ -1141,12 +1141,12 @@ describe('ext_multigrid', function() feed('<cr>') screen:expect{grid=[[ ## grid 1 - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| {11:[No Name] }{12:[No Name] }| [2:-----------------------------------------------------]| [2:-----------------------------------------------------]| @@ -1242,12 +1242,12 @@ describe('ext_multigrid', function() feed("<c-c>") screen:expect{grid=[[ ## grid 1 - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| - [5:--------------------------]{12:│}[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| + [5:--------------------------]│[4:--------------------------]| {11:[No Name] }{12:[No Name] }| [2:-----------------------------------------------------]| [2:-----------------------------------------------------]| @@ -1285,18 +1285,18 @@ describe('ext_multigrid', function() command('vsp') screen:expect{grid=[[ ## grid 1 - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {11:[No Name] }{12:[No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -1453,17 +1453,17 @@ describe('ext_multigrid', function() screen:expect{grid=[[ ## grid 1 {7: }{18:2}{7: [No Name] }{16: }{17:2}{16: [No Name] }{12: }{16:X}| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {11:[No Name] }{12:[No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -1637,18 +1637,18 @@ describe('ext_multigrid', function() command('tabclose') screen:expect{grid=[[ ## grid 1 - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {11:[No Name] }{12:[No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -1915,7 +1915,7 @@ describe('ext_multigrid', function() {1:~ }| ]]} - meths.input_mouse('left', 'press', '', 1,6, 20) + meths.input_mouse('left', 'press', '', 1, 6, 20) -- TODO(bfredl): "batching" input_mouse is formally not supported yet. -- Normally it should work fine in async context when nvim is not blocked, -- but add a poke_eventloop be sure. @@ -1960,13 +1960,13 @@ describe('ext_multigrid', function() [4:-----------------------------------------------------]| [4:-----------------------------------------------------]| {12:[No Name] [+] }| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| - [5:--------------------------]{12:│}[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| + [5:--------------------------]│[2:--------------------------]| {11:[No Name] [+] }{12:[No Name] [+] }| [3:-----------------------------------------------------]| ## grid 2 @@ -2002,13 +2002,13 @@ describe('ext_multigrid', function() [4:-----------------------------------------------------]| [4:-----------------------------------------------------]| {12:[No Name] [+] }| - [5:------------------------------]{12:│}[2:----------------------]| - [5:------------------------------]{12:│}[2:----------------------]| - [5:------------------------------]{12:│}[2:----------------------]| - [5:------------------------------]{12:│}[2:----------------------]| - [5:------------------------------]{12:│}[2:----------------------]| - [5:------------------------------]{12:│}[2:----------------------]| - [5:------------------------------]{12:│}[2:----------------------]| + [5:------------------------------]│[2:----------------------]| + [5:------------------------------]│[2:----------------------]| + [5:------------------------------]│[2:----------------------]| + [5:------------------------------]│[2:----------------------]| + [5:------------------------------]│[2:----------------------]| + [5:------------------------------]│[2:----------------------]| + [5:------------------------------]│[2:----------------------]| {11:[No Name] [+] }{12:[No Name] [+] }| [3:-----------------------------------------------------]| ## grid 2 @@ -2049,18 +2049,18 @@ describe('ext_multigrid', function() screen:expect{grid=[[ ## grid 1 - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}[5:--------------------------]| - [4:--------------------------]{12:│}{11:[No Name] [+] }| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| - [4:--------------------------]{12:│}[2:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│[5:--------------------------]| + [4:--------------------------]│{11:[No Name] [+] }| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| + [4:--------------------------]│[2:--------------------------]| {12:[No Name] [No Name] }| [3:-----------------------------------------------------]| ## grid 2 @@ -2092,7 +2092,6 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| ]]} - end) it('has viewport information', function() @@ -2369,4 +2368,223 @@ describe('ext_multigrid', function() [2] = {win = {id = 1000}, topline = 6, botline = 12, curline = 10, curcol = 1, linecount = 11}, }} end) + + it('with winbar', function() + command 'split' + command 'setlocal winbar=very\\ bar' + screen:expect{grid=[[ + ## grid 1 + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + {11:[No Name] }| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {12:[No Name] }| + [3:-----------------------------------------------------]| + ## grid 2 + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ## grid 4 + {7:very bar }| + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + end) + + it('with winbar dragging statusline with mouse works correctly', function() + meths.set_option('winbar', 'Set Up The Bars') + command('split') + screen:expect([[ + ## grid 1 + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + {11:[No Name] }| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {12:[No Name] }| + [3:-----------------------------------------------------]| + ## grid 2 + {7:Set Up The Bars }| + | + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ## grid 4 + {7:Set Up The Bars }| + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]) + + meths.input_mouse('left', 'press', '', 1, 6, 20) + poke_eventloop() + meths.input_mouse('left', 'drag', '', 1, 7, 20) + screen:expect([[ + ## grid 1 + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + {11:[No Name] }| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {12:[No Name] }| + [3:-----------------------------------------------------]| + ## grid 2 + {7:Set Up The Bars }| + | + {1:~ }| + {1:~ }| + ## grid 3 + | + ## grid 4 + {7:Set Up The Bars }| + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]) + + meths.input_mouse('left', 'drag', '', 1, 4, 20) + screen:expect([[ + ## grid 1 + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + {11:[No Name] }| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {12:[No Name] }| + [3:-----------------------------------------------------]| + ## grid 2 + {7:Set Up The Bars }| + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ## grid 4 + {7:Set Up The Bars }| + ^ | + {1:~ }| + {1:~ }| + ]]) + + meths.input_mouse('left', 'press', '', 1, 12, 10) + poke_eventloop() + meths.input_mouse('left', 'drag', '', 1, 10, 10) + screen:expect([[ + ## grid 1 + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + {11:[No Name] }| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {12:[No Name] }| + [3:-----------------------------------------------------]| + [3:-----------------------------------------------------]| + [3:-----------------------------------------------------]| + ## grid 2 + {7:Set Up The Bars }| + | + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + | + | + ## grid 4 + {7:Set Up The Bars }| + ^ | + {1:~ }| + {1:~ }| + ]]) + eq(3, meths.get_option('cmdheight')) + + meths.input_mouse('left', 'drag', '', 1, 12, 10) + screen:expect([[ + ## grid 1 + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + [4:-----------------------------------------------------]| + {11:[No Name] }| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + [2:-----------------------------------------------------]| + {12:[No Name] }| + [3:-----------------------------------------------------]| + ## grid 2 + {7:Set Up The Bars }| + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ## grid 4 + {7:Set Up The Bars }| + ^ | + {1:~ }| + {1:~ }| + ]]) + eq(1, meths.get_option('cmdheight')) + end) end) diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua index 2f113f6ac6..c2b0bcdb64 100644 --- a/test/functional/ui/options_spec.lua +++ b/test/functional/ui/options_spec.lua @@ -4,6 +4,7 @@ local clear = helpers.clear local command = helpers.command local eq = helpers.eq local shallowcopy = helpers.shallowcopy +local eval = helpers.eval describe('UI receives option updates', function() local screen @@ -62,17 +63,18 @@ describe('UI receives option updates', function() end screen:attach() screen:expect(function() - eq({'mouse_off'}, evs) + eq({'mouse_on'}, evs) end) - command("set mouse=nvi") + command("set mouse=") + command("set mouse&") screen:expect(function() - eq({'mouse_off','mouse_on'}, evs) + eq({'mouse_on','mouse_off', 'mouse_on'}, evs) end) screen:detach() - eq({'mouse_off','mouse_on'}, evs) + eq({'mouse_on','mouse_off', 'mouse_on'}, evs) screen:attach() screen:expect(function() - eq({'mouse_off','mouse_on','mouse_on'}, evs) + eq({'mouse_on','mouse_off','mouse_on', 'mouse_on'}, evs) end) end) @@ -86,6 +88,12 @@ describe('UI receives option updates', function() eq(expected, screen.options) end) + command("set pumblend=-1") + expected.pumblend = 0 + screen:expect(function() + eq(expected, screen.options) + end) + command("set guifont=Comic\\ Sans") expected.guifont = "Comic Sans" screen:expect(function() @@ -168,3 +176,42 @@ describe('UI receives option updates', function() it('from startup options with --headless', function() startup_test(true) end) it('from startup options with --embed', function() startup_test(false) end) end) + +describe('UI can set terminal option', function() + local screen + before_each(function() + -- by default we implicity "--cmd 'set bg=light'" which ruins everything + clear{args_rm={'--cmd'}} + screen = Screen.new(20,5) + end) + + it('term_background', function() + eq('dark', eval '&background') + + screen:attach {term_background='light'} + eq('light', eval '&background') + end) + + it("term_background but not if 'background' already set by user", function() + eq('dark', eval '&background') + command 'set background=dark' + + screen:attach {term_background='light'} + + eq('dark', eval '&background') + end) + + it('term_name', function() + eq('nvim', eval '&term') + + screen:attach {term_name='xterm'} + eq('xterm', eval '&term') + end) + + it('term_colors', function() + eq('256', eval '&t_Co') + + screen:attach {term_colors=8} + eq('8', eval '&t_Co') + end) +end) diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua index 50e5dfac84..71c6410013 100644 --- a/test/functional/ui/output_spec.lua +++ b/test/functional/ui/output_spec.lua @@ -9,6 +9,7 @@ local feed_command = helpers.feed_command local iswin = helpers.iswin local clear = helpers.clear local command = helpers.command +local testprg = helpers.testprg local nvim_dir = helpers.nvim_dir local has_powershell = helpers.has_powershell local set_shell_powershell = helpers.set_shell_powershell @@ -54,7 +55,7 @@ describe("shell command :!", function() if 'openbsd' == helpers.uname() then pending('FIXME #10804') end - child_session.feed_data(":!"..nvim_dir.."/shell-test REP 30001 foo\n") + child_session.feed_data((":!%s REP 30001 foo\n"):format(testprg('shell-test'))) -- If we observe any line starting with a dot, then throttling occurred. -- Avoid false failure on slow systems. @@ -207,12 +208,7 @@ describe("shell command :!", function() it('handles multibyte sequences split over buffer boundaries', function() command('cd '..nvim_dir) - local cmd - if iswin() then - cmd = '!shell-test UTF-8 ' - else - cmd = '!./shell-test UTF-8' - end + local cmd = iswin() and '!shell-test UTF-8 ' or '!./shell-test UTF-8' feed_command(cmd) -- Note: only the first example of split composed char works screen:expect([[ diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 4fc5c389e5..7b0005bcf1 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -10,6 +10,8 @@ local funcs = helpers.funcs local get_pathsep = helpers.get_pathsep local eq = helpers.eq local pcall_err = helpers.pcall_err +local exec_lua = helpers.exec_lua +local exec = helpers.exec describe('ui/ext_popupmenu', function() local screen @@ -25,6 +27,7 @@ describe('ui/ext_popupmenu', function() [5] = {bold = true, foreground = Screen.colors.SeaGreen}, [6] = {background = Screen.colors.WebGray}, [7] = {background = Screen.colors.LightMagenta}, + [8] = {foreground = Screen.colors.Red}, }) source([[ function! TestComplete() abort @@ -369,6 +372,111 @@ describe('ui/ext_popupmenu', function() {1:~ }| {2:-- INSERT --} | ]]) + + command('iunmap <f1>') + command('iunmap <f2>') + command('iunmap <f3>') + exec_lua([[ + vim.keymap.set('i', '<f1>', function() vim.api.nvim_select_popupmenu_item(2, true, false, {}) end) + vim.keymap.set('i', '<f2>', function() vim.api.nvim_select_popupmenu_item(-1, false, false, {}) end) + vim.keymap.set('i', '<f3>', function() vim.api.nvim_select_popupmenu_item(1, false, true, {}) end) + ]]) + feed('<C-r>=TestComplete()<CR>') + screen:expect([[ + | + foo^ | + {6:fo x the foo }{1: }| + {7:bar }{1: }| + {7:spam }{1: }| + {1:~ }| + {1:~ }| + {2:-- INSERT --} | + ]]) + + feed('<f1>') + screen:expect([[ + | + spam^ | + {7:fo x the foo }{1: }| + {7:bar }{1: }| + {6:spam }{1: }| + {1:~ }| + {1:~ }| + {2:-- INSERT --} | + ]]) + + feed('<f2>') + screen:expect([[ + | + spam^ | + {7:fo x the foo }{1: }| + {7:bar }{1: }| + {7:spam }{1: }| + {1:~ }| + {1:~ }| + {2:-- INSERT --} | + ]]) + + feed('<f3>') + screen:expect([[ + | + bar^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:-- INSERT --} | + ]]) + + feed('<esc>ddiaa bb cc<cr>') + feed('<c-x><c-n>') + screen:expect([[ + aa bb cc | + aa^ | + {6:aa }{1: }| + {7:bb }{1: }| + {7:cc }{1: }| + {1:~ }| + {1:~ }| + {2:-- Keyword Local completion (^N^P) }{5:match 1 of 3} | + ]]) + + feed('<f1>') + screen:expect([[ + aa bb cc | + cc^ | + {7:aa }{1: }| + {7:bb }{1: }| + {6:cc }{1: }| + {1:~ }| + {1:~ }| + {2:-- Keyword Local completion (^N^P) }{5:match 3 of 3} | + ]]) + + feed('<f2>') + screen:expect([[ + aa bb cc | + cc^ | + {7:aa }{1: }| + {7:bb }{1: }| + {7:cc }{1: }| + {1:~ }| + {1:~ }| + {2:-- Keyword Local completion (^N^P) }{8:Back at original} | + ]]) + + feed('<f3>') + screen:expect([[ + aa bb cc | + bb^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:-- INSERT --} | + ]]) end) local function source_complete_month() @@ -846,72 +954,72 @@ describe('builtin popupmenu', function() insert('aaa aab aac\n') feed(':vsplit<cr>') screen:expect([[ - aaa aab aac {3:│}aaa aab aac| - ^ {3:│} | - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| + aaa aab aac │aaa aab aac| + ^ │ | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| {4:[No Name] [+] }{3:<Name] [+] }| :vsplit | ]]) feed('ibbb a<c-x><c-n>') screen:expect([[ - aaa aab aac {3:│}aaa aab aac| - bbb aaa^ {3:│}bbb aaa | - {1:~ }{s: aaa }{1: }{3:│}{1:~ }| - {1:~ }{n: aab }{1: }{3:│}{1:~ }| - {1:~ }{n: aac }{1: }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| + aaa aab aac │aaa aab aac| + bbb aaa^ │bbb aaa | + {1:~ }{s: aaa }{1: }│{1:~ }| + {1:~ }{n: aab }{1: }│{1:~ }| + {1:~ }{n: aac }{1: }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| {4:[No Name] [+] }{3:<Name] [+] }| {2:-- }{5:match 1 of 3} | ]]) feed('<esc><c-w><c-w>oc a<c-x><c-n>') screen:expect([[ - aaa aab aac{3:│}aaa aab aac | - bbb aaa {3:│}bbb aaa | - c aaa {3:│}c aaa^ | - {1:~ }{3:│}{1:~}{s: aaa }{1: }| - {1:~ }{3:│}{1:~}{n: aab }{1: }| - {1:~ }{3:│}{1:~}{n: aac }{1: }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| - {1:~ }{3:│}{1:~ }| + aaa aab aac│aaa aab aac | + bbb aaa │bbb aaa | + c aaa │c aaa^ | + {1:~ }│{1:~}{s: aaa }{1: }| + {1:~ }│{1:~}{n: aab }{1: }| + {1:~ }│{1:~}{n: aac }{1: }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| {3:<Name] [+] }{4:[No Name] [+] }| {2:-- }{5:match 1 of 3} | ]]) @@ -1845,7 +1953,7 @@ describe('builtin popupmenu', function() ]]) end) - it('wildoptions=pum with scrolled mesages ', function() + it('wildoptions=pum with scrolled messages ', function() screen:try_resize(40,10) command('set wildmenu') command('set wildoptions=pum') @@ -2084,7 +2192,7 @@ describe('builtin popupmenu', function() {20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} | ]]) - -- can disable blending for indiviual attribute. For instance current + -- can disable blending for individual attribute. For instance current -- selected item. (also tests that `hi Pmenu*` take immediate effect) command('hi PMenuSel blend=0') screen:expect([[ @@ -2252,6 +2360,103 @@ describe('builtin popupmenu', function() {2:-- INSERT --} | ]]) end) + + it('supports mousemodel=popup', function() + screen:try_resize(32, 6) + exec([[ + call setline(1, 'popup menu test') + set mouse=a mousemodel=popup + + aunmenu PopUp + menu PopUp.foo :let g:menustr = 'foo'<CR> + menu PopUp.bar :let g:menustr = 'bar'<CR> + menu PopUp.baz :let g:menustr = 'baz'<CR> + ]]) + meths.input_mouse('right', 'press', '', 0, 0, 4) + screen:expect([[ + ^popup menu test | + {1:~ }{n: foo }{1: }| + {1:~ }{n: bar }{1: }| + {1:~ }{n: baz }{1: }| + {1:~ }| + | + ]]) + feed('<Down>') + screen:expect([[ + ^popup menu test | + {1:~ }{s: foo }{1: }| + {1:~ }{n: bar }{1: }| + {1:~ }{n: baz }{1: }| + {1:~ }| + | + ]]) + feed('<Down>') + screen:expect([[ + ^popup menu test | + {1:~ }{n: foo }{1: }| + {1:~ }{s: bar }{1: }| + {1:~ }{n: baz }{1: }| + {1:~ }| + | + ]]) + feed('<CR>') + screen:expect([[ + ^popup menu test | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + :let g:menustr = 'bar' | + ]]) + eq('bar', meths.get_var('menustr')) + meths.input_mouse('right', 'press', '', 0, 1, 20) + screen:expect([[ + ^popup menu test | + {1:~ }| + {1:~ }{n: foo }{1: }| + {1:~ }{n: bar }{1: }| + {1:~ }{n: baz }{1: }| + :let g:menustr = 'bar' | + ]]) + meths.input_mouse('left', 'press', '', 0, 4, 22) + screen:expect([[ + ^popup menu test | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + :let g:menustr = 'baz' | + ]]) + eq('baz', meths.get_var('menustr')) + meths.input_mouse('right', 'press', '', 0, 0, 4) + screen:expect([[ + ^popup menu test | + {1:~ }{n: foo }{1: }| + {1:~ }{n: bar }{1: }| + {1:~ }{n: baz }{1: }| + {1:~ }| + :let g:menustr = 'baz' | + ]]) + meths.input_mouse('right', 'drag', '', 0, 3, 6) + screen:expect([[ + ^popup menu test | + {1:~ }{n: foo }{1: }| + {1:~ }{n: bar }{1: }| + {1:~ }{s: baz }{1: }| + {1:~ }| + :let g:menustr = 'baz' | + ]]) + meths.input_mouse('right', 'release', '', 0, 1, 6) + screen:expect([[ + ^popup menu test | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + :let g:menustr = 'foo' | + ]]) + eq('foo', meths.get_var('menustr')) + end) end) describe('builtin popupmenu with ui/ext_multigrid', function() @@ -2343,4 +2548,121 @@ describe('builtin popupmenu with ui/ext_multigrid', function() {n: 哦哦哦哦哦哦哦哦哦>}{s: }| ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 11, false, 100}}}) end) + + it('supports mousemodel=popup', function() + screen:try_resize(32, 6) + exec([[ + call setline(1, 'popup menu test') + set mouse=a mousemodel=popup + + aunmenu PopUp + menu PopUp.foo :let g:menustr = 'foo'<CR> + menu PopUp.bar :let g:menustr = 'bar'<CR> + menu PopUp.baz :let g:menustr = 'baz'<CR> + ]]) + meths.input_mouse('right', 'press', '', 2, 1, 20) + screen:expect({grid=[[ + ## grid 1 + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [3:--------------------------------]| + ## grid 2 + ^popup menu test | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ## grid 4 + {n: foo }| + {n: bar }| + {n: baz }| + ]], float_pos={[4] = {{id = -1}, 'NW', 2, 2, 19, false, 100}}}) + meths.input_mouse('left', 'press', '', 4, 2, 2) + screen:expect({grid=[[ + ## grid 1 + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [3:--------------------------------]| + ## grid 2 + ^popup menu test | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + :let g:menustr = 'baz' | + ]]}) + eq('baz', meths.get_var('menustr')) + meths.input_mouse('right', 'press', '', 2, 0, 4) + screen:expect({grid=[[ + ## grid 1 + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [3:--------------------------------]| + ## grid 2 + ^popup menu test | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + :let g:menustr = 'baz' | + ## grid 4 + {n: foo }| + {n: bar }| + {n: baz }| + ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 100}}}) + meths.input_mouse('right', 'drag', '', 2, 3, 6) + screen:expect({grid=[[ + ## grid 1 + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [3:--------------------------------]| + ## grid 2 + ^popup menu test | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + :let g:menustr = 'baz' | + ## grid 4 + {n: foo }| + {n: bar }| + {s: baz }| + ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 100}}}) + meths.input_mouse('right', 'release', '', 2, 1, 6) + screen:expect({grid=[[ + ## grid 1 + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [2:--------------------------------]| + [3:--------------------------------]| + ## grid 2 + ^popup menu test | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + :let g:menustr = 'foo' | + ]]}) + eq('foo', meths.get_var('menustr')) + end) end) diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 61f19c3794..ea98705394 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -75,7 +75,7 @@ local busted = require('busted') local deepcopy = helpers.deepcopy local shallowcopy = helpers.shallowcopy local concat_tables = helpers.concat_tables -local request, run_session = helpers.request, helpers.run_session +local run_session = helpers.run_session local eq = helpers.eq local dedent = helpers.dedent local get_session = helpers.get_session @@ -90,8 +90,6 @@ end local Screen = {} Screen.__index = Screen -local debug_screen - local default_timeout_factor = 1 if os.getenv('VALGRIND') then default_timeout_factor = default_timeout_factor * 3 @@ -123,18 +121,6 @@ do Screen.colornames = colornames end -function Screen.debug(command) - if not command then - command = 'pynvim -n -c ' - end - command = command .. request('vim_eval', '$NVIM_LISTEN_ADDRESS') - if debug_screen then - debug_screen:close() - end - debug_screen = io.popen(command, 'r') - debug_screen:read() -end - function Screen.new(width, height) if not width then width = 53 @@ -179,6 +165,7 @@ function Screen.new(width, height) _width = width, _height = height, _grids = {}, + _grid_win_extmarks = {}, _cursor = { grid = 1, row = 1, col = 1 }, @@ -255,7 +242,7 @@ end -- canonical order of ext keys, used to generate asserts local ext_keys = { 'popupmenu', 'cmdline', 'cmdline_block', 'wildmenu_items', 'wildmenu_pos', - 'messages', 'showmode', 'showcmd', 'ruler', 'float_pos', 'win_viewport' + 'messages', 'msg_history', 'showmode', 'showcmd', 'ruler', 'float_pos', 'win_viewport' } -- Asserts that the screen state eventually matches an expected state. @@ -278,6 +265,8 @@ local ext_keys = { -- attributes in the final state are an error. -- Use screen:set_default_attr_ids() to define attributes for many -- expect() calls. +-- extmarks: Expected win_extmarks accumulated for the grids. For each grid, +-- the win_extmark messages are accumulated into an array. -- condition: Function asserting some arbitrary condition. Return value is -- ignored, throw an error (use eq() or similar) to signal failure. -- any: Lua pattern string expected to match a screen line. NB: the @@ -320,7 +309,7 @@ function Screen:expect(expected, attr_ids, ...) assert(not (attr_ids ~= nil)) local is_key = {grid=true, attr_ids=true, condition=true, mouse_enabled=true, any=true, mode=true, unchanged=true, intermediate=true, - reset=true, timeout=true, request_cb=true, hl_groups=true} + reset=true, timeout=true, request_cb=true, hl_groups=true, extmarks=true} for _, v in ipairs(ext_keys) do is_key[v] = true end @@ -394,7 +383,7 @@ function Screen:expect(expected, attr_ids, ...) for i, row in ipairs(expected_rows) do msg_expected_rows[i] = row local m = (row ~= actual_rows[i] and row:match('{MATCH:(.*)}') or nil) - if row ~= actual_rows[i] and (not m or not actual_rows[i]:match(m)) then + if row ~= actual_rows[i] and (not m or not (actual_rows[i] and actual_rows[i]:match(m))) then msg_expected_rows[i] = '*' .. msg_expected_rows[i] if i <= #actual_rows then actual_rows[i] = '*' .. actual_rows[i] @@ -459,6 +448,25 @@ screen:redraw_debug() to show all intermediate screen states. ]]) end end end + + if expected.extmarks ~= nil then + for gridid, expected_marks in pairs(expected.extmarks) do + local stored_marks = self._grid_win_extmarks[gridid] + if stored_marks == nil then + return 'no win_extmark for grid '..tostring(gridid) + end + local status, res = pcall(eq, expected_marks, stored_marks, "extmarks for grid "..tostring(gridid)) + if not status then + return tostring(res) + end + end + for gridid, _ in pairs(self._grid_win_extmarks) do + local expected_marks = expected.extmarks[gridid] + if expected_marks == nil then + return 'unexpected win_extmark for grid '..tostring(gridid) + end + end + end end, expected) end @@ -544,7 +552,7 @@ function Screen:_wait(check, flags) elseif not checked then err = check() if not err and flags.unchanged then - -- expecting NO screen change: use a shorter timout + -- expecting NO screen change: use a shorter timeout success_seen = true end end @@ -576,16 +584,16 @@ to the test if they make sense. print([[ warning: Screen changes were received after the expected state. This indicates -indeterminism in the test. Try adding screen:expect(...) (or wait()) between -asynchronous (feed(), nvim_input()) and synchronous API calls. +indeterminism in the test. Try adding screen:expect(...) (or poke_eventloop()) +between asynchronous (feed(), nvim_input()) and synchronous API calls. - Use screen:redraw_debug() to investigate; it may find relevant intermediate states that should be added to the test to make it more robust. - If the purpose of the test is to assert state after some user input sent with feed(), adding screen:expect() before the feed() will help to ensure the input is sent when Nvim is in a predictable state. This is preferable - to wait(), for being closer to real user interaction. - - wait() can trigger redraws and consequently generate more indeterminism. - Try removing wait(). + to poke_eventloop(), for being closer to real user interaction. + - poke_eventloop() can trigger redraws and thus generate more indeterminism. + Try removing poke_eventloop(). ]]) did_warn = true end @@ -703,6 +711,7 @@ function Screen:_reset() self.cmdline_block = {} self.wildmenu_items = nil self.wildmenu_pos = nil + self._grid_win_extmarks = {} end function Screen:_handle_mode_info_set(cursor_style_enabled, mode_info) @@ -803,6 +812,13 @@ function Screen:_handle_win_close(grid) self.float_pos[grid] = nil end +function Screen:_handle_win_extmark(grid, ...) + if self._grid_win_extmarks[grid] == nil then + self._grid_win_extmarks[grid] = {} + end + table.insert(self._grid_win_extmarks[grid], {...}) +end + function Screen:_handle_busy_start() self._busy = true end @@ -1067,6 +1083,10 @@ function Screen:_handle_msg_history_show(entries) self.msg_history = entries end +function Screen:_handle_msg_history_clear() + self.msg_history = {} +end + function Screen:_clear_block(grid, top, bot, left, right) for i = top, bot do self:_clear_row_section(grid, i, left, right) @@ -1155,7 +1175,7 @@ function Screen:_extstate_repr(attr_state) local msg_history = {} for i, entry in ipairs(self.msg_history) do - messages[i] = {kind=entry[1], content=self:_chunks_repr(entry[2], attr_state)} + msg_history[i] = {kind=entry[1], content=self:_chunks_repr(entry[2], attr_state)} end local win_viewport = (next(self.win_viewport) and self.win_viewport) or nil @@ -1560,9 +1580,10 @@ end function Screen:_equal_attrs(a, b) return a.bold == b.bold and a.standout == b.standout and a.underline == b.underline and a.undercurl == b.undercurl and - a.italic == b.italic and a.reverse == b.reverse and - a.foreground == b.foreground and a.background == b.background and - a.special == b.special and a.blend == b.blend and + a.underdouble == b.underdouble and a.underdotted == b.underdotted and + a.underdashed == b.underdashed and a.italic == b.italic and + a.reverse == b.reverse and a.foreground == b.foreground and + a.background == b.background and a.special == b.special and a.blend == b.blend and a.strikethrough == b.strikethrough and a.fg_indexed == b.fg_indexed and a.bg_indexed == b.bg_indexed end diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index 958e137f65..6c872e52d3 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -6,6 +6,7 @@ local insert = helpers.insert local eq = helpers.eq local eval = helpers.eval local iswin = helpers.iswin +local funcs, meths, exec_lua = helpers.funcs, helpers.meths, helpers.exec_lua describe('screen', function() local screen @@ -127,14 +128,67 @@ local function screen_tests(linegrid) end) it('has correct default title with named file', function() - local expected = (iswin() and 'myfile (C:\\mydir) - NVIM' - or 'myfile (/mydir) - NVIM') + local expected = (iswin() and 'myfile (C:\\mydir) - NVIM' or 'myfile (/mydir) - NVIM') command('set title') command(iswin() and 'file C:\\mydir\\myfile' or 'file /mydir/myfile') screen:expect(function() eq(expected, screen.title) end) end) + + describe('is not changed by', function() + local file1 = iswin() and 'C:\\mydir\\myfile1' or '/mydir/myfile1' + local file2 = iswin() and 'C:\\mydir\\myfile2' or '/mydir/myfile2' + local expected = (iswin() and 'myfile1 (C:\\mydir) - NVIM' or 'myfile1 (/mydir) - NVIM') + local buf2 + + before_each(function() + command('edit '..file1) + buf2 = funcs.bufadd(file2) + command('set title') + end) + + it('calling setbufvar() to set an option in a hidden buffer from i_CTRL-R', function() + command([[inoremap <F2> <C-R>=setbufvar(]]..buf2..[[, '&autoindent', 1) ? '' : ''<CR>]]) + feed('i<F2><Esc>') + command('redraw!') + screen:expect(function() + eq(expected, screen.title) + end) + end) + + it('an RPC call to nvim_buf_set_option in a hidden buffer', function() + meths.buf_set_option(buf2, 'autoindent', true) + command('redraw!') + screen:expect(function() + eq(expected, screen.title) + end) + end) + + it('a Lua callback calling nvim_buf_set_option in a hidden buffer', function() + exec_lua(string.format([[ + vim.schedule(function() + vim.api.nvim_buf_set_option(%d, 'autoindent', true) + end) + ]], buf2)) + command('redraw!') + screen:expect(function() + eq(expected, screen.title) + end) + end) + + it('a Lua callback calling nvim_buf_call in a hidden buffer', function() + exec_lua(string.format([[ + vim.schedule(function() + vim.api.nvim_buf_call(%d, function() end) + end) + ]], buf2)) + command('redraw!') + screen:expect(function() + eq(expected, screen.title) + end) + end) + end) end) describe(':set icon', function() @@ -272,12 +326,12 @@ local function screen_tests(linegrid) command('vsp') command('vsp') screen:expect([[ - ^ {3:│} {3:│} | - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| + ^ │ │ | + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| {1:[No Name] }{3:[No Name] [No Name] }| | {0:~ }| @@ -289,12 +343,12 @@ local function screen_tests(linegrid) ]]) insert('hello') screen:expect([[ - hell^o {3:│}hello {3:│}hello | - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| + hell^o │hello │hello | + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| hello | {0:~ }| @@ -315,12 +369,12 @@ local function screen_tests(linegrid) command('vsp') insert('hello') screen:expect([[ - hell^o {3:│}hello {3:│}hello | - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| + hell^o │hello │hello | + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| hello | {0:~ }| @@ -352,12 +406,12 @@ local function screen_tests(linegrid) command('tabprevious') screen:expect([[ {2: }{6:4}{2:+ [No Name] }{4: + [No Name] }{3: }{4:X}| - hell^o {3:│}hello {3:│}hello | - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| - {0:~ }{3:│}{0:~ }{3:│}{0:~ }| + hell^o │hello │hello | + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| + {0:~ }│{0:~ }│{0:~ }| {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| hello | {0:~ }| @@ -466,36 +520,36 @@ local function screen_tests(linegrid) command('vsplit') screen:expect([[ - ^foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | + ^foo │foo | + foo │foo | + foo │foo | + foo │foo | + foo │foo | + foo │foo | + foo │foo | + foo │foo | + foo │foo | + foo │foo | + foo │foo | + foo │foo | {1:[No Name] [+] }{3:[No Name] [+] }| | ]]) feed('<PageDown>') screen:expect([[ - ^foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - foo {3:│}foo | - bar {3:│}foo | - bar {3:│}foo | - bar {3:│}foo | - bar {3:│}foo | - bar {3:│}foo | - bar {3:│}foo | - bar {3:│}foo | - bar {3:│}foo | + ^foo │foo | + foo │foo | + foo │foo | + foo │foo | + bar │foo | + bar │foo | + bar │foo | + bar │foo | + bar │foo | + bar │foo | + bar │foo | + bar │foo | {1:[No Name] [+] }{3:[No Name] [+] }| | ]]) @@ -694,12 +748,12 @@ local function screen_tests(linegrid) command('vsp') command('vsp') screen:expect([[ - and {3:│}and {3:│}and | - clearing {3:│}clearing {3:│}clearing | - in {3:│}in {3:│}in | - split {3:│}split {3:│}split | - windows {3:│}windows {3:│}windows | - ^ {3:│} {3:│} | + and │and │and | + clearing │clearing │clearing | + in │in │in | + split │split │split | + windows │windows │windows | + ^ │ │ | {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| clearing | in | @@ -714,12 +768,12 @@ local function screen_tests(linegrid) it('only affects the current scroll region', function() feed('6k') screen:expect([[ - ^scrolling {3:│}and {3:│}and | - and {3:│}clearing {3:│}clearing | - clearing {3:│}in {3:│}in | - in {3:│}split {3:│}split | - split {3:│}windows {3:│}windows | - windows {3:│} {3:│} | + ^scrolling │and │and | + and │clearing │clearing | + clearing │in │in | + in │split │split | + split │windows │windows | + windows │ │ | {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| clearing | in | @@ -731,12 +785,12 @@ local function screen_tests(linegrid) ]]) feed('<c-w>l') screen:expect([[ - scrolling {3:│}and {3:│}and | - and {3:│}clearing {3:│}clearing | - clearing {3:│}in {3:│}in | - in {3:│}split {3:│}split | - split {3:│}windows {3:│}windows | - windows {3:│}^ {3:│} | + scrolling │and │and | + and │clearing │clearing | + clearing │in │in | + in │split │split | + split │windows │windows | + windows │^ │ | {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| clearing | in | @@ -748,12 +802,12 @@ local function screen_tests(linegrid) ]]) feed('gg') screen:expect([[ - scrolling {3:│}^Inserting {3:│}and | - and {3:│}text {3:│}clearing | - clearing {3:│}with {3:│}in | - in {3:│}many {3:│}split | - split {3:│}lines {3:│}windows | - windows {3:│}to {3:│} | + scrolling │^Inserting │and | + and │text │clearing | + clearing │with │in | + in │many │split | + split │lines │windows | + windows │to │ | {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| clearing | in | @@ -765,12 +819,12 @@ local function screen_tests(linegrid) ]]) feed('7j') screen:expect([[ - scrolling {3:│}with {3:│}and | - and {3:│}many {3:│}clearing | - clearing {3:│}lines {3:│}in | - in {3:│}to {3:│}split | - split {3:│}test {3:│}windows | - windows {3:│}^scrolling {3:│} | + scrolling │with │and | + and │many │clearing | + clearing │lines │in | + in │to │split | + split │test │windows | + windows │^scrolling │ | {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| clearing | in | @@ -782,12 +836,12 @@ local function screen_tests(linegrid) ]]) feed('2j') screen:expect([[ - scrolling {3:│}lines {3:│}and | - and {3:│}to {3:│}clearing | - clearing {3:│}test {3:│}in | - in {3:│}scrolling {3:│}split | - split {3:│}and {3:│}windows | - windows {3:│}^clearing {3:│} | + scrolling │lines │and | + and │to │clearing | + clearing │test │in | + in │scrolling │split | + split │and │windows | + windows │^clearing │ | {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| clearing | in | @@ -799,12 +853,12 @@ local function screen_tests(linegrid) ]]) feed('5k') screen:expect([[ - scrolling {3:│}^lines {3:│}and | - and {3:│}to {3:│}clearing | - clearing {3:│}test {3:│}in | - in {3:│}scrolling {3:│}split | - split {3:│}and {3:│}windows | - windows {3:│}clearing {3:│} | + scrolling │^lines │and | + and │to │clearing | + clearing │test │in | + in │scrolling │split | + split │and │windows | + windows │clearing │ | {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| clearing | in | @@ -816,12 +870,12 @@ local function screen_tests(linegrid) ]]) feed('k') screen:expect([[ - scrolling {3:│}^many {3:│}and | - and {3:│}lines {3:│}clearing | - clearing {3:│}to {3:│}in | - in {3:│}test {3:│}split | - split {3:│}scrolling {3:│}windows | - windows {3:│}and {3:│} | + scrolling │^many │and | + and │lines │clearing | + clearing │to │in | + in │test │split | + split │scrolling │windows | + windows │and │ | {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| clearing | in | diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua index 5540b3c2dc..c5c88323a2 100644 --- a/test/functional/ui/searchhl_spec.lua +++ b/test/functional/ui/searchhl_spec.lua @@ -5,7 +5,8 @@ local command = helpers.command local feed_command = helpers.feed_command local eq = helpers.eq local eval = helpers.eval -local nvim_dir = helpers.nvim_dir +local funcs = helpers.funcs +local testprg = helpers.testprg describe('search highlighting', function() local screen @@ -43,7 +44,7 @@ describe('search highlighting', function() insert("some text\nmore text") feed_command('1,2fold') feed("gg/text") - screen:expect([[ + screen:expect{grid=[[ {6:+-- 2 lines: some text·················}| {1:~ }| {1:~ }| @@ -51,7 +52,9 @@ describe('search highlighting', function() {1:~ }| {1:~ }| /text^ | - ]]) + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 9, linecount = 2}; + }} end) it('works', function() @@ -109,6 +112,146 @@ describe('search highlighting', function() ]]) end) + describe('CurSearch highlight', function() + before_each(function() + screen:set_default_attr_ids({ + [1] = {background = Screen.colors.Yellow}, -- Search + [2] = {foreground = Screen.colors.White, background = Screen.colors.Black}, -- CurSearch + [3] = {foreground = Screen.colors.Red}, -- WarningMsg + }) + command('highlight CurSearch guibg=Black guifg=White') + end) + + it('works for match under cursor', function() + insert([[ + There is no way that a bee should be + able to fly. Its wings are too small + to get its fat little body off the + ground. The bee, of course, flies + anyway because bees don't care what + humans think is impossible.]]) + + feed('/bee<CR>') + screen:expect{grid=[[ + There is no way that a {2:^bee} should be | + able to fly. Its wings are too small | + to get its fat little body off the | + ground. The {1:bee}, of course, flies | + anyway because {1:bee}s don't care what | + humans think is impossible. | + {3:search hit BOTTOM, continuing at TOP} | + ]]} + + feed('nn') + screen:expect{grid=[[ + There is no way that a {1:bee} should be | + able to fly. Its wings are too small | + to get its fat little body off the | + ground. The {1:bee}, of course, flies | + anyway because {2:^bee}s don't care what | + humans think is impossible. | + /bee | + ]]} + + feed('N') + screen:expect{grid=[[ + There is no way that a {1:bee} should be | + able to fly. Its wings are too small | + to get its fat little body off the | + ground. The {2:^bee}, of course, flies | + anyway because {1:bee}s don't care what | + humans think is impossible. | + ?bee | + ]]} + end) + + it('works for multiline match', function() + command([[call setline(1, ['one', 'foo', 'bar', 'baz', 'foo the foo and foo', 'bar'])]]) + feed('gg/foo<CR>') + screen:expect([[ + one | + {2:^foo} | + bar | + baz | + {1:foo} the {1:foo} and {1:foo} | + bar | + /foo | + ]]) + feed('n') + screen:expect([[ + one | + {1:foo} | + bar | + baz | + {2:^foo} the {1:foo} and {1:foo} | + bar | + /foo | + ]]) + feed('n') + screen:expect([[ + one | + {1:foo} | + bar | + baz | + {1:foo} the {2:^foo} and {1:foo} | + bar | + /foo | + ]]) + feed('n') + screen:expect([[ + one | + {1:foo} | + bar | + baz | + {1:foo} the {1:foo} and {2:^foo} | + bar | + /foo | + ]]) + command([[call setline(5, 'foo')]]) + feed('0?<CR>') + screen:expect([[ + one | + {2:^foo} | + bar | + baz | + {1:foo} | + bar | + ?foo | + ]]) + feed('gg/foo\\nbar<CR>') + screen:expect([[ + one | + {2:^foo} | + {2:bar} | + baz | + {1:foo} | + {1:bar} | + /foo\nbar | + ]]) + command([[call setline(1, ['---', 'abcdefg', 'hijkl', '---', 'abcdefg', 'hijkl'])]]) + feed('gg/efg\\nhij<CR>') + screen:expect([[ + --- | + abcd{2:^efg} | + {2:hij}kl | + --- | + abcd{1:efg} | + {1:hij}kl | + /efg\nhij | + ]]) + feed('n') + screen:expect([[ + --- | + abcd{1:efg} | + {1:hij}kl | + --- | + abcd{2:^efg} | + {2:hij}kl | + /efg\nhij | + ]]) + end) + end) + it('highlights after EOL', function() insert("\n\n\n\n\n\n") @@ -163,7 +306,7 @@ describe('search highlighting', function() end) it('is preserved during :terminal activity', function() - feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 5000 foo<cr>]]) + feed((':terminal "%s" REP 5000 foo<cr>'):format(testprg('shell-test'))) feed(':file term<CR>') feed('G') -- Follow :terminal output. @@ -179,100 +322,101 @@ describe('search highlighting', function() end) it('works with incsearch', function() - feed_command('set hlsearch') - feed_command('set incsearch') + command('set hlsearch') + command('set incsearch') + command('set laststatus=0') insert([[ the first line - in a little file - ]]) + in a little file]]) + command('vsplit') feed("gg/li") screen:expect([[ - the first {3:li}ne | - in a {2:li}ttle file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the first {3:li}ne │the first {2:li}ne | + in a {2:li}ttle file │in a {2:li}ttle file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| /li^ | ]]) -- check that consecutive matches are caught by C-g/C-t feed("<C-g>") screen:expect([[ - the first {2:li}ne | - in a {3:li}ttle file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the first {2:li}ne │the first {2:li}ne | + in a {3:li}ttle file │in a {2:li}ttle file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| /li^ | ]]) feed("<C-t>") screen:expect([[ - the first {3:li}ne | - in a {2:li}ttle file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the first {3:li}ne │the first {2:li}ne | + in a {2:li}ttle file │in a {2:li}ttle file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| /li^ | ]]) feed("t") screen:expect([[ - the first line | - in a {3:lit}tle file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the first line │the first line | + in a {3:lit}tle file │in a {2:lit}tle file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| /lit^ | ]]) feed("<cr>") screen:expect([[ - the first line | - in a {2:^lit}tle file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the first line │the first line | + in a {2:^lit}tle file │in a {2:lit}tle file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| /lit | ]]) feed("/fir") screen:expect([[ - the {3:fir}st line | - in a little file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the {3:fir}st line │the {2:fir}st line | + in a little file │in a little file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| /fir^ | ]]) -- incsearch have priority over hlsearch feed("<esc>/ttle") screen:expect([[ - the first line | - in a li{3:ttle} file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the first line │the first line | + in a li{3:ttle} file │in a li{2:ttle} file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| /ttle^ | ]]) -- cancelling search resets to the old search term feed('<esc>') screen:expect([[ - the first line | - in a {2:^lit}tle file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the first line │the first line | + in a {2:^lit}tle file │in a {2:lit}tle file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| | ]]) eq('lit', eval('@/')) @@ -280,91 +424,78 @@ describe('search highlighting', function() -- cancelling inc search restores the hl state feed(':noh<cr>') screen:expect([[ - the first line | - in a ^little file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the first line │the first line | + in a ^little file │in a little file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| :noh | ]]) feed('/first') screen:expect([[ - the {3:first} line | - in a little file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the {3:first} line │the {2:first} line | + in a little file │in a little file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| /first^ | ]]) feed('<esc>') screen:expect([[ - the first line | - in a ^little file | - | - {1:~ }| - {1:~ }| - {1:~ }| + the first line │the first line | + in a ^little file │in a little file | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| | ]]) -- test that pressing C-g in an empty command line does not move the cursor - feed('/<C-g>') - screen:expect([[ - the first line | - in a little file | - | - {1:~ }| - {1:~ }| - {1:~ }| - /^ | - ]]) - - -- same, for C-t - feed('<ESC>') - screen:expect([[ - the first line | - in a ^little file | - | - {1:~ }| - {1:~ }| - {1:~ }| - | - ]]) - feed('/<C-t>') - screen:expect([[ - the first line | - in a little file | - | - {1:~ }| - {1:~ }| - {1:~ }| - /^ | - ]]) + feed('gg0') + command([[let @/ = 'i']]) + -- moves to next match of previous search pattern, just like /<cr> + feed('/<c-g><cr>') + eq({0, 1, 6, 0}, funcs.getpos('.')) + -- moves to next match of previous search pattern, just like /<cr> + feed('/<cr>') + eq({0, 1, 12, 0}, funcs.getpos('.')) + -- moves to next match of previous search pattern, just like /<cr> + feed('/<c-t><cr>') + eq({0, 2, 1, 0}, funcs.getpos('.')) -- 8.0.1304, test that C-g and C-t works with incsearch and empty pattern feed('<esc>/fi<CR>') + screen:expect([[ + the {2:fi}rst line │the {2:fi}rst line | + in a little {2:^fi}le │in a little {2:fi}le | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + /fi | + ]]) feed('//') screen:expect([[ - the {3:fi}rst line | - in a little {2:fi}le | - | - {1:~ }| - {1:~ }| - {1:~ }| + the {3:fi}rst line │the {2:fi}rst line | + in a little {2:fi}le │in a little {2:fi}le | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| //^ | ]]) - feed('<C-g>') screen:expect([[ - the {2:fi}rst line | - in a little {3:fi}le | - | - {1:~ }| - {1:~ }| - {1:~ }| + the {2:fi}rst line │the {2:fi}rst line | + in a little {3:fi}le │in a little {2:fi}le | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| //^ | ]]) end) @@ -439,19 +570,20 @@ describe('search highlighting', function() end) it('works with matchadd and syntax', function() - screen:set_default_attr_ids( { - [1] = {bold=true, foreground=Screen.colors.Blue}, - [2] = {background = colors.Yellow}, - [3] = {reverse = true}, - [4] = {foreground = colors.Red}, - [5] = {bold = true, background = colors.Green}, - [6] = {italic = true, background = colors.Magenta}, - [7] = {bold = true, background = colors.Yellow}, - } ) + screen:set_default_attr_ids { + [1] = {bold=true, foreground=Screen.colors.Blue}; + [2] = {background = colors.Yellow}; + [3] = {reverse = true}; + [4] = {foreground = colors.Red}; + [5] = {bold = true, background = colors.Green}; + [6] = {italic = true, background = colors.Magenta}; + [7] = {bold = true, background = colors.Yellow}; + [8] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGray}; + } feed_command('set hlsearch') - insert([[ + insert [[ very special text - ]]) + ]] feed_command("syntax on") feed_command("highlight MyGroup guibg=Green gui=bold") feed_command("highlight MyGroup2 guibg=Magenta gui=italic") @@ -461,7 +593,7 @@ describe('search highlighting', function() -- searchhl and matchadd matches are exclusive, only the highest priority -- is used (and matches with lower priorities are not combined) feed_command("/ial te") - screen:expect([[ + screen:expect{grid=[[ very {5:spec^ial}{2: te}{6:xt} | | {1:~ }| @@ -469,10 +601,21 @@ describe('search highlighting', function() {1:~ }| {1:~ }| {4:search hit BOTTOM, continuing at TOP} | - ]]) + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 11, linecount = 2}; + }} - -- check hilights work also in folds + -- check highlights work also in folds feed("zf4j") + screen:expect{grid=[[ + {8:^+-- 2 lines: very special text·········}| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {4:search hit BOTTOM, continuing at TOP} | + ]]} command("%foldopen") screen:expect([[ very {5:spec^ial}{2: te}{6:xt} | diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index dcd31cfdb7..dbc92ca222 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -446,7 +446,7 @@ describe('Signs', function() {1:>>>>>>>>}{6: 1 }a | {2: }{6: 2 }b | {2: }{6: 3 }c | - {2: }{6:^ 4 } | + {2: }{6: 4 }^ | {0:~ }| {0:~ }| {0:~ }| @@ -468,7 +468,7 @@ describe('Signs', function() {1:>>>>>>>>>>}{6: 1 }a | {2: }{6: 2 }b | {2: }{6: 3 }c | - {2: ^ }{6: 4 } | + {2: }{6: 4 }^ | {0:~ }| {0:~ }| {0:~ }| @@ -482,7 +482,7 @@ describe('Signs', function() ]]) end) - it('ignores signs with no icon and text when calculting the signcolumn width', function() + it('ignores signs with no icon and text when calculating the signcolumn width', function() feed('ia<cr>b<cr>c<cr><esc>') command('set number') command('set signcolumn=auto:2') @@ -512,7 +512,33 @@ describe('Signs', function() {1:>>}{6: 1 }a | {2: }{6: 2 }b | {2: }{6: 3 }c | - {2: }{6: ^4 } | + {2: }{6: 4 }^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + end) + + it('shows the line number when signcolumn=number but no marks on a line have text', function() + feed('ia<cr>b<cr>c<cr><esc>') + command('set number signcolumn=number') + command('sign define pietSearch text=>> texthl=Search numhl=Error') + command('sign define pietError text= texthl=Search numhl=Error') + command('sign place 1 line=1 name=pietSearch buffer=1') + command('sign place 2 line=2 name=pietError buffer=1') + -- no signcolumn, line number for "a" is Search, for "b" is Error, for "c" is LineNr + screen:expect([[ + {1: >> }a | + {8: 2 }b | + {6: 3 }c | + {6: 4 }^ | {0:~ }| {0:~ }| {0:~ }| diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua new file mode 100644 index 0000000000..1e1066d48a --- /dev/null +++ b/test/functional/ui/statusline_spec.lua @@ -0,0 +1,342 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear = helpers.clear +local command = helpers.command +local feed = helpers.feed +local eq = helpers.eq +local funcs = helpers.funcs +local meths = helpers.meths +local exec = helpers.exec +local exec_lua = helpers.exec_lua +local eval = helpers.eval + +describe('statusline clicks', function() + local screen + + before_each(function() + clear() + screen = Screen.new(40, 8) + screen:attach() + command('set laststatus=2 mousemodel=extend') + exec([=[ + function! MyClickFunc(minwid, clicks, button, mods) + let mods = trim(a:mods) + if mods ==# '' + let g:testvar = printf("%d %d %s", a:minwid, a:clicks, a:button) + else + let g:testvar = printf("%d %d %s %s", a:minwid, a:clicks, a:button, mods) + endif + endfunction + ]=]) + end) + + it('works', function() + meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T') + meths.input_mouse('left', 'press', '', 0, 6, 17) + eq('0 1 l', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 6, 17) + eq('0 1 r', eval("g:testvar")) + end) + + it('works for winbar', function() + meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T') + meths.input_mouse('left', 'press', '', 0, 0, 17) + eq('0 1 l', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 0, 17) + eq('0 1 r', eval("g:testvar")) + end) + + it('works for winbar in floating window', function() + meths.open_win(0, true, { width=30, height=4, relative='editor', row=1, col=5, + border = "single" }) + meths.set_option_value('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', + { scope = 'local' }) + meths.input_mouse('left', 'press', '', 0, 2, 23) + eq('0 1 l', eval("g:testvar")) + end) + + it('works when there are multiple windows', function() + command('split') + meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T') + meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T') + meths.input_mouse('left', 'press', '', 0, 0, 17) + eq('0 1 l', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 4, 17) + eq('0 1 r', eval("g:testvar")) + meths.input_mouse('middle', 'press', '', 0, 3, 17) + eq('0 1 m', eval("g:testvar")) + meths.input_mouse('left', 'press', '', 0, 6, 17) + eq('0 1 l', eval("g:testvar")) + end) + + it('works with Lua function', function() + exec_lua([[ + function clicky_func(minwid, clicks, button, mods) + vim.g.testvar = string.format("%d %d %s", minwid, clicks, button) + end + ]]) + meths.set_option('statusline', 'Not clicky stuff %0@v:lua.clicky_func@Clicky stuff%T') + meths.input_mouse('left', 'press', '', 0, 6, 17) + eq('0 1 l', eval("g:testvar")) + end) + + it('ignores unsupported click items', function() + command('tabnew | tabprevious') + meths.set_option('statusline', '%2TNot clicky stuff%T') + meths.input_mouse('left', 'press', '', 0, 6, 0) + eq(1, meths.get_current_tabpage().id) + meths.set_option('statusline', '%2XNot clicky stuff%X') + meths.input_mouse('left', 'press', '', 0, 6, 0) + eq(2, #meths.list_tabpages()) + end) + + it("right click works when statusline isn't focused #18994", function() + meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T') + meths.input_mouse('right', 'press', '', 0, 6, 17) + eq('0 1 r', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 6, 17) + eq('0 2 r', eval("g:testvar")) + end) + + it("click works with modifiers #18994", function() + meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T') + meths.input_mouse('right', 'press', 's', 0, 6, 17) + eq('0 1 r s', eval("g:testvar")) + meths.input_mouse('left', 'press', 's', 0, 6, 17) + eq('0 1 l s', eval("g:testvar")) + end) +end) + +describe('global statusline', function() + local screen + + before_each(function() + clear() + screen = Screen.new(60, 16) + screen:attach() + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Blue}; + [2] = {bold = true, reverse = true}; + [3] = {bold = true}; + [4] = {reverse = true}; + }) + command('set laststatus=3') + command('set ruler') + end) + + it('works', function() + screen:expect([[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] 0,0-1 All}| + | + ]]) + + feed('i<CR><CR>') + screen:expect([[ + | + | + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] [+] 3,1 All}| + {3:-- INSERT --} | + ]]) + end) + + it('works with splits', function() + command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split') + screen:expect([[ + │ │ │^ | + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }├────────────────┤{1:~}│{1:~ }| + {1:~ }│ │{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}├────────────────────| + {1:~ }│{1:~ }│{1:~}│ | + ────────────────────┴────────────────┴─┤{1:~ }| + │{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {2:[No Name] 0,0-1 All}| + | + ]]) + end) + + it('works when switching between values of laststatus', function() + command('set laststatus=1') + screen:expect([[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + 0,0-1 All | + ]]) + + command('set laststatus=3') + screen:expect([[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] 0,0-1 All}| + | + ]]) + + command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split') + command('set laststatus=2') + screen:expect([[ + │ │ │^ | + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{4:< Name] 0,0-1 }│{1:~}│{1:~ }| + {1:~ }│ │{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{2:<No Name] 0,0-1 All}| + {1:~ }│{1:~ }│{1:~}│ | + {4:<No Name] 0,0-1 All < Name] 0,0-1 <}│{1:~ }| + │{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {4:[No Name] 0,0-1 All <No Name] 0,0-1 All}| + | + ]]) + + command('set laststatus=3') + screen:expect([[ + │ │ │^ | + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }├────────────────┤{1:~}│{1:~ }| + {1:~ }│ │{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}├────────────────────| + {1:~ }│{1:~ }│{1:~}│ | + ────────────────────┴────────────────┴─┤{1:~ }| + │{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {2:[No Name] 0,0-1 All}| + | + ]]) + + command('set laststatus=0') + screen:expect([[ + │ │ │^ | + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{4:< Name] 0,0-1 }│{1:~}│{1:~ }| + {1:~ }│ │{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{2:<No Name] 0,0-1 All}| + {1:~ }│{1:~ }│{1:~}│ | + {4:<No Name] 0,0-1 All < Name] 0,0-1 <}│{1:~ }| + │{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + 0,0-1 All | + ]]) + + command('set laststatus=3') + screen:expect([[ + │ │ │^ | + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }├────────────────┤{1:~}│{1:~ }| + {1:~ }│ │{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}│{1:~ }| + {1:~ }│{1:~ }│{1:~}├────────────────────| + {1:~ }│{1:~ }│{1:~}│ | + ────────────────────┴────────────────┴─┤{1:~ }| + │{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {2:[No Name] 0,0-1 All}| + | + ]]) + end) + + it('win_move_statusline() can reduce cmdheight to 1', function() + eq(1, meths.get_option('cmdheight')) + funcs.win_move_statusline(0, -1) + eq(2, meths.get_option('cmdheight')) + funcs.win_move_statusline(0, -1) + eq(3, meths.get_option('cmdheight')) + funcs.win_move_statusline(0, 1) + eq(2, meths.get_option('cmdheight')) + funcs.win_move_statusline(0, 1) + eq(1, meths.get_option('cmdheight')) + end) + + it('mouse dragging can reduce cmdheight to 1', function() + command('set mouse=a') + meths.input_mouse('left', 'press', '', 0, 14, 10) + eq(1, meths.get_option('cmdheight')) + meths.input_mouse('left', 'drag', '', 0, 13, 10) + eq(2, meths.get_option('cmdheight')) + meths.input_mouse('left', 'drag', '', 0, 12, 10) + eq(3, meths.get_option('cmdheight')) + meths.input_mouse('left', 'drag', '', 0, 13, 10) + eq(2, meths.get_option('cmdheight')) + meths.input_mouse('left', 'drag', '', 0, 14, 10) + eq(1, meths.get_option('cmdheight')) + meths.input_mouse('left', 'drag', '', 0, 15, 10) + eq(0, meths.get_option('cmdheight')) + meths.input_mouse('left', 'drag', '', 0, 14, 10) + eq(1, meths.get_option('cmdheight')) + end) +end) diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua index 4e1852162f..f790597140 100644 --- a/test/functional/ui/syntax_conceal_spec.lua +++ b/test/functional/ui/syntax_conceal_spec.lua @@ -3,6 +3,8 @@ local Screen = require('test.functional.ui.screen') local clear, feed, command = helpers.clear, helpers.feed, helpers.command local eq = helpers.eq local insert = helpers.insert +local poke_eventloop = helpers.poke_eventloop +local expect_exit = helpers.expect_exit describe('Screen', function() local screen @@ -255,6 +257,40 @@ describe('Screen', function() ]]) end) end) -- a region of text (implicit concealing) + + it("cursor position is correct when entering Insert mode with cocu=ni #13916", function() + insert([[foobarfoobarfoobar]]) + -- move to end of line + feed("$") + command("set concealcursor=ni") + command("syn match Foo /foobar/ conceal cchar=&") + screen:expect([[ + {1:&&&}^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + feed("i") + -- cursor should stay in place, not jump to column 16 + screen:expect([[ + {1:&&&}^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {4:-- INSERT --} | + ]]) + end) end) -- match and conceal describe("let the conceal level be", function() @@ -911,14 +947,64 @@ describe('Screen', function() {0:~ }| | ]]} - eq(grid_lines, {{2, 0, {{'c', 0, 3}}}}) + eq({{2, 0, {{'c', 0, 3}}}}, grid_lines) + end) + + it('K_EVENT should not cause extra redraws with concealcursor #13196', function() + command('set conceallevel=1') + command('set concealcursor=nv') + command('set redrawdebug+=nodelta') + + insert([[ + aaa + bbb + ccc + ]]) + screen:expect{grid=[[ + aaa | + bbb | + ccc | + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]} + + -- XXX: hack to get notifications, and check only a single line is + -- updated. Could use next_msg() also. + local orig_handle_grid_line = screen._handle_grid_line + local grid_lines = {} + function screen._handle_grid_line(self, grid, row, col, items) + table.insert(grid_lines, {row, col, items}) + orig_handle_grid_line(self, grid, row, col, items) + end + feed('k') + screen:expect{grid=[[ + aaa | + bbb | + ^ccc | + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]} + eq({{2, 0, {{'c', 0, 3}}}}, grid_lines) + poke_eventloop() -- causes K_EVENT key + screen:expect_unchanged() + eq({{2, 0, {{'c', 0, 3}}}}, grid_lines) end) -- Copy of Test_cursor_column_in_concealed_line_after_window_scroll in -- test/functional/ui/syntax_conceal_spec.lua. describe('concealed line after window scroll', function() after_each(function() - command(':qall!') + expect_exit(command, ':qall!') os.remove('Xcolesearch') end) diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index 65c6fabfa8..98398bc7a1 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -7,7 +7,7 @@ local meths = helpers.meths local eq = helpers.eq local eval = helpers.eval local retry = helpers.retry -local nvim_dir = helpers.nvim_dir +local testprg = helpers.testprg describe("'wildmenu'", function() local screen @@ -114,7 +114,7 @@ describe("'wildmenu'", function() it('is preserved during :terminal activity', function() command('set wildmenu wildmode=full') command('set scrollback=4') - feed([[:terminal "]]..nvim_dir..[[/shell-test" REP 5000 !terminal_output!<cr>]]) + feed((':terminal "%s" REP 5000 !terminal_output!<cr>'):format(testprg('shell-test'))) feed('G') -- Follow :terminal output. feed([[:sign <Tab>]]) -- Invoke wildmenu. -- NB: in earlier versions terminal output was redrawn during cmdline mode. diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua new file mode 100644 index 0000000000..92a6ab2e84 --- /dev/null +++ b/test/functional/ui/winbar_spec.lua @@ -0,0 +1,580 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear = helpers.clear +local command = helpers.command +local insert = helpers.insert +local meths = helpers.meths +local eq = helpers.eq +local poke_eventloop = helpers.poke_eventloop +local feed = helpers.feed +local pcall_err = helpers.pcall_err + +describe('winbar', function() + local screen + + before_each(function() + clear() + screen = Screen.new(60, 13) + screen:attach() + screen:set_default_attr_ids({ + [1] = {bold = true}, + [2] = {reverse = true}, + [3] = {bold = true, foreground = Screen.colors.Blue}, + [4] = {bold = true, reverse = true}, + [5] = {bold = true, foreground = Screen.colors.Red}, + [6] = {foreground = Screen.colors.Blue}, + [7] = {background = Screen.colors.LightGrey}, + [8] = {background = Screen.colors.LightMagenta}, + [9] = {bold = true, foreground = Screen.colors.Blue, background = Screen.colors.LightMagenta}, + [10] = {background = Screen.colors.LightGrey, underline = true}, + [11] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta}, + }) + meths.set_option('winbar', 'Set Up The Bars') + end) + + it('works', function() + screen:expect([[ + {1:Set Up The Bars }| + ^ | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]) + end) + + it('works with custom \'fillchars\' value', function() + command('set fillchars=wbr:+') + screen:expect([[ + {1:Set Up The Bars+++++++++++++++++++++++++++++++++++++++++++++}| + ^ | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]) + end) + + it('works with custom highlight', function() + command('hi WinBar guifg=red') + screen:expect([[ + {5:Set Up The Bars }| + ^ | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]) + end) + + it('works with splits', function() + command('hi WinBar guifg=red') + command('hi WinBarNC guifg=blue') + command('belowright vsplit | split | split') + screen:expect([[ + {6:Set Up The Bars }│{5:Set Up The Bars }| + │^ | + {3:~ }│{3:~ }| + {3:~ }│{4:[No Name] }| + {3:~ }│{6:Set Up The Bars }| + {3:~ }│ | + {3:~ }│{3:~ }| + {3:~ }│{2:[No Name] }| + {3:~ }│{6:Set Up The Bars }| + {3:~ }│ | + {3:~ }│{3:~ }| + {2:[No Name] [No Name] }| + | + ]]) + end) + + it('works when switching value of \'winbar\'', function() + command('belowright vsplit | split | split | set winbar=') + screen:expect([[ + │^ | + {3:~ }│{3:~ }| + {3:~ }│{3:~ }| + {3:~ }│{4:[No Name] }| + {3:~ }│ | + {3:~ }│{3:~ }| + {3:~ }│{3:~ }| + {3:~ }│{2:[No Name] }| + {3:~ }│ | + {3:~ }│{3:~ }| + {3:~ }│{3:~ }| + {2:[No Name] [No Name] }| + | + ]]) + command('set winbar=All\\ Your\\ Bar\\ Are\\ Belong\\ To\\ Us') + screen:expect([[ + {1:All Your Bar Are Belong To Us}│{1:All Your Bar Are Belong To Us }| + │^ | + {3:~ }│{3:~ }| + {3:~ }│{4:[No Name] }| + {3:~ }│{1:All Your Bar Are Belong To Us }| + {3:~ }│ | + {3:~ }│{3:~ }| + {3:~ }│{2:[No Name] }| + {3:~ }│{1:All Your Bar Are Belong To Us }| + {3:~ }│ | + {3:~ }│{3:~ }| + {2:[No Name] [No Name] }| + | + ]]) + command('set winbar=Changed\\ winbar') + screen:expect([[ + {1:Changed winbar }│{1:Changed winbar }| + │^ | + {3:~ }│{3:~ }| + {3:~ }│{4:[No Name] }| + {3:~ }│{1:Changed winbar }| + {3:~ }│ | + {3:~ }│{3:~ }| + {3:~ }│{2:[No Name] }| + {3:~ }│{1:Changed winbar }| + {3:~ }│ | + {3:~ }│{3:~ }| + {2:[No Name] [No Name] }| + | + ]]) + end) + + it('can be ruler', function() + insert [[ + just some + random text]] + meths.set_option('winbar', 'Hello, I am a ruler: %l,%c') + screen:expect{grid=[[ + {1:Hello, I am a ruler: 2,11 }| + just some | + random tex^t | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]} + feed 'b' + screen:expect{grid=[[ + {1:Hello, I am a ruler: 2,8 }| + just some | + random ^text | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]} + feed 'k' + screen:expect{grid=[[ + {1:Hello, I am a ruler: 1,8 }| + just so^me | + random text | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]} + end) + + it('works with laststatus=3', function() + command('set laststatus=3') + screen:expect([[ + {1:Set Up The Bars }| + ^ | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {4:[No Name] }| + | + ]]) + command('belowright vsplit | split | split') + screen:expect([[ + {1:Set Up The Bars }│{1:Set Up The Bars }| + │^ | + {3:~ }│{3:~ }| + {3:~ }├──────────────────────────────| + {3:~ }│{1:Set Up The Bars }| + {3:~ }│ | + {3:~ }│{3:~ }| + {3:~ }├──────────────────────────────| + {3:~ }│{1:Set Up The Bars }| + {3:~ }│ | + {3:~ }│{3:~ }| + {4:[No Name] }| + | + ]]) + -- Test for issue #18791 + command('tabnew') + screen:expect([[ + {10: }{11:4}{10: [No Name] }{1: [No Name] }{2: }{10:X}| + {1:Set Up The Bars }| + ^ | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {4:[No Name] }| + | + ]]) + end) + + it('mouse click and drag work correctly in buffer', function() + insert([[ + line 1 + line 2 + line 3 + line 4 + line -42 + line i + line sin(theta) + line 8]]) + + meths.input_mouse('left', 'press', '', 0, 5, 1) + screen:expect([[ + {1:Set Up The Bars }| + line 1 | + line 2 | + line 3 | + line 4 | + l^ine -42 | + line i | + line sin(theta) | + line 8 | + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]) + eq({5, 1}, meths.win_get_cursor(0)) + + meths.input_mouse('left', 'drag', '', 0, 6, 2) + screen:expect([[ + {1:Set Up The Bars }| + line 1 | + line 2 | + line 3 | + line 4 | + l{7:ine -42} | + {7:li}^ne i | + line sin(theta) | + line 8 | + {3:~ }| + {3:~ }| + {3:~ }| + {1:-- VISUAL --} | + ]]) + eq({6, 2}, meths.win_get_cursor(0)) + + meths.input_mouse('left', 'drag', '', 0, 1, 2) + screen:expect([[ + {1:Set Up The Bars }| + li^n{7:e 1} | + {7:line 2} | + {7:line 3} | + {7:line 4} | + {7:li}ne -42 | + line i | + line sin(theta) | + line 8 | + {3:~ }| + {3:~ }| + {3:~ }| + {1:-- VISUAL --} | + ]]) + eq({1, 2}, meths.win_get_cursor(0)) + + meths.input_mouse('left', 'drag', '', 0, 0, 2) + screen:expect_unchanged() + eq({1, 2}, meths.win_get_cursor(0)) + end) + + it('dragging statusline with mouse works correctly', function() + command('split') + screen:expect([[ + {1:Set Up The Bars }| + ^ | + {3:~ }| + {3:~ }| + {3:~ }| + {4:[No Name] }| + {1:Set Up The Bars }| + | + {3:~ }| + {3:~ }| + {3:~ }| + {2:[No Name] }| + | + ]]) + + meths.input_mouse('left', 'press', '', 1, 5, 10) + poke_eventloop() + meths.input_mouse('left', 'drag', '', 1, 6, 10) + screen:expect([[ + {1:Set Up The Bars }| + ^ | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {4:[No Name] }| + {1:Set Up The Bars }| + | + {3:~ }| + {3:~ }| + {2:[No Name] }| + | + ]]) + + meths.input_mouse('left', 'drag', '', 1, 4, 10) + screen:expect([[ + {1:Set Up The Bars }| + ^ | + {3:~ }| + {3:~ }| + {4:[No Name] }| + {1:Set Up The Bars }| + | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {2:[No Name] }| + | + ]]) + + meths.input_mouse('left', 'press', '', 1, 11, 10) + poke_eventloop() + meths.input_mouse('left', 'drag', '', 1, 9, 10) + screen:expect([[ + {1:Set Up The Bars }| + ^ | + {3:~ }| + {3:~ }| + {4:[No Name] }| + {1:Set Up The Bars }| + | + {3:~ }| + {3:~ }| + {2:[No Name] }| + | + | + | + ]]) + eq(3, meths.get_option('cmdheight')) + + meths.input_mouse('left', 'drag', '', 1, 11, 10) + screen:expect([[ + {1:Set Up The Bars }| + ^ | + {3:~ }| + {3:~ }| + {4:[No Name] }| + {1:Set Up The Bars }| + | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {2:[No Name] }| + | + ]]) + eq(1, meths.get_option('cmdheight')) + end) + + it('properly equalizes window height for window-local value', function() + command('set equalalways | set winbar= | setlocal winbar=a | split') + command('setlocal winbar= | split') + command('setlocal winbar=b | split') + screen:expect([[ + {1:b }| + ^ | + {4:[No Name] }| + {1:b }| + | + {2:[No Name] }| + | + {3:~ }| + {2:[No Name] }| + {1:a }| + | + {2:[No Name] }| + | + ]]) + end) + + it('requires window-local value for floating windows', function() + local win = meths.open_win(0, false, { relative = 'editor', row = 2, col = 10, height = 7, + width = 30 }) + meths.set_option_value('winbar', 'bar', {}) + screen:expect{grid=[[ + {1:bar }| + ^ | + {3:~ }{8: }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]} + meths.set_option_value('winbar', 'floaty bar', { scope = 'local', win = win.id }) + screen:expect{grid=[[ + {1:bar }| + ^ | + {3:~ }{1:floaty bar }{3: }| + {3:~ }{8: }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }{9:~ }{3: }| + {3:~ }| + {3:~ }| + {3:~ }| + | + ]]} + end) + + it('works correctly when moving a split', function() + screen:try_resize(45, 6) + command('set winbar=') + command('vsplit') + command('setlocal winbar=foo') + screen:expect([[ + {1:foo }│ | + ^ │{3:~ }| + {3:~ }│{3:~ }| + {3:~ }│{3:~ }| + {4:[No Name] }{2:[No Name] }| + | + ]]) + + command('wincmd L') + screen:expect([[ + │{1:foo }| + {3:~ }│^ | + {3:~ }│{3:~ }| + {3:~ }│{3:~ }| + {2:[No Name] }{4:[No Name] }| + | + ]]) + + command('wincmd w') + command('wincmd L') + screen:expect([[ + {1:foo }│^ | + │{3:~ }| + {3:~ }│{3:~ }| + {3:~ }│{3:~ }| + {2:[No Name] }{4:[No Name] }| + | + ]]) + end) + + it('properly resizes window when there is no space in it', function() + command('set winbar= | 1split') + screen:expect([[ + ^ | + {4:[No Name] }| + | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {2:[No Name] }| + | + ]]) + command('set winbar=a') + screen:expect([[ + {1:a }| + ^ | + {4:[No Name] }| + {1:a }| + | + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {3:~ }| + {2:[No Name] }| + | + ]]) + end) + + it('cannot be added unless there is room', function() + command('set winbar= | split | split | split | split | split') + screen:expect([[ + ^ | + {4:[No Name] }| + | + {2:[No Name] }| + | + {2:[No Name] }| + | + {2:[No Name] }| + | + {2:[No Name] }| + | + {2:[No Name] }| + | + ]]) + eq('Vim(set):E36: Not enough room', pcall_err(command, 'set winbar=test')) + end) +end) |