diff options
Diffstat (limited to 'test/functional/viml')
| -rw-r--r-- | test/functional/viml/completion_spec.lua | 802 | ||||
| -rw-r--r-- | test/functional/viml/errorlist_spec.lua | 30 | ||||
| -rw-r--r-- | test/functional/viml/function_spec.lua | 234 | ||||
| -rw-r--r-- | test/functional/viml/lang_spec.lua | 30 |
4 files changed, 750 insertions, 346 deletions
diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua index 33f481bae2..70b4717c32 100644 --- a/test/functional/viml/completion_spec.lua +++ b/test/functional/viml/completion_spec.lua @@ -2,7 +2,11 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed = helpers.clear, helpers.feed local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq -local execute, source, expect = helpers.execute, helpers.source, helpers.expect +local feed_command, source, expect = helpers.feed_command, helpers.source, helpers.expect +local curbufmeths = helpers.curbufmeths +local command = helpers.command +local meths = helpers.meths +local wait = helpers.wait describe('completion', function() local screen @@ -11,8 +15,8 @@ describe('completion', function() clear() screen = Screen.new(60, 8) screen:attach() - screen:set_default_attr_ignore({{bold=true, foreground=Screen.colors.Blue}}) 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}, @@ -20,6 +24,8 @@ describe('completion', function() [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}, }) end) @@ -32,22 +38,22 @@ describe('completion', function() screen:expect([[ foo | foo^ | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Keyword Local completion (^N^P) The only match} | ]]) feed('<C-e>') screen:expect([[ foo | ^ | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- INSERT --} | ]]) feed('<ESC>') @@ -56,38 +62,44 @@ 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 = ''}, + eq({word = 'foo', abbr = '', menu = '', + info = '', kind = '', user_data = ''}, eval('v:completed_item')) end) it('is readonly', function() screen:try_resize(80, 8) feed('ifoo<ESC>o<C-x><C-n><ESC>') - execute('let v:completed_item.word = "bar"') + feed_command('let v:completed_item.word = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') - execute('let v:completed_item.abbr = "bar"') + feed_command('let v:completed_item.abbr = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') - execute('let v:completed_item.menu = "bar"') + feed_command('let v:completed_item.menu = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') - execute('let v:completed_item.info = "bar"') + feed_command('let v:completed_item.info = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') - execute('let v:completed_item.kind = "bar"') + feed_command('let v:completed_item.kind = "bar"') neq(nil, string.find(eval('v:errmsg'), '^E46: ')) - execute('let v:errmsg = ""') + feed_command('let v:errmsg = ""') + + feed_command('let v:completed_item.user_data = "bar"') + neq(nil, string.find(eval('v:errmsg'), '^E46: ')) + feed_command('let v:errmsg = ""') end) it('returns expected dict in omni completion', function() source([[ function! TestOmni(findstart, base) abort return a:findstart ? 0 : [{'word': 'foo', 'abbr': 'bar', \ 'menu': 'baz', 'info': 'foobar', 'kind': 'foobaz'}, - \ {'word': 'word', 'abbr': 'abbr', 'menu': 'menu', 'info': 'info', 'kind': 'kind'}] + \ {'word': 'word', 'abbr': 'abbr', 'menu': 'menu', + \ 'info': 'info', 'kind': 'kind'}] endfunction setlocal omnifunc=TestOmni ]]) @@ -95,16 +107,16 @@ describe('completion', function() eq('foo', eval('getline(1)')) screen:expect([[ foo^ | - {2:bar foobaz baz } | - {1:abbr kind menu } | - ~ | - ~ | - ~ | - ~ | + {2:bar foobaz baz }{0: }| + {1:abbr kind menu }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Omni completion (^O^N^P) }{4:match 1 of 2} | ]]) eq({word = 'foo', abbr = 'bar', menu = 'baz', - info = 'foobar', kind = 'foobaz'}, + info = 'foobar', kind = 'foobaz', user_data = ''}, eval('v:completed_item')) end) end) @@ -120,16 +132,16 @@ describe('completion', function() end) it('inserts the first candidate if default', function() - execute('set completeopt+=menuone') + feed_command('set completeopt+=menuone') feed('ifoo<ESC>o') screen:expect([[ foo | ^ | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- INSERT --} | ]]) feed('<C-x>') @@ -137,22 +149,22 @@ describe('completion', function() screen:expect([[ foo | ^ | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)} | ]]) feed('<C-n>') screen:expect([[ foo | foo^ | - {2:foo } | - ~ | - ~ | - ~ | - ~ | + {2:foo }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Keyword Local completion (^N^P) The only match} | ]]) feed('bar<ESC>') @@ -162,36 +174,36 @@ describe('completion', function() foo | foobar | foo^ | - {2:foo } | - ~ | - ~ | - ~ | + {2:foo }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- INSERT --} | ]]) eq('foo', eval('getline(3)')) end) it('selects the first candidate if noinsert', function() - execute('set completeopt+=menuone,noinsert') + feed_command('set completeopt+=menuone,noinsert') feed('ifoo<ESC>o<C-x><C-n>') screen:expect([[ foo | ^ | - {2:foo } | - ~ | - ~ | - ~ | - ~ | + {2:foo }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Keyword Local completion (^N^P) The only match} | ]]) feed('<C-y>') screen:expect([[ foo | foo^ | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- INSERT --} | ]]) feed('<ESC>') @@ -201,37 +213,37 @@ describe('completion', function() foo | foo | ^ | - {2:foo } | - ~ | - ~ | - ~ | + {2:foo }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- INSERT --} | ]]) feed('<C-y><ESC>') eq('foo', eval('getline(3)')) end) it('does not insert the first candidate if noselect', function() - execute('set completeopt+=menuone,noselect') + feed_command('set completeopt+=menuone,noselect') feed('ifoo<ESC>o<C-x><C-n>') screen:expect([[ foo | ^ | - {1:foo } | - ~ | - ~ | - ~ | - ~ | + {1:foo }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Keyword Local completion (^N^P) }{5:Back at original} | ]]) feed('b') screen:expect([[ foo | b^ | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Keyword Local completion (^N^P) }{5:Back at original} | ]]) feed('ar<ESC>') @@ -241,37 +253,37 @@ describe('completion', function() foo | bar | ^ | - {1:foo } | - ~ | - ~ | - ~ | + {1:foo }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- INSERT --} | ]]) feed('bar<ESC>') eq('bar', eval('getline(3)')) end) it('does not select/insert the first candidate if noselect and noinsert', function() - execute('set completeopt+=menuone,noselect,noinsert') + feed_command('set completeopt+=menuone,noselect,noinsert') feed('ifoo<ESC>o<C-x><C-n>') screen:expect([[ foo | ^ | - {1:foo } | - ~ | - ~ | - ~ | - ~ | + {1:foo }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Keyword Local completion (^N^P) }{5:Back at original} | ]]) feed('<ESC>') screen:expect([[ foo | ^ | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| | ]]) eq('', eval('getline(2)')) @@ -280,10 +292,10 @@ describe('completion', function() foo | | ^ | - {1:foo } | - ~ | - ~ | - ~ | + {1:foo }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- INSERT --} | ]]) feed('<ESC>') @@ -291,28 +303,84 @@ describe('completion', function() foo | | ^ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| | ]]) eq('', eval('getline(3)')) end) it('does not change modified state if noinsert', function() - execute('set completeopt+=menuone,noinsert') - execute('setlocal nomodified') + feed_command('set completeopt+=menuone,noinsert') + feed_command('setlocal nomodified') feed('i<C-r>=TestComplete()<CR><ESC>') eq(0, eval('&l:modified')) end) it('does not change modified state if noselect', function() - execute('set completeopt+=menuone,noselect') - execute('setlocal nomodified') + feed_command('set completeopt+=menuone,noselect') + feed_command('setlocal nomodified') feed('i<C-r>=TestComplete()<CR><ESC>') eq(0, eval('&l:modified')) end) end) + describe('completeopt+=noinsert does not add blank undo items', function() + before_each(function() + source([[ + function! TestComplete() abort + call complete(1, ['foo', 'bar']) + return '' + endfunction + ]]) + feed_command('set completeopt+=noselect,noinsert') + feed_command('inoremap <right> <c-r>=TestComplete()<cr>') + end) + + local tests = { + ['<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 + it('using ' .. name, function() + feed('iaaa<esc>') + feed('A<right>' .. seq[1] .. '<esc>') + feed('A<right><esc>A<right><esc>') + feed('A<cr>bbb<esc>') + feed('A<right>' .. seq[2] .. '<esc>') + feed('A<right><esc>A<right><esc>') + feed('A<cr>ccc<esc>') + feed('A<right>' .. seq[1] .. '<esc>') + feed('A<right><esc>A<right><esc>') + + local expected = { + {'foo', 'bar', 'foo'}, + {'foo', 'bar', 'ccc'}, + {'foo', 'bar'}, + {'foo', 'bbb'}, + {'foo'}, + {'aaa'}, + {''}, + } + + for i = 1, #expected do + if i > 1 then + feed('u') + end + eq(expected[i], eval('getline(1, "$")')) + end + + for i = #expected, 1, -1 do + if i < #expected then + feed('<c-r>') + end + eq(expected[i], eval('getline(1, "$")')) + end + end) + end + end) + describe("refresh:always", function() before_each(function() source([[ @@ -344,56 +412,56 @@ describe('completion', function() feed('i<C-x><C-u>') screen:expect([[ ^ | - {1:January }{6: } | - {1:February }{6: } | - {1:March }{6: } | - {1:April }{2: } | - {1:May }{2: } | - {1:June }{2: } | + {1:January }{6: }{0: }| + {1:February }{6: }{0: }| + {1:March }{6: }{0: }| + {1:April }{2: }{0: }| + {1:May }{2: }{0: }| + {1:June }{2: }{0: }| {3:-- User defined completion (^U^N^P) }{5:Back at original} | ]]) feed('u') screen:expect([[ u^ | - {1:January } | - {1:February } | - {1:June } | - {1:July } | - {1:August } | - ~ | + {1:January }{0: }| + {1:February }{0: }| + {1:June }{0: }| + {1:July }{0: }| + {1:August }{0: }| + {0:~ }| {3:-- User defined completion (^U^N^P) }{5:Back at original} | ]]) feed('g') screen:expect([[ ug^ | - {1:August } | - ~ | - ~ | - ~ | - ~ | - ~ | + {1:August }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- User defined completion (^U^N^P) }{5:Back at original} | ]]) feed('<Down>') screen:expect([[ ug^ | - {2:August } | - ~ | - ~ | - ~ | - ~ | - ~ | + {2:August }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- User defined completion (^U^N^P) The only match} | ]]) feed('<C-y>') screen:expect([[ August^ | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- INSERT --} | ]]) expect('August') @@ -403,55 +471,55 @@ describe('completion', function() screen:expect([[ | Ja^ | - {1:January } | - ~ | - ~ | - ~ | - ~ | + {1:January }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- User defined completion (^U^N^P) }{5:Back at original} | ]]) feed('<BS>') screen:expect([[ | J^ | - {1:January } | - {1:June } | - {1:July } | - ~ | - ~ | + {1:January }{0: }| + {1:June }{0: }| + {1:July }{0: }| + {0:~ }| + {0:~ }| {3:-- User defined completion (^U^N^P) }{5:Back at original} | ]]) feed('<C-n>') screen:expect([[ | January^ | - {2:January } | - {1:June } | - {1:July } | - ~ | - ~ | + {2:January }{0: }| + {1:June }{0: }| + {1:July }{0: }| + {0:~ }| + {0:~ }| {3:-- User defined completion (^U^N^P) }{4:match 1 of 3} | ]]) feed('<C-n>') screen:expect([[ | June^ | - {1:January } | - {2:June } | - {1:July } | - ~ | - ~ | + {1:January }{0: }| + {2:June }{0: }| + {1:July }{0: }| + {0:~ }| + {0:~ }| {3:-- User defined completion (^U^N^P) }{4:match 2 of 3} | ]]) feed('<Esc>') screen:expect([[ | Jun^e | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| | ]]) feed('.') @@ -459,14 +527,14 @@ describe('completion', function() | June | Jun^e | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| | ]]) expect([[ - + June June]]) end) @@ -480,52 +548,52 @@ describe('completion', function() return '' endfunction ]]) - execute("set completeopt=menuone,noselect") + feed_command("set completeopt=menuone,noselect") end) it("works", function() feed('i<C-r>=TestComplete()<CR>') screen:expect([[ ^ | - {1:0 }{6: } | - {1:1 }{2: } | - {1:2 }{2: } | - {1:3 }{2: } | - {1:4 }{2: } | - {1:5 }{2: } | + {1:0 }{6: }{0: }| + {1:1 }{2: }{0: }| + {1:2 }{2: }{0: }| + {1:3 }{2: }{0: }| + {1:4 }{2: }{0: }| + {1:5 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('7') screen:expect([[ 7^ | - {1:7 }{6: } | - {1:70 }{6: } | - {1:71 }{6: } | - {1:72 }{2: } | - {1:73 }{2: } | - {1:74 }{2: } | + {1:7 }{6: }{0: }| + {1:70 }{6: }{0: }| + {1:71 }{6: }{0: }| + {1:72 }{2: }{0: }| + {1:73 }{2: }{0: }| + {1:74 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('<c-n>') screen:expect([[ 7^ | - {2:7 }{6: } | - {1:70 }{6: } | - {1:71 }{6: } | - {1:72 }{2: } | - {1:73 }{2: } | - {1:74 }{2: } | + {2:7 }{6: }{0: }| + {1:70 }{6: }{0: }| + {1:71 }{6: }{0: }| + {1:72 }{2: }{0: }| + {1:73 }{2: }{0: }| + {1:74 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('<c-n>') screen:expect([[ 70^ | - {1:7 }{6: } | - {2:70 }{6: } | - {1:71 }{6: } | - {1:72 }{2: } | - {1:73 }{2: } | - {1:74 }{2: } | + {1:7 }{6: }{0: }| + {2:70 }{6: }{0: }| + {1:71 }{6: }{0: }| + {1:72 }{2: }{0: }| + {1:73 }{2: }{0: }| + {1:74 }{2: }{0: }| {3:-- INSERT --} | ]]) end) @@ -534,111 +602,111 @@ describe('completion', function() feed('i<C-r>=TestComplete()<CR>') screen:expect([[ ^ | - {1:0 }{6: } | - {1:1 }{2: } | - {1:2 }{2: } | - {1:3 }{2: } | - {1:4 }{2: } | - {1:5 }{2: } | + {1:0 }{6: }{0: }| + {1:1 }{2: }{0: }| + {1:2 }{2: }{0: }| + {1:3 }{2: }{0: }| + {1:4 }{2: }{0: }| + {1:5 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('<PageDown>') screen:expect([[ ^ | - {1:0 }{6: } | - {1:1 }{2: } | - {1:2 }{2: } | - {2:3 } | - {1:4 }{2: } | - {1:5 }{2: } | + {1:0 }{6: }{0: }| + {1:1 }{2: }{0: }| + {1:2 }{2: }{0: }| + {2:3 }{0: }| + {1:4 }{2: }{0: }| + {1:5 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('<PageDown>') screen:expect([[ ^ | - {1:5 }{6: } | - {1:6 }{2: } | - {2:7 } | - {1:8 }{2: } | - {1:9 }{2: } | - {1:10 }{2: } | + {1:5 }{6: }{0: }| + {1:6 }{2: }{0: }| + {2:7 }{0: }| + {1:8 }{2: }{0: }| + {1:9 }{2: }{0: }| + {1:10 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('<Down>') screen:expect([[ ^ | - {1:5 }{6: } | - {1:6 }{2: } | - {1:7 }{2: } | - {2:8 } | - {1:9 }{2: } | - {1:10 }{2: } | + {1:5 }{6: }{0: }| + {1:6 }{2: }{0: }| + {1:7 }{2: }{0: }| + {2:8 }{0: }| + {1:9 }{2: }{0: }| + {1:10 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('<PageUp>') screen:expect([[ ^ | - {1:2 }{6: } | - {1:3 }{2: } | - {2:4 } | - {1:5 }{2: } | - {1:6 }{2: } | - {1:7 }{2: } | + {1:2 }{6: }{0: }| + {1:3 }{2: }{0: }| + {2:4 }{0: }| + {1:5 }{2: }{0: }| + {1:6 }{2: }{0: }| + {1:7 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('<PageUp>') -- stop on first item screen:expect([[ ^ | - {2:0 }{6: } | - {1:1 }{2: } | - {1:2 }{2: } | - {1:3 }{2: } | - {1:4 }{2: } | - {1:5 }{2: } | + {2:0 }{6: }{0: }| + {1:1 }{2: }{0: }| + {1:2 }{2: }{0: }| + {1:3 }{2: }{0: }| + {1:4 }{2: }{0: }| + {1:5 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('<PageUp>') -- when on first item, unselect screen:expect([[ ^ | - {1:0 }{6: } | - {1:1 }{2: } | - {1:2 }{2: } | - {1:3 }{2: } | - {1:4 }{2: } | - {1:5 }{2: } | + {1:0 }{6: }{0: }| + {1:1 }{2: }{0: }| + {1:2 }{2: }{0: }| + {1:3 }{2: }{0: }| + {1:4 }{2: }{0: }| + {1:5 }{2: }{0: }| {3:-- INSERT --} | ]]) feed('<PageUp>') -- when unselected, select last item screen:expect([[ ^ | - {1:95 }{2: } | - {1:96 }{2: } | - {1:97 }{2: } | - {1:98 }{2: } | - {1:99 }{2: } | - {2:100 }{6: } | + {1:95 }{2: }{0: }| + {1:96 }{2: }{0: }| + {1:97 }{2: }{0: }| + {1:98 }{2: }{0: }| + {1:99 }{2: }{0: }| + {2:100 }{6: }{0: }| {3:-- INSERT --} | ]]) feed('<PageUp>') screen:expect([[ ^ | - {1:94 }{2: } | - {1:95 }{2: } | - {2:96 } | - {1:97 }{2: } | - {1:98 }{2: } | - {1:99 }{6: } | + {1:94 }{2: }{0: }| + {1:95 }{2: }{0: }| + {2:96 }{0: }| + {1:97 }{2: }{0: }| + {1:98 }{2: }{0: }| + {1:99 }{6: }{0: }| {3:-- INSERT --} | ]]) feed('<cr>') screen:expect([[ 96^ | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- INSERT --} | ]]) end) @@ -646,74 +714,74 @@ describe('completion', function() it('disables folding during completion', function () - execute("set foldmethod=indent") + feed_command("set foldmethod=indent") feed('i<Tab>foo<CR><Tab>bar<Esc>gg') screen:expect([[ ^foo | bar | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| | ]]) feed('A<C-x><C-l>') screen:expect([[ foo^ | bar | - ~ | - ~ | - ~ | - ~ | - ~ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {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 () - execute("set complete=.") + feed_command("set complete=.") feed('ifoobar fooegg<cr>f<c-p>') screen:expect([[ foobar fooegg | fooegg^ | - {1:foobar } | - {2:fooegg } | - ~ | - ~ | - ~ | + {1:foobar }{0: }| + {2:fooegg }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | ]]) eval('1 + 1') -- popupmenu still visible - screen:expect([[ + screen:expect{grid=[[ foobar fooegg | fooegg^ | - {1:foobar } | - {2:fooegg } | - ~ | - ~ | - ~ | + {1:foobar }{0: }| + {2:fooegg }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | - ]]) + ]], unchanged=true} feed('<c-p>') -- Didn't restart completion: old matches still used screen:expect([[ foobar fooegg | foobar^ | - {2:foobar } | - {1:fooegg } | - ~ | - ~ | - ~ | + {2:foobar }{0: }| + {1:fooegg }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| {3:-- Keyword completion (^N^P) }{4:match 2 of 2} | ]]) end) - + describe('from the commandline window', function() it('is cleared after CTRL-C', function () @@ -722,43 +790,173 @@ describe('completion', function() screen:expect([[ | {8:[No Name] }| - :foo faa fee f^ | - :~ | - :~ | - :~ | + {0::}foo faa fee f^ | + {0::~ }| + {0::~ }| + {0::~ }| {9:[Command Line] }| {3:-- INSERT --} | - ]], {[3] = {bold = true}, - [4] = {bold = true, foreground = Screen.colors.SeaGreen}, - [8] = {reverse = true}, - [9] = {bold = true, reverse = true}}) + ]] ) feed('<c-x><c-n>') screen:expect([[ | {8:[No Name] }| - :foo faa fee foo^ | - :~ {2: foo } | - :~ {1: faa } | - :~ {1: fee } | + {0::}foo faa fee foo^ | + {0::~ }{2: foo }{0: }| + {0::~ }{1: faa }{0: }| + {0::~ }{1: fee }{0: }| {9:[Command Line] }| {3:-- Keyword Local completion (^N^P) }{4:match 1 of 3} | - ]],{[1] = {background = Screen.colors.LightMagenta}, - [2] = {background = Screen.colors.Grey}, - [3] = {bold = true}, - [4] = {bold = true, foreground = Screen.colors.SeaGreen}, - [8] = {reverse = true}, - [9] = {bold = true, reverse = true}}) + ]]) feed('<c-c>') screen:expect([[ | {8:[No Name] }| - :foo faa fee foo | - :~ | - :~ | - :~ | + {0::}foo faa fee foo | + {0::~ }| + {0::~ }| + {0::~ }| {9:[Command Line] }| :foo faa fee foo^ | - ]], {[8] = {reverse = true}, [9] = {bold = true, reverse = true}}) + ]]) end) end) + + describe('with numeric items', function() + before_each(function() + source([[ + function! TestComplete() abort + call complete(1, g:_complist) + return '' + endfunction + ]]) + meths.set_option('completeopt', 'menuone,noselect') + meths.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() + feed('i<C-r>=TestComplete()<CR>') + screen:expect([[ + ^ | + {1:1 3 2 }{0: }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {3:-- INSERT --} | + ]]) + end) + end) + + it("'ignorecase' 'infercase' CTRL-X CTRL-N #6451", function() + feed_command('set ignorecase infercase') + feed_command('edit BACKERS.md') + feed('oX<C-X><C-N>') + screen:expect([[ + # Bountysource Backers | + Xnull^ | + {2:Xnull }{6: } | + {1:Xoxomoon }{6: }ryone who backed our [Bountysource fundraise| + {1:Xu }{6: }ountysource.com/teams/neovim/fundraiser)! | + {1:Xpayn }{2: } | + {1:Xinity }{2: }d URL in BACKERS.md. | + {3:-- Keyword Local completion (^N^P) }{4:match 1 of 7} | + ]]) + end) + + it('TextChangedP autocommand', function() + curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar'}) + source([[ + set complete=. completeopt=menuone + let g:foo = [] + autocmd! TextChanged * :call add(g:foo, "N") + autocmd! TextChangedI * :call add(g:foo, "I") + autocmd! TextChangedP * :call add(g:foo, "P") + call cursor(3, 1) + ]]) + + command('let g:foo = []') + feed('o') + wait() + feed('<esc>') + eq({'I'}, eval('g:foo')) + + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + eq({'I', 'I'}, eval('g:foo')) + feed('<esc>') + + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + feed('<C-N>') + wait() + eq({'I', 'I', 'P'}, eval('g:foo')) + feed('<esc>') + + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + eq({'I', 'I', 'P', 'P'}, eval('g:foo')) + feed('<esc>') + + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + eq({'I', 'I', 'P', 'P', 'P'}, eval('g:foo')) + feed('<esc>') + + command('let g:foo = []') + feed('S') + wait() + feed('f') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + wait() + feed('<C-N>') + eq({'I', 'I', 'P', 'P', 'P', 'P'}, eval('g:foo')) + feed('<esc>') + + eq({'foo', 'bar', 'foobar', 'foo'}, eval('getline(1, "$")')) + + source([[ + au! TextChanged + au! TextChangedI + au! TextChangedP + set complete&vim completeopt&vim + ]]) + end) end) diff --git a/test/functional/viml/errorlist_spec.lua b/test/functional/viml/errorlist_spec.lua index 56d08771b7..6c5a63e6b1 100644 --- a/test/functional/viml/errorlist_spec.lua +++ b/test/functional/viml/errorlist_spec.lua @@ -18,29 +18,27 @@ describe('setqflist()', function() end) it('requires a string for {action}', function() - eq('Vim(call):E114: String required', exc_exec('call setqflist([], 5)')) - eq('Vim(call):E114: String required', exc_exec('call setqflist([], [])')) - eq('Vim(call):E114: String required', exc_exec('call setqflist([], {})')) + eq('Vim(call):E928: String required', exc_exec('call setqflist([], 5)')) + eq('Vim(call):E928: String required', exc_exec('call setqflist([], [])')) + eq('Vim(call):E928: String required', exc_exec('call setqflist([], {})')) end) it('sets w:quickfix_title', function() setqflist({''}, 'r', 'foo') command('copen') eq(':foo', get_cur_win_var('quickfix_title')) + setqflist({''}, 'r', {['title'] = 'qf_title'}) + eq('qf_title', get_cur_win_var('quickfix_title')) end) - it('requires string or number for {title}', function() - command('copen') + it('allows string {what} for backwards compatibility', function() setqflist({}, 'r', '5') + command('copen') eq(':5', get_cur_win_var('quickfix_title')) - setqflist({}, 'r', 6) - eq(':6', get_cur_win_var('quickfix_title')) - local exc = exc_exec('call setqflist([], "r", function("function"))') - eq('Vim(call):E729: using Funcref as a String', exc) - exc = exc_exec('call setqflist([], "r", [])') - eq('Vim(call):E730: using List as a String', exc) - exc = exc_exec('call setqflist([], "r", {})') - eq('Vim(call):E731: using Dictionary as a String', exc) + end) + + it('requires a dict for {what}', function() + eq('Vim(call):E715: Dictionary required', exc_exec('call setqflist([], "r", function("function"))')) end) end) @@ -56,9 +54,9 @@ describe('setloclist()', function() end) it('requires a string for {action}', function() - eq('Vim(call):E114: String required', exc_exec('call setloclist(0, [], 5)')) - eq('Vim(call):E114: String required', exc_exec('call setloclist(0, [], [])')) - eq('Vim(call):E114: String required', exc_exec('call setloclist(0, [], {})')) + eq('Vim(call):E928: String required', exc_exec('call setloclist(0, [], 5)')) + eq('Vim(call):E928: String required', exc_exec('call setloclist(0, [], [])')) + eq('Vim(call):E928: String required', exc_exec('call setloclist(0, [], {})')) end) it('sets w:quickfix_title for the correct window', function() diff --git a/test/functional/viml/function_spec.lua b/test/functional/viml/function_spec.lua index f0a4406593..b8137038b1 100644 --- a/test/functional/viml/function_spec.lua +++ b/test/functional/viml/function_spec.lua @@ -1,38 +1,216 @@ local helpers = require('test.functional.helpers')(after_each) -local clear = helpers.clear local eq = helpers.eq -local eval = helpers.eval -local exc_exec = helpers.exc_exec +local clear = helpers.clear +local dedent = helpers.dedent +local redir_exec = helpers.redir_exec -describe('Up to MAX_FUNC_ARGS arguments are handled by', function() - local max_func_args = 20 -- from eval.h - local range = helpers.funcs.range +before_each(clear) - before_each(clear) +local function check_func(fname, body, indent) + if type(body) == 'number' then + body = ('return %i'):format(body) + end + eq(dedent(([[ - it('printf()', function() - local printf = helpers.funcs.printf - local rep = helpers.funcs['repeat'] - local expected = '2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,' - eq(expected, printf(rep('%d,', max_func_args-1), unpack(range(2, max_func_args)))) - local ret = exc_exec('call printf("", 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)') - eq('Vim(call):E740: Too many arguments for function printf', ret) - end) + function %s()%s + endfunction]] + ), 3):format( + fname, + body and ('\n1' .. (' '):rep(2 + (indent or 8)) .. body) or ''), + redir_exec('function ' .. fname)) +end - it('rpcnotify()', function() - local rpcnotify = helpers.funcs.rpcnotify - local ret = rpcnotify(0, 'foo', unpack(range(3, max_func_args))) - eq(1, ret) - ret = exc_exec('call rpcnotify(0, "foo", 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)') - eq('Vim(call):E740: Too many arguments for function rpcnotify', ret) +describe(':endfunction', function() + it('accepts bang', function() + eq('', redir_exec([[ + function F() + endfunction! + ]])) + check_func('F') + eq('', redir_exec([[ + function! F() + return 1 + endfunction! + ]])) + check_func('F', 1) end) -end) - -describe('api_info()', function() - before_each(clear) - it('has the right keys', function() - local api_keys = eval("sort(keys(api_info()))") - eq({'error_types', 'functions', 'types'}, api_keys) + it('accepts comments', function() + eq('', redir_exec([[ + function F1() + endfunction " Comment + ]])) + check_func('F1') + eq('', redir_exec([[ + function F2() + endfunction " }}} + ]])) + check_func('F2') + eq('', redir_exec([[ + function F3() + endfunction " F3 + ]])) + check_func('F3') + eq('', redir_exec([[ + function F4() + endfunction! " F4 + ]])) + check_func('F4') + eq('', redir_exec([[ + function! F4() + return 2 + endfunction! " F4 + ]])) + check_func('F4', 2) + end) + it('accepts function name', function() + eq('', redir_exec([[ + function F0() + endfunction F0 + ]])) + check_func('F0') + eq('', redir_exec([[ + function F1() + endfunction! F1 + ]])) + check_func('F1') + eq('', redir_exec([[ + function! F2() + endfunction! F2 + ]])) + check_func('F2') + eq('', redir_exec([[ + function! F2() + return 3 + endfunction! F2 + ]])) + check_func('F2', 3) + end) + it('accepts weird characters', function() + eq('', redir_exec([[ + function F1() + endfunction: }}} + ]])) + check_func('F1') + -- From accurev + eq('', redir_exec([[ + function F2() + endfunction :}}} + ]])) + check_func('F2') + -- From cream-vimabbrev + eq('', redir_exec([[ + function F3() + endfunction 1}}} + ]])) + check_func('F3') + -- From pyunit + eq('', redir_exec([[ + function F4() + endfunction # }}} + ]])) + check_func('F4') + -- From vim-lldb + eq('', redir_exec([[ + function F5() + endfunction() + ]])) + check_func('F5') + -- From vim-mail + eq('', redir_exec([[ + function F6() + endfunction; + ]])) + check_func('F6') + end) + it('accepts commented bar', function() + eq('', redir_exec([[ + function F1() + endfunction " F1 | echo 42 + ]])) + check_func('F1') + eq('', redir_exec([[ + function! F1() + return 42 + endfunction! " F1 | echo 42 + ]])) + check_func('F1', 42) + end) + it('accepts uncommented bar', function() + eq('\n42', redir_exec([[ + function F1() + endfunction | echo 42 + ]])) + check_func('F1') + end) + it('allows running multiple commands', function() + eq('\n2', redir_exec([[ + function F1() + echo 2 + endfunction + call F1() + ]])) + check_func('F1', 'echo 2') + eq('\n2\n3\n4', redir_exec([[ + function F2() + echo 2 + endfunction F2 + function F3() + echo 3 + endfunction " F3 + function! F4() + echo 4 + endfunction! + call F2() + call F3() + call F4() + ]])) + check_func('F2', 'echo 2') + check_func('F3', 'echo 3') + check_func('F4', 'echo 4') + end) + it('allows running multiple commands with only one character in between', + function() + eq('\n3', redir_exec(dedent([[ + function! F1() + echo 3 + endfunction! + call F1()]]))) + check_func('F1', 'echo 3', 2) + eq('\n4', redir_exec(dedent([[ + function F5() + echo 4 + endfunction + call F5()]]))) + check_func('F5', 'echo 4', 2) + eq('\n5', redir_exec(dedent([[ + function F6() + echo 5 + endfunction " TEST + call F6()]]))) + check_func('F6', 'echo 5', 2) + eq('\n6', redir_exec(dedent([[ + function F7() + echo 6 + endfunction F7 + call F7()]]))) + check_func('F7', 'echo 6', 2) + eq('\n2\n3\n4', redir_exec(dedent([[ + function F2() + echo 2 + endfunction F2 + function F3() + echo 3 + endfunction " F3 + function! F4() + echo 4 + endfunction! + call F2() + call F3() + call F4()]]))) + check_func('F2', 'echo 2', 2) + check_func('F3', 'echo 3', 2) + check_func('F4', 'echo 4', 2) end) end) +-- vim: foldmarker=▶,▲ diff --git a/test/functional/viml/lang_spec.lua b/test/functional/viml/lang_spec.lua new file mode 100644 index 0000000000..6d603b8822 --- /dev/null +++ b/test/functional/viml/lang_spec.lua @@ -0,0 +1,30 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq +local exc_exec, source = helpers.exc_exec, helpers.source + +describe('viml', function() + before_each(clear) + + it('parses `<SID>` with turkish locale', function() + if exc_exec('lang ctype tr_TR.UTF-8') ~= 0 then + pending("Locale tr_TR.UTF-8 not supported") + return + end + source([[ + func! <sid>_dummy_function() + echo 1 + endfunc + au VimEnter * call <sid>_dummy_function() + ]]) + eq(nil, string.find(eval('v:errmsg'), '^E129')) + end) + + it('str2float is not affected by locale', function() + if exc_exec('lang ctype sv_SE.UTF-8') ~= 0 then + pending("Locale sv_SE.UTF-8 not supported") + return + end + clear{env={LANG="", LC_NUMERIC="sv_SE.UTF-8"}} + eq(2.2, eval('str2float("2.2")')) + end) +end) |