diff options
Diffstat (limited to 'test/functional/editor/completion_spec.lua')
-rw-r--r-- | test/functional/editor/completion_spec.lua | 589 |
1 files changed, 261 insertions, 328 deletions
diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua index cbaf401f06..33d0d47499 100644 --- a/test/functional/editor/completion_spec.lua +++ b/test/functional/editor/completion_spec.lua @@ -4,10 +4,9 @@ local assert_alive = helpers.assert_alive local clear, feed = helpers.clear, helpers.feed local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq local feed_command, source, expect = helpers.feed_command, helpers.source, helpers.expect -local funcs = helpers.funcs -local curbufmeths = helpers.curbufmeths +local fn = helpers.fn local command = helpers.command -local meths = helpers.meths +local api = helpers.api local poke_eventloop = helpers.poke_eventloop describe('completion', function() @@ -18,17 +17,17 @@ describe('completion', function() screen = Screen.new(60, 8) screen:attach() screen:set_default_attr_ids({ - [0] = {bold=true, foreground=Screen.colors.Blue}, - [1] = {background = Screen.colors.LightMagenta}, - [2] = {background = Screen.colors.Grey}, - [3] = {bold = true}, - [4] = {bold = true, foreground = Screen.colors.SeaGreen}, - [5] = {foreground = Screen.colors.Red}, - [6] = {background = Screen.colors.Black}, - [7] = {foreground = Screen.colors.White, background = Screen.colors.Red}, - [8] = {reverse = true}, - [9] = {bold = true, reverse = true}, - [10] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow}, + [0] = { bold = true, foreground = Screen.colors.Blue }, + [1] = { background = Screen.colors.LightMagenta }, + [2] = { background = Screen.colors.Grey }, + [3] = { bold = true }, + [4] = { bold = true, foreground = Screen.colors.SeaGreen }, + [5] = { foreground = Screen.colors.Red }, + [6] = { background = Screen.colors.Black }, + [7] = { foreground = Screen.colors.White, background = Screen.colors.Red }, + [8] = { reverse = true }, + [9] = { bold = true, reverse = true }, + [10] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow }, }) end) @@ -41,22 +40,14 @@ describe('completion', function() screen:expect([[ foo | foo^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- Keyword Local completion (^N^P) The only match} | ]]) feed('<C-e>') screen:expect([[ foo | ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- INSERT --} | ]]) feed('<ESC>') @@ -65,9 +56,10 @@ describe('completion', function() it('returns expected dict in normal completion', function() feed('ifoo<ESC>o<C-x><C-n>') eq('foo', eval('getline(2)')) - eq({word = 'foo', abbr = '', menu = '', - info = '', kind = '', user_data = ''}, - eval('v:completed_item')) + eq( + { word = 'foo', abbr = '', menu = '', info = '', kind = '', user_data = '' }, + eval('v:completed_item') + ) end) it('is readonly', function() screen:try_resize(80, 8) @@ -112,15 +104,17 @@ describe('completion', function() foo^ | {2:bar foobaz baz }{0: }| {1:abbr kind menu }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 {3:-- Omni completion (^O^N^P) }{4:match 1 of 2} | ]]) - eq({word = 'foo', abbr = 'bar', menu = 'baz', - info = 'foobar', kind = 'foobaz', user_data = ''}, - eval('v:completed_item')) + eq({ + word = 'foo', + abbr = 'bar', + menu = 'baz', + info = 'foobar', + kind = 'foobaz', + user_data = '', + }, eval('v:completed_item')) end) end) @@ -140,11 +134,7 @@ describe('completion', function() screen:expect([[ foo | ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- INSERT --} | ]]) feed('<C-x>') @@ -152,11 +142,7 @@ describe('completion', function() screen:expect([[ foo | ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)} | ]]) feed('<C-n>') @@ -164,10 +150,7 @@ describe('completion', function() foo | foo^ | {2:foo }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 {3:-- Keyword Local completion (^N^P) The only match} | ]]) feed('bar<ESC>') @@ -178,9 +161,7 @@ describe('completion', function() foobar | foo^ | {2:foo }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- INSERT --} | ]]) eq('foo', eval('getline(3)')) @@ -192,34 +173,24 @@ describe('completion', function() foo | ^ | {2:foo }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 {3:-- Keyword Local completion (^N^P) The only match} | ]]) feed('<C-y>') screen:expect([[ foo | foo^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- INSERT --} | ]]) feed('<ESC>') eq('foo', eval('getline(2)')) feed('o<C-r>=TestComplete()<CR>') screen:expect([[ - foo | - foo | + foo |*2 ^ | {2:foo }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- INSERT --} | ]]) feed('<C-y><ESC>') @@ -232,21 +203,14 @@ describe('completion', function() foo | ^ | {1:foo }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 {3:-- Keyword Local completion (^N^P) }{5:Back at original} | ]]) feed('b') screen:expect([[ foo | b^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- Keyword Local completion (^N^P) }{5:Back at original} | ]]) feed('ar<ESC>') @@ -257,9 +221,7 @@ describe('completion', function() bar | ^ | {1:foo }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- INSERT --} | ]]) feed('bar<ESC>') @@ -272,21 +234,14 @@ describe('completion', function() foo | ^ | {1:foo }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 {3:-- Keyword Local completion (^N^P) }{5:Back at original} | ]]) feed('<ESC>') screen:expect([[ foo | ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 | ]]) eq('', eval('getline(2)')) @@ -296,9 +251,7 @@ describe('completion', function() | ^ | {1:foo }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- INSERT --} | ]]) feed('<ESC>') @@ -306,10 +259,7 @@ describe('completion', function() foo | | ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 | ]]) eq('', eval('getline(3)')) @@ -341,8 +291,8 @@ describe('completion', function() end) local tests = { - ['<up>, <down>, <cr>'] = {'<down><cr>', '<up><cr>'}, - ['<c-n>, <c-p>, <c-y>'] = {'<c-n><c-y>', '<c-p><c-y>'}, + ['<up>, <down>, <cr>'] = { '<down><cr>', '<up><cr>' }, + ['<c-n>, <c-p>, <c-y>'] = { '<c-n><c-y>', '<c-p><c-y>' }, } for name, seq in pairs(tests) do @@ -358,13 +308,13 @@ describe('completion', function() feed('A<right><esc>A<right><esc>') local expected = { - {'foo', 'bar', 'foo'}, - {'foo', 'bar', 'ccc'}, - {'foo', 'bar'}, - {'foo', 'bbb'}, - {'foo'}, - {'aaa'}, - {''}, + { 'foo', 'bar', 'foo' }, + { 'foo', 'bar', 'ccc' }, + { 'foo', 'bar' }, + { 'foo', 'bbb' }, + { 'foo' }, + { 'aaa' }, + { '' }, } for i = 1, #expected do @@ -384,7 +334,7 @@ describe('completion', function() end end) - describe("refresh:always", function() + describe('refresh:always', function() before_each(function() source([[ function! TestCompletion(findstart, base) abort @@ -409,9 +359,9 @@ describe('completion', function() set completeopt=menuone,noselect set completefunc=TestCompletion ]]) - end ) + end) - it('completes on each input char', function () + it('completes on each input char', function() feed('i<C-x><C-u>') screen:expect([[ ^ | @@ -438,48 +388,32 @@ describe('completion', function() screen:expect([[ ug^ | {1:August }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- User defined completion (^U^N^P) }{5:Back at original} | ]]) feed('<Down>') screen:expect([[ ug^ | {2:August }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- User defined completion (^U^N^P) The only match} | ]]) feed('<C-y>') screen:expect([[ August^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 {3:-- INSERT --} | ]]) expect('August') end) - it("repeats correctly after backspace #2674", function () + it('repeats correctly after backspace #2674', function() feed('o<C-x><C-u>Ja') screen:expect([[ | Ja^ | {1:January }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 {3:-- User defined completion (^U^N^P) }{5:Back at original} | ]]) feed('<BS>') @@ -489,8 +423,7 @@ describe('completion', function() {1:January }{0: }| {1:June }{0: }| {1:July }{0: }| - {0:~ }| - {0:~ }| + {0:~ }|*2 {3:-- User defined completion (^U^N^P) }{5:Back at original} | ]]) feed('<C-n>') @@ -500,8 +433,7 @@ describe('completion', function() {2:January }{0: }| {1:June }{0: }| {1:July }{0: }| - {0:~ }| - {0:~ }| + {0:~ }|*2 {3:-- User defined completion (^U^N^P) }{4:match 1 of 3} | ]]) feed('<C-n>') @@ -511,19 +443,14 @@ describe('completion', function() {1:January }{0: }| {2:June }{0: }| {1:July }{0: }| - {0:~ }| - {0:~ }| + {0:~ }|*2 {3:-- User defined completion (^U^N^P) }{4:match 2 of 3} | ]]) feed('<Esc>') screen:expect([[ | Jun^e | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 | ]]) feed('.') @@ -531,10 +458,7 @@ describe('completion', function() | June | Jun^e | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 | ]]) expect([[ @@ -552,10 +476,10 @@ describe('completion', function() return '' endfunction ]]) - feed_command("set completeopt=menuone,noselect") + feed_command('set completeopt=menuone,noselect') end) - it("works", function() + it('works', function() feed('i<C-r>=TestComplete()<CR>') screen:expect([[ ^ | @@ -705,18 +629,13 @@ describe('completion', function() feed('<cr>') screen:expect([[ 96^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 {3:-- INSERT --} | ]]) end) end) - it("does not indent until an item is selected #8345", function () + it('does not indent until an item is selected #8345', function() -- Indents on "ind", unindents on "unind". source([[ function! TestIndent() @@ -735,129 +654,106 @@ describe('completion', function() ]]) -- Give some words to complete. - feed("iinc uninc indent unindent<CR>") + feed('iinc uninc indent unindent<CR>') -- Does not indent when "ind" is typed. - feed("in<C-X><C-N>") + feed('in<C-X><C-N>') -- Completion list is generated incorrectly if we send everything at once -- via nvim_input(). So poke_eventloop() before sending <BS>. #8480 poke_eventloop() - feed("<BS>d") + feed('<BS>d') screen:expect([[ inc uninc indent unindent | ind^ | {2:indent }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | ]]) -- Indents when the item is selected - feed("<C-Y>") + feed('<C-Y>') screen:expect([[ inc uninc indent unindent | indent^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- INSERT --} | ]]) -- Indents when completion is exited using ESC. - feed("<CR>in<C-N><BS>d<Esc>") + feed('<CR>in<C-N><BS>d<Esc>') screen:expect([[ inc uninc indent unindent | indent | in^d | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 | ]]) -- Works for unindenting too. - feed("ounin<C-X><C-N>") - helpers.poke_eventloop() - feed("<BS>d") + feed('ounin<C-X><C-N>') + poke_eventloop() + feed('<BS>d') screen:expect([[ inc uninc indent unindent | indent | ind | unind^ | {0:~ }{2: unindent }{0: }| - {0:~ }| - {0:~ }| + {0:~ }|*2 {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | ]]) -- Works when going back and forth. - feed("<BS>c") + feed('<BS>c') screen:expect([[ inc uninc indent unindent | indent | ind | uninc^ | {0:~ }{2: uninc }{0: }| - {0:~ }| - {0:~ }| + {0:~ }|*2 {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | ]]) - feed("<BS>d") + feed('<BS>d') screen:expect([[ inc uninc indent unindent | indent | ind | unind^ | {0:~ }{2: unindent }{0: }| - {0:~ }| - {0:~ }| + {0:~ }|*2 {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | ]]) - feed("<C-N><C-N><C-Y><Esc>") + feed('<C-N><C-N><C-Y><Esc>') screen:expect([[ inc uninc indent unindent | indent | ind | uninden^t | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 | ]]) end) - it('disables folding during completion', function () - feed_command("set foldmethod=indent") + it('disables folding during completion', function() + feed_command('set foldmethod=indent') feed('i<Tab>foo<CR><Tab>bar<Esc>gg') screen:expect([[ ^foo | bar | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 | ]]) feed('A<C-x><C-l>') screen:expect([[ foo^ | bar | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- Whole line completion (^L^N^P) }{7:Pattern not found} | ]]) eq(-1, eval('foldclosed(1)')) end) - it('popupmenu is not interrupted by events', function () - feed_command("set complete=.") + it('popupmenu is not interrupted by events', function() + feed_command('set complete=.') feed('ifoobar fooegg<cr>f<c-p>') screen:expect([[ @@ -865,24 +761,23 @@ describe('completion', function() fooegg^ | {1:foobar }{0: }| {2:fooegg }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | ]]) assert_alive() -- popupmenu still visible - screen:expect{grid=[[ + screen:expect { + grid = [[ foobar fooegg | fooegg^ | {1:foobar }{0: }| {2:fooegg }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | - ]], unchanged=true} + ]], + unchanged = true, + } feed('<c-p>') -- Didn't restart completion: old matches still used @@ -891,9 +786,7 @@ describe('completion', function() foobar^ | {2:foobar }{0: }| {1:fooegg }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- Keyword completion (^N^P) }{4:match 2 of 2} | ]]) end) @@ -902,68 +795,62 @@ describe('completion', function() it('expands when there is only one match', function() feed(':lua CURRENT_TESTING_VAR = 1<CR>') feed(':lua CURRENT_TESTING_<TAB>') - screen:expect{grid=[[ + screen:expect { + grid = [[ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 :lua CURRENT_TESTING_VAR^ | - ]]} + ]], + } end) it('expands when there is only one match', function() feed(':lua CURRENT_TESTING_FOO = 1<CR>') feed(':lua CURRENT_TESTING_BAR = 1<CR>') feed(':lua CURRENT_TESTING_<TAB>') - screen:expect{ grid = [[ + screen:expect { + grid = [[ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {10:CURRENT_TESTING_BAR}{9: CURRENT_TESTING_FOO }| :lua CURRENT_TESTING_BAR^ | - ]], unchanged = true } + ]], + unchanged = true, + } end) it('provides completion from `getcompletion()`', function() - eq({'vim'}, funcs.getcompletion('vi', 'lua')) - eq({'api'}, funcs.getcompletion('vim.ap', 'lua')) - eq({'tbl_filter'}, funcs.getcompletion('vim.tbl_fil', 'lua')) - eq({'vim'}, funcs.getcompletion('print(vi', 'lua')) + eq({ 'vim' }, fn.getcompletion('vi', 'lua')) + eq({ 'api' }, fn.getcompletion('vim.ap', 'lua')) + eq({ 'tbl_filter' }, fn.getcompletion('vim.tbl_fil', 'lua')) + eq({ 'vim' }, fn.getcompletion('print(vi', 'lua')) -- fuzzy completion is not supported, so the result should be the same command('set wildoptions+=fuzzy') - eq({'vim'}, funcs.getcompletion('vi', 'lua')) + eq({ 'vim' }, fn.getcompletion('vi', 'lua')) end) end) it('cmdline completion supports various string options', function() - eq('auto', funcs.getcompletion('set foldcolumn=', 'cmdline')[2]) - eq({'nosplit', 'split'}, funcs.getcompletion('set inccommand=', 'cmdline')) - eq({'ver:3,hor:6', 'hor:', 'ver:'}, funcs.getcompletion('set mousescroll=', 'cmdline')) - eq('BS', funcs.getcompletion('set termpastefilter=', 'cmdline')[2]) - eq('SpecialKey', funcs.getcompletion('set winhighlight=', 'cmdline')[1]) - eq('SpecialKey', funcs.getcompletion('set winhighlight=NonText:', 'cmdline')[1]) + eq('auto', fn.getcompletion('set foldcolumn=', 'cmdline')[2]) + eq({ 'nosplit', 'split' }, fn.getcompletion('set inccommand=', 'cmdline')) + eq({ 'ver:3,hor:6', 'hor:', 'ver:' }, fn.getcompletion('set mousescroll=', 'cmdline')) + eq('BS', fn.getcompletion('set termpastefilter=', 'cmdline')[2]) + eq('SpecialKey', fn.getcompletion('set winhighlight=', 'cmdline')[1]) + eq('SpecialKey', fn.getcompletion('set winhighlight=NonText:', 'cmdline')[1]) end) describe('from the commandline window', function() - it('is cleared after CTRL-C', function () + it('is cleared after CTRL-C', function() feed('q:') feed('ifoo faa fee f') screen:expect([[ | {8:[No Name] }| {0::}foo faa fee f^ | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {9:[Command Line] }| {3:-- INSERT --} | - ]] ) + ]]) feed('<c-x><c-n>') screen:expect([[ | @@ -980,9 +867,7 @@ describe('completion', function() | {8:[No Name] }| {0::}foo faa fee foo | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {9:[Command Line] }| :foo faa fee foo^ | ]]) @@ -997,17 +882,19 @@ describe('completion', function() return '' endfunction ]]) - meths.set_option_value('completeopt', 'menuone,noselect', {}) - meths.set_var('_complist', {{ - word=0, - abbr=1, - menu=2, - kind=3, - info=4, - icase=5, - dup=6, - empty=7, - }}) + api.nvim_set_option_value('completeopt', 'menuone,noselect', {}) + api.nvim_set_var('_complist', { + { + word = 0, + abbr = 1, + menu = 2, + kind = 3, + info = 4, + icase = 5, + dup = 6, + empty = 7, + }, + }) end) it('shows correct variant as word', function() @@ -1015,11 +902,7 @@ describe('completion', function() screen:expect([[ ^ | {1:1 3 2 }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- INSERT --} | ]]) end) @@ -1027,22 +910,24 @@ describe('completion', function() it("'ignorecase' 'infercase' CTRL-X CTRL-N #6451", function() feed_command('set ignorecase infercase') - feed_command('edit BACKERS.md') + feed_command('edit runtime/doc/backers.txt') feed('oX<C-X><C-N>') - screen:expect([[ - # Bountysource Backers | + screen:expect { + grid = [[ + *backers.txt* Nvim | Xnull^ | {2:Xnull }{6: } | - {1:Xoxomoon }{6: }ryone who backed our [Bountysource fundraise| - {1:Xu }{6: }ountysource.com/teams/neovim/fundraiser)! | + {1:Xoxomoon }{6: } | + {1:Xu }{6: } NVIM REFERENCE MANUAL | {1:Xpayn }{2: } | - {1:Xinity }{2: }d URL in BACKERS.md. | + {1:Xinity }{2: } | {3:-- Keyword Local completion (^N^P) }{4:match 1 of 7} | - ]]) + ]], + } end) it('CompleteChanged autocommand', function() - curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar', ''}) + api.nvim_buf_set_lines(0, 0, 1, false, { 'foo', 'bar', 'foobar', '' }) source([[ set complete=. completeopt=noinsert,noselect,menuone function! OnPumChange() @@ -1057,43 +942,45 @@ describe('completion', function() -- v:event.size should be set with ext_popupmenu #20646 screen:set_option('ext_popupmenu', true) feed('Sf<C-N>') - screen:expect({grid = [[ + screen:expect({ + grid = [[ foo | bar | foobar | f^ | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- Keyword completion (^N^P) }{5:Back at original} | - ]], popupmenu = { - anchor = { 1, 3, 0 }, - items = { { "foo", "", "", "" }, { "foobar", "", "", "" } }, - pos = -1 - }}) - eq({completed_item = {}, width = 0, - height = 2, size = 2, - col = 0, row = 4, scrollbar = false}, - eval('g:event')) + ]], + popupmenu = { + anchor = { 1, 3, 0 }, + items = { { 'foo', '', '', '' }, { 'foobar', '', '', '' } }, + pos = -1, + }, + }) + eq( + { completed_item = {}, width = 0, height = 2, size = 2, col = 0, row = 4, scrollbar = false }, + eval('g:event') + ) feed('oob') - screen:expect({grid = [[ + screen:expect({ + grid = [[ foo | bar | foobar | foob^ | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- Keyword completion (^N^P) }{5:Back at original} | - ]], popupmenu = { - anchor = { 1, 3, 0 }, - items = { { "foobar", "", "", "" } }, - pos = -1 - }}) - eq({completed_item = {}, width = 0, - height = 1, size = 1, - col = 0, row = 4, scrollbar = false}, - eval('g:event')) + ]], + popupmenu = { + anchor = { 1, 3, 0 }, + items = { { 'foobar', '', '', '' } }, + pos = -1, + }, + }) + eq( + { completed_item = {}, width = 0, height = 1, size = 1, col = 0, row = 4, scrollbar = false }, + eval('g:event') + ) feed('<Esc>') screen:set_option('ext_popupmenu', false) @@ -1108,10 +995,10 @@ describe('completion', function() {0:~ }| {3:-- Keyword completion (^N^P) }{5:Back at original} | ]]) - eq({completed_item = {}, width = 15, - height = 2, size = 2, - col = 0, row = 4, scrollbar = false}, - eval('g:event')) + eq( + { completed_item = {}, width = 15, height = 2, size = 2, col = 0, row = 4, scrollbar = false }, + eval('g:event') + ) feed('<C-N>') screen:expect([[ foo | @@ -1164,7 +1051,7 @@ describe('completion', function() end) it('is stopped by :stopinsert from timer #12976', function() - screen:try_resize(32,14) + screen:try_resize(32, 14) command([[call setline(1, ['hello', 'hullo', 'heeee', ''])]]) feed('Gah<c-x><c-n>') screen:expect([[ @@ -1175,36 +1062,40 @@ describe('completion', function() {2:hello }{0: }| {1:hullo }{0: }| {1:heeee }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 {3:-- }{4:match 1 of 3} | ]]) command([[call timer_start(100, { -> execute('stopinsert') })]]) - helpers.sleep(200) - feed('k') -- cursor should move up in Normal mode + vim.uv.sleep(200) + feed('k') -- cursor should move up in Normal mode screen:expect([[ hello | hullo | heee^e | hello | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*9 | ]]) end) - it('does not crash if text is changed by first call to complete function #17489', function() + -- oldtest: Test_complete_changed_complete_info() + it('no crash calling complete_info() in CompleteChanged', function() + source([[ + set completeopt=menuone + autocmd CompleteChanged * call complete_info(['items']) + call feedkeys("iii\<cr>\<c-p>") + ]]) + screen:expect([[ + ii | + ii^ | + {2:ii }{0: }| + {0:~ }|*4 + {3:-- Keyword completion (^N^P) The only match} | + ]]) + assert_alive() + end) + + it('no crash if text changed by first call to complete function #17489', function() source([[ func Complete(findstart, base) abort if a:findstart @@ -1223,7 +1114,7 @@ describe('completion', function() assert_alive() end) - it('does not crash when using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function() + it('no crash using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function() feed('icolorscheme NOSUCHCOLORSCHEME<C-X><C-V>') expect('colorscheme NOSUCHCOLORSCHEME') assert_alive() @@ -1233,28 +1124,70 @@ describe('completion', function() screen:try_resize(20, 9) command('set complete+=f | edit foo | edit bar |edit foa |edit .hidden') feed('i<C-n>') - screen:expect{grid=[[ + screen:expect { + grid = [[ foo^ | {2:foo }{0: }| {1:bar }{0: }| {1:foa }{0: }| {1:.hidden }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3:-- }{4:match 1 of 4} | - ]]} + ]], + } feed('<Esc>ccf<C-n>') - screen:expect{grid=[[ + screen:expect { + grid = [[ foo^ | {2:foo }{0: }| {1:foa }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*5 {3:-- }{4:match 1 of 2} | - ]]} + ]], + } + end) + + it('restores extmarks if original text is restored #23653', function() + screen:try_resize(screen._width, 4) + command([[ + call setline(1, ['aaaa']) + let ns_id = nvim_create_namespace('extmark') + let mark_id = nvim_buf_set_extmark(0, ns_id, 0, 0, { 'end_col':2, 'hl_group':'Error'}) + let mark = nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 }) + inoremap <C-x> <C-r>=Complete()<CR> + function Complete() abort + call complete(1, [{ 'word': 'aaaaa' }]) + return '' + endfunction + ]]) + feed('A<C-X><C-E><Esc>') + eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) + feed('A<C-N>') + eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) + feed('<Esc>0Yppia<Esc>ggI<C-N>') + screen:expect([[ + aaaa{7:^aa}aa | + {2:aaaa } | + {1:aaaaa } | + {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | + ]]) + feed('<C-N><C-N><Esc>') + eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) + feed('A<C-N>') + eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) + feed('<C-N>') + screen:expect([[ + aaaaa^ | + {1:aaaa } | + {2:aaaaa } | + {3:-- Keyword completion (^N^P) }{4:match 2 of 2} | + ]]) + feed('<C-E>') + screen:expect([[ + {7:aa}aa^ | + aaaa | + aaaaa | + {3:-- INSERT --} | + ]]) end) end) |