diff options
| author | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
|---|---|---|
| committer | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
| commit | 9be89f131f87608f224f0ee06d199fcd09d32176 (patch) | |
| tree | 11022dcfa9e08cb4ac5581b16734196128688d48 /test/functional/ui | |
| parent | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (diff) | |
| parent | 88085c2e80a7e3ac29aabb6b5420377eed99b8b6 (diff) | |
| download | rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.gz rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.bz2 rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.zip | |
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'test/functional/ui')
21 files changed, 3086 insertions, 407 deletions
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua index 8bfceb8cce..619153724b 100644 --- a/test/functional/ui/cursor_spec.lua +++ b/test/functional/ui/cursor_spec.lua @@ -246,11 +246,11 @@ describe('ui/cursor', function() end end if m.hl_id then - m.hl_id = 64 + m.hl_id = 66 m.attr = { background = Screen.colors.DarkGray } end if m.id_lm then - m.id_lm = 69 + m.id_lm = 73 end end diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 746bfb3262..042975f898 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -2341,21 +2341,28 @@ describe('extmark decorations', function() it('supports URLs', function() insert(example_text) - local url = 'https://example.com' + local url1 = 'https://example.com' + local url2 = 'http://127.0.0.1' screen:add_extra_attr_ids { - u = { url = "https://example.com" }, + u = { url = url1 }, + uh = { url = url2, background = Screen.colors.Yellow }, } api.nvim_buf_set_extmark(0, ns, 1, 4, { end_col = 14, - url = url, + url = url1, + }) + api.nvim_buf_set_extmark(0, ns, 2, 4, { + end_col = 17, + hl_group = 'Search', + url = url2, }) - screen:expect{grid=[[ + screen:expect([[ for _,item in ipairs(items) do | {u:local text}, hl_id_cell, count = unpack(item) | - if hl_id_cell ~= nil then | + {uh:if hl_id_cell} ~= nil then | hl_id = hl_id_cell | end | for _ = 1, (count or 1) do | @@ -2368,7 +2375,7 @@ describe('extmark decorations', function() {1:~ }| {1:~ }| | - ]]} + ]]) end) it('can replace marks in place with different decorations #27211', function() @@ -4027,11 +4034,85 @@ describe('decorations: inline virtual text', function() normal! $ ]]) api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = { { ('b'):rep(9) } }, virt_text_pos = 'inline' }) - screen:expect{grid=[[ + screen:expect([[ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}| ๅฃ1234^5 | | - ]]} + ]]) + feed('g0') + screen:expect([[ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}| + ^ๅฃ12345 | + | + ]]) + command('set showbreak=+++') + screen:expect([[ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}| + {1:+++}^ๅฃ12345 | + | + ]]) + end) + + it('cursor position is correct if end_row or end_col is specified', function() + screen:try_resize(50, 8) + api.nvim_buf_set_lines(0, 0, -1, false, { ('a'):rep(48), ('b'):rep(48), ('c'):rep(48), ('d'):rep(48) }) + api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 2, virt_text_pos = 'inline', virt_text = {{'I1', 'NonText'}}}) + api.nvim_buf_set_extmark(0, ns, 3, 0, {end_col = 2, virt_text_pos = 'inline', virt_text = {{'I2', 'NonText'}}}) + feed('$') + screen:expect([[ + {1:I1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^a| + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | + cccccccccccccccccccccccccccccccccccccccccccccccc | + {1:I2}dddddddddddddddddddddddddddddddddddddddddddddddd| + {1:~ }|*3 + | + ]]) + feed('j') + screen:expect([[ + {1:I1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^b | + cccccccccccccccccccccccccccccccccccccccccccccccc | + {1:I2}dddddddddddddddddddddddddddddddddddddddddddddddd| + {1:~ }|*3 + | + ]]) + feed('j') + screen:expect([[ + {1:I1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | + ccccccccccccccccccccccccccccccccccccccccccccccc^c | + {1:I2}dddddddddddddddddddddddddddddddddddddddddddddddd| + {1:~ }|*3 + | + ]]) + feed('j') + screen:expect([[ + {1:I1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | + cccccccccccccccccccccccccccccccccccccccccccccccc | + {1:I2}ddddddddddddddddddddddddddddddddddddddddddddddd^d| + {1:~ }|*3 + | + ]]) + end) + + it('cursor position is correct with invalidated inline virt text', function() + screen:try_resize(50, 8) + api.nvim_buf_set_lines(0, 0, -1, false, { ('a'):rep(48), ('b'):rep(48) }) + api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text_pos = 'inline', virt_text = {{'INLINE', 'NonText'}}, invalidate = true }) + screen:expect([[ + {1:INLINE}^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + aaaa | + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | + {1:~ }|*4 + | + ]]) + feed('dd$') + screen:expect([[ + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^b | + {1:~ }|*6 + | + ]]) end) end) @@ -4936,6 +5017,28 @@ if (h->n_buckets < new_n_buckets) { // expand | ]]) end) + + it('not drawn when invalid', function() + api.nvim_buf_set_lines(0, 0, -1, false, { 'foo', 'bar' }) + api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines = {{{'VIRT1'}}}, invalidate = true }) + screen:expect({ + grid = [[ + ^foo | + VIRT1 | + bar | + {1:~ }|*8 + | + ]] + }) + feed('dd') + screen:expect({ + grid = [[ + ^bar | + {1:~ }|*10 + | + ]] + }) + end) end) describe('decorations: signs', function() @@ -5497,6 +5600,60 @@ l5 api.nvim_buf_clear_namespace(0, ns, 0, -1) end) + + it([[correct numberwidth with 'signcolumn' set to "number" #28984]], function() + command('set number numberwidth=1 signcolumn=number') + api.nvim_buf_set_extmark(0, ns, 0, 0, { sign_text = 'S1' }) + screen:expect({ + grid = [[ + S1 ^ | + {1:~ }|*8 + | + ]] + }) + api.nvim_buf_del_extmark(0, ns, 1) + screen:expect({ + grid = [[ + {8:1 }^ | + {1:~ }|*8 + | + ]] + }) + end) + + it('supports emoji as signs', function() + insert(example_test3) + feed 'gg' + api.nvim_buf_set_extmark(0, ns, 1, 0, {sign_text='๐งโ๐พ'}) + -- VS16 can change width of character + api.nvim_buf_set_extmark(0, ns, 2, 0, {sign_text='โค๏ธ'}) + api.nvim_buf_set_extmark(0, ns, 3, 0, {sign_text='โค'}) + api.nvim_buf_set_extmark(0, ns, 4, 0, {sign_text='โคx'}) + screen:expect([[ + {7: }^l1 | + ๐งโ๐พl2 | + โค๏ธl3 | + โค l4 | + โคxl5 | + {7: } | + {1:~ }|*3 + | + ]]) + eq("Invalid 'sign_text'", pcall_err(api.nvim_buf_set_extmark, 0, ns, 5, 0, {sign_text='โค๏ธx'})) + end) + + it('auto signcolumn hides with invalidated sign', function() + api.nvim_set_option_value('signcolumn', 'auto', {}) + api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text='S1', invalidate=true}) + feed('ia<cr>b<esc>dd') + screen:expect({ + grid = [[ + ^a | + {1:~ }|*8 + | + ]] + }) + end) end) describe('decorations: virt_text', function() @@ -5575,20 +5732,26 @@ describe('decorations: virt_text', function() end) describe('decorations: window scoped', function() - local screen, ns + local screen, ns, win_other local url = 'https://example.com' before_each(function() clear() screen = Screen.new(20, 10) screen:attach() screen:add_extra_attr_ids { - [100] = { special = Screen.colors.Red, undercurl = true }, - [101] = { url = "https://example.com" }, + [100] = { special = Screen.colors.Red, undercurl = true }, + [101] = { url = 'https://example.com' }, } ns = api.nvim_create_namespace 'test' insert('12345') + + win_other = api.nvim_open_win(0, false, { + col=0,row=0,width=20,height=10, + relative = 'win',style = 'minimal', + hide = true + }) end) local noextmarks = { @@ -5596,28 +5759,28 @@ describe('decorations: window scoped', function() 1234^5 | {1:~ }|*8 | - ]]} + ]], + } - local function set_scoped_extmark(line, col, opts) - return api.nvim_buf_set_extmark(0, ns, line, col, vim.tbl_extend('error', { scoped = true }, opts)) + local function set_extmark(line, col, opts) + return api.nvim_buf_set_extmark(0, ns, line, col, opts) end it('hl_group', function() - set_scoped_extmark(0, 0, { + set_extmark(0, 0, { hl_group = 'Comment', end_col = 3, }) - screen:expect(noextmarks) - - api.nvim__win_add_ns(0, ns) + api.nvim__ns_set(ns, { wins = { 0 } }) screen:expect { grid = [[ {18:123}4^5 | {1:~ }|*8 | - ]]} + ]], + } command 'split' command 'only' @@ -5626,48 +5789,55 @@ describe('decorations: window scoped', function() end) it('virt_text', function() - set_scoped_extmark(0, 0, { + set_extmark(0, 0, { virt_text = { { 'a', 'Comment' } }, virt_text_pos = 'eol', }) - set_scoped_extmark(0, 5, { + set_extmark(0, 5, { virt_text = { { 'b', 'Comment' } }, virt_text_pos = 'inline', }) - set_scoped_extmark(0, 1, { + set_extmark(0, 1, { virt_text = { { 'c', 'Comment' } }, virt_text_pos = 'overlay', }) - set_scoped_extmark(0, 1, { + set_extmark(0, 1, { virt_text = { { 'd', 'Comment' } }, virt_text_pos = 'right_align', }) - screen:expect(noextmarks) - - api.nvim__win_add_ns(0, ns) + api.nvim__ns_set(ns, { wins = { 0 } }) screen:expect { grid = [[ 1{18:c}34^5{18:b} {18:a} {18:d}| {1:~ }|*8 | - ]]} + ]], + } command 'split' command 'only' screen:expect(noextmarks) + + api.nvim__ns_set(ns, { wins = {} }) + + screen:expect { + grid = [[ + 1{18:c}34^5{18:b} {18:a} {18:d}| + {1:~ }|*8 + | + ]], + } end) it('virt_lines', function() - set_scoped_extmark(0, 0, { + set_extmark(0, 0, { virt_lines = { { { 'a', 'Comment' } } }, }) - screen:expect(noextmarks) - - api.nvim__win_add_ns(0, ns) + api.nvim__ns_set(ns, { wins = { 0 } }) screen:expect { grid = [[ @@ -5675,7 +5845,8 @@ describe('decorations: window scoped', function() {18:a} | {1:~ }|*7 | - ]]} + ]], + } command 'split' command 'only' @@ -5684,14 +5855,12 @@ describe('decorations: window scoped', function() end) it('redraws correctly with inline virt_text and wrapping', function() - set_scoped_extmark(0, 2, { - virt_text = {{ ('b'):rep(18), 'Comment' }}, - virt_text_pos = 'inline' + set_extmark(0, 2, { + virt_text = { { ('b'):rep(18), 'Comment' } }, + virt_text_pos = 'inline', }) - screen:expect(noextmarks) - - api.nvim__win_add_ns(0, ns) + api.nvim__ns_set(ns, { wins = { 0 } }) screen:expect { grid = [[ @@ -5699,9 +5868,10 @@ describe('decorations: window scoped', function() 34^5 | {1:~ }|*7 | - ]]} + ]], + } - api.nvim__win_del_ns(0, ns) + api.nvim__ns_set(ns, { wins = { win_other } }) screen:expect(noextmarks) end) @@ -5709,21 +5879,20 @@ describe('decorations: window scoped', function() pending('sign_text', function() -- TODO(altermo): The window signcolumn width is calculated wrongly (when `signcolumn=auto`) -- This happens in function `win_redraw_signcols` on line containing `buf_meta_total(buf, kMTMetaSignText) > 0` - set_scoped_extmark(0, 0, { + set_extmark(0, 0, { sign_text = 'a', sign_hl_group = 'Comment', }) - screen:expect(noextmarks) - - api.nvim__win_add_ns(0, ns) + api.nvim__ns_set(ns, { wins = { 0 } }) screen:expect { grid = [[ a 1234^5 | {2:~ }|*8 | - ]]} + ]], + } command 'split' command 'only' @@ -5732,30 +5901,34 @@ describe('decorations: window scoped', function() end) it('statuscolumn hl group', function() - set_scoped_extmark(0, 0, { - number_hl_group='comment', + set_extmark(0, 0, { + number_hl_group = 'comment', }) - set_scoped_extmark(0, 0, { - line_hl_group='comment', + set_extmark(0, 0, { + line_hl_group = 'comment', }) command 'set number' + api.nvim__ns_set(ns, { wins = { win_other } }) + screen:expect { grid = [[ {8: 1 }1234^5 | {1:~ }|*8 | - ]]} + ]], + } - api.nvim__win_add_ns(0, ns) + api.nvim__ns_set(ns, { wins = { 0 } }) screen:expect { grid = [[ {18: 1 1234^5 }| {1:~ }|*8 | - ]]} + ]], + } command 'split' command 'only' @@ -5765,36 +5938,43 @@ describe('decorations: window scoped', function() {8: 1 }1234^5 | {1:~ }|*8 | - ]]} + ]], + } end) it('spell', function() - api.nvim_buf_set_lines(0,0,-1,true,{'aa'}) + api.nvim_buf_set_lines(0, 0, -1, true, { 'aa' }) - set_scoped_extmark(0, 0, { - spell=true, - end_col=2, + set_extmark(0, 0, { + spell = true, + end_col = 2, }) command 'set spelloptions=noplainbuffer' command 'set spell' command 'syntax off' + screen:expect({ unchanged = true }) + + api.nvim__ns_set(ns, { wins = { win_other } }) + screen:expect { grid = [[ a^a | {1:~ }|*8 | - ]]} + ]], + } - api.nvim__win_add_ns(0, ns) + api.nvim__ns_set(ns, { wins = { 0 } }) screen:expect { grid = [[ {100:a^a} | {1:~ }|*8 | - ]]} + ]], + } command 'split' command 'only' @@ -5804,25 +5984,25 @@ describe('decorations: window scoped', function() a^a | {1:~ }|*8 | - ]]} + ]], + } end) it('url', function() - set_scoped_extmark(0, 0, { - end_col=3, - url=url, + set_extmark(0, 0, { + end_col = 3, + url = url, }) - screen:expect(noextmarks) - - api.nvim__win_add_ns(0, ns) + api.nvim__ns_set(ns, { wins = { 0 } }) screen:expect { grid = [[ {101:123}4^5 | {1:~ }|*8 | - ]]} + ]], + } command 'split' command 'only' @@ -5830,85 +6010,72 @@ describe('decorations: window scoped', function() screen:expect(noextmarks) end) - it('change extmarks scoped option', function() - local id = set_scoped_extmark(0, 0, { + it('change namespace scope', function() + set_extmark(0, 0, { hl_group = 'Comment', end_col = 3, }) - api.nvim__win_add_ns(0, ns) + api.nvim__ns_set(ns, { wins = { 0 } }) + eq({ wins={ api.nvim_get_current_win() } }, api.nvim__ns_get(ns)) screen:expect { grid = [[ {18:123}4^5 | {1:~ }|*8 | - ]]} + ]], + } command 'split' command 'only' screen:expect(noextmarks) - api.nvim_buf_set_extmark(0, ns, 0, 0, { - id = id, - hl_group = 'Comment', - end_col = 3, - scoped = false, - }) + api.nvim__ns_set(ns, { wins = { 0 } }) + eq({ wins={ api.nvim_get_current_win() } }, api.nvim__ns_get(ns)) screen:expect { grid = [[ {18:123}4^5 | {1:~ }|*8 | - ]]} + ]], + } - api.nvim_buf_set_extmark(0, ns, 0, 0, { - id = id, - hl_group = 'Comment', - end_col = 3, - scoped = true, + local win_new = api.nvim_open_win(0, false, { + col=0,row=0,width=20,height=10, + relative = 'win',style = 'minimal', + hide = true }) + api.nvim__ns_set(ns, { wins = { win_new } }) + eq({ wins={ win_new } }, api.nvim__ns_get(ns)) + screen:expect(noextmarks) end) - it('change namespace scope', function() - set_scoped_extmark(0, 0, { - hl_group = 'Comment', - end_col = 3, - }) + it('namespace get works', function() + eq({ wins = {} }, api.nvim__ns_get(ns)) - eq(true, api.nvim__win_add_ns(0, ns)) - eq({ ns }, api.nvim__win_get_ns(0)) + api.nvim__ns_set(ns, { wins = { 0 } }) - screen:expect { - grid = [[ - {18:123}4^5 | - {1:~ }|*8 - | - ]]} + eq({ wins = { api.nvim_get_current_win() } }, api.nvim__ns_get(ns)) - command 'split' - command 'only' - eq({}, api.nvim__win_get_ns(0)) + api.nvim__ns_set(ns, { wins = {} }) - screen:expect(noextmarks) + eq({ wins = {} }, api.nvim__ns_get(ns)) + end) - eq(true, api.nvim__win_add_ns(0, ns)) - eq({ ns }, api.nvim__win_get_ns(0)) + it('remove window from namespace scope when deleted', function () + api.nvim__ns_set(ns, { wins = { 0 } }) - screen:expect { - grid = [[ - {18:123}4^5 | - {1:~ }|*8 - | - ]]} + eq({ wins = { api.nvim_get_current_win() } }, api.nvim__ns_get(ns)) - eq(true, api.nvim__win_del_ns(0, ns)) - eq({}, api.nvim__win_get_ns(0)) + command 'split' + command 'only' - screen:expect(noextmarks) + eq({ wins = {} }, api.nvim__ns_get(ns)) end) end) + diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua index e79621f364..d6a04f90f6 100644 --- a/test/functional/ui/diff_spec.lua +++ b/test/functional/ui/diff_spec.lua @@ -12,6 +12,19 @@ local exec = n.exec local eq = t.eq local api = n.api +local function WriteDiffFiles(text1, text2) + write_file('Xdifile1', text1) + write_file('Xdifile2', text2) + command('checktime') +end + +local function WriteDiffFiles3(text1, text2, text3) + write_file('Xdifile1', text1) + write_file('Xdifile2', text2) + write_file('Xdifile3', text3) + command('checktime') +end + before_each(clear) describe('Diff mode screen', function() @@ -614,6 +627,34 @@ int main(int argc, char **argv) ]]) end) + it('Diff empty and non-empty file', function() + write_file(fname, '', false) + write_file(fname_2, 'foo\nbar\nbaz', false) + reread() + + feed(':set diffopt=filler<cr>') + screen:expect([[ + {7: }{23:------------------}โ{7: }{22:foo }| + {7: }{23:------------------}โ{7: }{22:bar }| + {7: }{23:------------------}โ{7: }{22:baz }| + {7: }^ โ{1:~ }| + {1:~ }โ{1:~ }|*10 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| + :set diffopt=filler | + ]]) + + feed(':set diffopt+=internal<cr>') + screen:expect([[ + {7: }{23:------------------}โ{7: }{22:foo }| + {7: }{23:------------------}โ{7: }{22:bar }| + {7: }{23:------------------}โ{7: }{22:baz }| + {7: }^ โ{1:~ }| + {1:~ }โ{1:~ }|*10 + {3:<onal-diff-screen-1 }{2:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + it('diffopt+=icase', function() write_file(fname, 'a\nb\ncd\n', false) write_file(fname_2, 'A\nb\ncDe\n', false) @@ -1346,6 +1387,46 @@ it("diff mode doesn't restore invalid 'foldcolumn' value #21647", function() eq('0', api.nvim_get_option_value('foldcolumn', {})) end) +it("'relativenumber' doesn't draw beyond end of window in diff mode #29403", function() + local screen = Screen.new(60, 12) + screen:attach() + command('set relativenumber') + feed('10aa<CR><Esc>gg') + command('vnew') + feed('ab<CR><Esc>gg') + command('windo diffthis') + command('wincmd |') + screen:expect([[ + {8: }โ{7: }{8: 0 }{27:^a}{4: }| + {8: }โ{7: }{8: 1 }{22:a }| + {8: }โ{7: }{8: 2 }{22:a }| + {8: }โ{7: }{8: 3 }{22:a }| + {8: }โ{7: }{8: 4 }{22:a }| + {8: }โ{7: }{8: 5 }{22:a }| + {8: }โ{7: }{8: 6 }{22:a }| + {8: }โ{7: }{8: 7 }{22:a }| + {8: }โ{7: }{8: 8 }{22:a }| + {8: }โ{7: }{8: 9 }{22:a }| + {2:< }{3:[No Name] [+] }| + | + ]]) + feed('j') + screen:expect([[ + {8: }โ{7: }{8: 1 }{27:a}{4: }| + {8: }โ{7: }{8: 0 }{22:^a }| + {8: }โ{7: }{8: 1 }{22:a }| + {8: }โ{7: }{8: 2 }{22:a }| + {8: }โ{7: }{8: 3 }{22:a }| + {8: }โ{7: }{8: 4 }{22:a }| + {8: }โ{7: }{8: 5 }{22:a }| + {8: }โ{7: }{8: 6 }{22:a }| + {8: }โ{7: }{8: 7 }{22:a }| + {8: }โ{7: }{8: 8 }{22:a }| + {2:< }{3:[No Name] [+] }| + | + ]]) +end) + -- oldtest: Test_diff_binary() it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', function() local screen = Screen.new(40, 20) @@ -1447,3 +1528,529 @@ it("diff mode draws 'breakindent' correctly after filler lines", function() | ]]) end) + +-- oldtest: Test_diff_overlapped_diff_blocks_will_be_merged() +it('diff mode overlapped diff blocks will be merged', function() + write_file('Xdifile1', '') + write_file('Xdifile2', '') + write_file('Xdifile3', '') + + finally(function() + os.remove('Xdifile1') + os.remove('Xdifile2') + os.remove('Xdifile3') + os.remove('Xdiin1') + os.remove('Xdinew1') + os.remove('Xdiout1') + os.remove('Xdiin2') + os.remove('Xdinew2') + os.remove('Xdiout2') + end) + + exec([[ + func DiffExprStub() + let txt_in = readfile(v:fname_in) + let txt_new = readfile(v:fname_new) + if txt_in == ["line1"] && txt_new == ["line2"] + call writefile(["1c1"], v:fname_out) + elseif txt_in == readfile("Xdiin1") && txt_new == readfile("Xdinew1") + call writefile(readfile("Xdiout1"), v:fname_out) + elseif txt_in == readfile("Xdiin2") && txt_new == readfile("Xdinew2") + call writefile(readfile("Xdiout2"), v:fname_out) + endif + endfunc + ]]) + + local screen = Screen.new(35, 20) + screen:attach() + command('set winwidth=10 diffopt=filler,internal') + + command('args Xdifile1 Xdifile2 | vert all | windo diffthis') + + WriteDiffFiles('a\nb', 'x\nx') + write_file('Xdiin1', 'a\nb') + write_file('Xdinew1', 'x\nx') + write_file('Xdiout1', '1c1\n2c2') + command('set diffexpr=DiffExprStub()') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:^x}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }| + {1:~ }โ{1:~ }|*16 + {2:Xdifile1 }{3:Xdifile2 }| + | + ]]) + command('set diffexpr&') + + WriteDiffFiles('a\nb\nc', 'x\nc') + write_file('Xdiin1', 'a\nb\nc') + write_file('Xdinew1', 'x\nc') + write_file('Xdiout1', '1c1\n2c1') + command('set diffexpr=DiffExprStub()') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:^x}{4: }| + {7: }{22:b }โ{7: }{23:---------------}| + {7: }c โ{7: }c | + {1:~ }โ{1:~ }|*15 + {2:Xdifile1 }{3:Xdifile2 }| + | + ]]) + command('set diffexpr&') + + WriteDiffFiles('a\nc', 'x\nx\nc') + write_file('Xdiin1', 'a\nc') + write_file('Xdinew1', 'x\nx\nc') + write_file('Xdiout1', '1c1\n1a2') + command('set diffexpr=DiffExprStub()') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:^x}{4: }| + {7: }{23:---------------}โ{7: }{22:x }| + {7: }c โ{7: }c | + {1:~ }โ{1:~ }|*15 + {2:Xdifile1 }{3:Xdifile2 }| + | + ]]) + command('set diffexpr&') + + command('args Xdifile1 Xdifile2 Xdifile3 | vert all | windo diffthis') + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'y\nb\nc') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:b}{4: }| + {7: }c โ{7: }c โ{7: }c | + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'a\ny\nc') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }c โ{7: }c โ{7: }c | + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'a\nb\ny') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:b}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'y\ny\nc') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }c โ{7: }c โ{7: }c | + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'a\ny\ny') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'y\ny\ny') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nx', 'y\ny\nc') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:x}{4: }โ{7: }{27:c}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'x\nx\nc', 'a\ny\ny') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:x}{4: }โ{7: }{27:^a}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'y\ny\ny\nd\ne') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{27:d}{4: }| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'y\ny\ny\ny\ne') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'y\ny\ny\ny\ny') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:e}{4: }โ{7: }{27:e}{4: }โ{7: }{27:y}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\ny\ny\nd\ne') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{27:d}{4: }| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\ny\ny\ny\ne') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\ny\ny\ny\ny') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:e}{4: }โ{7: }{27:e}{4: }โ{7: }{27:y}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\nb\ny\nd\ne') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:b}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{27:d}{4: }| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\nb\ny\ny\ne') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:b}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\nb\ny\ny\ny') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:b}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:e}{4: }โ{7: }{27:e}{4: }โ{7: }{27:y}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb', 'x\nb', 'y\ny') + write_file('Xdiin1', 'a\nb') + write_file('Xdinew1', 'x\nb') + write_file('Xdiout1', '1c1') + write_file('Xdiin2', 'a\nb') + write_file('Xdinew2', 'y\ny') + write_file('Xdiout2', '1c1\n2c2') + command('set diffexpr=DiffExprStub()') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:x}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:b}{4: }โ{7: }{27:y}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*16 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + command('set diffexpr&') + + WriteDiffFiles3('a\nb\nc\nd', 'x\nb\nx\nd', 'y\ny\nc\nd') + write_file('Xdiin1', 'a\nb\nc\nd') + write_file('Xdinew1', 'x\nb\nx\nd') + write_file('Xdiout1', '1c1\n3c3') + write_file('Xdiin2', 'a\nb\nc\nd') + write_file('Xdinew2', 'y\ny\nc\nd') + write_file('Xdiout2', '1c1\n2c2') + command('set diffexpr=DiffExprStub()') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:x}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:b}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:x}{4: }โ{7: }{27:c}{4: }| + {7: }d โ{7: }d โ{7: }d | + {1:~ }โ{1:~ }โ{1:~ }|*14 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + command('set diffexpr&') + + WriteDiffFiles3('a\nb\nc\nd', 'x\nb\nx\nd', 'y\ny\ny\nd') + write_file('Xdiin1', 'a\nb\nc\nd') + write_file('Xdinew1', 'x\nb\nx\nd') + write_file('Xdiout1', '1c1\n3c3') + write_file('Xdiin2', 'a\nb\nc\nd') + write_file('Xdinew2', 'y\ny\ny\nd') + write_file('Xdiout2', '1c1\n2,3c2,3') + command('set diffexpr=DiffExprStub()') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:x}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:b}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }d โ{7: }d โ{7: }d | + {1:~ }โ{1:~ }โ{1:~ }|*14 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + command('set diffexpr&') + + WriteDiffFiles3('a\nb\nc\nd', 'x\nb\nx\nd', 'y\ny\ny\ny') + write_file('Xdiin1', 'a\nb\nc\nd') + write_file('Xdinew1', 'x\nb\nx\nd') + write_file('Xdiout1', '1c1\n3c3') + write_file('Xdiin2', 'a\nb\nc\nd') + write_file('Xdinew2', 'y\ny\ny\ny') + write_file('Xdiout2', '1c1\n2,4c2,4') + command('set diffexpr=DiffExprStub()') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:x}{4: }โ{7: }{27:^y}{4: }| + {7: }{27:b}{4: }โ{7: }{27:b}{4: }โ{7: }{27:y}{4: }| + {7: }{27:c}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{27:d}{4: }โ{7: }{27:d}{4: }โ{7: }{27:y}{4: }| + {1:~ }โ{1:~ }โ{1:~ }|*14 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + command('set diffexpr&') + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'b\nc') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^b}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }c โ{7: }c โ{7: }c | + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'c') + screen:expect([[ + {7: }{4:a }โ{7: }{4:a }โ{7: }{23:---------}| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }c โ{7: }c โ{7: }^c | + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', '') + screen:expect([[ + {7: }{4:a }โ{7: }{4:a }โ{7: }{23:---------}| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {1:~ }โ{1:~ }โ{7: }^ | + {1:~ }โ{1:~ }โ{1:~ }|*14 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'a\nc') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }c โ{7: }c โ{7: }c | + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'a') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'b') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^b}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {1:~ }โ{1:~ }โ{1:~ }|*15 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'd\ne') + screen:expect([[ + {7: }{27:a}{4: }โ{7: }{27:a}{4: }โ{7: }{27:^d}{4: }| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'e') + screen:expect([[ + {7: }{4:a }โ{7: }{4:a }โ{7: }{23:---------}| + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }e โ{7: }e โ{7: }^e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\nd\ne') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:d}{4: }| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\ne') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }{4:e }โ{7: }{4:e }โ{7: }{23:---------}| + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\nb\nd\ne') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:b}{4: }| + {7: }{27:c}{4: }โ{7: }{27:c}{4: }โ{7: }{27:d}{4: }| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\nb\ne') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:b}{4: }| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }e โ{7: }e โ{7: }e | + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc\nd\ne', 'a\nx\nc\nx\ne', 'a\nb') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:b}{4: }| + {7: }{4:c }โ{7: }{4:c }โ{7: }{23:---------}| + {7: }{27:d}{4: }โ{7: }{27:x}{4: }โ{7: }{23:---------}| + {7: }{4:e }โ{7: }{4:e }โ{7: }{23:---------}| + {1:~ }โ{1:~ }โ{1:~ }|*13 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'a\ny\nb\nc') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:y}{4: }| + {7: }{23:---------}โ{7: }{23:---------}โ{7: }{22:b }| + {7: }c โ{7: }c โ{7: }c | + {1:~ }โ{1:~ }โ{1:~ }|*14 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) + + WriteDiffFiles3('a\nb\nc', 'a\nx\nc', 'a\nb\ny\nc') + screen:expect([[ + {7: }a โ{7: }a โ{7: }^a | + {7: }{27:b}{4: }โ{7: }{27:x}{4: }โ{7: }{27:b}{4: }| + {7: }{23:---------}โ{7: }{23:---------}โ{7: }{22:y }| + {7: }c โ{7: }c โ{7: }c | + {1:~ }โ{1:~ }โ{1:~ }|*14 + {2:Xdifile1 Xdifile2 }{3:Xdifile3 }| + | + ]]) +end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 248220e28b..9b77cb4014 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -327,6 +327,35 @@ describe('float window', function() eq(12, pos[2]) end) + it('error message when invalid field specified for split', function() + local bufnr = api.nvim_create_buf(false, true) + eq( + "non-float cannot have 'row'", + pcall_err(api.nvim_open_win, bufnr, true, { split = 'right', row = 10 }) + ) + eq( + "non-float cannot have 'col'", + pcall_err(api.nvim_open_win, bufnr, true, { split = 'right', col = 10 }) + ) + eq( + "non-float cannot have 'bufpos'", + pcall_err(api.nvim_open_win, bufnr, true, { split = 'right', bufpos = { 0, 0 } }) + ) + local winid = api.nvim_open_win(bufnr, true, { split = 'right' }) + eq( + "non-float cannot have 'row'", + pcall_err(api.nvim_win_set_config, winid, { split = 'right', row = 10 }) + ) + eq( + "non-float cannot have 'col'", + pcall_err(api.nvim_win_set_config, winid, { split = 'right', col = 10 }) + ) + eq( + "non-float cannot have 'bufpos'", + pcall_err(api.nvim_win_set_config, winid, { split = 'right', bufpos = { 0, 0 } }) + ) + end) + it('error message when reconfig missing relative field', function() local bufnr = api.nvim_create_buf(false, true) local opts = { @@ -337,15 +366,16 @@ describe('float window', function() relative = 'editor', style = 'minimal', } - local win_id = api.nvim_open_win(bufnr, true, opts) + local winid = api.nvim_open_win(bufnr, true, opts) eq( - "Missing 'relative' field when reconfiguring floating window 1001", - pcall_err(api.nvim_win_set_config, win_id, { - width = 3, - height = 3, - row = 10, - col = 10, - })) + "Missing 'relative' field when reconfiguring floating window 1001", + pcall_err(api.nvim_win_set_config, winid, { + width = 3, + height = 3, + row = 10, + col = 10, + }) + ) end) it('is not operated on by windo when non-focusable #15374', function() @@ -632,6 +662,22 @@ describe('float window', function() screen:detach() end) + it('no crash with relative="win" after %bdelete #30569', function() + exec([[ + botright vsplit + %bdelete + ]]) + api.nvim_open_win(0, false, { + relative = 'win', + win = 0, + row = 0, + col = 5, + width = 5, + height = 5, + }) + assert_alive() + 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 @@ -1314,6 +1360,53 @@ describe('float window', function() | ]]) end + + -- + -- floating windows inherit NormalFloat from global-ns. + -- + command('fclose') + command('hi NormalFloat guibg=LightRed') + api.nvim_open_win(0, false, { relative = 'win', row = 3, col = 3, width = 12, height = 3, style = 'minimal' }) + api.nvim_set_hl_ns(api.nvim_create_namespace('test1')) + if multigrid then + screen:expect({ + grid = [[ + ## grid 1 + [2:----------------------------------------]|*6 + [3:----------------------------------------]| + ## grid 2 + {14: 1 }^x | + {14: 2 }y | + {14: 3 } | + {0:~ }|*3 + ## grid 3 + | + ## grid 5 + {22:x }| + {22:y }| + {22: }| + ]], float_pos={ + [5] = {1002, "NW", 2, 3, 3, true, 50}; + }, win_viewport={ + [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0}; + [5] = {win = 1002, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { bottom = 0, left = 0, right = 0, top = 0, win = 1000 }, + [5] = { bottom = 0, left = 0, right = 0, top = 0, win = 1002 } + }}) + else + screen:expect({ + grid = [[ + {14: 1 }^x | + {14: 2 }y | + {14: 3 } | + {0:~ }{22:x }{0: }| + {0:~ }{22:y }{0: }| + {0:~ }{22: }{0: }| + | + ]] + }) + end end) it("can use 'minimal' style", function() @@ -1532,9 +1625,9 @@ describe('float window', function() [2:----------------------------------------]|*6 [3:----------------------------------------]| ## grid 2 - {20:1}{19: }{20: }{22:^x}{21: }| - {14:2}{19: }{14: }{22:y} | - {14:3}{19: }{14: }{22: } | + {20: 1}{19: }{22:^x}{21: }| + {14: 2}{19: }{22:y} | + {14: 3}{19: }{22: } | {0:~ }|*3 ## grid 3 | @@ -1545,9 +1638,9 @@ describe('float window', function() ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}} else screen:expect{grid=[[ - {20:1}{19: }{20: }{22:^x}{21: }| - {14:2}{19: }{14: }{22:y} | - {14:3}{19: }{14: }{22: } {15:x } | + {20: 1}{19: }{22:^x}{21: }| + {14: 2}{19: }{22:y} | + {14: 3}{19: }{22: } {15:x } | {0:~ }{15:y }{0: }| {0:~ }{15: }{0: }|*2 | @@ -2127,7 +2220,7 @@ describe('float window', function() ## grid 3 | ## grid 4 - {5:โโโโโโ}๐ฆBB{5:โ}| + {5:โโโโโโ}{11:๐ฆBB}{5:โ}| {5:โ}{1: halloj! }{5:โ}| {5:โ}{1: BORDAA }{5:โ}| {5:โโโโโโโโโโโ}| @@ -2141,7 +2234,7 @@ describe('float window', function() screen:expect{grid=[[ ^ | {0:~ }| - {0:~ }{5:โโโโโโ}๐ฆBB{5:โ}{0: }| + {0:~ }{5:โโโโโโ}{11:๐ฆBB}{5:โ}{0: }| {0:~ }{5:โ}{1: halloj! }{5:โ}{0: }| {0:~ }{5:โ}{1: BORDAA }{5:โ}{0: }| {0:~ }{5:โโโโโโโโโโโ}{0: }| @@ -2275,7 +2368,7 @@ describe('float window', function() {5:โโโโโโโโโโโ}| {5:โ}{1: halloj! }{5:โ}| {5:โ}{1: BORDAA }{5:โ}| - {5:โโโโโโ}๐ฆBB{5:โ}| + {5:โโโโโโ}{11:๐ฆBB}{5:โ}| ]], float_pos={ [4] = { 1001, "NW", 1, 2, 5, true } }, win_viewport={ @@ -2289,7 +2382,7 @@ describe('float window', function() {0:~ }{5:โโโโโโโโโโโ}{0: }| {0:~ }{5:โ}{1: halloj! }{5:โ}{0: }| {0:~ }{5:โ}{1: BORDAA }{5:โ}{0: }| - {0:~ }{5:โโโโโโ}๐ฆBB{5:โ}{0: }| + {0:~ }{5:โโโโโโ}{11:๐ฆBB}{5:โ}{0: }| | ]]} end @@ -2423,10 +2516,10 @@ describe('float window', function() ## grid 3 | ## grid 4 - {5:โโโโโโ}๐ฆ{7:BB}{5:โ}| + {5:โโโโโโ}{11:๐ฆ}{7:BB}{5:โ}| {5:โ}{1: halloj! }{5:โ}| {5:โ}{1: BORDAA }{5:โ}| - {5:โโโโโโ}๐ฆ{7:BB}{5:โ}| + {5:โโโโโโ}{11:๐ฆ}{7:BB}{5:โ}| ]], float_pos={ [4] = { 1001, "NW", 1, 2, 5, true } }, win_viewport={ @@ -2437,10 +2530,10 @@ describe('float window', function() screen:expect{grid=[[ ^ | {0:~ }| - {0:~ }{5:โโโโโโ}๐ฆ{7:BB}{5:โ}{0: }| + {0:~ }{5:โโโโโโ}{11:๐ฆ}{7:BB}{5:โ}{0: }| {0:~ }{5:โ}{1: halloj! }{5:โ}{0: }| {0:~ }{5:โ}{1: BORDAA }{5:โ}{0: }| - {0:~ }{5:โโโโโโ}๐ฆ{7:BB}{5:โ}{0: }| + {0:~ }{5:โโโโโโ}{11:๐ฆ}{7:BB}{5:โ}{0: }| | ]]} end @@ -2485,6 +2578,37 @@ describe('float window', function() end eq({{"๐ฆ", ""}, {"BB", {"B0", "B1", ""}}}, api.nvim_win_get_config(win).title) eq({{"๐ฆ", ""}, {"BB", {"B0", "B1", ""}}}, api.nvim_win_get_config(win).footer) + + -- making it a split should not leak memory + api.nvim_win_set_config(win, { vertical = true }) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:--------------------]{5:โ}[2:-------------------]|*5 + {5:[No Name] [+] }{4:[No Name] }| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }|*4 + ## grid 3 + | + ## grid 4 + halloj! | + BORDAA | + {0:~ }|*3 + ]], win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + halloj! {5:โ}^ | + BORDAA {5:โ}{0:~ }| + {0:~ }{5:โ}{0:~ }|*3 + {5:[No Name] [+] }{4:[No Name] }| + | + ]]} + end end) it('terminates border on edge of viewport when window extends past viewport', function() @@ -8991,6 +9115,7 @@ describe('float window', function() end) it('float window with hide option', function() + local cwin = api.nvim_get_current_win() local buf = api.nvim_create_buf(false,false) local win = api.nvim_open_win(buf, false, {relative='editor', width=10, height=2, row=2, col=5, hide = true}) local expected_pos = { @@ -9070,6 +9195,22 @@ describe('float window', function() | ]]) end + -- check window jump with hide + feed('<C-W><C-W>') + -- should keep on current window + eq(cwin, api.nvim_get_current_win()) + api.nvim_win_set_config(win, {hide=false}) + api.nvim_set_current_win(win) + local win3 = api.nvim_open_win(buf, true, {relative='editor', width=4, height=4, row=2, col=5, hide = false}) + api.nvim_win_set_config(win, {hide=true}) + feed('<C-W>w') + -- should goto the first window with prev + eq(cwin, api.nvim_get_current_win()) + -- windo + command('windo set winheight=6') + eq(win3, api.nvim_get_current_win()) + eq(6, api.nvim_win_get_height(win3)) + eq(2, api.nvim_win_get_height(win)) end) it(':fclose command #9663', function() diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index b7b46ddfae..87d66fa604 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -596,13 +596,13 @@ describe('highlight', function() ]]) screen:expect( [[ - {1: }^ | + {1: }{5:^ }| {1: }{2:01}{3:234 67}{2:89}{5: }| {4:~ }|*2 {7:[No Name] [+] }| - {1: } | {1: }{6:-----------------------}| - {4:~ }| + {1: }{6:-----------------------}| + {1: } | {8:[No Name] }| | ]], @@ -1078,6 +1078,44 @@ describe('CursorLine and CursorLineNr highlights', function() ]]) end) + -- oldtest: Test_cursorline_screenline_resize() + it("'cursorlineopt' screenline is updated on window resize", function() + local screen = Screen.new(75, 8) + screen:attach() + exec([[ + 50vnew + call setline(1, repeat('xyz ', 30)) + setlocal number cursorline cursorlineopt=screenline + normal! $ + ]]) + screen:expect([[ + {8: 1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyโ | + {8: }z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz โ{1:~ }| + {8: }{21:xyz xyz xyz xyz xyz xyz xyz^ }โ{1:~ }| + {1:~ }โ{1:~ }|*3 + {3:[No Name] [+] }{2:[No Name] }| + | + ]]) + command('vertical resize -4') + screen:expect([[ + {8: 1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyโ | + {8: }z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz โ{1:~ }| + {8: }{21:xyz xyz xyz xyz xyz xyz xyz xyz xyz^ }โ{1:~ }| + {1:~ }โ{1:~ }|*3 + {3:[No Name] [+] }{2:[No Name] }| + | + ]]) + command('set cpoptions+=n') + screen:expect([[ + {8: 1 }xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyโ | + z xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz โ{1:~ }| + {21:xyz xyz xyz xyz xyz xyz xyz xyz^ }โ{1:~ }| + {1:~ }โ{1:~ }|*3 + {3:[No Name] [+] }{2:[No Name] }| + | + ]]) + end) + -- oldtest: Test_cursorline_after_yank() it('always updated. vim-patch:8.1.0849', function() local screen = Screen.new(50, 5) diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua index 8d14c9f73d..a255047ed7 100644 --- a/test/functional/ui/hlstate_spec.lua +++ b/test/functional/ui/hlstate_spec.lua @@ -1,7 +1,7 @@ local t = require('test.testutil') local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local tt = require('test.functional.terminal.testutil') +local tt = require('test.functional.testterm') local clear, insert = n.clear, n.insert local command = n.command diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index ca52a265fa..a3e5068e55 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -1081,6 +1081,22 @@ stack traceback: }, }) end) + + it('does not do showmode unnecessarily #29086', function() + local screen_showmode = screen._handle_msg_showmode + local showmode = 0 + screen._handle_msg_showmode = function(...) + screen_showmode(...) + showmode = showmode + 1 + end + screen:expect({ + grid = [[ + ^ | + {1:~ }|*4 + ]], + }) + eq(showmode, 1) + end) end) describe('ui/builtin messages', function() @@ -1149,7 +1165,12 @@ describe('ui/builtin messages', function() it(':syntax list langGroup output', function() command('syntax on') - command('set syntax=vim') + exec([[ + syn match vimComment excludenl +\s"[^\-:.%#=*].*$+lc=1 contains=@vimCommentGroup,vimCommentString + syn match vimComment +\<endif\s\+".*$+lc=5 contains=@vimCommentGroup,vimCommentString + syn match vimComment +\<else\s\+".*$+lc=4 contains=@vimCommentGroup,vimCommentString + hi link vimComment Comment + ]]) screen:try_resize(110, 7) feed(':syntax list vimComment<cr>') screen:expect([[ @@ -1420,6 +1441,41 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim } end) + it('supports nvim_echo messages with emoji', function() + -- stylua: ignore + async_meths.nvim_echo( + { { 'wow, ๐ณ๏ธโโง๏ธ๐งโ๐พโค๏ธ๐๐ดโโ ๏ธ\nvariant โค๏ธ one\nvariant โค two' } }, true, {} + ) + + screen:expect([[ + | + {1:~ }| + {3: }| + wow, ๐ณ๏ธโโง๏ธ๐งโ๐พโค๏ธ๐๐ดโโ ๏ธ | + variant โค๏ธ one | + variant โค two | + {6:Press ENTER or type command to continue}^ | + ]]) + + feed '<cr>' + screen:expect([[ + ^ | + {1:~ }|*5 + | + ]]) + + feed ':messages<cr>' + screen:expect([[ + | + {1:~ }| + {3: }| + wow, ๐ณ๏ธโโง๏ธ๐งโ๐พโค๏ธ๐๐ดโโ ๏ธ | + variant โค๏ธ one | + variant โค two | + {6: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') api.nvim_buf_set_lines(0, 0, 0, true, { 'aaa', 'bbb', 'ccc' }) diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index 42c877fd92..bc18680749 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -367,7 +367,7 @@ describe('ui/mouse/input', function() }) end) - it('left click in default tabline (position 4) switches to tab', function() + it('left click in default tabline (tabpage label) switches to tab', function() feed_command('%delete') insert('this is foo') feed_command('silent file foo | tabnew | file bar') @@ -385,9 +385,47 @@ describe('ui/mouse/input', function() {0:~ }|*2 | ]]) + feed('<LeftMouse><6,0>') + screen:expect_unchanged() + feed('<LeftMouse><10,0>') + screen:expect([[ + {tab: + foo }{sel: + bar }{fill: }{tab:X}| + this is ba^r{0:$} | + {0:~ }|*2 + | + ]]) + feed('<LeftMouse><12,0>') + screen:expect_unchanged() + end) + + it('left click in default tabline (blank space) switches tab', function() + feed_command('%delete') + insert('this is foo') + feed_command('silent file foo | tabnew | file bar') + insert('this is bar') + screen:expect([[ + {tab: + foo }{sel: + bar }{fill: }{tab:X}| + this is ba^r{0:$} | + {0:~ }|*2 + | + ]]) + feed('<LeftMouse><20,0>') + screen:expect([[ + {sel: + foo }{tab: + bar }{fill: }{tab:X}| + this is fo^o | + {0:~ }|*2 + | + ]]) + feed('<LeftMouse><22,0>') + screen:expect([[ + {tab: + foo }{sel: + bar }{fill: }{tab:X}| + this is ba^r{0:$} | + {0:~ }|*2 + | + ]]) end) - it('left click in default tabline (position 24) closes tab', function() + it('left click in default tabline (close label) closes tab', function() api.nvim_set_option_value('hidden', true, {}) feed_command('%delete') insert('this is foo') @@ -407,8 +445,7 @@ describe('ui/mouse/input', function() ]]) end) - it('double click in default tabline (position 4) opens new tab', function() - api.nvim_set_option_value('hidden', true, {}) + it('double click in default tabline opens new tab before', function() feed_command('%delete') insert('this is foo') feed_command('silent file foo | tabnew | file bar') @@ -426,6 +463,34 @@ describe('ui/mouse/input', function() {0:~ }|*2 | ]]) + command('tabclose') + screen:expect([[ + {sel: + foo }{tab: + bar }{fill: }{tab:X}| + this is fo^o | + {0:~ }|*2 + | + ]]) + feed('<2-LeftMouse><20,0>') + screen:expect([[ + {tab: + foo + bar }{sel: Name] }{fill: }{tab:X}| + {0:^$} | + {0:~ }|*2 + | + ]]) + command('tabclose') + screen:expect([[ + {tab: + foo }{sel: + bar }{fill: }{tab:X}| + this is ba^r{0:$} | + {0:~ }|*2 + | + ]]) + feed('<2-LeftMouse><10,0>') + screen:expect([[ + {tab: + foo }{sel: Name] }{tab: + bar }{fill: }{tab:X}| + {0:^$} | + {0:~ }|*2 + | + ]]) end) describe('%@ label', function() @@ -987,7 +1052,7 @@ describe('ui/mouse/input', function() command('set sidescroll=0') feed('<esc>:set nowrap<cr>') - feed('a <esc>20Ab<esc>') + feed('a <esc>17Ab<esc>3Ab<esc>') screen:expect([[ |*2 bbbbbbbbbbbbbbb^b | @@ -1017,7 +1082,7 @@ describe('ui/mouse/input', function() command('set sidescroll=0') feed('<esc>:set nowrap<cr>') - feed('a <esc>20Ab<esc>') + feed('a <esc>17Ab<esc>3Ab<esc>') screen:expect([[ |*2 bbbbbbbbbbbbbbb^b | @@ -2002,5 +2067,24 @@ describe('ui/mouse/input', function() feed('<Down><CR>') eq({ 4, 20 }, api.nvim_win_get_cursor(0)) eq('the moon', fn.getreg('"')) + + -- Try clicking in the cmdline + api.nvim_input_mouse('right', 'press', '', 0, 23, 0) + api.nvim_input_mouse('right', 'release', '', 0, 23, 0) + feed('<Down><Down><Down><CR>') + eq('baz', api.nvim_get_var('menustr')) + + -- Try clicking in horizontal separator with global statusline + command('set laststatus=3') + api.nvim_input_mouse('right', 'press', '', 0, 5, 0) + api.nvim_input_mouse('right', 'release', '', 0, 5, 0) + feed('<Down><CR>') + eq('foo', api.nvim_get_var('menustr')) + + -- Try clicking in the cmdline with global statusline + api.nvim_input_mouse('right', 'press', '', 0, 23, 0) + api.nvim_input_mouse('right', 'release', '', 0, 23, 0) + feed('<Down><Down><CR>') + eq('bar', api.nvim_get_var('menustr')) end) end) diff --git a/test/functional/ui/multibyte_spec.lua b/test/functional/ui/multibyte_spec.lua index dc25a09d0d..f16f750ea1 100644 --- a/test/functional/ui/multibyte_spec.lua +++ b/test/functional/ui/multibyte_spec.lua @@ -296,6 +296,86 @@ describe('multibyte rendering', function() ]], } end) + + it('supports emoji with variant selectors and ZWJ', function() + command('set ruler') + insert('๐ณ๏ธโโง๏ธ') + screen:expect([[ + ^๐ณ๏ธโโง๏ธ | + {1:~ }|*4 + 1,1 All | + ]]) + + feed('a word<esc>') + screen:expect([[ + ๐ณ๏ธโโง๏ธ wor^d | + {1:~ }|*4 + 1,21-7 All | + ]]) + + feed('0') + screen:expect([[ + ^๐ณ๏ธโโง๏ธ word | + {1:~ }|*4 + 1,1 All | + ]]) + + feed('l') + screen:expect([[ + ๐ณ๏ธโโง๏ธ^ word | + {1:~ }|*4 + 1,17-3 All | + ]]) + + feed('h') + screen:expect([[ + ^๐ณ๏ธโโง๏ธ word | + {1:~ }|*4 + 1,1 All | + ]]) + + feed('oโค๏ธ variant selected<esc>') + screen:expect([[ + ๐ณ๏ธโโง๏ธ word | + โค๏ธ variant selecte^d | + {1:~ }|*3 + 2,23-19 All | + ]]) + + feed('0') + screen:expect([[ + ๐ณ๏ธโโง๏ธ word | + ^โค๏ธ variant selected | + {1:~ }|*3 + 2,1 All | + ]]) + + feed('l') + screen:expect([[ + ๐ณ๏ธโโง๏ธ word | + โค๏ธ^ variant selected | + {1:~ }|*3 + 2,7-3 All | + ]]) + + feed('h') + screen:expect([[ + ๐ณ๏ธโโง๏ธ word | + ^โค๏ธ variant selected | + {1:~ }|*3 + 2,1 All | + ]]) + + -- without selector: single width (note column 18 and not 19) + feed('oโค variant selected<esc>') + screen:expect([[ + ๐ณ๏ธโโง๏ธ word | + โค๏ธ variant selected | + โค variant selecte^d | + {1:~ }|*2 + 3,20-18 All | + ]]) + end) end) describe('multibyte rendering: statusline', function() @@ -348,11 +428,12 @@ describe('multibyte rendering: statusline', function() it('non-printable followed by MAX_MCO unicode combination points', function() command('set statusline=ยแทฐโฏฬธโโงโ') -- U+9F + U+1DF0 + U+20EF + U+0338 + U+20D0 + U+20E7 + U+20DD + -- TODO: not ideal, better with plain ">" and then space+combining screen:expect([[ - ^ | - {1:~ }| - {3:<9f><1df0><20ef><0338><20d0><20e7><20dd>}| - | + ^ | + {1:~ }| + {3:<9f>แทฐโฏฬธโโงโ }| + | ]]) end) @@ -368,9 +449,20 @@ describe('multibyte rendering: statusline', function() } end) - it('unprintable chars in filename with default stl', function() + it('emoji with ZWJ in filename with default stl', function() command('file ๐งโ๐ป') - -- TODO: this is wrong but avoids a crash + screen:expect { + grid = [[ + ^ | + {1:~ }| + {3:๐งโ๐ป }| + | + ]], + } + end) + + it('unprintable chars in filename with default stl', function() + command('file ๐งโ๐ป') screen:expect { grid = [[ ^ | @@ -381,15 +473,27 @@ describe('multibyte rendering: statusline', function() } end) - it('unprintable chars in filename with custom stl', function() + it('emoji with ZWJ in filename with custom stl', function() command('set statusline=xx%#ErrorMsg#%f%##yy') command('file ๐งโ๐ป') - -- TODO: this is also wrong but also avoids a crash screen:expect { grid = [[ ^ | {1:~ }| - {3:xx}{9:๐ง<200d>๐ป}{3:yy }| + {3:xx}{9:๐งโ๐ป}{3:yy }| + | + ]], + } + end) + + it('unprintable chars in filename with custom stl', function() + command('set statusline=xx%#ErrorMsg#%f%##yy') + command('file ๐งโ๐ป') + screen:expect { + grid = [[ + ^ | + {1:~ }| + {3:xx}{9:๐ง<200b>๐ป}{3:yy }| | ]], } diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua index dc48061a6c..e009ed0a29 100644 --- a/test/functional/ui/multigrid_spec.lua +++ b/test/functional/ui/multigrid_spec.lua @@ -1095,6 +1095,7 @@ describe('ext_multigrid', function() end) it('supports mouse', function() + command('autocmd! nvim_popupmenu') -- Delete the default MenuPopup event handler. insert('some text\nto be clicked') screen:expect{grid=[[ ## grid 1 @@ -2598,4 +2599,257 @@ describe('ext_multigrid', function() ]]) eq(1, api.nvim_get_option_value('cmdheight', {})) end) + + describe('centered cursorline', function() + before_each(function() + -- Force a centered cursorline, this caused some redrawing problems described in #30576. + -- Most importantly, win_viewport was not received in time, and sum_scroll_delta did not refresh. + command('set cursorline scrolloff=9999') + end) + it('insert line scrolls correctly', function() + for i = 1, 11 do + insert('line' .. i .. '\n') + end + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line1 | + line2 | + line3 | + line4 | + line5 | + line6 | + line7 | + line8 | + line9 | + line10 | + line11 | + {23:^ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 0, botline = 12, curline = 11, curcol = 0, linecount = 12, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + insert('line12\n') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line2 | + line3 | + line4 | + line5 | + line6 | + line7 | + line8 | + line9 | + line10 | + line11 | + line12 | + {23:^ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 1, botline = 13, curline = 12, curcol = 0, linecount = 13, sum_scroll_delta = 1}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + end) + + it('got to top scrolls correctly', function() + for i = 1, 20 do + insert('line' .. i .. '\n') + end + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line10 | + line11 | + line12 | + line13 | + line14 | + line15 | + line16 | + line17 | + line18 | + line19 | + line20 | + {23:^ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 9, botline = 21, curline = 20, curcol = 0, linecount = 21, sum_scroll_delta = 9}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + feed('gg') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + {23:^line1 }| + line2 | + line3 | + line4 | + line5 | + line6 | + line7 | + line8 | + line9 | + line10 | + line11 | + line12 | + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 21, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + end) + + it('scrolls in the middle', function() + for i = 1, 20 do + insert('line' .. i .. '\n') + end + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line10 | + line11 | + line12 | + line13 | + line14 | + line15 | + line16 | + line17 | + line18 | + line19 | + line20 | + {23:^ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 9, botline = 21, curline = 20, curcol = 0, linecount = 21, sum_scroll_delta = 9}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + feed('M') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line10 | + line11 | + line12 | + line13 | + line14 | + {23:^line15 }| + line16 | + line17 | + line18 | + line19 | + line20 | + | + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 9, botline = 21, curline = 14, curcol = 0, linecount = 21, sum_scroll_delta = 9}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + feed('k') + screen:expect({ + grid = [[ + ## grid 1 + [2:-----------------------------------------------------]|*12 + {11:[No Name] [+] }| + [3:-----------------------------------------------------]| + ## grid 2 + line9 | + line10 | + line11 | + line12 | + line13 | + {23:^line14 }| + line15 | + line16 | + line17 | + line18 | + line19 | + line20 | + ## grid 3 + | + ]], win_viewport={ + [2] = {win = 1000, topline = 8, botline = 21, curline = 13, curcol = 0, linecount = 21, sum_scroll_delta = 8}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + } + }}) + end) + end) end) diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua index 4f6454a0fb..220af06f53 100644 --- a/test/functional/ui/output_spec.lua +++ b/test/functional/ui/output_spec.lua @@ -1,7 +1,7 @@ local t = require('test.testutil') local n = require('test.functional.testnvim')() local Screen = require('test.functional.ui.screen') -local tt = require('test.functional.terminal.testutil') +local tt = require('test.functional.testterm') local assert_alive = n.assert_alive local mkdir, write_file, rmdir = t.mkdir, t.write_file, n.rmdir diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 8f8604eecb..f84362ede8 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -851,6 +851,8 @@ describe('ui/ext_popupmenu', function() set mouse=a mousemodel=popup aunmenu PopUp + " Delete the default MenuPopup event handler. + autocmd! nvim_popupmenu menu PopUp.foo :let g:menustr = 'foo'<CR> menu PopUp.bar :let g:menustr = 'bar'<CR> menu PopUp.baz :let g:menustr = 'baz'<CR> @@ -1129,7 +1131,7 @@ describe("builtin popupmenu 'pumblend'", function() [10] = { foreground = tonumber('0x000002') }, }) screen:attach({ rgb = false }) - command('set notermguicolors pumblend=10') + command('set pumblend=10') insert([[ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor @@ -1160,23 +1162,47 @@ describe('builtin popupmenu', function() screen = Screen.new(32, 20) screen:set_default_attr_ids({ -- popup selected item / scrollbar track - ['s'] = { background = Screen.colors.WebGray }, + s = { background = Screen.colors.Grey }, -- popup non-selected item - ['n'] = { background = Screen.colors.LightMagenta }, + n = { background = Screen.colors.Plum1 }, -- popup scrollbar knob - ['c'] = { background = Screen.colors.Grey0 }, + c = { background = Screen.colors.Black }, [1] = { bold = true, foreground = Screen.colors.Blue }, [2] = { bold = true }, [3] = { reverse = true }, [4] = { bold = true, reverse = true }, [5] = { bold = true, foreground = Screen.colors.SeaGreen }, - [6] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, + [6] = { foreground = Screen.colors.White, background = Screen.colors.Red }, [7] = { background = Screen.colors.Yellow }, -- Search [8] = { foreground = Screen.colors.Red }, - kn = { foreground = Screen.colors.Red, background = Screen.colors.Magenta }, ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey }, - xn = { foreground = Screen.colors.White, background = Screen.colors.Magenta }, + kn = { foreground = Screen.colors.Red, background = Screen.colors.Plum1 }, xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey }, + xn = { foreground = Screen.colors.White, background = Screen.colors.Plum1 }, + ms = { foreground = Screen.colors.Blue, background = Screen.colors.Grey }, + mn = { foreground = Screen.colors.Blue, background = Screen.colors.Plum1 }, + ds = { foreground = Screen.colors.DarkRed, background = Screen.colors.Grey }, + dn = { foreground = Screen.colors.DarkRed, background = Screen.colors.Plum1 }, + ums = { + foreground = Screen.colors.Blue, + background = Screen.colors.Grey, + underline = true, + }, + umn = { + foreground = Screen.colors.Blue, + background = Screen.colors.Plum1, + underline = true, + }, + uds = { + foreground = Screen.colors.DarkRed, + background = Screen.colors.Grey, + underline = true, + }, + udn = { + foreground = Screen.colors.DarkRed, + background = Screen.colors.Plum1, + underline = true, + }, }) screen:attach({ ext_multigrid = multigrid }) end) @@ -2528,6 +2554,7 @@ describe('builtin popupmenu', function() ]], } + -- oldtest: Test_wildmenu_pum_rightleft() feed('<tab>') screen:expect { grid = [[ @@ -2917,11 +2944,12 @@ describe('builtin popupmenu', function() feed('<C-U>sign define <Tab>') screen:expect([[ | - {1:~ }|*2 + {1:~ }| {1:~ }{s: culhl= }{1: }| {1:~ }{n: icon= }{1: }| {1:~ }{n: linehl= }{1: }| {1:~ }{n: numhl= }{1: }| + {1:~ }{n: priority= }{1: }| {1:~ }{n: text= }{1: }| {1:~ }{n: texthl= }{1: }| :sign define culhl=^ | @@ -2930,11 +2958,12 @@ describe('builtin popupmenu', function() feed('<Space><Tab>') screen:expect([[ | - {1:~ }|*2 + {1:~ }| {1:~ }{s: culhl= }{1: }| {1:~ }{n: icon= }{1: }| {1:~ }{n: linehl= }{1: }| {1:~ }{n: numhl= }{1: }| + {1:~ }{n: priority= }{1: }| {1:~ }{n: text= }{1: }| {1:~ }{n: texthl= }{1: }| :sign define culhl= culhl=^ | @@ -3547,6 +3576,66 @@ describe('builtin popupmenu', function() | ]]) end) + + -- oldtest: Test_wildmenu_pum_hl_match() + it('highlighting matched text in cmdline pum', function() + exec([[ + set wildoptions=pum,fuzzy + hi PmenuMatchSel guifg=Blue guibg=Grey + hi PmenuMatch guifg=Blue guibg=Plum1 + ]]) + + feed(':sign plc<Tab>') + screen:expect([[ + | + {1:~ }|*16 + {1:~ }{s: }{ms:pl}{s:a}{ms:c}{s:e }{1: }| + {1:~ }{n: un}{mn:pl}{n:a}{mn:c}{n:e }{1: }| + :sign place^ | + ]]) + feed('<Tab>') + screen:expect([[ + | + {1:~ }|*16 + {1:~ }{n: }{mn:pl}{n:a}{mn:c}{n:e }{1: }| + {1:~ }{s: un}{ms:pl}{s:a}{ms:c}{s:e }{1: }| + :sign unplace^ | + ]]) + feed('<Tab>') + screen:expect([[ + | + {1:~ }|*16 + {1:~ }{n: }{mn:pl}{n:a}{mn:c}{n:e }{1: }| + {1:~ }{n: un}{mn:pl}{n:a}{mn:c}{n:e }{1: }| + :sign plc^ | + ]]) + feed('<Esc>') + command('set wildoptions-=fuzzy') + feed(':sign un<Tab>') + screen:expect([[ + | + {1:~ }|*16 + {1:~ }{s: }{ms:un}{s:define }{1: }| + {1:~ }{n: }{mn:un}{n:place }{1: }| + :sign undefine^ | + ]]) + feed('<Tab>') + screen:expect([[ + | + {1:~ }|*16 + {1:~ }{n: }{mn:un}{n:define }{1: }| + {1:~ }{s: }{ms:un}{s:place }{1: }| + :sign unplace^ | + ]]) + feed('<Tab>') + screen:expect([[ + | + {1:~ }|*16 + {1:~ }{n: }{mn:un}{n:define }{1: }| + {1:~ }{n: }{mn:un}{n:place }{1: }| + :sign un^ | + ]]) + end) end it("'pumheight'", function() @@ -3718,6 +3807,8 @@ describe('builtin popupmenu', function() call setline(1, 'popup menu test') set mouse=a mousemodel=popup + " Delete the default MenuPopup event handler. + autocmd! nvim_popupmenu aunmenu PopUp menu PopUp.foo :let g:menustr = 'foo'<CR> menu PopUp.bar :let g:menustr = 'bar'<CR> @@ -4402,6 +4493,9 @@ describe('builtin popupmenu', function() -- oldtest: Test_popup_command_dump() it(':popup command', function() exec([[ + " Delete the default MenuPopup event handler. + autocmd! nvim_popupmenu + func ChangeMenu() aunmenu PopUp.&Paste nnoremenu 1.40 PopUp.&Paste :echomsg "pasted"<CR> @@ -4477,6 +4571,27 @@ describe('builtin popupmenu', function() feed('<Esc>') + command('set rightleft') + feed('/X<CR>:popup PopUp<CR>') + screen:expect([[ + evif ruof eerht owt eno| + evif ruof eerht{7:^X} owt eno dna| + {n: odnU }wt erom eno| + {1: }{n: }{1: ~}| + {1: }{n: etsaP }{1: ~}| + {1: }{n: }{1: ~}| + {1: }{n: droW tceleS }{1: ~}| + {1: }{n: ecnetneS tceleS }{1: ~}| + {1: }{n: hpargaraP tceleS }{1: ~}| + {1: }{n: eniL tceleS }{1: ~}| + {1: }{n: kcolB tceleS }{1: ~}| + {1: }{n: llA tceleS }{1: ~}| + {1: ~}|*7 + :popup PopUp | + ]]) + feed('<Esc>') + command('set norightleft') + -- Set an <expr> mapping to change a menu entry while it's displayed. -- The text should not change but the command does. -- Also verify that "changed" shows up, which means the mapping triggered. @@ -4533,6 +4648,57 @@ describe('builtin popupmenu', function() feed('<Esc>') end) + -- oldtest: Test_mouse_popup_position() + it('position of right-click menu when clicking near edge', function() + screen:try_resize(50, 20) + exec([[ + set mousemodel=popup_setpos + " Delete the default MenuPopup event handler. + autocmd! nvim_popupmenu + aunmenu * + source $VIMRUNTIME/menu.vim + call setline(1, join(range(20))) + ]]) + + api.nvim_input_mouse('right', 'press', '', 0, 0, 45 - 1) + screen:expect([[ + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ^18 19 | + {1:~ }{n: Undo }| + {1:~ }{n: }| + {1:~ }{n: Paste }| + {1:~ }{n: }| + {1:~ }{n: Select Word }| + {1:~ }{n: Select Sentence }| + {1:~ }{n: Select Paragraph}| + {1:~ }{n: Select Line }| + {1:~ }{n: Select Block }| + {1:~ }{n: Select All }| + {1:~ }|*8 + | + ]]) + feed('<Esc>') + + command('set rightleft') + api.nvim_input_mouse('right', 'press', '', 0, 0, 50 - 45) + screen:expect([[ + 91 8^1 71 61 51 41 31 21 11 01 9 8 7 6 5 4 3 2 1 0| + {n: odnU }{1: ~}| + {n: }{1: ~}| + {n: etsaP }{1: ~}| + {n: }{1: ~}| + {n: droW tceleS }{1: ~}| + {n: ecnetneS tceleS }{1: ~}| + {n:hpargaraP tceleS }{1: ~}| + {n: eniL tceleS }{1: ~}| + {n: kcolB tceleS }{1: ~}| + {n: llA tceleS }{1: ~}| + {1: ~}|*8 + | + ]]) + feed('<Esc>') + command('set norightleft') + end) + describe('"kind" and "menu"', function() before_each(function() screen:try_resize(30, 8) @@ -4569,9 +4735,9 @@ describe('builtin popupmenu', function() -- oldtest: Test_pum_highlights_custom() it('custom highlight groups', function() exec([[ - hi PmenuKind guifg=Red guibg=Magenta + hi PmenuKind guifg=Red guibg=Plum1 hi PmenuKindSel guifg=Red guibg=Grey - hi PmenuExtra guifg=White guibg=Magenta + hi PmenuExtra guifg=White guibg=Plum1 hi PmenuExtraSel guifg=Black guibg=Grey ]]) feed('iaw<C-X><C-u>') @@ -4585,6 +4751,443 @@ describe('builtin popupmenu', function() ]]) end) end) + + -- oldtest: Test_pum_highlights_match() + it('can highlight matched text', function() + exec([[ + func Omni_test(findstart, base) + if a:findstart + return col(".") + endif + return { + \ 'words': [ + \ { 'word': 'foo', 'kind': 'fookind' }, + \ { 'word': 'foofoo', 'kind': 'fookind' }, + \ { 'word': 'foobar', 'kind': 'fookind' }, + \ { 'word': 'fooBaz', 'kind': 'fookind' }, + \ { 'word': 'foobala', 'kind': 'fookind' }, + \ { 'word': 'ไฝ ๅฅฝ' }, + \ { 'word': 'ไฝ ๅฅฝๅ' }, + \ { 'word': 'ไฝ ไธๅฅฝๅ' }, + \ { 'word': 'ไฝ ๅฏๅฅฝๅ' }, + \]} + endfunc + + func Comp() + let col = col('.') + if getline('.') == 'f' + let col -= 1 + endif + call complete(col, [ + \ #{word: "foo", icase: 1}, + \ #{word: "Foobar", icase: 1}, + \ #{word: "fooBaz", icase: 1}, + \]) + return '' + endfunc + + set omnifunc=Omni_test + set completeopt=menu,noinsert,fuzzy + hi PmenuMatchSel guifg=Blue guibg=Grey + hi PmenuMatch guifg=Blue guibg=Plum1 + ]]) + feed('i<C-X><C-O>') + local pum_start = [[ + ^ | + {s:foo fookind }{1: }| + {n:foofoo fookind }{1: }| + {n:foobar fookind }{1: }| + {n:fooBaz fookind }{1: }| + {n:foobala fookind }{1: }| + {n:ไฝ ๅฅฝ }{1: }| + {n:ไฝ ๅฅฝๅ }{1: }| + {n:ไฝ ไธๅฅฝๅ }{1: }| + {n:ไฝ ๅฏๅฅฝๅ }{1: }| + {1:~ }|*9 + {2:-- }{5:match 1 of 9} | + ]] + screen:expect(pum_start) + feed('fo') + screen:expect([[ + fo^ | + {ms:fo}{s:o fookind }{1: }| + {mn:fo}{n:ofoo fookind }{1: }| + {mn:fo}{n:obar fookind }{1: }| + {mn:fo}{n:oBaz fookind }{1: }| + {mn:fo}{n:obala fookind }{1: }| + {1:~ }|*13 + {2:-- }{5:match 1 of 9} | + ]]) + feed('<Esc>S<C-X><C-O>') + screen:expect(pum_start) + feed('ไฝ ') + screen:expect([[ + ไฝ ^ | + {ms:ไฝ }{s:ๅฅฝ }{1: }| + {mn:ไฝ }{n:ๅฅฝๅ }{1: }| + {mn:ไฝ }{n:ไธๅฅฝๅ }{1: }| + {mn:ไฝ }{n:ๅฏๅฅฝๅ }{1: }| + {1:~ }|*14 + {2:-- }{5:match 1 of 9} | + ]]) + feed('ๅ') + screen:expect([[ + ไฝ ๅ^ | + {ms:ไฝ }{s:ๅฅฝ}{ms:ๅ}{s: }{1: }| + {mn:ไฝ }{n:ไธๅฅฝ}{mn:ๅ}{n: }{1: }| + {mn:ไฝ }{n:ๅฏๅฅฝ}{mn:ๅ}{n: }{1: }| + {1:~ }|*15 + {2:-- }{5:match 1 of 9} | + ]]) + feed('<C-E><Esc>') + + command('set rightleft') + feed('S<C-X><C-O>') + local pum_start_rl = [[ + ^ | + {1: }{s: dnikoof oof}| + {1: }{n: dnikoof oofoof}| + {1: }{n: dnikoof raboof}| + {1: }{n: dnikoof zaBoof}| + {1: }{n: dnikoof alaboof}| + {1: }{n: ๅฅฝไฝ }| + {1: }{n: ๅๅฅฝไฝ }| + {1: }{n: ๅๅฅฝไธไฝ }| + {1: }{n: ๅๅฅฝๅฏไฝ }| + {1: ~}|*9 + {2:-- }{5:match 1 of 9} | + ]] + screen:expect(pum_start_rl) + feed('fo') + screen:expect([[ + ^ of| + {1: }{s: dnikoof o}{ms:of}| + {1: }{n: dnikoof oofo}{mn:of}| + {1: }{n: dnikoof rabo}{mn:of}| + {1: }{n: dnikoof zaBo}{mn:of}| + {1: }{n: dnikoof alabo}{mn:of}| + {1: ~}|*13 + {2:-- }{5:match 1 of 9} | + ]]) + feed('<Esc>S<C-X><C-O>') + screen:expect(pum_start_rl) + feed('ไฝ ') + screen:expect([[ + ^ ไฝ | + {1: }{s: ๅฅฝ}{ms:ไฝ }| + {1: }{n: ๅๅฅฝ}{mn:ไฝ }| + {1: }{n: ๅๅฅฝไธ}{mn:ไฝ }| + {1: }{n: ๅๅฅฝๅฏ}{mn:ไฝ }| + {1: ~}|*14 + {2:-- }{5:match 1 of 9} | + ]]) + feed('ๅ') + screen:expect([[ + ^ ๅไฝ | + {1: }{s: }{ms:ๅ}{s:ๅฅฝ}{ms:ไฝ }| + {1: }{n: }{mn:ๅ}{n:ๅฅฝไธ}{mn:ไฝ }| + {1: }{n: }{mn:ๅ}{n:ๅฅฝๅฏ}{mn:ไฝ }| + {1: ~}|*15 + {2:-- }{5:match 1 of 9} | + ]]) + feed('<C-E><Esc>') + command('set norightleft') + + command('set completeopt-=fuzzy') + feed('S<C-X><C-O>') + screen:expect(pum_start) + feed('fo') + screen:expect([[ + fo^ | + {ms:fo}{s:o fookind }{1: }| + {mn:fo}{n:ofoo fookind }{1: }| + {mn:fo}{n:obar fookind }{1: }| + {mn:fo}{n:oBaz fookind }{1: }| + {mn:fo}{n:obala fookind }{1: }| + {1:~ }|*13 + {2:-- }{5:match 1 of 9} | + ]]) + feed('<C-E><Esc>') + + command('set rightleft') + feed('S<C-X><C-O>') + screen:expect(pum_start_rl) + feed('fo') + screen:expect([[ + ^ of| + {1: }{s: dnikoof o}{ms:of}| + {1: }{n: dnikoof oofo}{mn:of}| + {1: }{n: dnikoof rabo}{mn:of}| + {1: }{n: dnikoof zaBo}{mn:of}| + {1: }{n: dnikoof alabo}{mn:of}| + {1: ~}|*13 + {2:-- }{5:match 1 of 9} | + ]]) + feed('<C-E><Esc>') + command('set norightleft') + + feed('S<C-R>=Comp()<CR>f') + screen:expect([[ + f^ | + {ms:f}{s:oo }{1: }| + {mn:F}{n:oobar }{1: }| + {mn:f}{n:ooBaz }{1: }| + {1:~ }|*15 + {2:-- INSERT --} | + ]]) + feed('o<BS><C-R>=Comp()<CR>') + screen:expect_unchanged(true) + + feed('<Esc>') + command('set completeopt+=fuzzy,menu') + feed('S hello helio hero h<C-X><C-P>') + screen:expect([[ + hello helio hero h^ | + {1:~ }{n: }{mn:h}{n:ello }{1: }| + {1:~ }{n: }{mn:h}{n:elio }{1: }| + {1:~ }{s: }{ms:h}{s:ero }{1: }| + {1:~ }|*15 + {2:-- }{5:match 1 of 3} | + ]]) + + feed('<Esc>S hello helio hero h<C-X><C-P><C-P>') + screen:expect([[ + hello helio hero h^ | + {1:~ }{n: }{mn:h}{n:ello }{1: }| + {1:~ }{s: }{ms:h}{s:elio }{1: }| + {1:~ }{n: }{mn:h}{n:ero }{1: }| + {1:~ }|*15 + {2:-- }{5:match 2 of 3} | + ]]) + + feed('<C-E><Esc>') + end) + + -- oldtest: Test_pum_user_hl_group() + it('custom hl_group override', function() + exec([[ + func CompleteFunc( findstart, base ) + if a:findstart + return 0 + endif + return { + \ 'words': [ + \ { 'word': 'aword1', 'menu': 'extra text 1', 'kind': 'W', 'hl_group': 'StrikeFake' }, + \ { 'word': 'aword2', 'menu': 'extra text 2', 'kind': 'W', }, + \ { 'word': 'ไฝ ๅฅฝ', 'menu': 'extra text 3', 'kind': 'W', 'hl_group': 'StrikeFake' }, + \]} + endfunc + set completeopt=menu + set completefunc=CompleteFunc + + hi StrikeFake guifg=DarkRed + func HlMatch() + hi PmenuMatchSel guifg=Blue guibg=Grey gui=underline + hi PmenuMatch guifg=Blue guibg=Plum1 gui=underline + endfunc + ]]) + + feed('Saw<C-X><C-U>') + screen:expect([[ + aword1^ | + {ds:aword1 W extra text 1 }{1: }| + {n:aword2 W extra text 2 }{1: }| + {dn:ไฝ ๅฅฝ W extra text 3 }{1: }| + {1:~ }|*15 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-E><Esc>') + + command('call HlMatch()') + + feed('Saw<C-X><C-U>') + screen:expect([[ + aword1^ | + {uds:aw}{ds:ord1 W extra text 1 }{1: }| + {umn:aw}{n:ord2 W extra text 2 }{1: }| + {dn:ไฝ ๅฅฝ W extra text 3 }{1: }| + {1:~ }|*15 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-N>') + screen:expect([[ + aword2^ | + {udn:aw}{dn:ord1 W extra text 1 }{1: }| + {ums:aw}{s:ord2 W extra text 2 }{1: }| + {dn:ไฝ ๅฅฝ W extra text 3 }{1: }| + {1:~ }|*15 + {2:-- }{5:match 2 of 3} | + ]]) + feed('<C-E><Esc>') + end) + + -- oldtest: Test_pum_user_kind_hlgroup() + it('custom kind_hlgroup override', function() + exec([[ + func CompleteFunc( findstart, base ) + if a:findstart + return 0 + endif + return { + \ 'words': [ + \ { 'word': 'aword1', 'menu': 'extra text 1', 'kind': 'variable', 'kind_hlgroup': 'KindVar', 'hl_group': 'StrikeFake' }, + \ { 'word': 'aword2', 'menu': 'extra text 2', 'kind': 'function', 'kind_hlgroup': 'KindFunc' }, + \ { 'word': 'ไฝ ๅฅฝ', 'menu': 'extra text 3', 'kind': 'class', 'kind_hlgroup': 'KindClass' }, + \]} + endfunc + set completeopt=menu + set completefunc=CompleteFunc + + hi StrikeFake guifg=DarkRed + hi KindVar guifg=DarkYellow + hi KindFunc guifg=DarkBlue + hi KindClass guifg=DarkGreen + ]]) + + local attr_ids = screen:get_default_attr_ids() + attr_ids.kvs = { foreground = Screen.colors.DarkYellow, background = Screen.colors.Grey } + attr_ids.kfn = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Plum1 } + attr_ids.kcn = { foreground = Screen.colors.DarkGreen, background = Screen.colors.Plum1 } + screen:set_default_attr_ids(attr_ids) + + feed('S<C-X><C-U>') + screen:expect([[ + aword1^ | + {ds:aword1 }{kvs:variable }{ds:extra text 1 }{1: }| + {n:aword2 }{kfn:function }{n:extra text 2 }{1: }| + {n:ไฝ ๅฅฝ }{kcn:class }{n:extra text 3 }{1: }| + {1:~ }|*15 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-E><Esc>') + end) + + -- oldtest: Test_pum_completeitemalign() + it('completeitemalign option', function() + screen:try_resize(30, 15) + exec([[ + func Omni_test(findstart, base) + if a:findstart + return col(".") + endif + return { + \ 'words': [ + \ { 'word': 'foo', 'kind': 'S', 'menu': 'menu' }, + \ { 'word': 'bar', 'kind': 'T', 'menu': 'menu' }, + \ { 'word': 'ไฝ ๅฅฝ', 'kind': 'C', 'menu': 'ไธญๆ' }, + \]} + endfunc + + func Omni_long(findstart, base) + if a:findstart + return col(".") + endif + return { + \ 'words': [ + \ { 'word': 'loooong_foo', 'kind': 'S', 'menu': 'menu' }, + \ { 'word': 'loooong_bar', 'kind': 'T', 'menu': 'menu' }, + \]} + endfunc + set omnifunc=Omni_test + ]]) + -- T1 + command('set cia=abbr,kind,menu') + feed('S<C-X><C-O>') + screen:expect([[ + foo^ | + {s:foo S menu }{1: }| + {n:bar T menu }{1: }| + {n:ไฝ ๅฅฝ C ไธญๆ }{1: }| + {1:~ }|*10 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-E><ESC>') + -- T2 + command('set cia=abbr,menu,kind') + feed('S<C-X><C-O>') + screen:expect([[ + foo^ | + {s:foo menu S }{1: }| + {n:bar menu T }{1: }| + {n:ไฝ ๅฅฝ ไธญๆ C }{1: }| + {1:~ }|*10 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-E><ESC>') + -- T3 + command('set cia=kind,abbr,menu') + feed('S<C-X><C-O>') + screen:expect([[ + foo^ | + {s:S foo menu }{1: }| + {n:T bar menu }{1: }| + {n:C ไฝ ๅฅฝ ไธญๆ }{1: }| + {1:~ }|*10 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-E><ESC>') + -- T4 + command('set cia=kind,menu,abbr') + feed('S<C-X><C-O>') + screen:expect([[ + foo^ | + {s:S menu foo }{1: }| + {n:T menu bar }{1: }| + {n:C ไธญๆ ไฝ ๅฅฝ }{1: }| + {1:~ }|*10 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-E><ESC>') + -- T5 + command('set cia=menu,abbr,kind') + feed('S<C-X><C-O>') + screen:expect([[ + foo^ | + {s:menu foo S }{1: }| + {n:menu bar T }{1: }| + {n:ไธญๆ ไฝ ๅฅฝ C }{1: }| + {1:~ }|*10 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-E><ESC>') + -- T6 + command('set cia=menu,kind,abbr') + feed('S<C-X><C-O>') + screen:expect([[ + foo^ | + {s:menu S foo }{1: }| + {n:menu T bar }{1: }| + {n:ไธญๆ C ไฝ ๅฅฝ }{1: }| + {1:~ }|*10 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-E><ESC>') + -- T7 + command('set cia&') + feed('S<C-X><C-O>') + screen:expect([[ + foo^ | + {s:foo S menu }{1: }| + {n:bar T menu }{1: }| + {n:ไฝ ๅฅฝ C ไธญๆ }{1: }| + {1:~ }|*10 + {2:-- }{5:match 1 of 3} | + ]]) + feed('<C-E><ESC>') + + -- Test_pum_completeitemalign_07 + command('set cia=menu,kind,abbr columns=12 cmdheight=2 omnifunc=Omni_long') + feed('S<C-X><C-O>') + screen:expect([[ + loooong_foo^ | + {s:menu S loooo}| + {n:menu T loooo}| + {1:~ }|*10 + | + {2:--} | + ]]) + feed('<C-E><ESC>') + end) end end diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 4625ce8553..f1891b608e 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -255,6 +255,7 @@ end function Screen:set_default_attr_ids(attr_ids) self._default_attr_ids = attr_ids + self._attrs_overridden = true end function Screen:add_extra_attr_ids(extra_attr_ids) @@ -437,7 +438,7 @@ end --- @field mouse_enabled? boolean --- --- @field win_viewport? table<integer,table<string,integer>> ---- @field float_pos? {[1]:integer,[2]:integer} +--- @field float_pos? [integer,integer] --- @field hl_groups? table<string,integer> --- --- The following keys should be used to expect the state of various ext_ @@ -699,9 +700,9 @@ screen:redraw_debug() to show all intermediate screen states.]] end, expected) end -function Screen:expect_unchanged(intermediate, waittime_ms, ignore_attrs) +function Screen:expect_unchanged(intermediate, waittime_ms) -- Collect the current screen state. - local kwargs = self:get_snapshot(nil, ignore_attrs) + local kwargs = self:get_snapshot() if intermediate then kwargs.intermediate = true @@ -787,7 +788,9 @@ function Screen:_wait(check, flags) end local eof = run_session(self._session, flags.request_cb, notification_cb, nil, minimal_timeout) if not did_flush then - err = 'no flush received' + if eof then + err = 'no flush received' + end elseif not checked then err = check() if not err and flags.unchanged then @@ -800,6 +803,9 @@ function Screen:_wait(check, flags) did_minimal_timeout = true eof = run_session(self._session, flags.request_cb, notification_cb, nil, timeout - minimal_timeout) + if not did_flush then + err = 'no flush received' + end end local did_warn = false @@ -1536,13 +1542,14 @@ end -- Use snapshot_util({}) to generate a text-only (no attributes) test. -- -- @see Screen:redraw_debug() -function Screen:snapshot_util(attrs, ignore, request_cb) +function Screen:snapshot_util(request_cb) + -- TODO: simplify this later when existing tests have been updated self:sleep(250, request_cb) - self:print_snapshot(attrs, ignore) + self:print_snapshot() end -function Screen:redraw_debug(attrs, ignore, timeout) - self:print_snapshot(attrs, ignore) +function Screen:redraw_debug(timeout) + self:print_snapshot() local function notification_cb(method, args) assert(method == 'redraw') for _, update in ipairs(args) do @@ -1552,7 +1559,7 @@ function Screen:redraw_debug(attrs, ignore, timeout) end end self:_redraw(args) - self:print_snapshot(attrs, ignore) + self:print_snapshot() return true end if timeout == nil then @@ -1596,23 +1603,12 @@ end -- Returns the current screen state in the form of a screen:expect() -- keyword-args map. -function Screen:get_snapshot(attrs, ignore) - if ignore == nil then - ignore = self._default_attr_ignore - end +function Screen:get_snapshot() local attr_state = { ids = {}, - ignore = ignore, mutable = true, -- allow _row_repr to add missing highlights } - if attrs == nil then - attrs = self._default_attr_ids - elseif isempty(attrs) then - attrs = nil - attr_state.ids = nil - else - attr_state.modified = true - end + local attrs = self._default_attr_ids if attrs ~= nil then for i, a in pairs(attrs) do @@ -1708,9 +1704,10 @@ local function fmt_ext_state(name, state) end end -function Screen:_print_snapshot(attrs, ignore) - local kwargs, ext_state, attr_state = self:get_snapshot(attrs, ignore) +function Screen:_print_snapshot() + local kwargs, ext_state, attr_state = self:get_snapshot() local attrstr = '' + local modify_attrs = not self._attrs_overridden if attr_state.modified then local attrstrs = {} for i, a in pairs(attr_state.ids) do @@ -1721,16 +1718,20 @@ function Screen:_print_snapshot(attrs, ignore) dict = '{ ' .. self:_pprint_attrs(a) .. ' }' end local keyval = (type(i) == 'number') and '[' .. tostring(i) .. ']' or i - table.insert(attrstrs, ' ' .. keyval .. ' = ' .. dict .. ',') + if not (type(i) == 'number' and modify_attrs and i <= 30) then + table.insert(attrstrs, ' ' .. keyval .. ' = ' .. dict .. ',') + end + if modify_attrs then + self._default_attr_ids = attr_state.ids + end end - attrstr = (',\n attr_ids = {\n ' .. table.concat(attrstrs, '\n ') .. '\n },') - elseif isempty(attrs) then - attrstr = ',\n attr_ids = {},' + local fn_name = modify_attrs and 'add_extra_attr_ids' or 'set_default_attr_ids' + attrstr = ('screen:' .. fn_name .. ' {\n' .. table.concat(attrstrs, '\n') .. '\n}\n\n') end - local result = ('screen:expect({\n grid = [[\n %s\n ]]%s'):format( - kwargs.grid:gsub('\n', '\n '), - attrstr + local result = ('%sscreen:expect({\n grid = [[\n %s\n ]]'):format( + attrstr, + kwargs.grid:gsub('\n', '\n ') ) for _, k in ipairs(ext_keys) do if ext_state[k] ~= nil and not (k == 'win_viewport' and not self.options.ext_multigrid) then @@ -1742,8 +1743,8 @@ function Screen:_print_snapshot(attrs, ignore) return result end -function Screen:print_snapshot(attrs, ignore) - print('\n' .. self:_print_snapshot(attrs, ignore) .. '\n') +function Screen:print_snapshot() + print('\n' .. self:_print_snapshot() .. '\n') io.stdout:flush() end diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index 54580bf47c..85a653df36 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -4,6 +4,7 @@ local Screen = require('test.functional.ui.screen') local spawn, set_session, clear = n.spawn, n.set_session, n.clear local feed, command = n.feed, n.command +local exec = n.exec local insert = n.insert local eq = t.eq local fn, api = n.fn, n.api @@ -819,3 +820,39 @@ it("showcmd doesn't cause empty grid_line with redrawdebug=compositor #22593", f ]], } end) + +it("scrolling in narrow window doesn't draw over separator #29033", function() + clear() + local screen = Screen.new(60, 8) + screen:attach() + feed('100Oa<Esc>gg') + exec([[ + set number nowrap + vsplit + set scrollbind + wincmd l + set scrollbind + wincmd | + ]]) + screen:expect([[ + {8: }โ{8: 1 }^a | + {8: }โ{8: 2 }a | + {8: }โ{8: 3 }a | + {8: }โ{8: 4 }a | + {8: }โ{8: 5 }a | + {8: }โ{8: 6 }a | + {2:< }{3:[No Name] [+] }| + | + ]]) + feed('<C-F>') + screen:expect([[ + {8: }โ{8: 5 }^a | + {8: }โ{8: 6 }a | + {8: }โ{8: 7 }a | + {8: }โ{8: 8 }a | + {8: }โ{8: 9 }a | + {8: }โ{8: 10 }a | + {2:< }{3:[No Name] [+] }| + | + ]]) +end) diff --git a/test/functional/ui/scrollbind_spec.lua b/test/functional/ui/scrollbind_spec.lua new file mode 100644 index 0000000000..9e70b25efa --- /dev/null +++ b/test/functional/ui/scrollbind_spec.lua @@ -0,0 +1,442 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local clear = n.clear +local Screen = require('test.functional.ui.screen') + +before_each(clear) + +describe('Scrollbind', function() + local screen --- @type test.functional.ui.screen + + before_each(function() + screen = Screen.new(40, 12) + screen:attach() + end) + + it('works with one buffer with virtual lines', function() + n.exec_lua(function() + local lines = {} --- @type string[] + + for i = 1, 20 do + lines[i] = tostring(i * 2 - 1) + end + + local ns = vim.api.nvim_create_namespace('test') + + vim.api.nvim_buf_set_lines(0, 0, -1, false, lines) + vim.bo.buftype = 'nofile' + + for i in ipairs(lines) do + vim.api.nvim_buf_set_extmark(0, ns, i - 1, 0, { + virt_lines = { { { tostring(2 * i) .. ' v' } } }, + }) + end + + vim.wo.scrollbind = true + vim.cmd.vsplit() + vim.wo.scrollbind = true + end) + + n.feed('<C-d>') + + t.eq(5, n.api.nvim_get_option_value('scroll', {})) + + screen:expect({ + grid = [[ + 6 v โ6 v | + 7 โ7 | + 8 v โ8 v | + 9 โ9 | + 10 v โ10 v | + ^11 โ11 | + 12 v โ12 v | + 13 โ13 | + 14 v โ14 v | + 15 โ15 | + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('<C-u>') + + local line1_grid = [[ + ^1 โ1 | + 2 v โ2 v | + 3 โ3 | + 4 v โ4 v | + 5 โ5 | + 6 v โ6 v | + 7 โ7 | + 8 v โ8 v | + 9 โ9 | + 10 v โ10 v | + {3:[Scratch] }{2:[Scratch] }| + | + ]] + + screen:expect({ grid = line1_grid }) + + n.api.nvim_set_option_value('scroll', 6, {}) + + n.feed('<C-d>') + + screen:expect({ + grid = [[ + 7 โ7 | + 8 v โ8 v | + 9 โ9 | + 10 v โ10 v | + 11 โ11 | + 12 v โ12 v | + ^13 โ13 | + 14 v โ14 v | + 15 โ15 | + 16 v โ16 v | + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('<C-u>') + + screen:expect({ grid = line1_grid }) + end) + + it('works with two buffers with virtual lines on one side', function() + n.exec_lua(function() + local lines = {} --- @type string[] + + for i = 1, 20 do + lines[i] = tostring(i) + end + + local ns = vim.api.nvim_create_namespace('test') + + vim.api.nvim_buf_set_lines(0, 0, -1, false, lines) + vim.bo.buftype = 'nofile' + + vim.wo.scrollbind = true + vim.cmd.vnew() + + lines = {} --- @type string[] + + for i = 1, 20 do + lines[i] = tostring(i + (i > 3 and 4 or 0)) + end + vim.api.nvim_buf_set_lines(0, 0, -1, false, lines) + vim.bo.buftype = 'nofile' + + vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { + virt_lines = { + { { '4 v' } }, + { { '5 v' } }, + { { '6 v' } }, + { { '7 v' } }, + }, + }) + + vim.wo.scrollbind = true + end) + + n.feed('<C-d>') + + t.eq(5, n.api.nvim_get_option_value('scroll', {})) + + screen:expect({ + grid = [[ + 6 v โ6 | + 7 v โ7 | + 8 โ8 | + 9 โ9 | + ^10 โ10 | + 11 โ11 | + 12 โ12 | + 13 โ13 | + 14 โ14 | + 15 โ15 | + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('<C-u>') + + local line1_grid = [[ + ^1 โ1 | + 2 โ2 | + 3 โ3 | + 4 v โ4 | + 5 v โ5 | + 6 v โ6 | + 7 v โ7 | + 8 โ8 | + 9 โ9 | + 10 โ10 | + {3:[Scratch] }{2:[Scratch] }| + | + ]] + + screen:expect({ grid = line1_grid }) + + n.api.nvim_set_option_value('scroll', 6, {}) + + n.feed('<C-d>') + + screen:expect({ + grid = [[ + 7 v โ7 | + 8 โ8 | + 9 โ9 | + 10 โ10 | + ^11 โ11 | + 12 โ12 | + 13 โ13 | + 14 โ14 | + 15 โ15 | + 16 โ16 | + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('<C-u>') + + screen:expect({ grid = line1_grid }) + + -- Note: not the same as n.feed('4<C-e>') + n.feed('<C-e>') + n.feed('<C-e>') + n.feed('<C-e>') + n.feed('<C-e>') + + screen:expect({ + grid = [[ + 5 v โ5 | + 6 v โ6 | + 7 v โ7 | + ^8 โ8 | + 9 โ9 | + 10 โ10 | + 11 โ11 | + 12 โ12 | + 13 โ13 | + 14 โ14 | + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('<C-e>') + + screen:expect({ + grid = [[ + 6 v โ6 | + 7 v โ7 | + ^8 โ8 | + 9 โ9 | + 10 โ10 | + 11 โ11 | + 12 โ12 | + 13 โ13 | + 14 โ14 | + 15 โ15 | + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('<C-y>') + n.feed('<C-y>') + + screen:expect({ + grid = [[ + 4 v โ4 | + 5 v โ5 | + 6 v โ6 | + 7 v โ7 | + ^8 โ8 | + 9 โ9 | + 10 โ10 | + 11 โ11 | + 12 โ12 | + 13 โ13 | + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + end) + + it('works with buffers of different lengths', function() + n.exec_lua(function() + vim.api.nvim_buf_set_lines(0, 0, -1, false, { '1', '2', '3' }) + vim.bo.buftype = 'nofile' + + vim.wo.scrollbind = true + vim.cmd.vnew() + + local lines = {} --- @type string[] + + for i = 1, 50 do + lines[i] = tostring(i) + end + + vim.api.nvim_buf_set_lines(0, 0, -1, false, lines) + vim.bo.buftype = 'nofile' + vim.wo.scrollbind = true + end) + + n.feed('10<C-e>') + + screen:expect({ + grid = [[ + ^11 โ3 | + 12 โ{1:~ }| + 13 โ{1:~ }| + 14 โ{1:~ }| + 15 โ{1:~ }| + 16 โ{1:~ }| + 17 โ{1:~ }| + 18 โ{1:~ }| + 19 โ{1:~ }| + 20 โ{1:~ }| + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('<C-y>') + + screen:expect({ + grid = [[ + 10 โ3 | + ^11 โ{1:~ }| + 12 โ{1:~ }| + 13 โ{1:~ }| + 14 โ{1:~ }| + 15 โ{1:~ }| + 16 โ{1:~ }| + 17 โ{1:~ }| + 18 โ{1:~ }| + 19 โ{1:~ }| + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + end) + + it('works with buffers of different lengths and virtual lines', function() + n.exec_lua(function() + vim.api.nvim_buf_set_lines(0, 0, -1, false, { '1', '5', '6' }) + + local ns = vim.api.nvim_create_namespace('test') + vim.api.nvim_buf_set_extmark(0, ns, 0, 0, { + virt_lines = { + { { '2 v' } }, + { { '3 v' } }, + { { '4 v' } }, + }, + }) + + vim.bo.buftype = 'nofile' + + vim.wo.scrollbind = true + vim.cmd.vnew() + + local lines = {} --- @type string[] + + for i = 1, 50 do + lines[i] = tostring(i) + end + + vim.api.nvim_buf_set_lines(0, 0, -1, false, lines) + vim.bo.buftype = 'nofile' + vim.wo.scrollbind = true + end) + + n.feed('<C-e>') + n.feed('<C-e>') + screen:expect({ + grid = [[ + ^3 โ3 v | + 4 โ4 v | + 5 โ5 | + 6 โ6 | + 7 โ{1:~ }| + 8 โ{1:~ }| + 9 โ{1:~ }| + 10 โ{1:~ }| + 11 โ{1:~ }| + 12 โ{1:~ }| + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('8<C-e>') + + screen:expect({ + grid = [[ + ^11 โ6 | + 12 โ{1:~ }| + 13 โ{1:~ }| + 14 โ{1:~ }| + 15 โ{1:~ }| + 16 โ{1:~ }| + 17 โ{1:~ }| + 18 โ{1:~ }| + 19 โ{1:~ }| + 20 โ{1:~ }| + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('<C-y>') + n.feed('<C-y>') + n.feed('<C-y>') + n.feed('<C-y>') + n.feed('<C-y>') + + t.eq(n.exec_lua [[return vim.fn.line('w0', 1001)]], 6) + t.eq(n.exec_lua [[return vim.fn.line('w0', 1000)]], 3) + + screen:expect({ + grid = [[ + 6 โ6 | + 7 โ{1:~ }| + 8 โ{1:~ }| + 9 โ{1:~ }| + 10 โ{1:~ }| + ^11 โ{1:~ }| + 12 โ{1:~ }| + 13 โ{1:~ }| + 14 โ{1:~ }| + 15 โ{1:~ }| + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + + n.feed('<C-y>') + n.feed('<C-y>') + n.feed('<C-y>') + + screen:expect({ + grid = [[ + 3 โ3 v | + 4 โ4 v | + 5 โ5 | + 6 โ6 | + 7 โ{1:~ }| + 8 โ{1:~ }| + 9 โ{1:~ }| + 10 โ{1:~ }| + ^11 โ{1:~ }| + 12 โ{1:~ }| + {3:[Scratch] }{2:[Scratch] }| + | + ]], + }) + end) +end) diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua index 8bdf528412..eab265cbb1 100644 --- a/test/functional/ui/searchhl_spec.lua +++ b/test/functional/ui/searchhl_spec.lua @@ -197,7 +197,8 @@ describe('search highlighting', function() } end) - it('works for multiline match', function() + -- oldtest: Test_hlsearch_cursearch() + it('works for multiline match, no duplicate highlight', function() command([[call setline(1, ['one', 'foo', 'bar', 'baz', 'foo the foo and foo', 'bar'])]]) feed('gg/foo<CR>') screen:expect([[ @@ -281,6 +282,28 @@ describe('search highlighting', function() {2:hij}kl | /efg\nhij | ]]) + + -- check clearing CurSearch when using it for another match + feed('G?^abcd<CR>Y') + screen:expect([[ + --- | + {1:abcd}efg | + hijkl | + --- | + {2:^abcd}efg | + hijkl | + ?^abcd | + ]]) + feed('kkP') + screen:expect([[ + --- | + {1:abcd}efg | + {2:^abcd}efg | + hijkl | + --- | + {1:abcd}efg | + ?^abcd | + ]]) end) end) @@ -345,12 +368,19 @@ describe('search highlighting', function() bar baz foo bar foo baz]]) feed('/foo') + screen:set_default_attr_ids({ + [1] = { bold = true, foreground = Screen.colors.Blue }, + [2] = { background = Screen.colors.Yellow }, -- Search + [3] = { reverse = true }, + [4] = { bold = true, reverse = true }, + [5] = { foreground = Screen.colors.White, background = Screen.colors.DarkGreen }, + }) screen:expect([[ {3:foo} bar baz โ{MATCH:%d+}: {2:foo}{MATCH:%s+}| bar baz {2:foo} โ{MATCH:%d+}: {2:foo}{MATCH:%s+}| bar {2:foo} baz โ{MATCH:%d+}: {2:foo}{MATCH:%s+}| {1:~ }โ{MATCH:.*}|*2 - {5:[No Name] [+] }{3:term }| + {4:[No Name] [+] }{5:term }| /foo^ | ]]) end) diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index b353b3738a..30da79af47 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -4,6 +4,7 @@ local Screen = require('test.functional.ui.screen') local api, clear, eq = n.api, n.clear, t.eq local eval, exec, feed = n.eval, n.exec, n.feed +local exec_lua = n.exec_lua describe('Signs', function() local screen @@ -577,4 +578,45 @@ describe('Signs', function() ]]) eq({}, eval('sign_getdefined()')) end) + + it('no crash when unplacing signs beyond end of buffer', function() + exec([[ + sign define S1 text=S1 + sign define S2 text=S2 + sign place 1 line=8 name=S1 + sign place 2 line=9 name=S2 + ]]) + -- Now placed at end of buffer + local s1 = { + grid = [[ + S2^ | + {0:~ }|*12 + | + ]], + } + screen:expect(s1) + -- Signcolumn tracking used to not count signs placed beyond end of buffer here + exec('set signcolumn=auto:9') + screen:expect({ + grid = [[ + S2S1^ | + {0:~ }|*12 + | + ]], + }) + -- Unplacing the sign does not crash by decrementing tracked signs below zero + exec('sign unplace 1') + screen:expect(s1) + end) + + it('signcolumn width is set immediately after splitting window #30547', function() + local infos = exec_lua([[ + vim.o.number = true + vim.o.signcolumn = 'yes' + vim.cmd.wincmd('v') + return vim.fn.getwininfo() + ]]) + eq(6, infos[1].textoff) + eq(6, infos[2].textoff) + end) end) diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua index faf94bccbe..b4d4c94a5e 100644 --- a/test/functional/ui/statuscolumn_spec.lua +++ b/test/functional/ui/statuscolumn_spec.lua @@ -91,49 +91,87 @@ describe('statuscolumn', function() {8:2 }aaaaa | | ]]) + -- Doesn't crash when clicking inside padded area without click_defs + command('set numberwidth=10') + api.nvim_input_mouse('left', 'press', '', 0, 0, 5) + assert_alive() end) it("works with 'number' and 'relativenumber'", function() - command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}โ]]) - screen:expect([[ - {8:4 โ}aaaaa | - {8:5 โ}aaaaa | - {8:6 โ}aaaaa | - {8:7 โ}aaaaa | - {8:8 โ}^aaaaa | - {8:9 โ}aaaaa | - {8:10โ}aaaaa | - {8:11โ}aaaaa | - {8:12โ}aaaaa | - {8:13โ}aaaaa | - {8:14โ}aaaaa | - {8:15โ}aaaaa | - {8:16โ}aaaaa | - | - ]]) - command([[set stc=%l%=%{&rnu?'\ ':''}%rโ]]) + screen:expect([[ + {8: 4 }aaaaa | + {8: 5 }aaaaa | + {8: 6 }aaaaa | + {8: 7 }aaaaa | + {8: 8 }^aaaaa | + {8: 9 }aaaaa | + {8:10 }aaaaa | + {8:11 }aaaaa | + {8:12 }aaaaa | + {8:13 }aaaaa | + {8:14 }aaaaa | + {8:15 }aaaaa | + {8:16 }aaaaa | + | + ]]) + command([[set stc=%l\ ]]) screen:expect_unchanged() - command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}โ]]) command('set relativenumber') screen:expect([[ - {8:4 4โ}aaaaa | - {8:5 3โ}aaaaa | - {8:6 2โ}aaaaa | - {8:7 1โ}aaaaa | - {8:8 0โ}^aaaaa | - {8:9 1โ}aaaaa | - {8:10 2โ}aaaaa | - {8:11 3โ}aaaaa | - {8:12 4โ}aaaaa | - {8:13 5โ}aaaaa | - {8:14 6โ}aaaaa | - {8:15 7โ}aaaaa | - {8:16 8โ}aaaaa | - | - ]]) - command([[set stc=%l%=%{&rnu?'\ ':''}%rโ]]) + {8: 4 }aaaaa | + {8: 3 }aaaaa | + {8: 2 }aaaaa | + {8: 1 }aaaaa | + {8:8 }^aaaaa | + {8: 1 }aaaaa | + {8: 2 }aaaaa | + {8: 3 }aaaaa | + {8: 4 }aaaaa | + {8: 5 }aaaaa | + {8: 6 }aaaaa | + {8: 7 }aaaaa | + {8: 8 }aaaaa | + | + ]]) + command('set stc=') + screen:expect_unchanged() + command([[set nonu stc=%l\ ]]) + screen:expect([[ + {8: 4 }aaaaa | + {8: 3 }aaaaa | + {8: 2 }aaaaa | + {8: 1 }aaaaa | + {8: 0 }^aaaaa | + {8: 1 }aaaaa | + {8: 2 }aaaaa | + {8: 3 }aaaaa | + {8: 4 }aaaaa | + {8: 5 }aaaaa | + {8: 6 }aaaaa | + {8: 7 }aaaaa | + {8: 8 }aaaaa | + | + ]]) + command('set nuw=1 stc=') screen:expect_unchanged() - command([[set stc=%{&nu?v:lnum:''}%=%{&rnu?'\ '.v:relnum:''}โ]]) + -- Correct alignment with items before and after number column + command([[set nu stc=foo\ %l\ bar]]) + screen:expect([[ + {8:foo 4 bar}aaaaa | + {8:foo 3 bar}aaaaa | + {8:foo 2 bar}aaaaa | + {8:foo 1 bar}aaaaa | + {8:foo 8 bar}^aaaaa | + {8:foo 1 bar}aaaaa | + {8:foo 2 bar}aaaaa | + {8:foo 3 bar}aaaaa | + {8:foo 4 bar}aaaaa | + {8:foo 5 bar}aaaaa | + {8:foo 6 bar}aaaaa | + {8:foo 7 bar}aaaaa | + {8:foo 8 bar}aaaaa | + | + ]]) end) it("works with highlighted 'statuscolumn'", function() @@ -160,36 +198,36 @@ describe('statuscolumn', function() ]]) command('set relativenumber') screen:expect([[ - {1:4 }{8: 4โ}aaaaa | - {1:5 3}{8:โ}aaaaa | - {1:6 }{8: 2โ}aaaaa | - {1:7 1}{8:โ}aaaaa | - {1:8 }{8: 0โ}^aaaaa | - {1:9 1}{8:โ}aaaaa | - {1:10}{8: 2โ}aaaaa | - {1:11 3}{8:โ}aaaaa | - {1:12}{8: 4โ}aaaaa | - {1:13 5}{8:โ}aaaaa | - {1:14}{8: 6โ}aaaaa | - {1:15 7}{8:โ}aaaaa | - {1:16}{8: 8โ}aaaaa | + {1:4 }{8: 4โ}aaaaa | + {1:5 3}{8:โ}aaaaa | + {1:6 }{8: 2โ}aaaaa | + {1:7 1}{8:โ}aaaaa | + {1:8 }{8: 0โ}^aaaaa | + {1:9 1}{8:โ}aaaaa | + {1:10 }{8: 2โ}aaaaa | + {1:11 3}{8:โ}aaaaa | + {1:12 }{8: 4โ}aaaaa | + {1:13 5}{8:โ}aaaaa | + {1:14 }{8: 6โ}aaaaa | + {1:15 7}{8:โ}aaaaa | + {1:16 }{8: 8โ}aaaaa | | ]]) command('set nonumber') screen:expect([[ - {8:4โ}aaaaa | - {1:3}{8:โ}aaaaa | - {8:2โ}aaaaa | - {1:1}{8:โ}aaaaa | - {8:0โ}^aaaaa | - {1:1}{8:โ}aaaaa | - {8:2โ}aaaaa | - {1:3}{8:โ}aaaaa | - {8:4โ}aaaaa | - {1:5}{8:โ}aaaaa | - {8:6โ}aaaaa | - {1:7}{8:โ}aaaaa | - {8:8โ}aaaaa | + {1: }{8:4โ}aaaaa | + {1: 3}{8:โ}aaaaa | + {1: }{8:2โ}aaaaa | + {1: 1}{8:โ}aaaaa | + {1: }{8:0โ}^aaaaa | + {1: 1}{8:โ}aaaaa | + {1: }{8:2โ}aaaaa | + {1: 3}{8:โ}aaaaa | + {1: }{8:4โ}aaaaa | + {1: 5}{8:โ}aaaaa | + {1: }{8:6โ}aaaaa | + {1: 7}{8:โ}aaaaa | + {1: }{8:8โ}aaaaa | | ]]) end) @@ -305,36 +343,36 @@ describe('statuscolumn', function() -- v:relnum is the same value on wrapped lines command([[set stc=%C%=\ %{v:relnum}โ%s\ ]]) screen:expect([[ - {2: }{1: 4โ>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: 4โ}{2: }{1: }aaaaaa | - {2: }{1: 3โ}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: 3โ}{2: }{1: }aaaaaa | - {2: }{1: 2โ}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: 2โ}{2: }{1: }aaaaaa | - {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: 1โ}{2: }{1: }aaaaaa | - {2:+}{4: 0โ}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| - {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: 1โ}{2: }{1: }aaaaaa | - {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: 2โ}{2: }{1: }aaaaaa | + {2: }{1: 4โ>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 4โ}{2: }{1: }aaaaaaa | + {2: }{1: 3โ}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 3โ}{2: }{1: }aaaaaaa | + {2: }{1: 2โ}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 2โ}{2: }{1: }aaaaaaa | + {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 1โ}{2: }{1: }aaaaaaa | + {2:+}{4: 0โ}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 1โ}{2: }{1: }aaaaaaa | + {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: 2โ}{2: }{1: }aaaaaaa | | ]]) command([[set stc=%C%=\ %{v:virtnum?'':v:relnum}โ%s\ ]]) screen:expect([[ - {2: }{1: 4โ>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaa | - {2: }{1: 3โ}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaa | - {2: }{1: 2โ}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaa | - {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaa | - {2:+}{4: 0โ}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| - {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaa | - {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaa | + {2: }{1: 4โ>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaa | + {2: }{1: 3โ}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaa | + {2: }{1: 2โ}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaa | + {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaa | + {2:+}{4: 0โ}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaa | + {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaa | | ]]) -- Up to 9 signs in a line @@ -347,75 +385,75 @@ describe('statuscolumn', function() command('sign place 10 line=6 name=piet2 buffer=1') command('sign place 11 line=6 name=piet1 buffer=1') screen:expect([[ - {2: }{1: 4โ>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 3โ}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 2โ>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | - {2:+}{4: 0โ}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaa}| - {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 4โ>>}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 3โ}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2โ>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa | + {2:+}{4: 0โ}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaa}| + {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }{1: โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaa | | ]]) -- Also test fold and sign column when 'cpoptions' includes "n" command('set cpoptions+=n') feed('Hgjg0') screen:expect([[ - {2: }{4: 0โ}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| - {2: }{5:^aaaaaaaaaaaaaaaaaaaa }| - {2: }{1: 3โ}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 2โ>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }aaaaaaaaaaaaaaaaaaaa | - {2:+}{1: 4โ}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaaa}| - {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }aaaaaaaaaaaaaaaaaaaa | + {2: }{4: 0โ}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: }{5:^aaaaaaaaaaaaaaaaaaaaa }| + {2: }{1: 3โ}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2โ>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaaa | + {2:+}{1: 4โ}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaa}| + {2: }{1: 1โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaaa | | ]]) command('set breakindent') command('sign unplace 2') feed('J2gjg0') screen:expect([[ - {2: }{4: 0โ}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| - {2: } {5:aaaaaaaaaaaaaaaaaaaa aaaaaaaaa}| - {2: } {5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| - {2: } {5:^aaaaaaaaaaa }| - {2: }{1: 1โ>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: } aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: } aaaaaaaaaaaaaaaaaaaa | - {2:+}{1: 3โ}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaaa}| - {2: }{1: 4โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: } aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 5โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: } aaaaaaaaaaaaaaaaaaaa | + {2: }{4: 0โ}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: } {5:aaaaaaaaaaaaaaaaaaaaa aaaaaaa}| + {2: } {5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: } {5:^aaaaaaaaaaaaaa }| + {2: }{1: 1โ>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: } aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: } aaaaaaaaaaaaaaaaaaaaa | + {2:+}{1: 3โ}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaa}| + {2: }{1: 4โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: } aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 5โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: } aaaaaaaaaaaaaaaaaaaaa | | ]]) command('set nobreakindent') feed('$g0') screen:expect([[ - {2: }{4: 0โ}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| - {2: }{5:aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaa}| + {2: }{4: 0โ}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: }{5:aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaa}| {2: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| - {2: }{5:^aaa }| - {2: }{1: 1โ>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }aaaaaaaaaaaaaaaaaaaa | - {2:+}{1: 3โ}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaaa}| - {2: }{1: 4โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }aaaaaaaaaaaaaaaaaaaa | - {2: }{1: 5โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| - {2: }aaaaaaaaaaaaaaaaaaaa | + {2: }{5:^aaaa }| + {2: }{1: 1โ>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaaa | + {2:+}{1: 3โ}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaa}| + {2: }{1: 4โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaaa | + {2: }{1: 5โ}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaaa | | ]]) command('silent undo') @@ -427,7 +465,23 @@ describe('statuscolumn', function() virt_lines_above = true, virt_lines = {{{"virt_line above", ""}}} }) vim.api.nvim_buf_set_extmark(0, ns, 4, 0, { virt_lines = {{{"virt_line", ""}}} }) ]]) - command('set foldcolumn=0 signcolumn=no') + command('set foldcolumn=0 signcolumn=number stc=%l') + screen:expect([[ + {1:>>}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {1: 5}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {1: }virt_line | + {1: }virt_line above | + {1:>>}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {1: 7}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {4: 8}{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {1: 9}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {1:10}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {1:11}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {1:12}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {1:13}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + {1:14}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + | + ]]) command( [[set stc=%{v:virtnum<0?'virtual':(!v:virtnum?'buffer':'wrapped')}%=%{'\ '.v:virtnum.'\ '.v:lnum}]] ) @@ -533,8 +587,8 @@ describe('statuscolumn', function() command([[set stc=%6s\ %l]]) exec_lua('vim.api.nvim_buf_set_extmark(0, ns, 7, 0, {sign_text = "๐"})') screen:expect([[ - {8: ๐ 8 }^aaaaa | - {8: }{7: }{8: 9 }aaaaa | + {8: ๐ 8}^aaaaa | + {8: }{7: }{8: 9}aaaaa | | ]]) end) @@ -598,9 +652,6 @@ describe('statuscolumn', function() -- Check that statusline click doesn't register as statuscolumn click api.nvim_input_mouse('right', 'press', '', 0, 12, 0) eq('', eval('g:testvar')) - -- Check that cmdline click doesn't register as statuscolumn click - api.nvim_input_mouse('right', 'press', '', 0, 13, 0) - eq('', eval('g:testvar')) end) it('clicks and highlights work with control characters', function() @@ -644,26 +695,26 @@ describe('statuscolumn', function() -- clicking an item does not drag mouse api.nvim_input_mouse('left', 'press', '', 0, 0, 0) screen:expect([[ - {0:8 }^aaaaa | + {0: 8}^aaaaa | {1: Echo } | ]]) api.nvim_input_mouse('left', 'press', '', 0, 1, 5) api.nvim_input_mouse('left', 'release', '', 0, 1, 5) screen:expect([[ - {0:8 }^aaaaa | + {0: 8}^aaaaa | 0 1 l 8 | ]]) command('echo') -- clicking outside to close the menu does not drag mouse api.nvim_input_mouse('left', 'press', '', 0, 0, 0) screen:expect([[ - {0:8 }^aaaaa | + {0: 8}^aaaaa | {1: Echo } | ]]) api.nvim_input_mouse('left', 'press', '', 0, 0, 10) api.nvim_input_mouse('left', 'release', '', 0, 0, 10) screen:expect([[ - {0:8 }^aaaaa | + {0: 8}^aaaaa | | ]]) end) @@ -749,9 +800,9 @@ describe('statuscolumn', function() it('works with cmdwin', function() feed(':set stc=%l<CR>q:k$') screen:expect([[ - {8:7 }aaaaa | - {8:8 }aaaaa | - {8:9 }aaaaa | + {8: 7}aaaaa | + {8: 8}aaaaa | + {8: 9}aaaaa | {8:10}aaaaa | {2:[No Name] [+] }| {1::}{8:1}set stc=%^l | @@ -899,16 +950,16 @@ describe('statuscolumn', function() command([[set spell stc=%l\ ]]) command('call setline(8, "This is a line that contains แถ multibyte character.")') screen:expect([[ - {8:8 }^This is a line that contains {31:แถ}| + {8: 8 }^This is a line that contains {31:แถ}| {8: } {31:multibyte} character. | - {8:9 }{31:aaaaa} | + {8: 9 }{31:aaaaa} | | ]]) end) it('line increase properly redraws buffer text with relativenumber #27709', function() screen:try_resize(33, 4) - command([[set rnu nuw=3 stc=%l\ ]]) + command([[set rnu nuw=3 stc=%{v:lnum}\ ]]) command('call setline(1, range(1, 99))') feed('Gyyp') screen:expect([[ diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua index 3087a0cde1..937e709d66 100644 --- a/test/functional/ui/statusline_spec.lua +++ b/test/functional/ui/statusline_spec.lua @@ -63,6 +63,22 @@ for _, model in ipairs(mousemodels) do eq('0 3 r', eval('g:testvar')) api.nvim_input_mouse('right', 'press', '', 0, 6, 28) eq('0 4 r', eval('g:testvar')) + api.nvim_input_mouse('x1', 'press', '', 0, 6, 17) + eq('0 1 x1', eval('g:testvar')) + api.nvim_input_mouse('x1', 'press', '', 0, 6, 17) + eq('0 2 x1', eval('g:testvar')) + api.nvim_input_mouse('x1', 'press', '', 0, 6, 17) + eq('0 3 x1', eval('g:testvar')) + api.nvim_input_mouse('x1', 'press', '', 0, 6, 17) + eq('0 4 x1', eval('g:testvar')) + api.nvim_input_mouse('x2', 'press', '', 0, 6, 28) + eq('0 1 x2', eval('g:testvar')) + api.nvim_input_mouse('x2', 'press', '', 0, 6, 28) + eq('0 2 x2', eval('g:testvar')) + api.nvim_input_mouse('x2', 'press', '', 0, 6, 28) + eq('0 3 x2', eval('g:testvar')) + api.nvim_input_mouse('x2', 'press', '', 0, 6, 28) + eq('0 4 x2', eval('g:testvar')) end) it('works with control characters and highlight', function() diff --git a/test/functional/ui/title_spec.lua b/test/functional/ui/title_spec.lua index e86fdbe5a3..3189232957 100644 --- a/test/functional/ui/title_spec.lua +++ b/test/functional/ui/title_spec.lua @@ -22,7 +22,7 @@ describe('title', function() end) it('has correct default title with unnamed file', function() - local expected = '[No Name] - NVIM' + local expected = '[No Name] - Nvim' command('set title') screen:expect(function() eq(expected, screen.title) @@ -30,7 +30,7 @@ describe('title', function() end) it('has correct default title with named file', function() - local expected = (is_os('win') and 'myfile (C:\\mydir) - NVIM' or 'myfile (/mydir) - NVIM') + local expected = (is_os('win') and 'myfile (C:\\mydir) - Nvim' or 'myfile (/mydir) - Nvim') command('set title') command(is_os('win') and 'file C:\\mydir\\myfile' or 'file /mydir/myfile') screen:expect(function() @@ -41,7 +41,7 @@ describe('title', function() describe('is not changed by', function() local file1 = is_os('win') and 'C:\\mydir\\myfile1' or '/mydir/myfile1' local file2 = is_os('win') and 'C:\\mydir\\myfile2' or '/mydir/myfile2' - local expected = (is_os('win') and 'myfile1 (C:\\mydir) - NVIM' or 'myfile1 (/mydir) - NVIM') + local expected = (is_os('win') and 'myfile1 (C:\\mydir) - Nvim' or 'myfile1 (/mydir) - Nvim') local buf2 before_each(function() @@ -82,11 +82,11 @@ describe('title', function() end) end) - it('a Lua callback calling nvim_buf_call in a hidden buffer', function() + it('a Lua callback calling vim._with in a hidden buffer', function() exec_lua(string.format( [[ vim.schedule(function() - vim.api.nvim_buf_call(%d, function() end) + vim._with({buf = %d}, function() end) end) ]], buf2 diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index 0feec6bd03..4d01b7a779 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -16,30 +16,24 @@ describe("'wildmenu'", function() before_each(function() clear() screen = Screen.new(25, 5) - screen:set_default_attr_ids { - [1] = { foreground = Screen.colors.Blue, bold = true }, - [2] = { reverse = true }, - [3] = { bold = true, reverse = true }, - [5] = { bold = true }, - [31] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow }, + screen:add_extra_attr_ids { + [100] = { background = Screen.colors.Yellow1, foreground = Screen.colors.Black }, } screen:attach() end) -- oldtest: Test_wildmenu_screendump() it('works', function() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { foreground = Screen.colors.Black, background = Screen.colors.Yellow }, -- WildMenu - [2] = { bold = true, reverse = true }, -- StatusLine - }) + screen:add_extra_attr_ids { + [100] = { background = Screen.colors.Yellow1, foreground = Screen.colors.Black }, + } -- Test simple wildmenu feed(':sign <Tab>') screen:expect { grid = [[ | - {0:~ }|*2 - {1:define}{2: jump list > }| + {1:~ }|*2 + {100:define}{3: jump list > }| :sign define^ | ]], } @@ -48,8 +42,8 @@ describe("'wildmenu'", function() screen:expect { grid = [[ | - {0:~ }|*2 - {2:define }{1:jump}{2: list > }| + {1:~ }|*2 + {3:define }{100:jump}{3: list > }| :sign jump^ | ]], } @@ -58,8 +52,8 @@ describe("'wildmenu'", function() screen:expect { grid = [[ | - {0:~ }|*2 - {2:define jump }{1:list}{2: > }| + {1:~ }|*2 + {3:define jump }{100:list}{3: > }| :sign list^ | ]], } @@ -69,8 +63,8 @@ describe("'wildmenu'", function() screen:expect { grid = [[ | - {0:~ }|*2 - {2:define jump list > }| + {1:~ }|*2 + {3:define jump list > }| :sign ^ | ]], } @@ -80,7 +74,7 @@ describe("'wildmenu'", function() screen:expect { grid = [[ | - {0:~ }|*3 + {1:~ }|*3 :sign ^ | ]], } @@ -92,8 +86,8 @@ describe("'wildmenu'", function() screen:expect { grid = [[ | - {0:~ }|*2 - {1:define}{2: jump list > }| + {1:~ }|*2 + {100:define}{3: jump list > }| :sign define^ | ]], } @@ -104,7 +98,7 @@ describe("'wildmenu'", function() screen:expect { grid = [[ ^ | - {0:~ }|*3 + {1:~ }|*3 | ]], } @@ -115,7 +109,7 @@ describe("'wildmenu'", function() screen:expect([[ | {1:~ }|*2 - {31:define}{3: jump list > }| + {100:define}{3: jump list > }| :sign define^ | ]]) feed('<C-E>') @@ -131,7 +125,7 @@ describe("'wildmenu'", function() screen:expect([[ | {1:~ }|*2 - {31:define}{3: jump list > }| + {100:define}{3: jump list > }| :sign define^ | ]]) feed('<tab><C-Y>') @@ -148,7 +142,7 @@ describe("'wildmenu'", function() screen:expect([[ | {1:~ }|*2 - {31:define}{3: jump list > }| + {100:define}{3: jump list > }| :sign define^ | ]]) end) @@ -162,7 +156,7 @@ describe("'wildmenu'", function() screen:expect([[ | {1:~ }|*2 - {31:define}{3: jump list > }| + {100:define}{3: jump list > }| :sign define^ | ]]) feed('<space>') @@ -188,7 +182,7 @@ describe("'wildmenu'", function() screen:expect([[ | {1:~ }|*2 - {31:!}{3: # & < = > @ > }| + {100:!}{3: # & < = > @ > }| :!^ | ]]) end) @@ -199,9 +193,17 @@ describe("'wildmenu'", function() feed((':terminal "%s" REP 5000 !terminal_output!<cr>'):format(testprg('shell-test'))) feed('G') -- Follow :terminal output. feed([[:sign <Tab>]]) -- Invoke wildmenu. + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Black, background = Screen.colors.Yellow }, + [101] = { + bold = true, + foreground = Screen.colors.White, + background = Screen.colors.DarkGreen, + }, + } -- NB: in earlier versions terminal output was redrawn during cmdline mode. -- For now just assert that the screen remains unchanged. - screen:expect { any = '{31:define}{3: jump list > }|\n:sign define^ |' } + screen:expect { any = '{100:define}{101: jump list > }|\n:sign define^ |' } screen:expect_unchanged() -- cmdline CTRL-D display should also be preserved. @@ -232,7 +234,7 @@ describe("'wildmenu'", function() grid = [[ | {1:~ }|*2 - {31:define}{3: jump list > }| + {100:define}{3: jump list > }| :sign define^ | ]], } @@ -259,9 +261,17 @@ describe("'wildmenu'", function() feed([[<C-\><C-N>]]) feed([[:<Tab>]]) -- Invoke wildmenu. + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Black, background = Screen.colors.Yellow }, + [101] = { + bold = true, + foreground = Screen.colors.White, + background = Screen.colors.DarkGreen, + }, + } -- Check only the last 2 lines, because the shell output is -- system-dependent. - screen:expect { any = '{31:!}{3: # & < = > @ > }|\n:!^' } + screen:expect { any = '{100:!}{101: # & < = > @ > }|\n:!^' } -- Because this test verifies a _lack_ of activity, we must wait the full timeout. -- So make it reasonable. screen:expect_unchanged(false, 1000) @@ -290,7 +300,7 @@ describe("'wildmenu'", function() {3: }| :set wildm | wildmenu wildmode | - {31:wildmenu}{3: wildmode }| + {100:wildmenu}{3: wildmode }| :set wildmenu^ | ]]) feed('<Esc>') @@ -416,10 +426,8 @@ describe("'wildmenu'", function() end) it('works with c_CTRL_Z standard mapping', function() - screen:set_default_attr_ids { - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow }, - [3] = { bold = true, reverse = true }, + screen:add_extra_attr_ids { + [100] = { background = Screen.colors.Yellow1, foreground = Screen.colors.Black }, } -- Wildcharm? where we are going we aint't no need no wildcharm. @@ -436,7 +444,7 @@ describe("'wildmenu'", function() grid = [[ | {1:~ }|*2 - {2:case}{3: clear cluster > }| + {100:case}{3: clear cluster > }| :syntax case^ | ]], } @@ -481,11 +489,9 @@ describe('command line completion', function() before_each(function() clear() screen = Screen.new(40, 5) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow }, - [3] = { bold = true, reverse = true }, - }) + screen:add_extra_attr_ids { + [100] = { background = Screen.colors.Yellow1, foreground = Screen.colors.Black }, + } screen:attach() end) after_each(function() @@ -513,7 +519,7 @@ describe('command line completion', function() screen:expect([[ | {1:~ }|*2 - {2:XTEST_1}{3: XTEST_2 }| + {100:XTEST_1}{3: XTEST_2 }| :!echo $XTEST_1^ | ]]) end) @@ -529,7 +535,7 @@ describe('command line completion', function() screen:expect([[ | {1:~ }|*2 - {2:XTEST_1AaใB}{3: XTEST_2 }| + {100:XTEST_1AaใB}{3: XTEST_2 }| :!echo $XTEST_1AaใB^ | ]]) end) |