2016-04-23 16:53:11 -07:00
local helpers = require ( ' test.functional.helpers ' ) ( after_each )
2015-07-27 04:39:38 -07:00
local Screen = require ( ' test.functional.ui.screen ' )
2017-11-04 16:41:44 -07:00
2021-09-01 07:29:38 -07:00
local fmt = string.format
2021-09-01 09:42:53 -07:00
local assert_alive = helpers.assert_alive
2016-04-26 12:14:33 -07:00
local NIL = helpers.NIL
2015-07-27 04:39:38 -07:00
local clear , nvim , eq , neq = helpers.clear , helpers.nvim , helpers.eq , helpers.neq
2018-05-02 14:38:18 -07:00
local command = helpers.command
2018-05-06 18:24:01 -07:00
local eval = helpers.eval
2019-08-19 14:43:19 -07:00
local expect = helpers.expect
2018-05-02 14:38:18 -07:00
local funcs = helpers.funcs
local iswin = helpers.iswin
local meths = helpers.meths
2019-09-06 17:17:37 -07:00
local matches = helpers.matches
2021-10-02 01:37:30 -07:00
local mkdir_p = helpers.mkdir_p
2015-07-27 04:39:38 -07:00
local ok , nvim_async , feed = helpers.ok , helpers.nvim_async , helpers.feed
2019-09-04 06:58:04 -07:00
local is_os = helpers.is_os
2019-07-17 13:00:50 -07:00
local parse_context = helpers.parse_context
2016-06-28 12:45:19 -07:00
local request = helpers.request
2021-10-02 01:37:30 -07:00
local rmdir = helpers.rmdir
2018-05-02 14:38:18 -07:00
local source = helpers.source
2018-12-01 08:44:36 -07:00
local next_msg = helpers.next_msg
2019-12-01 23:26:36 -07:00
local tmpname = helpers.tmpname
2019-10-06 19:40:36 -07:00
local write_file = helpers.write_file
2020-12-24 15:15:20 -07:00
local exec_lua = helpers.exec_lua
2021-12-16 04:40:23 -07:00
local exc_exec = helpers.exc_exec
2014-10-08 09:56:01 -07:00
2019-09-03 13:51:45 -07:00
local pcall_err = helpers.pcall_err
2019-05-18 05:09:43 -07:00
local format_string = helpers.format_string
local intchar2lua = helpers.intchar2lua
local mergedicts_copy = helpers.mergedicts_copy
2020-01-25 05:29:52 -07:00
local endswith = helpers.endswith
2017-11-04 16:41:44 -07:00
2018-06-07 01:56:44 -07:00
describe ( ' API ' , function ( )
2014-10-08 09:56:01 -07:00
before_each ( clear )
2018-06-07 01:56:44 -07:00
it ( ' validates requests ' , function ( )
2018-08-29 22:50:18 -07:00
-- RPC
2019-09-06 17:17:37 -07:00
matches ( ' Invalid method: bogus$ ' ,
pcall_err ( request , ' bogus ' ) )
matches ( ' Invalid method: … の り 。…$ ' ,
pcall_err ( request , ' … の り 。… ' ) )
matches ( ' Invalid method: <empty>$ ' ,
pcall_err ( request , ' ' ) )
2018-08-29 22:50:18 -07:00
-- Non-RPC: rpcrequest(v:servername) uses internal channel.
2019-09-06 17:17:37 -07:00
matches ( ' Invalid method: … の り 。…$ ' ,
pcall_err ( request , ' nvim_eval ' ,
[=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), '… の り 。…')]=] ) )
matches ( ' Invalid method: bogus$ ' ,
pcall_err ( request , ' nvim_eval ' ,
[=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), 'bogus')]=] ) )
2018-08-29 22:50:18 -07:00
-- XXX: This must be the last one, else next one will fail:
-- "Packer instance already working. Use another Packer ..."
2019-09-06 17:17:37 -07:00
matches ( " can't serialize object$ " ,
pcall_err ( request , nil ) )
2018-06-07 01:56:44 -07:00
end )
2018-12-01 08:44:36 -07:00
it ( ' handles errors in async requests ' , function ( )
local error_types = meths.get_api_info ( ) [ 2 ] . error_types
2019-04-12 17:13:29 -07:00
nvim_async ( ' bogus ' )
2018-12-01 08:44:36 -07:00
eq ( { ' notification ' , ' nvim_error_event ' ,
{ error_types.Exception . id , ' Invalid method: nvim_bogus ' } } , next_msg ( ) )
-- error didn't close channel.
2021-09-01 09:42:53 -07:00
assert_alive ( )
2018-12-01 08:44:36 -07:00
end )
2019-04-12 17:13:29 -07:00
it ( ' failed async request emits nvim_error_event ' , function ( )
local error_types = meths.get_api_info ( ) [ 2 ] . error_types
nvim_async ( ' command ' , ' bogus ' )
eq ( { ' notification ' , ' nvim_error_event ' ,
{ error_types.Exception . id , ' Vim:E492: Not an editor command: bogus ' } } ,
next_msg ( ) )
-- error didn't close channel.
2021-09-01 09:42:53 -07:00
assert_alive ( )
2019-04-12 17:13:29 -07:00
end )
2019-04-07 17:33:00 -07:00
it ( ' does not set CA_COMMAND_BUSY #7254 ' , function ( )
nvim ( ' command ' , ' split ' )
nvim ( ' command ' , ' autocmd WinEnter * startinsert ' )
nvim ( ' command ' , ' wincmd w ' )
eq ( { mode = ' i ' , blocking = false } , nvim ( " get_mode " ) )
end )
2019-12-01 23:26:36 -07:00
describe ( ' nvim_exec ' , function ( )
2019-10-06 19:40:36 -07:00
it ( ' one-line input ' , function ( )
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , " let x1 = 'a' " , false )
2019-10-06 19:40:36 -07:00
eq ( ' a ' , nvim ( ' get_var ' , ' x1 ' ) )
2019-10-06 13:37:54 -07:00
end )
2019-10-06 19:40:36 -07:00
it ( ' :verbose set {option}? ' , function ( )
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , ' set nowrap ' , false )
2021-10-13 16:40:46 -07:00
eq ( ' nowrap \n \t Last set from anonymous :source ' ,
nvim ( ' exec ' , ' verbose set wrap? ' , true ) )
-- Using script var to force creation of a script item
nvim ( ' exec ' , [ [
let s : a = 1
set nowrap
] ] , false )
2021-10-09 14:13:11 -07:00
eq ( ' nowrap \n \t Last set from anonymous :source (script id 1) ' ,
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , ' verbose set wrap? ' , true ) )
2019-10-06 13:37:54 -07:00
end )
2019-10-06 19:40:36 -07:00
it ( ' multiline input ' , function ( )
-- Heredoc + empty lines.
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , " let x2 = 'a' \n " , false )
2019-10-06 19:40:36 -07:00
eq ( ' a ' , nvim ( ' get_var ' , ' x2 ' ) )
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , ' lua <<EOF \n \n \n \n y=3 \n \n \n EOF ' , false )
2019-10-06 19:40:36 -07:00
eq ( 3 , nvim ( ' eval ' , " luaeval('y') " ) )
2019-10-06 13:37:54 -07:00
2019-12-01 23:26:36 -07:00
eq ( ' ' , nvim ( ' exec ' , ' lua <<EOF \n y=3 \n EOF ' , false ) )
2019-10-06 19:40:36 -07:00
eq ( 3 , nvim ( ' eval ' , " luaeval('y') " ) )
-- Multiple statements
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , ' let x1=1 \n let x2=2 \n let x3=3 \n ' , false )
2019-10-06 19:40:36 -07:00
eq ( 1 , nvim ( ' eval ' , ' x1 ' ) )
eq ( 2 , nvim ( ' eval ' , ' x2 ' ) )
eq ( 3 , nvim ( ' eval ' , ' x3 ' ) )
-- Functions
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , ' function Foo() \n call setline(1,["xxx"]) \n endfunction ' , false )
2019-10-06 19:40:36 -07:00
eq ( nvim ( ' get_current_line ' ) , ' ' )
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , ' call Foo() ' , false )
2019-10-06 19:40:36 -07:00
eq ( nvim ( ' get_current_line ' ) , ' xxx ' )
-- Autocmds
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , ' autocmd BufAdd * :let x1 = "Hello" ' , false )
2019-10-06 19:40:36 -07:00
nvim ( ' command ' , ' new foo ' )
eq ( ' Hello ' , request ( ' nvim_eval ' , ' g:x1 ' ) )
2021-09-14 16:35:33 -07:00
-- Line continuations
nvim ( ' exec ' , [ [
let abc = # {
\ a : 1 ,
" \ b: 2,
\ c : 3
\ } ] ] , false )
eq ( { a = 1 , c = 3 } , request ( ' nvim_eval ' , ' g:abc ' ) )
-- try no spaces before continuations to catch off-by-one error
nvim ( ' exec ' , ' let ab = #{ \n \\ a: 98, \n " \\ b: 2 \n \\ } ' , false )
eq ( { a = 98 } , request ( ' nvim_eval ' , ' g:ab ' ) )
2021-10-09 14:13:11 -07:00
-- Script scope (s:)
eq ( ' ahoy! script-scoped varrrrr ' , nvim ( ' exec ' , [ [
let s : pirate = ' script-scoped varrrrr '
function ! s : avast_ye_hades ( s ) abort
return a : s .. ' ' .. s : pirate
endfunction
echo < sid > avast_ye_hades ( ' ahoy! ' )
] ] , true ) )
eq ( ' ahoy! script-scoped varrrrr ' , nvim ( ' exec ' , [ [
let s : pirate = ' script-scoped varrrrr '
function ! Avast_ye_hades ( s ) abort
return a : s .. ' ' .. s : pirate
endfunction
echo nvim_exec ( ' echo Avast_ye_hades( ' ' ahoy! ' ' ) ' , 1 )
] ] , true ) )
eq ( ' Vim(call):E5555: API call: Vim(echo):E121: Undefined variable: s:pirate ' ,
pcall_err ( request , ' nvim_exec ' , [ [
let s : pirate = ' script-scoped varrrrr '
call nvim_exec ( ' echo s:pirate ' , 1 )
] ] , false ) )
2021-10-13 16:40:46 -07:00
-- Script items are created only on script var access
eq ( ' 1 \n 0 ' , nvim ( ' exec ' , [ [
echo expand ( " <SID> " ) -> empty ( )
let s : a = 123
echo expand ( " <SID> " ) -> empty ( )
] ] , true ) )
eq ( ' 1 \n 0 ' , nvim ( ' exec ' , [ [
echo expand ( " <SID> " ) -> empty ( )
function s : a ( ) abort
endfunction
echo expand ( " <SID> " ) -> empty ( )
] ] , true ) )
2019-10-06 13:37:54 -07:00
end )
2019-10-06 19:40:36 -07:00
it ( ' non-ASCII input ' , function ( )
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , [ = [
2019-10-06 19:40:36 -07:00
new
exe " normal! i ax \n Ax "
: % s / ax /-- a1234 --/g | :%s/Ax/--A1234--/g
2019-12-01 23:26:36 -07:00
] = ] , false )
2019-10-06 19:40:36 -07:00
nvim ( ' command ' , ' 1 ' )
eq ( ' --a1234-- ' , nvim ( ' get_current_line ' ) )
nvim ( ' command ' , ' 2 ' )
eq ( ' --A1234-- ' , nvim ( ' get_current_line ' ) )
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , [ [
2019-10-06 19:40:36 -07:00
new
call setline ( 1 , [ ' xxx ' ] )
call feedkeys ( ' r ' )
call feedkeys ( ' ñ ' , ' xt ' )
2019-12-01 23:26:36 -07:00
] ] , false )
2019-10-06 19:40:36 -07:00
eq ( ' ñxx ' , nvim ( ' get_current_line ' ) )
2019-10-06 13:37:54 -07:00
end )
2019-10-06 19:40:36 -07:00
it ( ' execution error ' , function ( )
eq ( ' Vim:E492: Not an editor command: bogus_command ' ,
2019-12-01 23:26:36 -07:00
pcall_err ( request , ' nvim_exec ' , ' bogus_command ' , false ) )
2019-10-06 19:40:36 -07:00
eq ( ' ' , nvim ( ' eval ' , ' v:errmsg ' ) ) -- v:errmsg was not updated.
2019-10-06 13:37:54 -07:00
eq ( ' ' , eval ( ' v:exception ' ) )
2019-10-06 19:40:36 -07:00
eq ( ' Vim(buffer):E86: Buffer 23487 does not exist ' ,
2019-12-01 23:26:36 -07:00
pcall_err ( request , ' nvim_exec ' , ' buffer 23487 ' , false ) )
2019-10-06 13:37:54 -07:00
eq ( ' ' , eval ( ' v:errmsg ' ) ) -- v:errmsg was not updated.
eq ( ' ' , eval ( ' v:exception ' ) )
end )
2019-10-06 19:40:36 -07:00
it ( ' recursion ' , function ( )
2019-12-01 23:26:36 -07:00
local fname = tmpname ( )
2019-10-06 19:40:36 -07:00
write_file ( fname , ' let x1 = "set from :source file" \n ' )
2019-12-01 23:26:36 -07:00
-- nvim_exec
2019-10-06 19:40:36 -07:00
-- :source
2019-12-01 23:26:36 -07:00
-- nvim_exec
request ( ' nvim_exec ' , [ [
2019-10-06 19:40:36 -07:00
let x2 = substitute ( ' foo ' , ' o ' , ' X ' , ' g ' )
let x4 = ' should be overwritten '
2019-12-01 23:26:36 -07:00
call nvim_exec ( " source ]]..fname..[[ \n let x3 = substitute('foo','foo','set by recursive nvim_exec','g') \n let x5='overwritten' \n let x4=x5 \n " , v : false )
] ] , false )
2019-10-06 19:40:36 -07:00
eq ( ' set from :source file ' , request ( ' nvim_get_var ' , ' x1 ' ) )
eq ( ' fXX ' , request ( ' nvim_get_var ' , ' x2 ' ) )
2019-12-01 23:26:36 -07:00
eq ( ' set by recursive nvim_exec ' , request ( ' nvim_get_var ' , ' x3 ' ) )
2019-10-06 19:40:36 -07:00
eq ( ' overwritten ' , request ( ' nvim_get_var ' , ' x4 ' ) )
eq ( ' overwritten ' , request ( ' nvim_get_var ' , ' x5 ' ) )
os.remove ( fname )
2019-10-06 13:37:54 -07:00
end )
2019-10-09 06:04:37 -07:00
it ( ' traceback ' , function ( )
2019-12-01 23:26:36 -07:00
local fname = tmpname ( )
2019-10-09 06:04:37 -07:00
write_file ( fname , ' echo "hello" \n ' )
2019-12-01 23:26:36 -07:00
local sourcing_fname = tmpname ( )
write_file ( sourcing_fname , ' call nvim_exec("source ' .. fname .. ' ", v:false) \n ' )
meths.exec ( ' set verbose=2 ' , false )
2019-10-09 06:04:37 -07:00
local traceback_output = ' line 0: sourcing " ' .. sourcing_fname .. ' " \n ' ..
' line 0: sourcing " ' .. fname .. ' " \n ' ..
' hello \n ' ..
' finished sourcing ' .. fname .. ' \n ' ..
2019-12-01 23:26:36 -07:00
' continuing in nvim_exec() called at ' .. sourcing_fname .. ' :1 \n ' ..
2019-10-09 06:04:37 -07:00
' finished sourcing ' .. sourcing_fname .. ' \n ' ..
2019-12-01 23:26:36 -07:00
' continuing in nvim_exec() called at nvim_exec():0 '
eq ( traceback_output ,
meths.exec ( ' call nvim_exec("source ' .. sourcing_fname .. ' ", v:false) ' , true ) )
2019-10-09 06:04:37 -07:00
os.remove ( fname )
os.remove ( sourcing_fname )
end )
2019-12-01 23:26:36 -07:00
it ( ' returns output ' , function ( )
2019-10-09 06:04:37 -07:00
eq ( ' this is spinal tap ' ,
2019-12-01 23:26:36 -07:00
nvim ( ' exec ' , ' lua <<EOF \n \n \n print("this is spinal tap") \n \n \n EOF ' , true ) )
eq ( ' ' , nvim ( ' exec ' , ' echo ' , true ) )
eq ( ' foo 42 ' , nvim ( ' exec ' , ' echo "foo" 42 ' , true ) )
2019-10-09 06:04:37 -07:00
end )
2021-04-21 01:41:37 -07:00
it ( ' displays messages when output=false ' , function ( )
local screen = Screen.new ( 40 , 8 )
screen : attach ( )
screen : set_default_attr_ids ( {
[ 0 ] = { bold = true , foreground = Screen.colors . Blue } ,
} )
meths.exec ( " echo 'hello' " , false )
screen : expect { grid = [ [
^ |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
hello |
] ] }
end )
it ( ' does \' t display messages when output=true ' , function ( )
local screen = Screen.new ( 40 , 8 )
screen : attach ( )
screen : set_default_attr_ids ( {
[ 0 ] = { bold = true , foreground = Screen.colors . Blue } ,
} )
meths.exec ( " echo 'hello' " , true )
screen : expect { grid = [ [
^ |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
|
] ] }
end )
2019-10-06 13:37:54 -07:00
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_command ' , function ( )
2014-10-08 09:56:01 -07:00
it ( ' works ' , function ( )
2019-12-01 23:26:36 -07:00
local fname = tmpname ( )
2014-10-08 09:56:01 -07:00
nvim ( ' command ' , ' new ' )
nvim ( ' command ' , ' edit ' .. fname )
nvim ( ' command ' , ' normal itesting \n api ' )
nvim ( ' command ' , ' w ' )
local f = io.open ( fname )
ok ( f ~= nil )
2019-09-04 06:58:04 -07:00
if is_os ( ' win ' ) then
2015-12-29 12:23:51 -07:00
eq ( ' testing \r \n api \r \n ' , f : read ( ' *a ' ) )
else
eq ( ' testing \n api \n ' , f : read ( ' *a ' ) )
end
2014-10-08 09:56:01 -07:00
f : close ( )
os.remove ( fname )
end )
2016-10-22 15:02:22 -07:00
2018-05-06 18:24:01 -07:00
it ( ' VimL validation error: fails with specific error ' , function ( )
2016-10-22 15:02:22 -07:00
local status , rv = pcall ( nvim , " command " , " bogus_command " )
eq ( false , status ) -- nvim_command() failed.
eq ( " E492: " , string.match ( rv , " E%d*: " ) ) -- VimL error was returned.
2018-05-06 18:24:01 -07:00
eq ( ' ' , nvim ( ' eval ' , ' v:errmsg ' ) ) -- v:errmsg was not updated.
eq ( ' ' , eval ( ' v:exception ' ) )
2016-10-22 15:02:22 -07:00
end )
2018-01-05 03:17:21 -07:00
2018-05-06 18:24:01 -07:00
it ( ' VimL execution error: fails with specific error ' , function ( )
2019-04-07 17:33:00 -07:00
local status , rv = pcall ( nvim , " command " , " buffer 23487 " )
2018-01-05 03:17:21 -07:00
eq ( false , status ) -- nvim_command() failed.
eq ( " E86: Buffer 23487 does not exist " , string.match ( rv , " E%d*:.* " ) )
2018-05-06 18:24:01 -07:00
eq ( ' ' , eval ( ' v:errmsg ' ) ) -- v:errmsg was not updated.
eq ( ' ' , eval ( ' v:exception ' ) )
2018-01-05 03:17:21 -07:00
end )
end )
describe ( ' nvim_command_output ' , function ( )
it ( ' does not induce hit-enter prompt ' , function ( )
2022-01-24 23:59:17 -07:00
nvim ( " ui_attach " , 80 , 20 , { } )
2018-01-05 03:17:21 -07:00
-- Induce a hit-enter prompt use nvim_input (non-blocking).
nvim ( ' command ' , ' set cmdheight=1 ' )
nvim ( ' input ' , [[:echo "hi\nhi2"<CR>]] )
-- Verify hit-enter prompt.
eq ( { mode = ' r ' , blocking = true } , nvim ( " get_mode " ) )
nvim ( ' input ' , [[<C-c>]] )
-- Verify NO hit-enter prompt.
nvim ( ' command_output ' , [[echo "hi\nhi2"]] )
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
end )
2018-01-09 02:36:25 -07:00
it ( ' captures command output ' , function ( )
2018-01-05 03:17:21 -07:00
eq ( ' this is \n spinal tap ' ,
nvim ( ' command_output ' , [[echo "this is\nspinal tap"]] ) )
2018-04-12 15:49:37 -07:00
eq ( ' no line ending! ' ,
nvim ( ' command_output ' , [[echon "no line ending!"]] ) )
2018-01-05 03:17:21 -07:00
end )
2018-01-09 02:36:25 -07:00
it ( ' captures empty command output ' , function ( )
eq ( ' ' , nvim ( ' command_output ' , ' echo ' ) )
end )
it ( ' captures single-char command output ' , function ( )
eq ( ' x ' , nvim ( ' command_output ' , ' echo "x" ' ) )
end )
it ( ' captures multiple commands ' , function ( )
eq ( ' foo \n 1 %a "[No Name]" line 1 ' ,
nvim ( ' command_output ' , ' echo "foo" | ls ' ) )
end )
it ( ' captures nested execute() ' , function ( )
eq ( ' \n nested1 \n nested2 \n 1 %a "[No Name]" line 1 ' ,
nvim ( ' command_output ' ,
[[echo execute('echo "nested1\nnested2"') | ls]] ) )
end )
it ( ' captures nested nvim_command_output() ' , function ( )
eq ( ' nested1 \n nested2 \n 1 %a "[No Name]" line 1 ' ,
nvim ( ' command_output ' ,
[[echo nvim_command_output('echo "nested1\nnested2"') | ls]] ) )
end )
2018-01-21 11:58:19 -07:00
it ( ' returns shell |:!| output ' , function ( )
2017-05-10 06:04:49 -07:00
local win_lf = iswin ( ) and ' \r ' or ' '
2018-01-21 11:58:19 -07:00
eq ( ' :!echo foo \r \n \n foo ' .. win_lf .. ' \n ' , nvim ( ' command_output ' , [[!echo foo]] ) )
2018-01-05 03:17:21 -07:00
end )
2018-05-06 18:24:01 -07:00
it ( ' VimL validation error: fails with specific error ' , function ( )
2018-01-05 03:17:21 -07:00
local status , rv = pcall ( nvim , " command_output " , " bogus commannnd " )
eq ( false , status ) -- nvim_command_output() failed.
eq ( " E492: Not an editor command: bogus commannnd " ,
string.match ( rv , " E%d*:.* " ) )
2018-05-06 18:24:01 -07:00
eq ( ' ' , eval ( ' v:errmsg ' ) ) -- v:errmsg was not updated.
2018-01-05 03:17:21 -07:00
-- Verify NO hit-enter prompt.
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
end )
2018-05-06 18:24:01 -07:00
it ( ' VimL execution error: fails with specific error ' , function ( )
2018-01-05 03:17:21 -07:00
local status , rv = pcall ( nvim , " command_output " , " buffer 42 " )
eq ( false , status ) -- nvim_command_output() failed.
eq ( " E86: Buffer 42 does not exist " , string.match ( rv , " E%d*:.* " ) )
2018-05-06 18:24:01 -07:00
eq ( ' ' , eval ( ' v:errmsg ' ) ) -- v:errmsg was not updated.
2018-01-05 03:17:21 -07:00
-- Verify NO hit-enter prompt.
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
end )
2019-08-22 01:07:54 -07:00
it ( ' Does not cause heap buffer overflow with large output ' , function ( )
eq ( eval ( ' string(range(1000000)) ' ) ,
nvim ( ' command_output ' , ' echo range(1000000) ' ) )
end )
2014-10-08 09:56:01 -07:00
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_eval ' , function ( )
2014-10-08 09:56:01 -07:00
it ( ' works ' , function ( )
nvim ( ' command ' , ' let g:v1 = "a" ' )
nvim ( ' command ' , ' let g:v2 = [1, 2, {"v3": 3}] ' )
2017-02-22 15:12:26 -07:00
eq ( { v1 = ' a ' , v2 = { 1 , 2 , { v3 = 3 } } } , nvim ( ' eval ' , ' g: ' ) )
2014-10-08 09:56:01 -07:00
end )
2015-02-12 10:55:13 -07:00
it ( ' handles NULL-initialized strings correctly ' , function ( )
eq ( 1 , nvim ( ' eval ' , " matcharg(1) == ['', ''] " ) )
eq ( { ' ' , ' ' } , nvim ( ' eval ' , ' matcharg(1) ' ) )
end )
2016-06-28 12:45:19 -07:00
it ( ' works under deprecated name ' , function ( )
eq ( 2 , request ( " vim_eval " , " 1+1 " ) )
end )
2016-10-22 15:02:22 -07:00
2018-05-08 18:23:18 -07:00
it ( " VimL error: returns error details, does NOT update v:errmsg " , function ( )
2019-09-06 17:17:37 -07:00
eq ( ' Vim:E121: Undefined variable: bogus ' ,
pcall_err ( request , ' nvim_eval ' , ' bogus expression ' ) )
2018-05-06 18:24:01 -07:00
eq ( ' ' , eval ( ' v:errmsg ' ) ) -- v:errmsg was not updated.
2016-10-22 15:02:22 -07:00
end )
2014-10-08 09:56:01 -07:00
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_call_function ' , function ( )
2015-07-07 22:40:28 -07:00
it ( ' works ' , function ( )
2017-02-22 15:12:26 -07:00
nvim ( ' call_function ' , ' setqflist ' , { { { filename = ' something ' , lnum = 17 } } , ' r ' } )
2015-07-07 22:40:28 -07:00
eq ( 17 , nvim ( ' call_function ' , ' getqflist ' , { } ) [ 1 ] . lnum )
eq ( 17 , nvim ( ' call_function ' , ' eval ' , { 17 } ) )
eq ( ' foo ' , nvim ( ' call_function ' , ' simplify ' , { ' this/./is//redundant/../../../foo ' } ) )
end )
2018-05-06 18:24:01 -07:00
it ( " VimL validation error: returns specific error, does NOT update v:errmsg " , function ( )
2019-09-06 17:17:37 -07:00
eq ( ' Vim:E117: Unknown function: bogus function ' ,
pcall_err ( request , ' nvim_call_function ' , ' bogus function ' , { ' arg1 ' } ) )
eq ( ' Vim:E119: Not enough arguments for function: atan ' ,
pcall_err ( request , ' nvim_call_function ' , ' atan ' , { } ) )
2018-05-06 18:24:01 -07:00
eq ( ' ' , eval ( ' v:exception ' ) )
eq ( ' ' , eval ( ' v:errmsg ' ) ) -- v:errmsg was not updated.
end )
it ( " VimL error: returns error details, does NOT update v:errmsg " , function ( )
2019-09-06 17:17:37 -07:00
eq ( ' Vim:E808: Number or Float required ' ,
pcall_err ( request , ' nvim_call_function ' , ' atan ' , { ' foo ' } ) )
eq ( ' Vim:Invalid channel stream "xxx" ' ,
pcall_err ( request , ' nvim_call_function ' , ' chanclose ' , { 999 , ' xxx ' } ) )
eq ( ' Vim:E900: Invalid channel id ' ,
pcall_err ( request , ' nvim_call_function ' , ' chansend ' , { 999 , ' foo ' } ) )
2018-05-06 18:24:01 -07:00
eq ( ' ' , eval ( ' v:exception ' ) )
eq ( ' ' , eval ( ' v:errmsg ' ) ) -- v:errmsg was not updated.
end )
it ( " VimL exception: returns exception details, does NOT update v:errmsg " , function ( )
source ( [ [
function ! Foo ( ) abort
throw ' wtf '
endfunction
] ] )
2019-09-06 17:17:37 -07:00
eq ( ' wtf ' , pcall_err ( request , ' nvim_call_function ' , ' Foo ' , { } ) )
2018-05-06 18:24:01 -07:00
eq ( ' ' , eval ( ' v:exception ' ) )
eq ( ' ' , eval ( ' v:errmsg ' ) ) -- v:errmsg was not updated.
2016-10-22 15:02:22 -07:00
end )
2018-05-06 18:24:01 -07:00
2018-05-03 23:23:37 -07:00
it ( ' validates args ' , function ( )
local too_many_args = { ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' , ' x ' }
source ( [ [
function ! Foo ( ... ) abort
echo a : 000
endfunction
] ] )
-- E740
2019-09-06 17:17:37 -07:00
eq ( ' Function called with too many arguments ' ,
pcall_err ( request , ' nvim_call_function ' , ' Foo ' , too_many_args ) )
2018-05-03 23:23:37 -07:00
end )
2016-10-22 15:02:22 -07:00
end )
2018-05-02 14:38:18 -07:00
describe ( ' nvim_call_dict_function ' , function ( )
2018-05-03 23:20:37 -07:00
it ( ' invokes VimL dict function ' , function ( )
source ( [ [
function ! F ( name ) dict
2018-05-06 05:37:51 -07:00
return self.greeting . ' , ' . a : name . ' ! '
endfunction
let g : test_dict_fn = { ' greeting ' : ' Hello ' , ' F ' : function ( ' F ' ) }
let g : test_dict_fn2 = { ' greeting ' : ' Hi ' }
function g : test_dict_fn2 . F2 ( name )
return self.greeting . ' , ' . a : name . ' ... '
2018-05-03 23:20:37 -07:00
endfunction
] ] )
2018-05-06 05:37:51 -07:00
-- :help Dictionary-function
eq ( ' Hello, World! ' , nvim ( ' call_dict_function ' , ' g:test_dict_fn ' , ' F ' , { ' World ' } ) )
-- Funcref is sent as NIL over RPC.
eq ( { greeting = ' Hello ' , F = NIL } , nvim ( ' get_var ' , ' test_dict_fn ' ) )
2018-05-03 23:20:37 -07:00
2018-05-06 05:37:51 -07:00
-- :help numbered-function
eq ( ' Hi, Moon ... ' , nvim ( ' call_dict_function ' , ' g:test_dict_fn2 ' , ' F2 ' , { ' Moon ' } ) )
-- Funcref is sent as NIL over RPC.
eq ( { greeting = ' Hi ' , F2 = NIL } , nvim ( ' get_var ' , ' test_dict_fn2 ' ) )
-- Function specified via RPC dict.
source ( ' function! G() dict \n return "@".(self.result)."@" \n endfunction ' )
eq ( ' @it works@ ' , nvim ( ' call_dict_function ' , { result = ' it works ' , G = ' G ' } , ' G ' , { } ) )
2018-05-02 14:38:18 -07:00
end )
2018-05-06 05:37:51 -07:00
2018-05-02 15:20:14 -07:00
it ( ' validates args ' , function ( )
command ( ' let g:d={"baz":"zub","meep":[]} ' )
2019-09-06 17:17:37 -07:00
eq ( ' Not found: bogus ' ,
pcall_err ( request , ' nvim_call_dict_function ' , ' g:d ' , ' bogus ' , { 1 , 2 } ) )
eq ( ' Not a function: baz ' ,
pcall_err ( request , ' nvim_call_dict_function ' , ' g:d ' , ' baz ' , { 1 , 2 } ) )
eq ( ' Not a function: meep ' ,
pcall_err ( request , ' nvim_call_dict_function ' , ' g:d ' , ' meep ' , { 1 , 2 } ) )
eq ( ' Vim:E117: Unknown function: f ' ,
pcall_err ( request , ' nvim_call_dict_function ' , { f = ' ' } , ' f ' , { 1 , 2 } ) )
eq ( ' Not a function: f ' ,
pcall_err ( request , ' nvim_call_dict_function ' , " { 'f': '' } " , ' f ' , { 1 , 2 } ) )
eq ( ' dict argument type must be String or Dictionary ' ,
pcall_err ( request , ' nvim_call_dict_function ' , 42 , ' f ' , { 1 , 2 } ) )
eq ( ' Failed to evaluate dict expression ' ,
pcall_err ( request , ' nvim_call_dict_function ' , ' foo ' , ' f ' , { 1 , 2 } ) )
eq ( ' dict not found ' ,
pcall_err ( request , ' nvim_call_dict_function ' , ' 42 ' , ' f ' , { 1 , 2 } ) )
eq ( ' Invalid (empty) function name ' ,
pcall_err ( request , ' nvim_call_dict_function ' , " { 'f': '' } " , ' ' , { 1 , 2 } ) )
2018-05-02 14:38:18 -07:00
end )
end )
2022-02-09 18:41:25 -07:00
describe ( ' nvim_set_current_dir ' , function ( )
local start_dir
before_each ( function ( )
clear ( )
funcs.mkdir ( " Xtestdir " )
start_dir = funcs.getcwd ( )
end )
after_each ( function ( )
helpers.rmdir ( " Xtestdir " )
end )
it ( ' works ' , function ( )
meths.set_current_dir ( " Xtestdir " )
eq ( funcs.getcwd ( ) , start_dir .. helpers.get_pathsep ( ) .. " Xtestdir " )
end )
it ( ' sets previous directory ' , function ( )
meths.set_current_dir ( " Xtestdir " )
meths.exec ( ' cd - ' , false )
eq ( funcs.getcwd ( ) , start_dir )
end )
end )
2019-12-02 01:46:46 -07:00
describe ( ' nvim_exec_lua ' , function ( )
2017-05-08 23:55:04 -07:00
it ( ' works ' , function ( )
2019-12-02 01:46:46 -07:00
meths.exec_lua ( ' vim.api.nvim_set_var("test", 3) ' , { } )
2017-05-08 23:55:04 -07:00
eq ( 3 , meths.get_var ( ' test ' ) )
2019-12-02 01:46:46 -07:00
eq ( 17 , meths.exec_lua ( ' a, b = ... \n return a + b ' , { 10 , 7 } ) )
2017-05-08 23:55:04 -07:00
2019-12-02 01:46:46 -07:00
eq ( NIL , meths.exec_lua ( ' function xx(a,b) \n return a..b \n end ' , { } ) )
eq ( " xy " , meths.exec_lua ( ' return xx(...) ' , { ' x ' , ' y ' } ) )
-- Deprecated name: nvim_execute_lua.
2017-05-08 23:55:04 -07:00
eq ( " xy " , meths.execute_lua ( ' return xx(...) ' , { ' x ' , ' y ' } ) )
end )
it ( ' reports errors ' , function ( )
2020-09-12 19:04:22 -07:00
eq ( [[Error loading lua: [string "<nvim>"]:0: '=' expected near '+']] ,
2019-12-02 01:46:46 -07:00
pcall_err ( meths.exec_lua , ' a+*b ' , { } ) )
2017-05-08 23:55:04 -07:00
2020-09-12 19:04:22 -07:00
eq ( [[Error loading lua: [string "<nvim>"]:0: unexpected symbol near '1']] ,
2019-12-02 01:46:46 -07:00
pcall_err ( meths.exec_lua , ' 1+2 ' , { } ) )
2017-05-08 23:55:04 -07:00
2020-09-12 19:04:22 -07:00
eq ( [[Error loading lua: [string "<nvim>"]:0: unexpected symbol]] ,
2019-12-02 01:46:46 -07:00
pcall_err ( meths.exec_lua , ' aa=bb \0 ' , { } ) )
2017-05-08 23:55:04 -07:00
2020-09-12 19:04:22 -07:00
eq ( [[Error executing lua: [string "<nvim>"]:0: attempt to call global 'bork' (a nil value)]] ,
2019-12-02 01:46:46 -07:00
pcall_err ( meths.exec_lua , ' bork() ' , { } ) )
2019-01-22 11:55:31 -07:00
2020-09-12 19:04:22 -07:00
eq ( ' Error executing lua: [string "<nvim>"]:0: did \n the \n fail ' ,
2019-12-02 01:46:46 -07:00
pcall_err ( meths.exec_lua , ' error("did \\ nthe \\ nfail") ' , { } ) )
2017-05-08 23:55:04 -07:00
end )
2019-07-01 06:50:57 -07:00
it ( ' uses native float values ' , function ( )
2019-12-02 01:46:46 -07:00
eq ( 2.5 , meths.exec_lua ( " return select(1, ...) " , { 2.5 } ) )
eq ( " 2.5 " , meths.exec_lua ( " return vim.inspect(...) " , { 2.5 } ) )
2019-07-01 06:50:57 -07:00
-- "special" float values are still accepted as return values.
2019-12-02 01:46:46 -07:00
eq ( 2.5 , meths.exec_lua ( " return vim.api.nvim_eval('2.5') " , { } ) )
eq ( " { \n [false] = 2.5, \n [true] = 3 \n } " , meths.exec_lua ( " return vim.inspect(vim.api.nvim_eval('2.5')) " , { } ) )
2019-07-01 06:50:57 -07:00
end )
2017-05-08 23:55:04 -07:00
end )
2021-02-01 15:16:50 -07:00
describe ( ' nvim_notify ' , function ( )
2021-02-09 03:41:02 -07:00
it ( ' can notify a info message ' , function ( )
nvim ( " notify " , " hello world " , 2 , { } )
end )
2021-09-17 10:07:00 -07:00
it ( ' can be overridden ' , function ( )
2021-02-01 15:16:50 -07:00
command ( " lua vim.notify = function(...) return 42 end " )
eq ( 42 , meths.exec_lua ( " return vim.notify('Hello world') " , { } ) )
nvim ( " notify " , " hello world " , 4 , { } )
end )
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_input ' , function ( )
it ( " VimL error: does NOT fail, updates v:errmsg " , function ( )
local status , _ = pcall ( nvim , " input " , " :call bogus_fn()<CR> " )
local v_errnum = string.match ( nvim ( " eval " , " v:errmsg " ) , " E%d*: " )
eq ( true , status ) -- nvim_input() did not fail.
eq ( " E117: " , v_errnum ) -- v:errmsg was updated.
end )
2020-05-24 22:57:44 -07:00
it ( ' does not crash even if trans_special result is largest #11788, #12287 ' , function ( )
command ( " call nvim_input('<M-'.nr2char(0x40000000).'>') " )
eq ( 1 , eval ( ' 1 ' ) )
end )
2015-07-07 22:40:28 -07:00
end )
2019-08-24 04:54:27 -07:00
describe ( ' nvim_paste ' , function ( )
2022-03-05 15:56:24 -07:00
before_each ( function ( )
-- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
feed ( ' ifoo<Esc>u ' )
end )
2019-08-24 04:54:27 -07:00
it ( ' validates args ' , function ( )
2019-09-06 17:17:37 -07:00
eq ( ' Invalid phase: -2 ' ,
pcall_err ( request , ' nvim_paste ' , ' foo ' , true , - 2 ) )
eq ( ' Invalid phase: 4 ' ,
pcall_err ( request , ' nvim_paste ' , ' foo ' , true , 4 ) )
2019-08-24 04:54:27 -07:00
end )
2019-08-31 03:44:42 -07:00
it ( ' stream: multiple chunks form one undo-block ' , function ( )
nvim ( ' paste ' , ' 1/chunk 1 (start) \n ' , true , 1 )
nvim ( ' paste ' , ' 1/chunk 2 (end) \n ' , true , 3 )
local expected1 = [ [
1 / chunk 1 ( start )
1 / chunk 2 ( end )
] ]
expect ( expected1 )
nvim ( ' paste ' , ' 2/chunk 1 (start) \n ' , true , 1 )
nvim ( ' paste ' , ' 2/chunk 2 \n ' , true , 2 )
expect ( [ [
1 / chunk 1 ( start )
1 / chunk 2 ( end )
2 / chunk 1 ( start )
2 / chunk 2
] ] )
nvim ( ' paste ' , ' 2/chunk 3 \n ' , true , 2 )
nvim ( ' paste ' , ' 2/chunk 4 (end) \n ' , true , 3 )
expect ( [ [
1 / chunk 1 ( start )
1 / chunk 2 ( end )
2 / chunk 1 ( start )
2 / chunk 2
2 / chunk 3
2 / chunk 4 ( end )
] ] )
feed ( ' u ' ) -- Undo.
expect ( expected1 )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Insert mode ' , function ( )
feed ( ' i ' )
nvim ( ' paste ' , ' aaaaaa ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' aaaaaabbbbbbccccccdddddd ' )
end )
it ( ' stream: Normal mode on empty line ' , function ( )
nvim ( ' paste ' , ' aaaaaa ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' aaaaaabbbbbbccccccdddddd ' )
feed ( ' u ' )
expect ( ' ' )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Normal mode on empty line pasting multiple lines ' , function ( )
nvim ( ' paste ' , ' aaaaaa \n ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb \n ' , false , 2 )
nvim ( ' paste ' , ' cccccc \n ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( [ [
aaaaaa
bbbbbb
cccccc
dddddd ] ] )
feed ( ' u ' )
expect ( ' ' )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Normal mode not at the end of a line ' , function ( )
feed ( ' i||<Esc>0 ' )
nvim ( ' paste ' , ' aaaaaa ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' |aaaaaabbbbbbccccccdddddd| ' )
feed ( ' u ' )
expect ( ' || ' )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Normal mode not at the end of a line pasting multiple lines ' , function ( )
feed ( ' i||<Esc>0 ' )
nvim ( ' paste ' , ' aaaaaa \n ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb \n ' , false , 2 )
nvim ( ' paste ' , ' cccccc \n ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( [ [
| aaaaaa
bbbbbb
cccccc
dddddd | ] ] )
feed ( ' u ' )
expect ( ' || ' )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Normal mode at the end of a line ' , function ( )
feed ( ' i||<Esc> ' )
nvim ( ' paste ' , ' aaaaaa ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' ||aaaaaabbbbbbccccccdddddd ' )
feed ( ' u ' )
expect ( ' || ' )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Normal mode at the end of a line pasting multiple lines ' , function ( )
feed ( ' i||<Esc> ' )
nvim ( ' paste ' , ' aaaaaa \n ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb \n ' , false , 2 )
nvim ( ' paste ' , ' cccccc \n ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( [ [
|| aaaaaa
bbbbbb
cccccc
dddddd ] ] )
feed ( ' u ' )
expect ( ' || ' )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Visual mode neither end at the end of a line ' , function ( )
2022-03-05 15:56:24 -07:00
feed ( ' i|xxx<CR>xxx|<Esc>hvhk ' )
nvim ( ' paste ' , ' aaaaaa ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' |aaaaaabbbbbbccccccdddddd| ' )
feed ( ' u ' )
expect ( [ [
| xxx
xxx | ] ] )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Visual mode neither end at the end of a line with empty first chunk ' , function ( )
feed ( ' i|xxx<CR>xxx|<Esc>hvhk ' )
nvim ( ' paste ' , ' ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' |bbbbbbccccccdddddd| ' )
feed ( ' u ' )
expect ( [ [
| xxx
xxx | ] ] )
end )
it ( ' stream: Visual mode neither end at the end of a line with all chunks empty ' , function ( )
feed ( ' i|xxx<CR>xxx|<Esc>hvhk ' )
nvim ( ' paste ' , ' ' , false , 1 )
nvim ( ' paste ' , ' ' , false , 2 )
nvim ( ' paste ' , ' ' , false , 2 )
nvim ( ' paste ' , ' ' , false , 3 )
expect ( ' || ' )
feed ( ' u ' )
expect ( [ [
| xxx
xxx | ] ] )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Visual mode cursor at the end of a line ' , function ( )
feed ( ' i||xxx<CR>xxx<Esc>vko ' )
nvim ( ' paste ' , ' aaaaaa ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' ||aaaaaabbbbbbccccccdddddd ' )
feed ( ' u ' )
expect ( [ [
|| xxx
xxx ] ] )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Visual mode cursor at the end of a line with empty first chunk ' , function ( )
feed ( ' i||xxx<CR>xxx<Esc>vko ' )
nvim ( ' paste ' , ' ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' ||bbbbbbccccccdddddd ' )
feed ( ' u ' )
expect ( [ [
|| xxx
xxx ] ] )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Visual mode other end at the end of a line ' , function ( )
feed ( ' i||xxx<CR>xxx<Esc>vk ' )
nvim ( ' paste ' , ' aaaaaa ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' ||aaaaaabbbbbbccccccdddddd ' )
feed ( ' u ' )
expect ( [ [
|| xxx
xxx ] ] )
end )
2022-03-05 15:56:24 -07:00
it ( ' stream: Visual mode other end at the end of a line with empty first chunk ' , function ( )
feed ( ' i||xxx<CR>xxx<Esc>vk ' )
nvim ( ' paste ' , ' ' , false , 1 )
nvim ( ' paste ' , ' bbbbbb ' , false , 2 )
nvim ( ' paste ' , ' cccccc ' , false , 2 )
nvim ( ' paste ' , ' dddddd ' , false , 3 )
expect ( ' ||bbbbbbccccccdddddd ' )
feed ( ' u ' )
expect ( [ [
|| xxx
xxx ] ] )
end )
2019-08-24 04:54:27 -07:00
it ( ' non-streaming ' , function ( )
-- With final "\n".
2019-08-29 15:16:19 -07:00
nvim ( ' paste ' , ' line 1 \n line 2 \n line 3 \n ' , true , - 1 )
2019-08-24 04:54:27 -07:00
expect ( [ [
line 1
line 2
line 3
] ] )
2019-08-29 14:45:02 -07:00
eq ( { 0 , 4 , 1 , 0 } , funcs.getpos ( ' . ' ) ) -- Cursor follows the paste.
2019-08-24 04:54:27 -07:00
eq ( false , nvim ( ' get_option ' , ' paste ' ) )
command ( ' %delete _ ' )
-- Without final "\n".
2019-08-29 15:16:19 -07:00
nvim ( ' paste ' , ' line 1 \n line 2 \n line 3 ' , true , - 1 )
2019-08-24 04:54:27 -07:00
expect ( [ [
line 1
line 2
line 3 ] ] )
eq ( { 0 , 3 , 6 , 0 } , funcs.getpos ( ' . ' ) )
2019-08-29 14:45:02 -07:00
command ( ' %delete _ ' )
-- CRLF #10872
2019-08-29 15:16:19 -07:00
nvim ( ' paste ' , ' line 1 \r \n line 2 \r \n line 3 \r \n ' , true , - 1 )
2019-08-29 14:45:02 -07:00
expect ( [ [
line 1
line 2
line 3
] ] )
eq ( { 0 , 4 , 1 , 0 } , funcs.getpos ( ' . ' ) )
command ( ' %delete _ ' )
-- CRLF without final "\n".
2019-08-29 15:16:19 -07:00
nvim ( ' paste ' , ' line 1 \r \n line 2 \r \n line 3 \r ' , true , - 1 )
2019-08-29 14:45:02 -07:00
expect ( [ [
line 1
line 2
line 3
] ] )
eq ( { 0 , 4 , 1 , 0 } , funcs.getpos ( ' . ' ) )
command ( ' %delete _ ' )
-- CRLF without final "\r\n".
2019-08-29 15:16:19 -07:00
nvim ( ' paste ' , ' line 1 \r \n line 2 \r \n line 3 ' , true , - 1 )
2019-08-29 14:45:02 -07:00
expect ( [ [
line 1
line 2
line 3 ] ] )
eq ( { 0 , 3 , 6 , 0 } , funcs.getpos ( ' . ' ) )
command ( ' %delete _ ' )
-- Various other junk.
2019-08-29 15:16:19 -07:00
nvim ( ' paste ' , ' line 1 \r \n \r \r line 2 \n line 3 \r line 4 \r ' , true , - 1 )
2019-08-29 14:45:02 -07:00
expect ( ' line 1 \n \n \n line 2 \n line 3 \n line 4 \n ' )
eq ( { 0 , 7 , 1 , 0 } , funcs.getpos ( ' . ' ) )
2019-08-24 04:54:27 -07:00
eq ( false , nvim ( ' get_option ' , ' paste ' ) )
end )
2020-05-05 04:18:41 -07:00
it ( ' Replace-mode ' , function ( )
-- Within single line
nvim ( ' put ' , { ' aabbccdd ' , ' eeffgghh ' , ' iijjkkll ' } , " c " , true , false )
command ( ' normal l ' )
command ( ' startreplace ' )
nvim ( ' paste ' , ' 123456 ' , true , - 1 )
expect ( [ [
a123456d
eeffgghh
iijjkkll ] ] )
command ( ' %delete _ ' )
-- Across lines
nvim ( ' put ' , { ' aabbccdd ' , ' eeffgghh ' , ' iijjkkll ' } , " c " , true , false )
command ( ' normal l ' )
command ( ' startreplace ' )
nvim ( ' paste ' , ' 123 \n 456 ' , true , - 1 )
expect ( [ [
a123
456 d
eeffgghh
iijjkkll ] ] )
end )
2022-03-05 15:56:24 -07:00
it ( ' when searching in Visual mode ' , function ( )
feed ( ' v/ ' )
nvim ( ' paste ' , ' aabbccdd ' , true , - 1 )
eq ( ' aabbccdd ' , funcs.getcmdline ( ) )
expect ( ' ' )
end )
2022-03-05 15:56:24 -07:00
it ( ' pasting with empty last chunk in Cmdline mode ' , function ( )
local screen = Screen.new ( 20 , 4 )
screen : attach ( )
feed ( ' : ' )
nvim ( ' paste ' , ' Foo ' , true , 1 )
nvim ( ' paste ' , ' ' , true , 3 )
screen : expect ( [ [
|
~ |
~ |
: Foo ^ |
] ] )
end )
2019-08-29 15:16:19 -07:00
it ( ' crlf=false does not break lines at CR, CRLF ' , function ( )
nvim ( ' paste ' , ' line 1 \r \n \r \r line 2 \n line 3 \r line 4 \r ' , false , - 1 )
expect ( ' line 1 \r \n \r \r line 2 \n line 3 \r line 4 \r ' )
eq ( { 0 , 3 , 14 , 0 } , funcs.getpos ( ' . ' ) )
end )
2019-08-26 11:57:57 -07:00
it ( ' vim.paste() failure ' , function ( )
2019-12-02 01:46:46 -07:00
nvim ( ' exec_lua ' , ' vim.paste = (function(lines, phase) error("fake fail") end) ' , { } )
2020-09-12 19:04:22 -07:00
eq ( [[Error executing lua: [string "<nvim>"]:0: fake fail]] ,
2019-09-06 17:17:37 -07:00
pcall_err ( request , ' nvim_paste ' , ' line 1 \n line 2 \n line 3 ' , false , 1 ) )
2019-08-26 11:57:57 -07:00
end )
2019-08-24 04:54:27 -07:00
end )
2019-08-19 14:43:19 -07:00
describe ( ' nvim_put ' , function ( )
2019-08-24 04:54:27 -07:00
it ( ' validates args ' , function ( )
2019-09-06 17:17:37 -07:00
eq ( ' Invalid lines (expected array of strings) ' ,
pcall_err ( request , ' nvim_put ' , { 42 } , ' l ' , false , false ) )
eq ( " Invalid type: 'x' " ,
pcall_err ( request , ' nvim_put ' , { ' foo ' } , ' x ' , false , false ) )
2019-08-24 04:54:27 -07:00
end )
2019-08-26 20:19:32 -07:00
it ( " fails if 'nomodifiable' " , function ( )
command ( ' set nomodifiable ' )
2019-09-06 17:17:37 -07:00
eq ( [[Vim:E21: Cannot make changes, 'modifiable' is off]] ,
pcall_err ( request , ' nvim_put ' , { ' a ' , ' b ' } , ' l ' , true , true ) )
2019-08-26 20:19:32 -07:00
end )
2019-08-19 14:43:19 -07:00
it ( ' inserts text ' , function ( )
-- linewise
2019-08-20 14:53:13 -07:00
nvim ( ' put ' , { ' line 1 ' , ' line 2 ' , ' line 3 ' } , ' l ' , true , true )
2019-08-19 14:43:19 -07:00
expect ( [ [
line 1
line 2
line 3 ] ] )
2019-08-20 14:53:13 -07:00
eq ( { 0 , 4 , 1 , 0 } , funcs.getpos ( ' . ' ) )
2019-08-19 14:43:19 -07:00
command ( ' %delete _ ' )
-- charwise
2019-08-20 14:53:13 -07:00
nvim ( ' put ' , { ' line 1 ' , ' line 2 ' , ' line 3 ' } , ' c ' , true , false )
2019-08-19 14:43:19 -07:00
expect ( [ [
line 1
line 2
line 3 ] ] )
2019-08-20 14:53:13 -07:00
eq ( { 0 , 1 , 1 , 0 } , funcs.getpos ( ' . ' ) ) -- follow=false
2019-08-19 14:43:19 -07:00
-- blockwise
2019-08-20 14:53:13 -07:00
nvim ( ' put ' , { ' AA ' , ' BB ' } , ' b ' , true , true )
2019-08-19 14:43:19 -07:00
expect ( [ [
lAAine 1
lBBine 2
line 3 ] ] )
2019-08-20 14:53:13 -07:00
eq ( { 0 , 2 , 4 , 0 } , funcs.getpos ( ' . ' ) )
2019-08-19 14:43:19 -07:00
command ( ' %delete _ ' )
-- Empty lines list.
2019-08-20 14:53:13 -07:00
nvim ( ' put ' , { } , ' c ' , true , true )
eq ( { 0 , 1 , 1 , 0 } , funcs.getpos ( ' . ' ) )
2019-08-19 14:43:19 -07:00
expect ( [[]] )
-- Single empty line.
2019-08-20 14:53:13 -07:00
nvim ( ' put ' , { ' ' } , ' c ' , true , true )
eq ( { 0 , 1 , 1 , 0 } , funcs.getpos ( ' . ' ) )
2019-08-19 14:43:19 -07:00
expect ( [ [
] ] )
2019-08-20 14:53:13 -07:00
nvim ( ' put ' , { ' AB ' } , ' c ' , true , true )
-- after=false, follow=true
nvim ( ' put ' , { ' line 1 ' , ' line 2 ' } , ' c ' , false , true )
expect ( [ [
Aline 1
line 2 B ] ] )
eq ( { 0 , 2 , 7 , 0 } , funcs.getpos ( ' . ' ) )
command ( ' %delete _ ' )
nvim ( ' put ' , { ' AB ' } , ' c ' , true , true )
-- after=false, follow=false
nvim ( ' put ' , { ' line 1 ' , ' line 2 ' } , ' c ' , false , false )
expect ( [ [
Aline 1
line 2 B ] ] )
eq ( { 0 , 1 , 2 , 0 } , funcs.getpos ( ' . ' ) )
2019-08-19 14:43:19 -07:00
eq ( ' ' , nvim ( ' eval ' , ' v:errmsg ' ) )
end )
2019-08-26 11:57:57 -07:00
it ( ' detects charwise/linewise text (empty {type}) ' , function ( )
-- linewise (final item is empty string)
nvim ( ' put ' , { ' line 1 ' , ' line 2 ' , ' line 3 ' , ' ' } , ' ' , true , true )
expect ( [ [
line 1
line 2
line 3 ] ] )
eq ( { 0 , 4 , 1 , 0 } , funcs.getpos ( ' . ' ) )
command ( ' %delete _ ' )
-- charwise (final item is non-empty)
nvim ( ' put ' , { ' line 1 ' , ' line 2 ' , ' line 3 ' } , ' ' , true , true )
expect ( [ [
line 1
line 2
line 3 ] ] )
eq ( { 0 , 3 , 6 , 0 } , funcs.getpos ( ' . ' ) )
end )
2019-08-30 11:19:56 -07:00
it ( ' allows block width ' , function ( )
-- behave consistently with setreg(); support "\022{NUM}" return by getregtype()
meths.put ( { ' line 1 ' , ' line 2 ' , ' line 3 ' } , ' l ' , false , false )
expect ( [ [
line 1
line 2
line 3
] ] )
-- larger width create spaces
meths.put ( { ' a ' , ' bc ' } , ' b3 ' , false , false )
expect ( [ [
a line 1
bc line 2
line 3
] ] )
-- smaller width is ignored
meths.put ( { ' xxx ' , ' yyy ' } , ' \022 1 ' , false , true )
expect ( [ [
xxxa line 1
yyybc line 2
line 3
] ] )
2019-09-03 13:51:45 -07:00
eq ( " Invalid type: 'bx' " ,
pcall_err ( meths.put , { ' xxx ' , ' yyy ' } , ' bx ' , false , true ) )
eq ( " Invalid type: 'b3x' " ,
pcall_err ( meths.put , { ' xxx ' , ' yyy ' } , ' b3x ' , false , true ) )
2019-08-30 11:19:56 -07:00
end )
2019-08-19 14:43:19 -07:00
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_strwidth ' , function ( )
2014-10-08 09:56:01 -07:00
it ( ' works ' , function ( )
eq ( 3 , nvim ( ' strwidth ' , ' abc ' ) )
-- 6 + (neovim)
-- 19 * 2 (each japanese character occupies two cells)
eq ( 44 , nvim ( ' strwidth ' , ' neovimのデザインかなりまともなのになってる。 ' ) )
end )
2014-10-24 13:36:30 -07:00
it ( ' cannot handle NULs ' , function ( )
eq ( 0 , nvim ( ' strwidth ' , ' \0 abc ' ) )
end )
2014-10-08 09:56:01 -07:00
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_get_current_line, nvim_set_current_line ' , function ( )
2014-10-08 09:56:01 -07:00
it ( ' works ' , function ( )
eq ( ' ' , nvim ( ' get_current_line ' ) )
nvim ( ' set_current_line ' , ' abc ' )
eq ( ' abc ' , nvim ( ' get_current_line ' ) )
end )
end )
2019-01-13 16:40:38 -07:00
describe ( ' set/get/del variables ' , function ( )
it ( ' nvim_get_var, nvim_set_var, nvim_del_var ' , function ( )
2014-10-08 09:56:01 -07:00
nvim ( ' set_var ' , ' lua ' , { 1 , 2 , { [ ' 3 ' ] = 1 } } )
eq ( { 1 , 2 , { [ ' 3 ' ] = 1 } } , nvim ( ' get_var ' , ' lua ' ) )
eq ( { 1 , 2 , { [ ' 3 ' ] = 1 } } , nvim ( ' eval ' , ' g:lua ' ) )
2016-02-10 16:01:17 -07:00
eq ( 1 , funcs.exists ( ' g:lua ' ) )
meths.del_var ( ' lua ' )
eq ( 0 , funcs.exists ( ' g:lua ' ) )
2019-09-03 13:51:45 -07:00
eq ( " Key not found: lua " , pcall_err ( meths.del_var , ' lua ' ) )
2017-02-22 15:34:25 -07:00
meths.set_var ( ' lua ' , 1 )
2019-01-13 16:40:38 -07:00
-- Set locked g: var.
2017-02-22 15:34:25 -07:00
command ( ' lockvar lua ' )
2019-09-03 13:51:45 -07:00
eq ( ' Key is locked: lua ' , pcall_err ( meths.del_var , ' lua ' ) )
eq ( ' Key is locked: lua ' , pcall_err ( meths.set_var , ' lua ' , 1 ) )
2022-02-11 21:54:25 -07:00
-- Check if autoload works properly
local pathsep = helpers.get_pathsep ( )
local xconfig = ' Xhome ' .. pathsep .. ' Xconfig '
local xdata = ' Xhome ' .. pathsep .. ' Xdata '
local autoload_folder = table.concat ( { xconfig , ' nvim ' , ' autoload ' } , pathsep )
local autoload_file = table.concat ( { autoload_folder , ' testload.vim ' } , pathsep )
mkdir_p ( autoload_folder )
write_file ( autoload_file , [[let testload#value = 2]] )
clear { args_rm = { ' -u ' } , env = { XDG_CONFIG_HOME = xconfig , XDG_DATA_HOME = xdata } }
eq ( 2 , meths.get_var ( ' testload#value ' ) )
rmdir ( ' Xhome ' )
2014-10-08 09:56:01 -07:00
end )
2014-10-24 13:36:30 -07:00
2019-01-13 16:40:38 -07:00
it ( ' nvim_get_vvar, nvim_set_vvar ' , function ( )
-- Set readonly v: var.
2019-09-06 17:17:37 -07:00
eq ( ' Key is read-only: count ' ,
pcall_err ( request , ' nvim_set_vvar ' , ' count ' , 42 ) )
2019-01-13 16:40:38 -07:00
-- Set writable v: var.
meths.set_vvar ( ' errmsg ' , ' set by API ' )
eq ( ' set by API ' , meths.get_vvar ( ' errmsg ' ) )
end )
2016-09-14 02:17:07 -07:00
it ( ' vim_set_var returns the old value ' , function ( )
2015-06-24 21:13:33 -07:00
local val1 = { 1 , 2 , { [ ' 3 ' ] = 1 } }
local val2 = { 4 , 7 }
2016-09-14 02:17:07 -07:00
eq ( NIL , request ( ' vim_set_var ' , ' lua ' , val1 ) )
eq ( val1 , request ( ' vim_set_var ' , ' lua ' , val2 ) )
2015-06-24 21:13:33 -07:00
end )
2016-09-14 02:17:07 -07:00
it ( ' vim_del_var returns the old value ' , function ( )
2016-02-10 16:01:17 -07:00
local val1 = { 1 , 2 , { [ ' 3 ' ] = 1 } }
local val2 = { 4 , 7 }
2016-09-14 02:17:07 -07:00
eq ( NIL , request ( ' vim_set_var ' , ' lua ' , val1 ) )
eq ( val1 , request ( ' vim_set_var ' , ' lua ' , val2 ) )
eq ( val2 , request ( ' vim_del_var ' , ' lua ' ) )
2016-02-10 16:01:17 -07:00
end )
2014-10-24 13:36:30 -07:00
it ( ' truncates values with NULs in them ' , function ( )
nvim ( ' set_var ' , ' xxx ' , ' ab \0 cd ' )
eq ( ' ab ' , nvim ( ' get_var ' , ' xxx ' ) )
end )
2014-10-08 09:56:01 -07:00
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_get_option, nvim_set_option ' , function ( )
2014-10-08 09:56:01 -07:00
it ( ' works ' , function ( )
ok ( nvim ( ' get_option ' , ' equalalways ' ) )
nvim ( ' set_option ' , ' equalalways ' , false )
ok ( not nvim ( ' get_option ' , ' equalalways ' ) )
end )
2017-03-30 13:03:52 -07:00
it ( ' works to get global value of local options ' , function ( )
eq ( false , nvim ( ' get_option ' , ' lisp ' ) )
eq ( 8 , nvim ( ' get_option ' , ' shiftwidth ' ) )
end )
it ( ' works to set global value of local options ' , function ( )
nvim ( ' set_option ' , ' lisp ' , true )
eq ( true , nvim ( ' get_option ' , ' lisp ' ) )
eq ( false , helpers.curbuf ( ' get_option ' , ' lisp ' ) )
eq ( nil , nvim ( ' command_output ' , ' setglobal lisp? ' ) : match ( ' nolisp ' ) )
eq ( ' nolisp ' , nvim ( ' command_output ' , ' setlocal lisp? ' ) : match ( ' nolisp ' ) )
nvim ( ' set_option ' , ' shiftwidth ' , 20 )
eq ( ' 20 ' , nvim ( ' command_output ' , ' setglobal shiftwidth? ' ) : match ( ' %d+ ' ) )
eq ( ' 8 ' , nvim ( ' command_output ' , ' setlocal shiftwidth? ' ) : match ( ' %d+ ' ) )
end )
it ( ' most window-local options have no global value ' , function ( )
local status , err = pcall ( nvim , ' get_option ' , ' foldcolumn ' )
eq ( false , status )
ok ( err : match ( ' Invalid option name ' ) ~= nil )
end )
2018-04-29 19:02:17 -07:00
it ( ' updates where the option was last set from ' , function ( )
nvim ( ' set_option ' , ' equalalways ' , false )
local status , rv = pcall ( nvim , ' command_output ' ,
' verbose set equalalways? ' )
eq ( true , status )
ok ( nil ~= string.find ( rv , ' noequalalways \n ' ..
' \t Last set from API client %(channel id %d+%) ' ) )
2019-12-02 01:46:46 -07:00
nvim ( ' exec_lua ' , ' vim.api.nvim_set_option("equalalways", true) ' , { } )
2018-05-11 01:08:09 -07:00
status , rv = pcall ( nvim , ' command_output ' ,
2018-04-29 19:02:17 -07:00
' verbose set equalalways? ' )
eq ( true , status )
eq ( ' equalalways \n \t Last set from Lua ' , rv )
end )
2014-10-08 09:56:01 -07:00
end )
2021-10-11 21:09:08 -07:00
describe ( ' nvim_get_option_value, nvim_set_option_value ' , function ( )
it ( ' works ' , function ( )
ok ( nvim ( ' get_option_value ' , ' equalalways ' , { } ) )
nvim ( ' set_option_value ' , ' equalalways ' , false , { } )
ok ( not nvim ( ' get_option_value ' , ' equalalways ' , { } ) )
end )
it ( ' can get local values when global value is set ' , function ( )
eq ( 0 , nvim ( ' get_option_value ' , ' scrolloff ' , { } ) )
eq ( - 1 , nvim ( ' get_option_value ' , ' scrolloff ' , { scope = ' local ' } ) )
end )
it ( ' can set global and local values ' , function ( )
nvim ( ' set_option_value ' , ' makeprg ' , ' hello ' , { } )
eq ( ' hello ' , nvim ( ' get_option_value ' , ' makeprg ' , { } ) )
eq ( ' ' , nvim ( ' get_option_value ' , ' makeprg ' , { scope = ' local ' } ) )
nvim ( ' set_option_value ' , ' makeprg ' , ' world ' , { scope = ' local ' } )
eq ( ' world ' , nvim ( ' get_option_value ' , ' makeprg ' , { scope = ' local ' } ) )
nvim ( ' set_option_value ' , ' makeprg ' , ' goodbye ' , { scope = ' global ' } )
eq ( ' goodbye ' , nvim ( ' get_option_value ' , ' makeprg ' , { scope = ' global ' } ) )
nvim ( ' set_option_value ' , ' makeprg ' , ' hello ' , { } )
eq ( ' hello ' , nvim ( ' get_option_value ' , ' makeprg ' , { scope = ' global ' } ) )
eq ( ' hello ' , nvim ( ' get_option_value ' , ' makeprg ' , { } ) )
eq ( ' ' , nvim ( ' get_option_value ' , ' makeprg ' , { scope = ' local ' } ) )
end )
2021-12-21 14:20:34 -07:00
it ( ' clears the local value of an option with nil ' , function ( )
-- Set global value
nvim ( ' set_option_value ' , ' shiftwidth ' , 42 , { } )
eq ( 42 , nvim ( ' get_option_value ' , ' shiftwidth ' , { } ) )
-- Set local value
nvim ( ' set_option_value ' , ' shiftwidth ' , 8 , { scope = ' local ' } )
eq ( 8 , nvim ( ' get_option_value ' , ' shiftwidth ' , { } ) )
eq ( 8 , nvim ( ' get_option_value ' , ' shiftwidth ' , { scope = ' local ' } ) )
eq ( 42 , nvim ( ' get_option_value ' , ' shiftwidth ' , { scope = ' global ' } ) )
-- Clear value without scope
nvim ( ' set_option_value ' , ' shiftwidth ' , NIL , { } )
eq ( 42 , nvim ( ' get_option_value ' , ' shiftwidth ' , { } ) )
eq ( 42 , nvim ( ' get_option_value ' , ' shiftwidth ' , { scope = ' local ' } ) )
-- Clear value with explicit scope
nvim ( ' set_option_value ' , ' shiftwidth ' , 8 , { scope = ' local ' } )
nvim ( ' set_option_value ' , ' shiftwidth ' , NIL , { scope = ' local ' } )
eq ( 42 , nvim ( ' get_option_value ' , ' shiftwidth ' , { } ) )
eq ( 42 , nvim ( ' get_option_value ' , ' shiftwidth ' , { scope = ' local ' } ) )
-- Now try with options with a special "local is unset" value (e.g. 'undolevels')
nvim ( ' set_option_value ' , ' undolevels ' , 1000 , { } )
eq ( 1000 , nvim ( ' get_option_value ' , ' undolevels ' , { scope = ' local ' } ) )
nvim ( ' set_option_value ' , ' undolevels ' , NIL , { scope = ' local ' } )
eq ( - 123456 , nvim ( ' get_option_value ' , ' undolevels ' , { scope = ' local ' } ) )
nvim ( ' set_option_value ' , ' autoread ' , true , { } )
eq ( true , nvim ( ' get_option_value ' , ' autoread ' , { scope = ' local ' } ) )
nvim ( ' set_option_value ' , ' autoread ' , NIL , { scope = ' local ' } )
eq ( NIL , nvim ( ' get_option_value ' , ' autoread ' , { scope = ' local ' } ) )
end )
2021-10-11 21:09:08 -07:00
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_{get,set}_current_buf, nvim_list_bufs ' , function ( )
2014-10-08 09:56:01 -07:00
it ( ' works ' , function ( )
2016-09-16 21:30:36 -07:00
eq ( 1 , # nvim ( ' list_bufs ' ) )
eq ( nvim ( ' list_bufs ' ) [ 1 ] , nvim ( ' get_current_buf ' ) )
2014-10-08 09:56:01 -07:00
nvim ( ' command ' , ' new ' )
2016-09-16 21:30:36 -07:00
eq ( 2 , # nvim ( ' list_bufs ' ) )
eq ( nvim ( ' list_bufs ' ) [ 2 ] , nvim ( ' get_current_buf ' ) )
nvim ( ' set_current_buf ' , nvim ( ' list_bufs ' ) [ 1 ] )
eq ( nvim ( ' list_bufs ' ) [ 1 ] , nvim ( ' get_current_buf ' ) )
2014-10-08 09:56:01 -07:00
end )
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_{get,set}_current_win, nvim_list_wins ' , function ( )
2014-10-08 09:56:01 -07:00
it ( ' works ' , function ( )
2016-09-16 21:30:36 -07:00
eq ( 1 , # nvim ( ' list_wins ' ) )
eq ( nvim ( ' list_wins ' ) [ 1 ] , nvim ( ' get_current_win ' ) )
2014-10-08 09:56:01 -07:00
nvim ( ' command ' , ' vsplit ' )
nvim ( ' command ' , ' split ' )
2016-09-16 21:30:36 -07:00
eq ( 3 , # nvim ( ' list_wins ' ) )
eq ( nvim ( ' list_wins ' ) [ 1 ] , nvim ( ' get_current_win ' ) )
nvim ( ' set_current_win ' , nvim ( ' list_wins ' ) [ 2 ] )
eq ( nvim ( ' list_wins ' ) [ 2 ] , nvim ( ' get_current_win ' ) )
2014-10-08 09:56:01 -07:00
end )
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_{get,set}_current_tabpage, nvim_list_tabpages ' , function ( )
2014-10-08 09:56:01 -07:00
it ( ' works ' , function ( )
2016-09-16 21:30:36 -07:00
eq ( 1 , # nvim ( ' list_tabpages ' ) )
eq ( nvim ( ' list_tabpages ' ) [ 1 ] , nvim ( ' get_current_tabpage ' ) )
2014-10-08 09:56:01 -07:00
nvim ( ' command ' , ' tabnew ' )
2016-09-16 21:30:36 -07:00
eq ( 2 , # nvim ( ' list_tabpages ' ) )
eq ( 2 , # nvim ( ' list_wins ' ) )
eq ( nvim ( ' list_wins ' ) [ 2 ] , nvim ( ' get_current_win ' ) )
eq ( nvim ( ' list_tabpages ' ) [ 2 ] , nvim ( ' get_current_tabpage ' ) )
nvim ( ' set_current_win ' , nvim ( ' list_wins ' ) [ 1 ] )
2014-10-08 09:56:01 -07:00
-- Switching window also switches tabpages if necessary
2016-09-16 21:30:36 -07:00
eq ( nvim ( ' list_tabpages ' ) [ 1 ] , nvim ( ' get_current_tabpage ' ) )
eq ( nvim ( ' list_wins ' ) [ 1 ] , nvim ( ' get_current_win ' ) )
nvim ( ' set_current_tabpage ' , nvim ( ' list_tabpages ' ) [ 2 ] )
eq ( nvim ( ' list_tabpages ' ) [ 2 ] , nvim ( ' get_current_tabpage ' ) )
eq ( nvim ( ' list_wins ' ) [ 2 ] , nvim ( ' get_current_win ' ) )
2014-10-08 09:56:01 -07:00
end )
end )
2014-10-23 17:14:50 -07:00
2017-03-13 07:02:37 -07:00
describe ( ' nvim_get_mode ' , function ( )
it ( " during normal-mode `g` returns blocking=true " , function ( )
nvim ( " input " , " o " ) -- add a line
eq ( { mode = ' i ' , blocking = false } , nvim ( " get_mode " ) )
nvim ( " input " , [[<C-\><C-N>]] )
eq ( 2 , nvim ( " eval " , " line('.') " ) )
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
nvim ( " input " , " g " )
eq ( { mode = ' n ' , blocking = true } , nvim ( " get_mode " ) )
nvim ( " input " , " k " ) -- complete the operator
eq ( 1 , nvim ( " eval " , " line('.') " ) ) -- verify the completed operator
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
end )
it ( " returns the correct result multiple consecutive times " , function ( )
for _ = 1 , 5 do
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
end
nvim ( " input " , " g " )
for _ = 1 , 4 do
eq ( { mode = ' n ' , blocking = true } , nvim ( " get_mode " ) )
end
nvim ( " input " , " g " )
for _ = 1 , 7 do
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
end
end )
it ( " during normal-mode CTRL-W, returns blocking=true " , function ( )
nvim ( " input " , " <C-W> " )
eq ( { mode = ' n ' , blocking = true } , nvim ( " get_mode " ) )
nvim ( " input " , " s " ) -- complete the operator
eq ( 2 , nvim ( " eval " , " winnr('$') " ) ) -- verify the completed operator
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
end )
2022-01-24 23:59:17 -07:00
it ( " during press-enter prompt without UI returns blocking=false " , function ( )
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
command ( " echom 'msg1' " )
command ( " echom 'msg2' " )
command ( " echom 'msg3' " )
command ( " echom 'msg4' " )
command ( " echom 'msg5' " )
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
nvim ( " input " , " :messages<CR> " )
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
end )
2017-03-13 07:02:37 -07:00
it ( " during press-enter prompt returns blocking=true " , function ( )
2022-01-24 23:59:17 -07:00
nvim ( " ui_attach " , 80 , 20 , { } )
2017-03-13 07:02:37 -07:00
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
command ( " echom 'msg1' " )
command ( " echom 'msg2' " )
command ( " echom 'msg3' " )
command ( " echom 'msg4' " )
command ( " echom 'msg5' " )
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
nvim ( " input " , " :messages<CR> " )
eq ( { mode = ' r ' , blocking = true } , nvim ( " get_mode " ) )
end )
it ( " during getchar() returns blocking=false " , function ( )
nvim ( " input " , " :let g:test_input = nr2char(getchar())<CR> " )
-- Events are enabled during getchar(), RPC calls are *not* blocked. #5384
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
eq ( 0 , nvim ( " eval " , " exists('g:test_input') " ) )
nvim ( " input " , " J " )
eq ( " J " , nvim ( " eval " , " g:test_input " ) )
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
end )
-- TODO: bug #6247#issuecomment-286403810
it ( " batched with input " , function ( )
2022-01-24 23:59:17 -07:00
nvim ( " ui_attach " , 80 , 20 , { } )
2017-03-13 07:02:37 -07:00
eq ( { mode = ' n ' , blocking = false } , nvim ( " get_mode " ) )
command ( " echom 'msg1' " )
command ( " echom 'msg2' " )
command ( " echom 'msg3' " )
command ( " echom 'msg4' " )
command ( " echom 'msg5' " )
local req = {
{ ' nvim_get_mode ' , { } } ,
{ ' nvim_input ' , { ' :messages<CR> ' } } ,
{ ' nvim_get_mode ' , { } } ,
{ ' nvim_eval ' , { ' 1 ' } } ,
}
2017-05-22 14:16:23 -07:00
eq ( { { { mode = ' n ' , blocking = false } ,
13 ,
2017-09-02 06:12:32 -07:00
{ mode = ' n ' , blocking = false } , -- TODO: should be blocked=true ?
2017-05-22 14:16:23 -07:00
1 } ,
NIL } , meths.call_atomic ( req ) )
2017-03-13 07:02:37 -07:00
eq ( { mode = ' r ' , blocking = true } , nvim ( " get_mode " ) )
end )
it ( " during insert-mode map-pending, returns blocking=true #6166 " , function ( )
command ( " inoremap xx foo " )
nvim ( " input " , " ix " )
eq ( { mode = ' i ' , blocking = true } , nvim ( " get_mode " ) )
end )
it ( " during normal-mode gU, returns blocking=false #6166 " , function ( )
nvim ( " input " , " gu " )
eq ( { mode = ' no ' , blocking = false } , nvim ( " get_mode " ) )
end )
2020-02-19 03:00:09 -07:00
it ( " at '-- More --' prompt returns blocking=true #11899 " , function ( )
command ( ' set more ' )
feed ( ' :digraphs<cr> ' )
eq ( { mode = ' rm ' , blocking = true } , nvim ( " get_mode " ) )
end )
2017-03-13 07:02:37 -07:00
end )
2021-12-26 00:23:39 -07:00
describe ( ' RPC (K_EVENT) ' , function ( )
it ( ' does not complete ("interrupt") normal-mode operator-pending #6166 ' , function ( )
2017-09-02 06:12:32 -07:00
helpers.insert ( [ [
FIRST LINE
SECOND LINE ] ] )
nvim ( ' input ' , ' gg ' )
nvim ( ' input ' , ' gu ' )
2017-09-04 13:45:14 -07:00
-- Make any RPC request (can be non-async: op-pending does not block).
2017-09-02 06:12:32 -07:00
nvim ( ' get_current_buf ' )
-- Buffer should not change.
2019-08-19 14:43:19 -07:00
expect ( [ [
2017-09-02 06:12:32 -07:00
FIRST LINE
SECOND LINE ] ] )
-- Now send input to complete the operator.
2017-09-04 13:45:14 -07:00
nvim ( ' input ' , ' j ' )
2019-08-19 14:43:19 -07:00
expect ( [ [
2017-09-04 13:45:14 -07:00
first line
second line ] ] )
2017-09-02 06:12:32 -07:00
end )
2017-09-16 03:17:59 -07:00
it ( ' does not complete ("interrupt") `d` #3732 ' , function ( )
local screen = Screen.new ( 20 , 4 )
screen : attach ( )
command ( ' set listchars=eol:$ ' )
command ( ' set list ' )
feed ( ' ia<cr>b<cr>c<cr><Esc>kkk ' )
feed ( ' d ' )
-- Make any RPC request (can be non-async: op-pending does not block).
nvim ( ' get_current_buf ' )
screen : expect ( [ [
^ a $ |
b $ |
c $ |
|
] ] )
end )
2021-12-26 00:23:39 -07:00
it ( ' does not complete ("interrupt") normal-mode map-pending #6166 ' , function ( )
2017-09-02 06:12:32 -07:00
command ( " nnoremap dd :let g:foo='it worked...'<CR> " )
helpers.insert ( [ [
FIRST LINE
SECOND LINE ] ] )
nvim ( ' input ' , ' gg ' )
nvim ( ' input ' , ' d ' )
2017-09-04 13:45:14 -07:00
-- Make any RPC request (must be async, because map-pending blocks).
nvim ( ' get_api_info ' )
2017-09-02 06:12:32 -07:00
-- Send input to complete the mapping.
nvim ( ' input ' , ' d ' )
2019-08-19 14:43:19 -07:00
expect ( [ [
2017-09-02 06:12:32 -07:00
FIRST LINE
SECOND LINE ] ] )
2017-09-03 23:46:10 -07:00
eq ( ' it worked... ' , helpers.eval ( ' g:foo ' ) )
2017-09-02 06:12:32 -07:00
end )
2021-12-26 00:23:39 -07:00
it ( ' does not complete ("interrupt") insert-mode map-pending #6166 ' , function ( )
2017-09-04 13:45:14 -07:00
command ( ' inoremap xx foo ' )
command ( ' set timeoutlen=9999 ' )
2017-09-02 06:12:32 -07:00
helpers.insert ( [ [
FIRST LINE
SECOND LINE ] ] )
nvim ( ' input ' , ' ix ' )
2017-09-04 13:45:14 -07:00
-- Make any RPC request (must be async, because map-pending blocks).
nvim ( ' get_api_info ' )
2017-09-02 06:12:32 -07:00
-- Send input to complete the mapping.
nvim ( ' input ' , ' x ' )
2019-08-19 14:43:19 -07:00
expect ( [ [
2017-09-02 06:12:32 -07:00
FIRST LINE
2017-09-04 13:45:14 -07:00
SECOND LINfooE ] ] )
2017-09-02 06:12:32 -07:00
end )
2021-12-26 00:23:39 -07:00
it ( ' does not interrupt Insert mode i_CTRL-O #10035 ' , function ( )
feed ( ' iHello World<c-o> ' )
eq ( { mode = ' niI ' , blocking = false } , meths.get_mode ( ) ) -- fast event
eq ( 2 , eval ( ' 1+1 ' ) ) -- causes K_EVENT key
eq ( { mode = ' niI ' , blocking = false } , meths.get_mode ( ) ) -- still in ctrl-o mode
feed ( ' dd ' )
eq ( { mode = ' i ' , blocking = false } , meths.get_mode ( ) ) -- left ctrl-o mode
expect ( ' ' ) -- executed the command
end )
it ( ' does not interrupt Select mode v_CTRL-O #15688 ' , function ( )
feed ( ' iHello World<esc>gh<c-o> ' )
eq ( { mode = ' vs ' , blocking = false } , meths.get_mode ( ) ) -- fast event
eq ( { mode = ' vs ' , blocking = false } , meths.get_mode ( ) ) -- again #15288
eq ( 2 , eval ( ' 1+1 ' ) ) -- causes K_EVENT key
eq ( { mode = ' vs ' , blocking = false } , meths.get_mode ( ) ) -- still in ctrl-o mode
feed ( ' ^ ' )
eq ( { mode = ' s ' , blocking = false } , meths.get_mode ( ) ) -- left ctrl-o mode
feed ( ' h ' )
eq ( { mode = ' i ' , blocking = false } , meths.get_mode ( ) ) -- entered insert mode
expect ( ' h ' ) -- selection is the whole line and is replaced
end )
it ( ' does not interrupt Insert mode i_0_CTRL-D #13997 ' , function ( )
command ( ' set timeoutlen=9999 ' )
feed ( ' i<Tab><Tab>a0 ' )
eq ( 2 , eval ( ' 1+1 ' ) ) -- causes K_EVENT key
feed ( ' <C-D> ' )
expect ( ' a ' ) -- recognized i_0_CTRL-D
end )
2017-09-02 06:12:32 -07:00
end )
2019-07-17 13:00:50 -07:00
describe ( ' nvim_get_context ' , function ( )
2019-09-14 18:13:02 -07:00
it ( ' validates args ' , function ( )
2021-08-21 04:55:12 -07:00
eq ( " Invalid key: 'blah' " ,
2019-09-14 18:13:02 -07:00
pcall_err ( nvim , ' get_context ' , { blah = { } } ) )
eq ( ' invalid value for key: types ' ,
pcall_err ( nvim , ' get_context ' , { types = 42 } ) )
eq ( ' unexpected type: zub ' ,
pcall_err ( nvim , ' get_context ' , { types = { ' jumps ' , ' zub ' , ' zam ' , } } ) )
end )
it ( ' returns map of current editor state ' , function ( )
2019-09-14 18:52:16 -07:00
local opts = { types = { ' regs ' , ' jumps ' , ' bufs ' , ' gvars ' } }
2019-09-14 18:13:02 -07:00
eq ( { } , parse_context ( nvim ( ' get_context ' , { } ) ) )
2019-07-17 13:00:50 -07:00
feed ( ' i1<cr>2<cr>3<c-[>ddddddqahjklquuu ' )
feed ( ' gg ' )
feed ( ' G ' )
command ( ' edit! BUF1 ' )
command ( ' edit BUF2 ' )
nvim ( ' set_var ' , ' one ' , 1 )
nvim ( ' set_var ' , ' Two ' , 2 )
nvim ( ' set_var ' , ' THREE ' , 3 )
local expected_ctx = {
[ ' regs ' ] = {
{ [ ' rt ' ] = 1 , [ ' rc ' ] = { ' 1 ' } , [ ' n ' ] = 49 , [ ' ru ' ] = true } ,
{ [ ' rt ' ] = 1 , [ ' rc ' ] = { ' 2 ' } , [ ' n ' ] = 50 } ,
{ [ ' rt ' ] = 1 , [ ' rc ' ] = { ' 3 ' } , [ ' n ' ] = 51 } ,
{ [ ' rc ' ] = { ' hjkl ' } , [ ' n ' ] = 97 } ,
} ,
[ ' jumps ' ] = eval ( ( [ [
2019-09-03 10:18:24 -07:00
filter ( map ( getjumplist ( ) [ 0 ] , ' filter(
{ " f " : expand ( " # " . v : val.bufnr . " :p " ) , " l " : v : val.lnum } ,
{ k , v -> k ! = " l " || v ! = 1 } ) ' ), ' ! empty ( v : val.f ) ' )
2019-07-17 13:00:50 -07:00
] ] ) : gsub ( ' \n ' , ' ' ) ) ,
2019-09-14 18:52:16 -07:00
[ ' bufs ' ] = eval ( [ [
2019-07-17 13:00:50 -07:00
filter ( map ( getbufinfo ( ) , ' { "f": v:val.name } ' ) , ' !empty(v:val.f) ' )
] ] ) ,
[ ' gvars ' ] = { { ' one ' , 1 } , { ' Two ' , 2 } , { ' THREE ' , 3 } } ,
}
2019-09-14 18:13:02 -07:00
eq ( expected_ctx , parse_context ( nvim ( ' get_context ' , opts ) ) )
eq ( expected_ctx , parse_context ( nvim ( ' get_context ' , { } ) ) )
eq ( expected_ctx , parse_context ( nvim ( ' get_context ' , { types = { } } ) ) )
2019-07-17 13:00:50 -07:00
end )
end )
describe ( ' nvim_load_context ' , function ( )
it ( ' sets current editor state to given context dictionary ' , function ( )
2019-09-14 18:52:16 -07:00
local opts = { types = { ' regs ' , ' jumps ' , ' bufs ' , ' gvars ' } }
2019-09-14 18:13:02 -07:00
eq ( { } , parse_context ( nvim ( ' get_context ' , opts ) ) )
2019-07-17 13:00:50 -07:00
nvim ( ' set_var ' , ' one ' , 1 )
nvim ( ' set_var ' , ' Two ' , 2 )
nvim ( ' set_var ' , ' THREE ' , 3 )
2019-09-14 18:13:02 -07:00
local ctx = nvim ( ' get_context ' , opts )
2019-07-17 13:00:50 -07:00
nvim ( ' set_var ' , ' one ' , ' a ' )
nvim ( ' set_var ' , ' Two ' , ' b ' )
nvim ( ' set_var ' , ' THREE ' , ' c ' )
eq ( { ' a ' , ' b ' , ' c ' } , eval ( ' [g:one, g:Two, g:THREE] ' ) )
nvim ( ' load_context ' , ctx )
eq ( { 1 , 2 , 3 } , eval ( ' [g:one, g:Two, g:THREE] ' ) )
end )
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_replace_termcodes ' , function ( )
2014-10-20 02:21:24 -07:00
it ( ' escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER ' , function ( )
2016-02-20 15:09:15 -07:00
eq ( ' \128 \254 X ' , helpers.nvim ( ' replace_termcodes ' , ' \128 ' , true , true , true ) )
2014-10-20 02:21:24 -07:00
end )
2016-02-20 15:09:15 -07:00
it ( ' leaves non-K_SPECIAL string unchanged ' , function ( )
eq ( ' abc ' , helpers.nvim ( ' replace_termcodes ' , ' abc ' , true , true , true ) )
2014-10-20 02:21:24 -07:00
end )
it ( ' converts <expressions> ' , function ( )
2016-02-20 15:09:15 -07:00
eq ( ' \\ ' , helpers.nvim ( ' replace_termcodes ' , ' <Leader> ' , true , true , true ) )
end )
it ( ' converts <LeftMouse> to K_SPECIAL KS_EXTRA KE_LEFTMOUSE ' , function ( )
-- K_SPECIAL KS_EXTRA KE_LEFTMOUSE
-- 0x80 0xfd 0x2c
-- 128 253 44
eq ( ' \128 \253 \44 ' , helpers.nvim ( ' replace_termcodes ' ,
' <LeftMouse> ' , true , true , true ) )
2014-10-20 02:21:24 -07:00
end )
2016-07-15 16:26:04 -07:00
2017-05-20 13:20:21 -07:00
it ( ' converts keycodes ' , function ( )
eq ( ' \n x \27 x \r x<x ' , helpers.nvim ( ' replace_termcodes ' ,
' <NL>x<Esc>x<CR>x<lt>x ' , true , true , true ) )
end )
2017-07-02 04:21:38 -07:00
it ( ' does not convert keycodes if special=false ' , function ( )
eq ( ' <NL>x<Esc>x<CR>x<lt>x ' , helpers.nvim ( ' replace_termcodes ' ,
' <NL>x<Esc>x<CR>x<lt>x ' , true , true , false ) )
end )
2016-07-15 16:26:04 -07:00
it ( ' does not crash when transforming an empty string ' , function ( )
-- Actually does not test anything, because current code will use NULL for
-- an empty string.
--
-- Problem here is that if String argument has .data in allocated memory
-- then `return str` in vim_replace_termcodes body will make Neovim free
-- `str.data` twice: once when freeing arguments, then when freeing return
-- value.
eq ( ' ' , meths.replace_termcodes ( ' ' , true , true , true ) )
end )
2014-10-20 02:21:24 -07:00
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_feedkeys ' , function ( )
2022-01-21 03:08:56 -07:00
it ( ' K_SPECIAL escaping ' , function ( )
2014-10-20 02:21:24 -07:00
local function on_setup ( )
-- notice the special char(…) \xe2\80\xa6
nvim ( ' feedkeys ' , ' :let x1="…" \n ' , ' ' , true )
2017-07-02 04:21:38 -07:00
-- Both nvim_replace_termcodes and nvim_feedkeys escape \x80
2014-10-20 02:21:24 -07:00
local inp = helpers.nvim ( ' replace_termcodes ' , ' :let x2="…"<CR> ' , true , true , true )
2022-01-21 03:08:56 -07:00
nvim ( ' feedkeys ' , inp , ' ' , true ) -- escape_ks=true
2014-10-20 02:21:24 -07:00
2022-01-21 03:08:56 -07:00
-- nvim_feedkeys with K_SPECIAL escaping disabled
2014-10-20 02:21:24 -07:00
inp = helpers.nvim ( ' replace_termcodes ' , ' :let x3="…"<CR> ' , true , true , true )
2022-01-21 03:08:56 -07:00
nvim ( ' feedkeys ' , inp , ' ' , false ) -- escape_ks=false
2014-10-20 02:21:24 -07:00
helpers.stop ( )
end
-- spin the loop a bit
helpers.run ( nil , nil , on_setup )
eq ( nvim ( ' get_var ' , ' x1 ' ) , ' … ' )
-- Because of the double escaping this is neq
neq ( nvim ( ' get_var ' , ' x2 ' ) , ' … ' )
eq ( nvim ( ' get_var ' , ' x3 ' ) , ' … ' )
end )
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_err_write ' , function ( )
2015-11-17 15:31:22 -07:00
local screen
2015-07-27 04:39:38 -07:00
before_each ( function ( )
clear ( )
screen = Screen.new ( 40 , 8 )
screen : attach ( )
screen : set_default_attr_ids ( {
2016-08-09 06:11:04 -07:00
[ 0 ] = { bold = true , foreground = Screen.colors . Blue } ,
2015-07-27 04:39:38 -07:00
[ 1 ] = { foreground = Screen.colors . White , background = Screen.colors . Red } ,
2018-03-31 02:12:27 -07:00
[ 2 ] = { bold = true , foreground = Screen.colors . SeaGreen } ,
[ 3 ] = { bold = true , reverse = true } ,
2015-07-27 04:39:38 -07:00
} )
end )
it ( ' can show one line ' , function ( )
nvim_async ( ' err_write ' , ' has bork \n ' )
screen : expect ( [ [
^ |
2016-08-09 06:11:04 -07:00
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
2015-07-27 04:39:38 -07:00
{ 1 : has bork } |
] ] )
end )
it ( ' shows return prompt when more than &cmdheight lines ' , function ( )
nvim_async ( ' err_write ' , ' something happened \n very bad \n ' )
screen : expect ( [ [
2018-03-31 02:12:27 -07:00
|
2016-08-09 06:11:04 -07:00
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
2018-03-31 02:12:27 -07:00
{ 3 : } |
2015-07-27 04:39:38 -07:00
{ 1 : something happened } |
{ 1 : very bad } |
{ 2 : Press ENTER or type command to continue } ^ |
] ] )
end )
it ( ' shows return prompt after all lines are shown ' , function ( )
nvim_async ( ' err_write ' , ' FAILURE \n ERROR \n EXCEPTION \n TRACEBACK \n ' )
screen : expect ( [ [
2018-03-31 02:12:27 -07:00
|
2016-08-09 06:11:04 -07:00
{ 0 : ~ } |
2018-03-31 02:12:27 -07:00
{ 3 : } |
2015-07-27 04:39:38 -07:00
{ 1 : FAILURE } |
{ 1 : ERROR } |
{ 1 : EXCEPTION } |
{ 1 : TRACEBACK } |
{ 2 : Press ENTER or type command to continue } ^ |
] ] )
end )
it ( ' handles multiple calls ' , function ( )
-- without linebreak text is joined to one line
nvim_async ( ' err_write ' , ' very ' )
nvim_async ( ' err_write ' , ' fail \n ' )
screen : expect ( [ [
^ |
2016-08-09 06:11:04 -07:00
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
2015-07-27 04:39:38 -07:00
{ 1 : very fail } |
] ] )
2020-10-19 11:17:51 -07:00
helpers.poke_eventloop ( )
2015-07-27 04:39:38 -07:00
-- shows up to &cmdheight lines
2015-10-05 06:13:18 -07:00
nvim_async ( ' err_write ' , ' more fail \n too fail \n ' )
2015-07-27 04:39:38 -07:00
screen : expect ( [ [
2018-03-31 02:12:27 -07:00
|
2016-08-09 06:11:04 -07:00
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
2018-03-31 02:12:27 -07:00
{ 3 : } |
2015-07-27 04:39:38 -07:00
{ 1 : more fail } |
{ 1 : too fail } |
{ 2 : Press ENTER or type command to continue } ^ |
] ] )
2015-10-05 06:13:18 -07:00
feed ( ' <cr> ' ) -- exit the press ENTER screen
2015-07-27 04:39:38 -07:00
end )
end )
2021-09-01 07:29:38 -07:00
describe ( ' nvim_list_chans, nvim_get_chan_info ' , function ( )
2017-05-13 22:43:07 -07:00
before_each ( function ( )
2021-09-01 07:29:38 -07:00
command ( ' autocmd ChanOpen * let g:opened_event = deepcopy(v:event) ' )
command ( ' autocmd ChanInfo * let g:info_event = deepcopy(v:event) ' )
2017-05-13 22:43:07 -07:00
end )
local testinfo = {
stream = ' stdio ' ,
id = 1 ,
mode = ' rpc ' ,
client = { } ,
}
local stderr = {
stream = ' stderr ' ,
id = 2 ,
mode = ' bytes ' ,
}
it ( ' returns {} for invalid channel ' , function ( )
eq ( { } , meths.get_chan_info ( 0 ) )
eq ( { } , meths.get_chan_info ( - 1 ) )
-- more preallocated numbers might be added, try something high
eq ( { } , meths.get_chan_info ( 10 ) )
end )
2021-09-01 07:29:38 -07:00
it ( ' stream=stdio channel ' , function ( )
2017-05-13 22:43:07 -07:00
eq ( { [ 1 ] = testinfo , [ 2 ] = stderr } , meths.list_chans ( ) )
eq ( testinfo , meths.get_chan_info ( 1 ) )
eq ( stderr , meths.get_chan_info ( 2 ) )
meths.set_client_info ( " functionaltests " ,
{ major = 0 , minor = 3 , patch = 17 } ,
' ui ' ,
{ do_stuff = { n_args = { 2 , 3 } } } ,
{ license = ' Apache2 ' } )
local info = {
stream = ' stdio ' ,
id = 1 ,
mode = ' rpc ' ,
client = {
name = ' functionaltests ' ,
version = { major = 0 , minor = 3 , patch = 17 } ,
type = ' ui ' ,
methods = { do_stuff = { n_args = { 2 , 3 } } } ,
attributes = { license = ' Apache2 ' } ,
} ,
}
eq ( { info = info } , meths.get_var ( " info_event " ) )
eq ( { [ 1 ] = info , [ 2 ] = stderr } , meths.list_chans ( ) )
eq ( info , meths.get_chan_info ( 1 ) )
end )
2021-09-01 07:29:38 -07:00
it ( ' stream=job channel ' , function ( )
2017-05-13 22:43:07 -07:00
eq ( 3 , eval ( " jobstart(['cat'], {'rpc': v:true}) " ) )
2021-09-01 07:29:38 -07:00
local catpath = eval ( ' exepath("cat") ' )
2017-05-13 22:43:07 -07:00
local info = {
stream = ' job ' ,
id = 3 ,
2021-09-01 07:29:38 -07:00
argv = { catpath } ,
2017-05-13 22:43:07 -07:00
mode = ' rpc ' ,
client = { } ,
}
eq ( { info = info } , meths.get_var ( " opened_event " ) )
eq ( { [ 1 ] = testinfo , [ 2 ] = stderr , [ 3 ] = info } , meths.list_chans ( ) )
eq ( info , meths.get_chan_info ( 3 ) )
2019-01-24 11:15:39 -07:00
eval ( ' rpcrequest(3, "nvim_set_client_info", "amazing-cat", {}, "remote", ' ..
2017-05-13 22:43:07 -07:00
' {"nvim_command":{"n_args":1}}, ' .. -- and so on
' {"description":"The Amazing Cat"}) ' )
info = {
stream = ' job ' ,
id = 3 ,
2021-09-01 07:29:38 -07:00
argv = { catpath } ,
2017-05-13 22:43:07 -07:00
mode = ' rpc ' ,
client = {
2019-01-24 11:15:39 -07:00
name = ' amazing-cat ' ,
2017-05-13 22:43:07 -07:00
version = { major = 0 } ,
type = ' remote ' ,
methods = { nvim_command = { n_args = 1 } } ,
attributes = { description = " The Amazing Cat " } ,
} ,
}
eq ( { info = info } , meths.get_var ( " info_event " ) )
eq ( { [ 1 ] = testinfo , [ 2 ] = stderr , [ 3 ] = info } , meths.list_chans ( ) )
2019-01-24 11:15:39 -07:00
2020-11-13 11:50:03 -07:00
eq ( " Vim:Error invoking 'nvim_set_current_buf' on channel 3 (amazing-cat): \n Wrong type for argument 1 when calling nvim_set_current_buf, expecting Buffer " ,
2019-09-03 13:51:45 -07:00
pcall_err ( eval , ' rpcrequest(3, "nvim_set_current_buf", -1) ' ) )
2017-05-13 22:43:07 -07:00
end )
2021-09-01 07:29:38 -07:00
it ( ' stream=job :terminal channel ' , function ( )
command ( ' :terminal ' )
2017-05-13 22:43:07 -07:00
eq ( { id = 1 } , meths.get_current_buf ( ) )
2021-09-01 07:29:38 -07:00
eq ( 3 , meths.buf_get_option ( 1 , ' channel ' ) )
2017-05-13 22:43:07 -07:00
local info = {
stream = ' job ' ,
id = 3 ,
2021-09-01 07:29:38 -07:00
argv = { eval ( ' exepath(&shell) ' ) } ,
2017-05-13 22:43:07 -07:00
mode = ' terminal ' ,
buffer = 1 ,
pty = ' ? ' ,
}
local event = meths.get_var ( " opened_event " )
if not iswin ( ) then
info.pty = event.info . pty
neq ( nil , string.match ( info.pty , " ^/dev/ " ) )
end
eq ( { info = info } , event )
info.buffer = { id = 1 }
eq ( { [ 1 ] = testinfo , [ 2 ] = stderr , [ 3 ] = info } , meths.list_chans ( ) )
eq ( info , meths.get_chan_info ( 3 ) )
2021-09-01 07:29:38 -07:00
-- :terminal with args + running process.
command ( ' :exe "terminal" shellescape(v:progpath) "-u NONE -i NONE" ' )
eq ( - 1 , eval ( ' jobwait([&channel], 0)[0] ' ) ) -- Running?
local expected2 = {
stream = ' job ' ,
id = 4 ,
argv = (
iswin ( ) and {
eval ( ' &shell ' ) ,
' /s ' ,
' /c ' ,
fmt ( ' "%s -u NONE -i NONE" ' , eval ( ' shellescape(v:progpath) ' ) ) ,
} or {
eval ( ' &shell ' ) ,
eval ( ' &shellcmdflag ' ) ,
fmt ( ' %s -u NONE -i NONE ' , eval ( ' shellescape(v:progpath) ' ) ) ,
}
) ,
mode = ' terminal ' ,
buffer = 2 ,
pty = ' ? ' ,
}
local actual2 = eval ( ' nvim_get_chan_info(&channel) ' )
expected2.pty = actual2.pty
eq ( expected2 , actual2 )
-- :terminal with args + stopped process.
eq ( 1 , eval ( ' jobstop(&channel) ' ) )
eval ( ' jobwait([&channel], 1000) ' ) -- Wait.
expected2.pty = ( iswin ( ) and ' ? ' or ' ' ) -- pty stream was closed.
eq ( expected2 , eval ( ' nvim_get_chan_info(&channel) ' ) )
2017-05-13 22:43:07 -07:00
end )
end )
2016-10-22 15:02:22 -07:00
describe ( ' nvim_call_atomic ' , function ( )
2016-04-13 07:37:09 -07:00
it ( ' works ' , function ( )
meths.buf_set_lines ( 0 , 0 , - 1 , true , { ' first ' } )
local req = {
{ ' nvim_get_current_line ' , { } } ,
{ ' nvim_set_current_line ' , { ' second ' } } ,
}
eq ( { { ' first ' , NIL } , NIL } , meths.call_atomic ( req ) )
eq ( { ' second ' } , meths.buf_get_lines ( 0 , 0 , - 1 , true ) )
end )
it ( ' allows multiple return values ' , function ( )
local req = {
{ ' nvim_set_var ' , { ' avar ' , true } } ,
{ ' nvim_set_var ' , { ' bvar ' , ' string ' } } ,
{ ' nvim_get_var ' , { ' avar ' } } ,
{ ' nvim_get_var ' , { ' bvar ' } } ,
}
eq ( { { NIL , NIL , true , ' string ' } , NIL } , meths.call_atomic ( req ) )
end )
it ( ' is aborted by errors in call ' , function ( )
local error_types = meths.get_api_info ( ) [ 2 ] . error_types
local req = {
{ ' nvim_set_var ' , { ' one ' , 1 } } ,
{ ' nvim_buf_set_lines ' , { } } ,
{ ' nvim_set_var ' , { ' two ' , 2 } } ,
}
eq ( { { NIL } , { 1 , error_types.Exception . id ,
' Wrong number of arguments: expecting 5 but got 0 ' } } ,
meths.call_atomic ( req ) )
eq ( 1 , meths.get_var ( ' one ' ) )
eq ( false , pcall ( meths.get_var , ' two ' ) )
-- still returns all previous successful calls
req = {
{ ' nvim_set_var ' , { ' avar ' , 5 } } ,
{ ' nvim_set_var ' , { ' bvar ' , ' string ' } } ,
{ ' nvim_get_var ' , { ' avar ' } } ,
{ ' nvim_buf_get_lines ' , { 0 , 10 , 20 , true } } ,
{ ' nvim_get_var ' , { ' bvar ' } } ,
}
eq ( { { NIL , NIL , 5 } , { 3 , error_types.Validation . id , ' Index out of bounds ' } } ,
meths.call_atomic ( req ) )
req = {
{ ' i_am_not_a_method ' , { ' xx ' } } ,
{ ' nvim_set_var ' , { ' avar ' , 10 } } ,
}
2018-06-07 01:56:44 -07:00
eq ( { { } , { 0 , error_types.Exception . id , ' Invalid method: i_am_not_a_method ' } } ,
2016-04-13 07:37:09 -07:00
meths.call_atomic ( req ) )
eq ( 5 , meths.get_var ( ' avar ' ) )
end )
2017-04-21 05:58:52 -07:00
it ( ' throws error on malformed arguments ' , function ( )
2016-04-13 07:37:09 -07:00
local req = {
{ ' nvim_set_var ' , { ' avar ' , 1 } } ,
{ ' nvim_set_var ' } ,
{ ' nvim_set_var ' , { ' avar ' , 2 } } ,
}
local status , err = pcall ( meths.call_atomic , req )
eq ( false , status )
2018-08-29 01:06:35 -07:00
ok ( err : match ( ' Items in calls array must be arrays of size 2 ' ) ~= nil )
2016-04-13 07:37:09 -07:00
-- call before was done, but not after
eq ( 1 , meths.get_var ( ' avar ' ) )
req = {
2017-02-22 15:12:26 -07:00
{ ' nvim_set_var ' , { ' bvar ' , { 2 , 3 } } } ,
2016-04-13 07:37:09 -07:00
12 ,
}
status , err = pcall ( meths.call_atomic , req )
eq ( false , status )
2018-08-29 01:06:35 -07:00
ok ( err : match ( ' Items in calls array must be arrays ' ) ~= nil )
2016-04-13 07:37:09 -07:00
eq ( { 2 , 3 } , meths.get_var ( ' bvar ' ) )
req = {
{ ' nvim_set_current_line ' , ' little line ' } ,
{ ' nvim_set_var ' , { ' avar ' , 3 } } ,
}
status , err = pcall ( meths.call_atomic , req )
eq ( false , status )
2017-04-23 13:30:08 -07:00
ok ( err : match ( ' Args must be Array ' ) ~= nil )
2016-04-13 07:37:09 -07:00
-- call before was done, but not after
eq ( 1 , meths.get_var ( ' avar ' ) )
eq ( { ' ' } , meths.buf_get_lines ( 0 , 0 , - 1 , true ) )
end )
end )
2018-02-16 01:40:40 -07:00
describe ( ' nvim_list_runtime_paths ' , function ( )
2021-10-02 01:37:30 -07:00
setup ( function ( )
local pathsep = helpers.get_pathsep ( )
mkdir_p ( ' Xtest ' .. pathsep .. ' a ' )
mkdir_p ( ' Xtest ' .. pathsep .. ' b ' )
end )
teardown ( function ( )
rmdir ' Xtest '
end )
before_each ( function ( )
meths.set_current_dir ' Xtest '
end )
2017-05-22 14:16:23 -07:00
it ( ' returns nothing with empty &runtimepath ' , function ( )
meths.set_option ( ' runtimepath ' , ' ' )
eq ( { } , meths.list_runtime_paths ( ) )
end )
it ( ' returns single runtimepath ' , function ( )
meths.set_option ( ' runtimepath ' , ' a ' )
eq ( { ' a ' } , meths.list_runtime_paths ( ) )
end )
it ( ' returns two runtimepaths ' , function ( )
meths.set_option ( ' runtimepath ' , ' a,b ' )
eq ( { ' a ' , ' b ' } , meths.list_runtime_paths ( ) )
end )
it ( ' returns empty strings when appropriate ' , function ( )
meths.set_option ( ' runtimepath ' , ' a,,b ' )
eq ( { ' a ' , ' ' , ' b ' } , meths.list_runtime_paths ( ) )
meths.set_option ( ' runtimepath ' , ' ,a,b ' )
eq ( { ' ' , ' a ' , ' b ' } , meths.list_runtime_paths ( ) )
2021-09-11 07:20:59 -07:00
-- trailing , is ignored, use ,, if you really really want $CWD
2017-05-22 14:16:23 -07:00
meths.set_option ( ' runtimepath ' , ' a,b, ' )
2021-09-11 07:20:59 -07:00
eq ( { ' a ' , ' b ' } , meths.list_runtime_paths ( ) )
meths.set_option ( ' runtimepath ' , ' a,b,, ' )
2017-05-22 14:16:23 -07:00
eq ( { ' a ' , ' b ' , ' ' } , meths.list_runtime_paths ( ) )
end )
it ( ' truncates too long paths ' , function ( )
local long_path = ( ' /a ' ) : rep ( 8192 )
meths.set_option ( ' runtimepath ' , long_path )
local paths_list = meths.list_runtime_paths ( )
2021-10-02 01:37:30 -07:00
eq ( { } , paths_list )
2017-05-22 14:16:23 -07:00
end )
end )
2014-10-23 17:14:50 -07:00
it ( ' can throw exceptions ' , function ( )
local status , err = pcall ( nvim , ' get_option ' , ' invalid-option ' )
eq ( false , status )
ok ( err : match ( ' Invalid option name ' ) ~= nil )
end )
2016-07-16 07:51:56 -07:00
2017-04-21 05:58:52 -07:00
it ( ' does not truncate error message <1 MB #5984 ' , function ( )
local very_long_name = ' A ' .. ( ' x ' ) : rep ( 10000 ) .. ' Z '
local status , err = pcall ( nvim , ' get_option ' , very_long_name )
eq ( false , status )
eq ( very_long_name , err : match ( ' Ax+Z? ' ) )
end )
2017-03-13 07:02:37 -07:00
it ( " does not leak memory on incorrect argument types " , function ( )
2016-09-16 21:30:36 -07:00
local status , err = pcall ( nvim , ' set_current_dir ' , { ' not ' , ' a ' , ' dir ' } )
2016-07-16 07:51:56 -07:00
eq ( false , status )
2020-11-13 11:50:03 -07:00
ok ( err : match ( ' : Wrong type for argument 1 when calling nvim_set_current_dir, expecting String ' ) ~= nil )
2016-07-16 07:51:56 -07:00
end )
2017-11-03 01:38:59 -07:00
describe ( ' nvim_parse_expression ' , function ( )
2017-11-26 06:08:53 -07:00
before_each ( function ( )
meths.set_option ( ' isident ' , ' ' )
end )
2019-08-14 14:57:45 -07:00
local it_maybe_pending = it
2021-10-27 15:27:17 -07:00
if helpers.isCI ( ) and os.getenv ( ' CONFIGURATION ' ) == ' MSVC_32 ' then
2019-08-14 14:57:45 -07:00
-- For "works with &opt" (flaky on MSVC_32), but not easy to skip alone. #10241
it_maybe_pending = pending
end
2017-11-04 16:41:44 -07:00
local function simplify_east_api_node ( line , east_api_node )
2017-11-05 11:06:12 -07:00
if east_api_node == NIL then
return nil
end
2017-11-04 16:41:44 -07:00
if east_api_node.children then
for k , v in pairs ( east_api_node.children ) do
east_api_node.children [ k ] = simplify_east_api_node ( line , v )
end
end
local typ = east_api_node.type
if typ == ' Register ' then
typ = typ .. ( ' (name=%s) ' ) : format (
tostring ( intchar2lua ( east_api_node.name ) ) )
east_api_node.name = nil
elseif typ == ' PlainIdentifier ' then
typ = typ .. ( ' (scope=%s,ident=%s) ' ) : format (
tostring ( intchar2lua ( east_api_node.scope ) ) , east_api_node.ident )
east_api_node.scope = nil
east_api_node.ident = nil
elseif typ == ' PlainKey ' then
typ = typ .. ( ' (key=%s) ' ) : format ( east_api_node.ident )
east_api_node.ident = nil
elseif typ == ' Comparison ' then
typ = typ .. ( ' (type=%s,inv=%u,ccs=%s) ' ) : format (
east_api_node.cmp_type , east_api_node.invert and 1 or 0 ,
east_api_node.ccs_strategy )
east_api_node.ccs_strategy = nil
east_api_node.cmp_type = nil
east_api_node.invert = nil
elseif typ == ' Integer ' then
typ = typ .. ( ' (val=%u) ' ) : format ( east_api_node.ivalue )
east_api_node.ivalue = nil
elseif typ == ' Float ' then
2017-11-19 11:40:34 -07:00
typ = typ .. format_string ( ' (val=%e) ' , east_api_node.fvalue )
2017-11-04 16:41:44 -07:00
east_api_node.fvalue = nil
elseif typ == ' SingleQuotedString ' or typ == ' DoubleQuotedString ' then
typ = format_string ( ' %s(val=%q) ' , typ , east_api_node.svalue )
east_api_node.svalue = nil
elseif typ == ' Option ' then
typ = ( ' %s(scope=%s,ident=%s) ' ) : format (
typ ,
tostring ( intchar2lua ( east_api_node.scope ) ) ,
east_api_node.ident )
east_api_node.ident = nil
east_api_node.scope = nil
elseif typ == ' Environment ' then
typ = ( ' %s(ident=%s) ' ) : format ( typ , east_api_node.ident )
east_api_node.ident = nil
2017-11-19 10:20:06 -07:00
elseif typ == ' Assignment ' then
local aug = east_api_node.augmentation
if aug == ' ' then aug = ' Plain ' end
typ = ( ' %s(%s) ' ) : format ( typ , aug )
east_api_node.augmentation = nil
2017-11-04 16:41:44 -07:00
end
typ = ( ' %s:%u:%u:%s ' ) : format (
typ , east_api_node.start [ 1 ] , east_api_node.start [ 2 ] ,
line : sub ( east_api_node.start [ 2 ] + 1 ,
east_api_node.start [ 2 ] + 1 + east_api_node.len - 1 ) )
assert ( east_api_node.start [ 2 ] + east_api_node.len - 1 <= # line )
for k , _ in pairs ( east_api_node.start ) do
assert ( ( { true , true } ) [ k ] )
end
east_api_node.start = nil
east_api_node.type = nil
east_api_node.len = nil
local can_simplify = true
for _ , _ in pairs ( east_api_node ) do
if can_simplify then can_simplify = false end
end
if can_simplify then
return typ
else
east_api_node [ 1 ] = typ
return east_api_node
end
end
local function simplify_east_api ( line , east_api )
if east_api.error then
east_api.err = east_api.error
east_api.error = nil
east_api.err . msg = east_api.err . message
east_api.err . message = nil
end
if east_api.ast then
east_api.ast = { simplify_east_api_node ( line , east_api.ast ) }
2017-11-19 10:20:06 -07:00
if # east_api.ast == 0 then
east_api.ast = nil
end
2017-11-04 16:41:44 -07:00
end
2017-11-05 15:15:18 -07:00
if east_api.len == # line then
east_api.len = nil
end
2017-11-04 16:41:44 -07:00
return east_api
end
local function simplify_east_hl ( line , east_hl )
for i , v in ipairs ( east_hl ) do
east_hl [ i ] = ( ' %s:%u:%u:%s ' ) : format (
v [ 4 ] ,
v [ 1 ] ,
v [ 2 ] ,
line : sub ( v [ 2 ] + 1 , v [ 3 ] ) )
end
return east_hl
end
2017-11-05 11:06:12 -07:00
local FLAGS_TO_STR = {
[ 0 ] = " " ,
[ 1 ] = " m " ,
[ 2 ] = " E " ,
[ 3 ] = " mE " ,
2017-11-19 10:20:06 -07:00
[ 4 ] = " l " ,
[ 5 ] = " lm " ,
[ 6 ] = " lE " ,
[ 7 ] = " lmE " ,
2017-11-05 11:06:12 -07:00
}
2017-11-19 10:20:06 -07:00
local function _check_parsing ( opts , str , exp_ast , exp_highlighting_fs ,
nz_flags_exps )
if type ( str ) ~= ' string ' then
return
end
local zflags = opts.flags [ 1 ]
2017-11-05 11:06:12 -07:00
nz_flags_exps = nz_flags_exps or { }
2017-11-19 10:20:06 -07:00
for _ , flags in ipairs ( opts.flags ) do
2017-11-05 11:06:12 -07:00
local err , msg = pcall ( function ( )
local east_api = meths.parse_expression ( str , FLAGS_TO_STR [ flags ] , true )
local east_hl = east_api.highlight
east_api.highlight = nil
local ast = simplify_east_api ( str , east_api )
local hls = simplify_east_hl ( str , east_hl )
local exps = {
ast = exp_ast ,
hl_fs = exp_highlighting_fs ,
}
local add_exps = nz_flags_exps [ flags ]
2017-11-19 10:20:06 -07:00
if not add_exps and flags == 3 + zflags then
add_exps = nz_flags_exps [ 1 + zflags ] or nz_flags_exps [ 2 + zflags ]
2017-11-04 16:41:44 -07:00
end
2017-11-05 11:06:12 -07:00
if add_exps then
if add_exps.ast then
exps.ast = mergedicts_copy ( exps.ast , add_exps.ast )
end
if add_exps.hl_fs then
exps.hl_fs = mergedicts_copy ( exps.hl_fs , add_exps.hl_fs )
end
end
eq ( exps.ast , ast )
if exp_highlighting_fs then
local exp_highlighting = { }
local next_col = 0
for i , h in ipairs ( exps.hl_fs ) do
exp_highlighting [ i ] , next_col = h ( next_col )
end
eq ( exp_highlighting , hls )
end
end )
if not err then
2018-02-01 14:55:22 -07:00
if type ( msg ) == ' table ' then
local merr , new_msg = pcall (
format_string , ' table error: \n %s \n \n (%r) ' , msg.message , msg )
if merr then
msg = new_msg
else
msg = format_string ( ' table error without .message: \n (%r) ' ,
msg )
end
elseif type ( msg ) ~= ' string ' then
msg = format_string ( ' non-string non-table error: \n %r ' , msg )
end
error ( format_string ( ' Error while processing test (%r, %s): \n %s ' ,
str , FLAGS_TO_STR [ flags ] , msg ) )
2017-11-04 16:41:44 -07:00
end
end
end
local function hl ( group , str , shift )
return function ( next_col )
local col = next_col + ( shift or 0 )
return ( ( ' %s:%u:%u:%s ' ) : format (
2017-11-30 01:53:25 -07:00
' Nvim ' .. group ,
2017-11-04 16:41:44 -07:00
0 ,
col ,
str ) ) , ( col + # str )
end
end
2017-11-19 10:20:06 -07:00
local function fmtn ( typ , args , rest )
if ( typ == ' UnknownFigure '
or typ == ' DictLiteral '
or typ == ' CurlyBracesIdentifier '
or typ == ' Lambda ' ) then
return ( ' %s%s ' ) : format ( typ , rest )
elseif typ == ' DoubleQuotedString ' or typ == ' SingleQuotedString ' then
if args : sub ( - 4 ) == ' NULL ' then
args = args : sub ( 1 , - 5 ) .. ' "" '
end
return ( ' %s(%s)%s ' ) : format ( typ , args , rest )
end
end
require ( ' test.unit.viml.expressions.parser_tests ' ) (
2019-08-14 14:57:45 -07:00
it_maybe_pending , _check_parsing , hl , fmtn )
2017-11-03 01:38:59 -07:00
end )
2018-02-16 01:40:40 -07:00
describe ( ' nvim_list_uis ' , function ( )
it ( ' returns empty if --headless ' , function ( )
2018-11-15 18:00:04 -07:00
-- Test runner defaults to --headless.
2018-02-16 01:40:40 -07:00
eq ( { } , nvim ( " list_uis " ) )
end )
it ( ' returns attached UIs ' , function ( )
local screen = Screen.new ( 20 , 4 )
UI/nvim_ui_attach(): add `override` option
Before now, Nvim always degrades UI capabilities to the lowest-common
denominator. For example, if any connected UI has `ext_messages=false`
then `ext_messages=true` requested by any other connected UI is ignored.
Now `nvim_ui_attach()` supports `override=true`, which flips the
behavior: if any UI requests an `ext_*` UI capability then the
capability is enabled (and the legacy behavior is disabled).
Legacy UIs will be broken while a `override=true` UI is connected, but
it's useful for debugging: you can type into the TUI and observe the UI
events from another connected (UI) client. And the legacy UI will
"recover" after the `override=true` UI disconnects.
Example using pynvim:
>>> n.ui_attach(2048, 2048, rgb=True, override=True, ext_multigrid=True, ext_messages=True, ext_popupmenu=True)
>>> while True: n.next_message();
2019-05-09 10:35:38 -07:00
screen : attach ( { override = true } )
2018-02-16 01:40:40 -07:00
local expected = {
{
2018-05-31 01:58:31 -07:00
chan = 1 ,
2018-02-16 01:40:40 -07:00
ext_cmdline = false ,
ext_popupmenu = false ,
ext_tabline = false ,
ext_wildmenu = false ,
2018-09-28 05:19:37 -07:00
ext_linegrid = screen._options . ext_linegrid or false ,
2017-12-09 03:26:06 -07:00
ext_multigrid = false ,
2017-10-31 08:46:02 -07:00
ext_hlstate = false ,
ext_termcolors = false ,
ext_messages = false ,
2018-02-16 01:40:40 -07:00
height = 4 ,
rgb = true ,
UI/nvim_ui_attach(): add `override` option
Before now, Nvim always degrades UI capabilities to the lowest-common
denominator. For example, if any connected UI has `ext_messages=false`
then `ext_messages=true` requested by any other connected UI is ignored.
Now `nvim_ui_attach()` supports `override=true`, which flips the
behavior: if any UI requests an `ext_*` UI capability then the
capability is enabled (and the legacy behavior is disabled).
Legacy UIs will be broken while a `override=true` UI is connected, but
it's useful for debugging: you can type into the TUI and observe the UI
events from another connected (UI) client. And the legacy UI will
"recover" after the `override=true` UI disconnects.
Example using pynvim:
>>> n.ui_attach(2048, 2048, rgb=True, override=True, ext_multigrid=True, ext_messages=True, ext_popupmenu=True)
>>> while True: n.next_message();
2019-05-09 10:35:38 -07:00
override = true ,
2018-02-16 01:40:40 -07:00
width = 20 ,
}
}
eq ( expected , nvim ( " list_uis " ) )
screen : detach ( )
screen = Screen.new ( 44 , 99 )
screen : attach ( { rgb = false } )
2018-07-06 05:39:50 -07:00
expected [ 1 ] . rgb = false
UI/nvim_ui_attach(): add `override` option
Before now, Nvim always degrades UI capabilities to the lowest-common
denominator. For example, if any connected UI has `ext_messages=false`
then `ext_messages=true` requested by any other connected UI is ignored.
Now `nvim_ui_attach()` supports `override=true`, which flips the
behavior: if any UI requests an `ext_*` UI capability then the
capability is enabled (and the legacy behavior is disabled).
Legacy UIs will be broken while a `override=true` UI is connected, but
it's useful for debugging: you can type into the TUI and observe the UI
events from another connected (UI) client. And the legacy UI will
"recover" after the `override=true` UI disconnects.
Example using pynvim:
>>> n.ui_attach(2048, 2048, rgb=True, override=True, ext_multigrid=True, ext_messages=True, ext_popupmenu=True)
>>> while True: n.next_message();
2019-05-09 10:35:38 -07:00
expected [ 1 ] . override = false
2018-07-06 05:39:50 -07:00
expected [ 1 ] . width = 44
expected [ 1 ] . height = 99
2018-02-16 01:40:40 -07:00
eq ( expected , nvim ( " list_uis " ) )
end )
end )
2017-06-23 00:56:35 -07:00
describe ( ' nvim_create_namespace ' , function ( )
it ( ' works ' , function ( )
eq ( { } , meths.get_namespaces ( ) )
eq ( 1 , meths.create_namespace ( " ns-1 " ) )
eq ( 2 , meths.create_namespace ( " ns-2 " ) )
eq ( 1 , meths.create_namespace ( " ns-1 " ) )
eq ( { [ " ns-1 " ] = 1 , [ " ns-2 " ] = 2 } , meths.get_namespaces ( ) )
eq ( 3 , meths.create_namespace ( " " ) )
eq ( 4 , meths.create_namespace ( " " ) )
eq ( { [ " ns-1 " ] = 1 , [ " ns-2 " ] = 2 } , meths.get_namespaces ( ) )
end )
end )
2017-09-02 05:21:06 -07:00
describe ( ' nvim_create_buf ' , function ( )
it ( ' works ' , function ( )
2019-02-09 08:38:36 -07:00
eq ( { id = 2 } , meths.create_buf ( true , false ) )
eq ( { id = 3 } , meths.create_buf ( false , false ) )
2017-09-02 05:21:06 -07:00
eq ( ' 1 %a "[No Name]" line 1 \n ' ..
2019-06-03 04:08:05 -07:00
' 2 h "[No Name]" line 0 ' ,
2017-09-02 05:21:06 -07:00
meths.command_output ( " ls " ) )
-- current buffer didn't change
eq ( { id = 1 } , meths.get_current_buf ( ) )
local screen = Screen.new ( 20 , 4 )
screen : attach ( )
meths.buf_set_lines ( 2 , 0 , - 1 , true , { " some text " } )
meths.set_current_buf ( 2 )
screen : expect ( [ [
^ some text |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] , {
[ 1 ] = { bold = true , foreground = Screen.colors . Blue1 } ,
} )
end )
it ( ' can change buftype before visiting ' , function ( )
meths.set_option ( " hidden " , false )
2019-02-09 08:38:36 -07:00
eq ( { id = 2 } , meths.create_buf ( true , false ) )
2017-09-02 05:21:06 -07:00
meths.buf_set_option ( 2 , " buftype " , " nofile " )
meths.buf_set_lines ( 2 , 0 , - 1 , true , { " test text " } )
command ( " split | buffer 2 " )
eq ( { id = 2 } , meths.get_current_buf ( ) )
-- if the buf_set_option("buftype") didn't work, this would error out.
command ( " close " )
eq ( { id = 1 } , meths.get_current_buf ( ) )
end )
2019-02-09 08:38:36 -07:00
2020-05-29 09:45:32 -07:00
it ( " does not trigger BufEnter, BufWinEnter " , function ( )
2019-06-03 04:08:05 -07:00
command ( " let g:fired = v:false " )
command ( " au BufEnter,BufWinEnter * let g:fired = v:true " )
eq ( { id = 2 } , meths.create_buf ( true , false ) )
meths.buf_set_lines ( 2 , 0 , - 1 , true , { " test " , " text " } )
eq ( false , eval ( ' g:fired ' ) )
end )
2020-05-29 09:45:32 -07:00
it ( ' scratch-buffer ' , function ( )
2019-02-09 08:38:36 -07:00
eq ( { id = 2 } , meths.create_buf ( false , true ) )
eq ( { id = 3 } , meths.create_buf ( true , true ) )
eq ( { id = 4 } , meths.create_buf ( true , true ) )
local scratch_bufs = { 2 , 3 , 4 }
eq ( ' 1 %a "[No Name]" line 1 \n ' ..
2019-06-03 04:08:05 -07:00
' 3 h "[Scratch]" line 0 \n ' ..
' 4 h "[Scratch]" line 0 ' ,
2019-12-01 23:43:16 -07:00
meths.exec ( ' ls ' , true ) )
2019-02-09 08:38:36 -07:00
-- current buffer didn't change
eq ( { id = 1 } , meths.get_current_buf ( ) )
local screen = Screen.new ( 20 , 4 )
2019-03-04 09:53:41 -07:00
screen : set_default_attr_ids ( {
[ 1 ] = { bold = true , foreground = Screen.colors . Blue1 } ,
} )
2019-02-09 08:38:36 -07:00
screen : attach ( )
--
-- Editing a scratch-buffer does NOT change its properties.
--
local edited_buf = 2
meths.buf_set_lines ( edited_buf , 0 , - 1 , true , { " some text " } )
for _ , b in ipairs ( scratch_bufs ) do
eq ( ' nofile ' , meths.buf_get_option ( b , ' buftype ' ) )
eq ( ' hide ' , meths.buf_get_option ( b , ' bufhidden ' ) )
eq ( false , meths.buf_get_option ( b , ' swapfile ' ) )
2020-05-29 09:45:32 -07:00
eq ( false , meths.buf_get_option ( b , ' modeline ' ) )
2019-02-09 08:38:36 -07:00
end
--
2019-03-04 09:53:41 -07:00
-- Visiting a scratch-buffer DOES NOT change its properties.
2019-02-09 08:38:36 -07:00
--
meths.set_current_buf ( edited_buf )
screen : expect ( [ [
^ some text |
{ 1 : ~ } |
{ 1 : ~ } |
|
2019-03-04 09:53:41 -07:00
] ] )
eq ( ' nofile ' , meths.buf_get_option ( edited_buf , ' buftype ' ) )
eq ( ' hide ' , meths.buf_get_option ( edited_buf , ' bufhidden ' ) )
2019-02-09 08:38:36 -07:00
eq ( false , meths.buf_get_option ( edited_buf , ' swapfile ' ) )
2020-05-29 09:45:32 -07:00
eq ( false , meths.buf_get_option ( edited_buf , ' modeline ' ) )
2019-03-04 09:53:41 -07:00
2020-05-29 09:45:32 -07:00
-- Scratch buffer can be wiped without error.
2019-03-04 09:53:41 -07:00
command ( ' bwipe ' )
screen : expect ( [ [
^ |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
2019-02-09 08:38:36 -07:00
end )
2019-08-25 00:11:22 -07:00
it ( ' does not cause heap-use-after-free on exit while setting options ' , function ( )
command ( ' au OptionSet * q ' )
command ( ' silent! call nvim_create_buf(0, 1) ' )
end )
2017-09-02 05:21:06 -07:00
end )
2020-01-25 05:29:52 -07:00
describe ( ' nvim_get_runtime_file ' , function ( )
2020-11-24 06:18:46 -07:00
local p = helpers.alter_slashes
it ( ' can find files ' , function ( )
2020-01-25 05:29:52 -07:00
eq ( { } , meths.get_runtime_file ( " bork.borkbork " , false ) )
eq ( { } , meths.get_runtime_file ( " bork.borkbork " , true ) )
eq ( 1 , # meths.get_runtime_file ( " autoload/msgpack.vim " , false ) )
eq ( 1 , # meths.get_runtime_file ( " autoload/msgpack.vim " , true ) )
local val = meths.get_runtime_file ( " autoload/remote/*.vim " , true )
eq ( 2 , # val )
if endswith ( val [ 1 ] , " define.vim " ) then
2020-11-24 06:18:46 -07:00
ok ( endswith ( val [ 1 ] , p " autoload/remote/define.vim " ) )
ok ( endswith ( val [ 2 ] , p " autoload/remote/host.vim " ) )
2020-01-25 05:29:52 -07:00
else
2020-11-24 06:18:46 -07:00
ok ( endswith ( val [ 1 ] , p " autoload/remote/host.vim " ) )
ok ( endswith ( val [ 2 ] , p " autoload/remote/define.vim " ) )
2020-01-25 05:29:52 -07:00
end
val = meths.get_runtime_file ( " autoload/remote/*.vim " , false )
eq ( 1 , # val )
2020-11-24 06:18:46 -07:00
ok ( endswith ( val [ 1 ] , p " autoload/remote/define.vim " )
or endswith ( val [ 1 ] , p " autoload/remote/host.vim " ) )
2021-09-11 07:20:59 -07:00
val = meths.get_runtime_file ( " lua " , true )
eq ( 1 , # val )
ok ( endswith ( val [ 1 ] , p " lua " ) )
val = meths.get_runtime_file ( " lua/vim " , true )
eq ( 1 , # val )
ok ( endswith ( val [ 1 ] , p " lua/vim " ) )
2020-11-24 06:18:46 -07:00
end )
it ( ' can find directories ' , function ( )
local val = meths.get_runtime_file ( " lua/ " , true )
eq ( 1 , # val )
ok ( endswith ( val [ 1 ] , p " lua/ " ) )
val = meths.get_runtime_file ( " lua/vim/ " , true )
eq ( 1 , # val )
ok ( endswith ( val [ 1 ] , p " lua/vim/ " ) )
eq ( { } , meths.get_runtime_file ( " foobarlang/ " , true ) )
2020-01-25 05:29:52 -07:00
end )
2021-12-16 04:40:23 -07:00
it ( ' can handle bad patterns ' , function ( )
if helpers.pending_win32 ( pending ) then return end
eq ( " Vim:E220: Missing }. " , pcall_err ( meths.get_runtime_file , " { " , false ) )
eq ( ' Vim(echo):E5555: API call: Vim:E220: Missing }. ' ,
exc_exec ( " echo nvim_get_runtime_file('{', v:false) " ) )
end )
2020-01-25 05:29:52 -07:00
end )
2020-12-03 18:59:36 -07:00
2020-12-04 02:59:58 -07:00
describe ( ' nvim_get_all_options_info ' , function ( )
2020-12-03 18:59:36 -07:00
it ( ' should have key value pairs of option names ' , function ( )
2020-12-04 02:59:58 -07:00
local options_info = meths.get_all_options_info ( )
2020-12-03 18:59:36 -07:00
neq ( nil , options_info.listchars )
neq ( nil , options_info.tabstop )
2020-12-04 02:59:58 -07:00
eq ( meths.get_option_info ' winhighlight ' , options_info.winhighlight )
2020-12-03 18:59:36 -07:00
end )
2021-05-24 22:06:50 -07:00
it ( ' should not crash when echoed ' , function ( )
meths.exec ( " echo nvim_get_all_options_info() " , true )
end )
2020-12-03 18:59:36 -07:00
end )
describe ( ' nvim_get_option_info ' , function ( )
it ( ' should error for unknown options ' , function ( )
2020-12-04 02:59:58 -07:00
eq ( " no such option: 'bogus' " , pcall_err ( meths.get_option_info , ' bogus ' ) )
2020-12-03 18:59:36 -07:00
end )
it ( ' should return the same options for short and long name ' , function ( )
2020-12-04 02:59:58 -07:00
eq ( meths.get_option_info ' winhl ' , meths.get_option_info ' winhighlight ' )
2020-12-03 18:59:36 -07:00
end )
it ( ' should have information about window options ' , function ( )
2020-12-04 02:59:58 -07:00
eq ( {
2021-06-11 10:39:59 -07:00
allows_duplicates = true ,
2020-12-04 02:59:58 -07:00
commalist = false ;
default = " " ;
flaglist = false ;
global_local = false ;
last_set_chan = 0 ;
last_set_linenr = 0 ;
last_set_sid = 0 ;
name = " winhighlight " ;
scope = " win " ;
shortname = " winhl " ;
type = " string " ;
was_set = false ;
} , meths.get_option_info ' winhl ' )
2020-12-03 18:59:36 -07:00
end )
it ( ' should have information about buffer options ' , function ( )
2020-12-04 02:59:58 -07:00
eq ( {
2021-06-11 10:39:59 -07:00
allows_duplicates = true ,
2020-12-04 02:59:58 -07:00
commalist = false ,
default = " " ,
flaglist = false ,
global_local = false ,
last_set_chan = 0 ,
last_set_linenr = 0 ,
last_set_sid = 0 ,
name = " filetype " ,
scope = " buf " ,
shortname = " ft " ,
type = " string " ,
was_set = false
} , meths.get_option_info ' filetype ' )
2020-12-03 18:59:36 -07:00
end )
it ( ' should have information about global options ' , function ( )
2020-12-04 02:59:58 -07:00
-- precondition: the option was changed from its default
-- in test setup.
eq ( false , meths.get_option ' showcmd ' )
eq ( {
2021-06-11 10:39:59 -07:00
allows_duplicates = true ,
2020-12-04 02:59:58 -07:00
commalist = false ,
default = true ,
flaglist = false ,
global_local = false ,
last_set_chan = 0 ,
last_set_linenr = 0 ,
last_set_sid = - 2 ,
name = " showcmd " ,
scope = " global " ,
shortname = " sc " ,
type = " boolean " ,
was_set = true
} , meths.get_option_info ' showcmd ' )
2020-12-03 18:59:36 -07:00
end )
end )
2021-01-10 23:18:51 -07:00
describe ( ' nvim_echo ' , function ( )
local screen
before_each ( function ( )
clear ( )
screen = Screen.new ( 40 , 8 )
screen : attach ( )
screen : set_default_attr_ids ( {
[ 0 ] = { bold = true , foreground = Screen.colors . Blue } ,
[ 1 ] = { bold = true , foreground = Screen.colors . SeaGreen } ,
[ 2 ] = { bold = true , reverse = true } ,
[ 3 ] = { foreground = Screen.colors . Brown , bold = true } , -- Statement
[ 4 ] = { foreground = Screen.colors . SlateBlue } , -- Special
} )
command ( ' highlight Statement gui=bold guifg=Brown ' )
command ( ' highlight Special guifg=SlateBlue ' )
end )
2021-01-21 05:49:25 -07:00
it ( ' should clear cmdline message before echo ' , function ( )
feed ( ' :call nvim_echo([["msg"]], v:false, {})<CR> ' )
screen : expect { grid = [ [
^ |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
msg |
] ] }
end )
2021-01-10 23:18:51 -07:00
it ( ' can show highlighted line ' , function ( )
nvim_async ( " echo " , { { " msg_a " } , { " msg_b " , " Statement " } , { " msg_c " , " Special " } } , true , { } )
screen : expect { grid = [ [
^ |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
msg_a { 3 : msg_b } { 4 : msg_c } |
] ] }
end )
it ( ' can show highlighted multiline ' , function ( )
nvim_async ( " echo " , { { " msg_a \n msg_a " , " Statement " } , { " msg_b " , " Special " } } , true , { } )
screen : expect { grid = [ [
|
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 2 : } |
{ 3 : msg_a } |
{ 3 : msg_a } { 4 : msg_b } |
{ 1 : Press ENTER or type command to continue } ^ |
] ] }
end )
it ( ' can save message history ' , function ( )
nvim ( ' command ' , ' set cmdheight=2 ' ) -- suppress Press ENTER
nvim ( " echo " , { { " msg \n msg " } , { " msg " } } , true , { } )
eq ( " msg \n msgmsg " , meths.exec ( ' messages ' , true ) )
end )
it ( ' can disable saving message history ' , function ( )
nvim ( ' command ' , ' set cmdheight=2 ' ) -- suppress Press ENTER
nvim_async ( " echo " , { { " msg \n msg " } , { " msg " } } , false , { } )
eq ( " " , meths.exec ( " messages " , true ) )
end )
end )
2020-12-20 08:52:01 -07:00
describe ( ' nvim_open_term ' , function ( )
local screen
before_each ( function ( )
clear ( )
screen = Screen.new ( 100 , 35 )
screen : attach ( )
screen : set_default_attr_ids ( {
[ 0 ] = { bold = true , foreground = Screen.colors . Blue } ,
[ 1 ] = { background = Screen.colors . Plum1 } ;
[ 2 ] = { background = tonumber ( ' 0xffff40 ' ) , bg_indexed = true } ;
[ 3 ] = { background = Screen.colors . Plum1 , fg_indexed = true , foreground = tonumber ( ' 0x00e000 ' ) } ;
[ 4 ] = { bold = true , reverse = true , background = Screen.colors . Plum1 } ;
2020-12-24 15:15:20 -07:00
[ 5 ] = { foreground = Screen.colors . Blue , background = Screen.colors . LightMagenta , bold = true } ;
[ 6 ] = { bold = true } ;
[ 7 ] = { reverse = true , background = Screen.colors . LightMagenta } ;
2020-12-20 08:52:01 -07:00
} )
end )
it ( ' can batch process sequences ' , function ( )
local b = meths.create_buf ( true , true )
meths.open_win ( b , false , { width = 79 , height = 31 , row = 1 , col = 1 , relative = ' editor ' } )
local t = meths.open_term ( b , { } )
meths.chan_send ( t , io.open ( " test/functional/fixtures/smile2.cat " , " r " ) : read ( " *a " ) )
screen : expect { grid = [ [
^ |
{ 0 : ~ } { 1 :: smile } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : oooo $ $ $ $ $ $ $ $ $ $ $ $ oooo } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : oo $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ o } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : oo $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ o } { 1 : } { 2 : o $ } { 1 : } { 2 : $ $ } { 1 : } { 2 : o $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : o } { 1 : } { 2 : $ } { 1 : } { 2 : oo } { 1 : } { 2 : o $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ o } { 1 : } { 2 : $ $ } { 1 : } { 2 : $ $ } { 1 : } { 2 : $ $ o $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : oo } { 1 : } { 2 : $ } { 1 : } { 2 : $ } { 1 : " }{2:$}{1: }{2:o$$$$$$$$$}{1: }{2:$$$$$$$$$$$$$}{1: }{2:$$$$$$$$$o}{1: }{2:$$$o$$o$}{1: }{0: }|
{ 0 : ~ } { 1 : " }{2:$$$$$$o$}{1: }{2:o$$$$$$$$$}{1: }{2:$$$$$$$$$$$}{1: }{2:$$$$$$$$$$o}{1: }{2:$$$$$$$$}{1: }{0: }|
{ 0 : ~ } { 1 : } { 2 : $ $ $ $ $ $ $ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ $ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ $ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : " " " }{2:$$$}{1: }{0: }|
{ 0 : ~ } { 1 : " }{2:$$$}{1: " " " " }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: " } { 2 : $ $ $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : $ $ $ } { 1 : } { 2 : o $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : " }{2:$$$o}{1: }{0: }|
{ 0 : ~ } { 1 : } { 2 : o $ $ } { 1 : " }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:$$$o}{1: }{0: }|
{ 0 : ~ } { 1 : } { 2 : $ $ $ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : " " } { 2 : $ $ $ $ $ $ ooooo $ $ $ $ o } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : o $ $ $ oooo $ $ $ $ $ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : } { 2 : o $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : $ $ $ $ $ $ $ $ } { 1 : " }{2:$$$$}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:$$$$}{1: " " " " " " " " }{0: }|
{ 0 : ~ } { 1 : " " " " } { 2 : $ $ $ $ } { 1 : " }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: " } { 2 : o $ $ $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : " }{2:$$$o}{1: " " " } { 2 : $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : " }{2:$$}{1: " } { 2 : $ $ $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : $ $ $ o } { 1 : " }{2:$$}{1: " " }{2:$$$$$$}{1: " " " " }{2:o$$$}{1: }{0: }|
{ 0 : ~ } { 1 : } { 2 : $ $ $ $ o } { 1 : } { 2 : o $ $ $ } { 1 : " }{0: }|
{ 0 : ~ } { 1 : " }{2:$$$$o}{1: }{2:o$$$$$$o}{1: " } { 2 : $ $ $ $ o } { 1 : } { 2 : o $ $ $ $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : " }{2:$$$$$oo}{1: " " }{2:$$$$o$$$$$o}{1: }{2:o$$$$}{1: " " }{0: }|
{ 0 : ~ } { 1 : " " } { 2 : $ $ $ $ $ oooo } { 1 : " }{2:$$$o$$$$$$$$$}{1: " " " } { 0 : } |
{ 0 : ~ } { 1 : " " } { 2 : $ $ $ $ $ $ $ oo } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : " " " " } { 2 : $ $ $ $ $ $ $ $ $ $ $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ $ $ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 2 : $ $ $ $ $ $ $ $ $ $ } { 1 : " }{0: }|
{ 0 : ~ } { 1 : " }{2:$$$}{1: " " " " }{0: }|
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 3 : Press ENTER or type command to continue } { 1 : } { 0 : } |
{ 0 : ~ } { 4 : term : //~/ config2 / docs / pres // 32693 : vim --clean +smile 29,39 All}{0: }|
{ 0 : ~ } { 1 :: call nvim__screenshot ( " smile2 . cat " ) } { 0 : } |
{ 0 : ~ } |
{ 0 : ~ } |
|
] ] }
end )
2020-12-24 15:15:20 -07:00
it ( ' can handle input ' , function ( )
screen : try_resize ( 50 , 10 )
eq ( { 3 , 2 } , exec_lua [ [
buf = vim.api . nvim_create_buf ( 1 , 1 )
stream = ' '
do_the_echo = false
function input ( _ , t1 , b1 , data )
stream = stream .. data
_G.vals = { t1 , b1 }
if do_the_echo then
vim.api . nvim_chan_send ( t1 , data )
end
end
term = vim.api . nvim_open_term ( buf , { on_input = input } )
vim.api . nvim_open_win ( buf , true , { width = 40 , height = 5 , row = 1 , col = 1 , relative = ' editor ' } )
return { term , buf }
] ] )
screen : expect { grid = [ [
|
{ 0 : ~ } { 1 : ^ } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
|
] ] }
feed ' iba<c-x>bla '
screen : expect { grid = [ [
|
{ 0 : ~ } { 7 : } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 6 : -- TERMINAL --} |
] ] }
eq ( ' ba \024 bla ' , exec_lua [[ return stream ]] )
eq ( { 3 , 2 } , exec_lua [[ return vals ]] )
exec_lua [[ do_the_echo = true ]]
feed ' herrejösses! '
screen : expect { grid = [ [
|
{ 0 : ~ } { 1 : herrejösses ! } { 7 : } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } { 1 : } { 0 : } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 0 : ~ } |
{ 6 : -- TERMINAL --} |
] ] }
eq ( ' ba \024 blaherrejösses! ' , exec_lua [[ return stream ]] )
end )
2020-12-20 08:52:01 -07:00
end )
2021-10-05 08:49:20 -07:00
describe ( ' nvim_del_mark ' , function ( )
it ( ' works ' , function ( )
local buf = meths.create_buf ( false , true )
meths.buf_set_lines ( buf , - 1 , - 1 , true , { ' a ' , ' bit of ' , ' text ' } )
2021-11-01 06:46:26 -07:00
eq ( true , meths.buf_set_mark ( buf , ' F ' , 2 , 2 , { } ) )
2021-10-05 08:49:20 -07:00
eq ( true , meths.del_mark ( ' F ' ) )
eq ( { 0 , 0 } , meths.buf_get_mark ( buf , ' F ' ) )
end )
it ( ' fails when invalid marks are used ' , function ( )
eq ( false , pcall ( meths.del_mark , ' f ' ) )
eq ( false , pcall ( meths.del_mark , ' ! ' ) )
eq ( false , pcall ( meths.del_mark , ' fail ' ) )
end )
end )
describe ( ' nvim_get_mark ' , function ( )
it ( ' works ' , function ( )
local buf = meths.create_buf ( false , true )
meths.buf_set_lines ( buf , - 1 , - 1 , true , { ' a ' , ' bit of ' , ' text ' } )
2021-11-01 06:46:26 -07:00
meths.buf_set_mark ( buf , ' F ' , 2 , 2 , { } )
2021-10-05 08:49:20 -07:00
meths.buf_set_name ( buf , " mybuf " )
2021-11-01 06:46:26 -07:00
local mark = meths.get_mark ( ' F ' , { } )
2021-10-05 08:49:20 -07:00
-- Compare the path tail ony
assert ( string.find ( mark [ 4 ] , " mybuf$ " ) )
eq ( { 2 , 2 , buf.id , mark [ 4 ] } , mark )
end )
it ( ' fails when invalid marks are used ' , function ( )
eq ( false , pcall ( meths.del_mark , ' f ' ) )
eq ( false , pcall ( meths.del_mark , ' ! ' ) )
eq ( false , pcall ( meths.del_mark , ' fail ' ) )
end )
it ( ' returns the expected when mark is not set ' , function ( )
eq ( true , meths.del_mark ( ' A ' ) )
2021-11-01 06:46:26 -07:00
eq ( { 0 , 0 , 0 , ' ' } , meths.get_mark ( ' A ' , { } ) )
2021-10-05 08:49:20 -07:00
end )
it ( ' works with deleted buffers ' , function ( )
local fname = tmpname ( )
write_file ( fname , ' a \n bit of \t ext ' )
nvim ( " command " , " edit " .. fname )
local buf = meths.get_current_buf ( )
2021-11-01 06:46:26 -07:00
meths.buf_set_mark ( buf , ' F ' , 2 , 2 , { } )
2021-10-05 08:49:20 -07:00
nvim ( " command " , " new " ) -- Create new buf to avoid :bd failing
nvim ( " command " , " bd! " .. buf.id )
os.remove ( fname )
2021-11-01 06:46:26 -07:00
local mark = meths.get_mark ( ' F ' , { } )
2021-10-05 08:49:20 -07:00
-- To avoid comparing relative vs absolute path
local mfname = mark [ 4 ]
local tail_patt = [[[\/][^\/]*$]]
-- tail of paths should be equals
eq ( fname : match ( tail_patt ) , mfname : match ( tail_patt ) )
eq ( { 2 , 2 , buf.id , mark [ 4 ] } , mark )
end )
end )
2021-10-18 12:44:17 -07:00
describe ( ' nvim_eval_statusline ' , function ( )
it ( ' works ' , function ( )
eq ( {
str = ' %StatusLineStringWithHighlights ' ,
width = 31
} ,
meths.eval_statusline (
' %%StatusLineString%#WarningMsg#WithHighlights ' ,
{ } ) )
end )
it ( ' doesn \' t exceed maxwidth ' , function ( )
eq ( {
str = ' Should be trun> ' ,
width = 15
} ,
meths.eval_statusline (
' Should be truncated%< ' ,
{ maxwidth = 15 } ) )
end )
2022-01-16 03:44:28 -07:00
it ( ' supports ASCII fillchar ' , function ( )
eq ( { str = ' a~~~b ' , width = 5 } ,
meths.eval_statusline ( ' a%=b ' , { fillchar = ' ~ ' , maxwidth = 5 } ) )
end )
it ( ' supports single-width multibyte fillchar ' , function ( )
eq ( { str = ' a━━━b ' , width = 5 } ,
meths.eval_statusline ( ' a%=b ' , { fillchar = ' ━ ' , maxwidth = 5 } ) )
end )
2022-03-09 16:18:49 -07:00
it ( ' treats double-width fillchar as single-width ' , function ( )
eq ( { str = ' a哦哦哦b ' , width = 5 } ,
meths.eval_statusline ( ' a%=b ' , { fillchar = ' 哦 ' , maxwidth = 5 } ) )
2022-01-16 03:44:28 -07:00
end )
2022-03-09 16:18:49 -07:00
it ( ' treats control character fillchar as single-width ' , function ( )
eq ( { str = ' a \031 \031 \031 b ' , width = 5 } ,
meths.eval_statusline ( ' a%=b ' , { fillchar = ' \031 ' , maxwidth = 5 } ) )
2022-01-16 03:44:28 -07:00
end )
it ( ' rejects multiple-character fillchar ' , function ( )
2022-03-09 16:18:49 -07:00
eq ( ' fillchar must be a single character ' ,
2022-01-16 03:44:28 -07:00
pcall_err ( meths.eval_statusline , ' ' , { fillchar = ' aa ' } ) )
end )
it ( ' rejects empty string fillchar ' , function ( )
2022-03-09 16:18:49 -07:00
eq ( ' fillchar must be a single character ' ,
2022-01-16 03:44:28 -07:00
pcall_err ( meths.eval_statusline , ' ' , { fillchar = ' ' } ) )
end )
it ( ' rejects non-string fillchar ' , function ( )
2022-03-09 16:18:49 -07:00
eq ( ' fillchar must be a single character ' ,
2022-01-16 03:44:28 -07:00
pcall_err ( meths.eval_statusline , ' ' , { fillchar = 1 } ) )
end )
2021-10-18 12:44:17 -07:00
describe ( ' highlight parsing ' , function ( )
it ( ' works ' , function ( )
eq ( {
str = " TextWithWarningHighlightTextWithUserHighlight " ,
width = 45 ,
highlights = {
{ start = 0 , group = ' WarningMsg ' } ,
{ start = 24 , group = ' User1 ' }
} ,
} ,
meths.eval_statusline (
' %#WarningMsg#TextWithWarningHighlight%1*TextWithUserHighlight ' ,
{ highlights = true } ) )
end )
it ( ' works with no highlight ' , function ( )
eq ( {
str = " TextWithNoHighlight " ,
width = 19 ,
highlights = {
{ start = 0 , group = ' StatusLine ' } ,
} ,
} ,
meths.eval_statusline (
' TextWithNoHighlight ' ,
{ highlights = true } ) )
end )
it ( ' works with inactive statusline ' , function ( )
command ( ' split ' )
eq ( {
str = ' TextWithNoHighlightTextWithWarningHighlight ' ,
width = 43 ,
highlights = {
{ start = 0 , group = ' StatusLineNC ' } ,
{ start = 19 , group = ' WarningMsg ' }
}
} ,
meths.eval_statusline (
' TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight ' ,
{ winid = meths.list_wins ( ) [ 2 ] . id , highlights = true } ) )
end )
it ( ' works with tabline ' , function ( )
eq ( {
str = ' TextWithNoHighlightTextWithWarningHighlight ' ,
width = 43 ,
highlights = {
{ start = 0 , group = ' TabLineFill ' } ,
{ start = 19 , group = ' WarningMsg ' }
}
} ,
meths.eval_statusline (
' TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight ' ,
{ use_tabline = true , highlights = true } ) )
end )
end )
end )
2014-10-08 09:56:01 -07:00
end )