neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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)