api_functions_spec.lua (8083B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 local Screen = require('test.functional.ui.screen') 4 5 local neq, eq, command = t.neq, t.eq, n.command 6 local clear = n.clear 7 local exc_exec, expect, eval = n.exc_exec, n.expect, n.eval 8 local exec_lua = n.exec_lua 9 local insert, pcall_err = n.insert, t.pcall_err 10 local matches = t.matches 11 local api = n.api 12 local feed = n.feed 13 14 describe('eval-API', function() 15 before_each(clear) 16 17 it('work', function() 18 command("call nvim_command('let g:test = 1')") 19 eq(1, eval("nvim_get_var('test')")) 20 21 local buf = eval('nvim_get_current_buf()') 22 command('call nvim_buf_set_lines(' .. buf .. ", 0, -1, v:true, ['aa', 'bb'])") 23 expect([[ 24 aa 25 bb]]) 26 27 command('call nvim_win_set_cursor(0, [1, 1])') 28 command("call nvim_input('ax<esc>')") 29 expect([[ 30 aax 31 bb]]) 32 end) 33 34 it('throw errors for invalid arguments', function() 35 local err = exc_exec('call nvim_get_current_buf("foo")') 36 eq('Vim(call):E118: Too many arguments for function: nvim_get_current_buf', err) 37 38 err = exc_exec('call nvim_set_option_value("hlsearch")') 39 eq('Vim(call):E119: Not enough arguments for function: nvim_set_option_value', err) 40 41 err = exc_exec('call nvim_buf_set_lines(1, 0, -1, [], ["list"])') 42 eq( 43 'Vim(call):E5555: API call: Wrong type for argument 4 when calling nvim_buf_set_lines, expecting Boolean', 44 err 45 ) 46 47 err = exc_exec('call nvim_buf_set_lines(0, 0, -1, v:true, "string")') 48 eq( 49 'Vim(call):E5555: API call: Wrong type for argument 5 when calling nvim_buf_set_lines, expecting ArrayOf(String)', 50 err 51 ) 52 53 err = exc_exec('call nvim_buf_get_number("0")') 54 eq( 55 'Vim(call):E5555: API call: Wrong type for argument 1 when calling nvim_buf_get_number, expecting Buffer', 56 err 57 ) 58 59 err = exc_exec('call nvim_buf_line_count(17)') 60 eq('Vim(call):E5555: API call: Invalid buffer id: 17', err) 61 end) 62 63 it('cannot change text or window if textlocked', function() 64 command('autocmd TextYankPost <buffer> ++once call nvim_buf_set_lines(0, 0, -1, v:false, [])') 65 matches( 66 'Vim%(call%):E5555: API call: E565: Not allowed to change text or change window$', 67 pcall_err(command, 'normal! yy') 68 ) 69 70 command('autocmd TextYankPost <buffer> ++once call nvim_open_term(0, {})') 71 matches( 72 'Vim%(call%):E5555: API call: E565: Not allowed to change text or change window$', 73 pcall_err(command, 'normal! yy') 74 ) 75 76 -- Functions checking textlock should also not be usable from <expr> mappings. 77 command('inoremap <expr> <f2> nvim_win_close(0, 1)') 78 eq( 79 'Vim(normal):E5555: API call: E565: Not allowed to change text or change window', 80 pcall_err(command, [[execute "normal i\<f2>"]]) 81 ) 82 83 -- Text-changing functions gave a "Failed to save undo information" error when called from an 84 -- <expr> mapping outside do_cmdline() (msg_list == NULL), so use feed() to test this. 85 command("inoremap <expr> <f2> nvim_buf_set_text(0, 0, 0, 0, 0, ['hi'])") 86 api.nvim_set_vvar('errmsg', '') 87 feed('i<f2><esc>') 88 eq( 89 'E5555: API call: E565: Not allowed to change text or change window', 90 api.nvim_get_vvar('errmsg') 91 ) 92 93 -- Some functions checking textlock (usually those that may change the current window or buffer) 94 -- also ought to not be usable in the cmdwin. 95 local old_win = api.nvim_get_current_win() 96 feed('q:') 97 eq( 98 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', 99 pcall_err(api.nvim_set_current_win, old_win) 100 ) 101 102 -- But others, like nvim_buf_set_lines(), which just changes text, is OK. 103 api.nvim_buf_set_lines(0, 0, -1, 1, { 'wow!' }) 104 eq({ 'wow!' }, api.nvim_buf_get_lines(0, 0, -1, 1)) 105 106 -- Turning the cmdwin buffer into a terminal buffer would be pretty weird. 107 eq( 108 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', 109 pcall_err(api.nvim_open_term, 0, {}) 110 ) 111 112 matches( 113 'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$', 114 pcall_err( 115 exec_lua, 116 [[ 117 local cmdwin_buf = vim.api.nvim_get_current_buf() 118 vim._with({buf = vim.api.nvim_create_buf(false, true)}, function() 119 vim.api.nvim_open_term(cmdwin_buf, {}) 120 end) 121 ]] 122 ) 123 ) 124 125 -- But turning a different buffer into a terminal from the cmdwin is OK. 126 local term_buf = api.nvim_create_buf(false, true) 127 api.nvim_open_term(term_buf, {}) 128 eq('terminal', api.nvim_get_option_value('buftype', { buf = term_buf })) 129 end) 130 131 it('use buffer numbers and windows ids as handles', function() 132 local bnr = eval("bufnr('')") 133 local bhnd = eval('nvim_get_current_buf()') 134 local wid = eval('win_getid()') 135 local whnd = eval('nvim_get_current_win()') 136 eq(bnr, bhnd) 137 eq(wid, whnd) 138 139 command('new') -- creates new buffer and new window 140 local bnr2 = eval("bufnr('')") 141 local bhnd2 = eval('nvim_get_current_buf()') 142 local wid2 = eval('win_getid()') 143 local whnd2 = eval('nvim_get_current_win()') 144 eq(bnr2, bhnd2) 145 eq(wid2, whnd2) 146 neq(bnr, bnr2) 147 neq(wid, wid2) 148 -- 0 is synonymous to the current buffer 149 eq(bnr2, eval('nvim_buf_get_number(0)')) 150 151 command('bn') -- show old buffer in new window 152 eq(bnr, eval('nvim_get_current_buf()')) 153 eq(bnr, eval("bufnr('')")) 154 eq(bnr, eval('nvim_buf_get_number(0)')) 155 eq(wid2, eval('win_getid()')) 156 eq(whnd2, eval('nvim_get_current_win()')) 157 end) 158 159 it('get_lines and set_lines use NL to represent NUL', function() 160 api.nvim_buf_set_lines(0, 0, -1, true, { 'aa\0', 'b\0b' }) 161 eq({ 'aa\n', 'b\nb' }, eval('nvim_buf_get_lines(0, 0, -1, 1)')) 162 163 command('call nvim_buf_set_lines(0, 1, 2, v:true, ["xx", "\\nyy"])') 164 eq({ 'aa\0', 'xx', '\0yy' }, api.nvim_buf_get_lines(0, 0, -1, 1)) 165 end) 166 167 it('that are FUNC_ATTR_NOEVAL cannot be called', function() 168 -- Deprecated vim_ prefix is not exported. 169 local err = exc_exec('call vim_get_current_buffer("foo")') 170 eq('Vim(call):E117: Unknown function: vim_get_current_buffer', err) 171 172 -- Deprecated buffer_ prefix is not exported. 173 err = exc_exec('call buffer_line_count(0)') 174 eq('Vim(call):E117: Unknown function: buffer_line_count', err) 175 176 -- Functions deprecated before the api functions became available 177 -- in vimscript are not exported. 178 err = exc_exec('call buffer_get_line(0, 1)') 179 eq('Vim(call):E117: Unknown function: buffer_get_line', err) 180 181 -- some api functions are only useful from a msgpack-rpc channel 182 err = exc_exec('call nvim_set_client_info()') 183 eq('Vim(call):E117: Unknown function: nvim_set_client_info', err) 184 end) 185 186 it('have metadata accessible with api_info()', function() 187 local api_keys = eval('sort(keys(api_info()))') 188 eq({ 'error_types', 'functions', 'types', 'ui_events', 'ui_options', 'version' }, api_keys) 189 end) 190 191 it('are highlighted by vim.vim syntax file', function() 192 local screen = Screen.new(40, 8) 193 194 command('set ft=vim') 195 n.add_builddir_to_rtp() 196 command('syntax on') 197 insert([[ 198 call bufnr('%') 199 call nvim_input('typing...') 200 call not_a_function(42)]]) 201 202 screen:expect([[ 203 {15:call} {25:bufnr}{16:(}{26:'%'}{16:)} | 204 {15:call} {25:nvim_input}{16:(}{26:'typing...'}{16:)} | 205 {15:call} {9:not_a_function}{16:(}{26:42}{16:^)} | 206 {1:~ }|*4 207 | 208 ]]) 209 end) 210 211 it('cannot be called from sandbox', function() 212 eq( 213 'Vim(call):E48: Not allowed in sandbox', 214 pcall_err(command, "sandbox call nvim_input('ievil')") 215 ) 216 eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, true)) 217 end) 218 219 it('converts blobs to API strings', function() 220 command('let g:v1 = nvim__id(0z68656c6c6f)') 221 command('let g:v2 = nvim__id(v:_null_blob)') 222 eq(1, eval('type(g:v1)')) 223 eq(1, eval('type(g:v2)')) 224 eq('hello', eval('g:v1')) 225 eq('', eval('g:v2')) 226 end) 227 end)