diff options
author | Jan Edmund Lazo <jan.lazo@mail.utoronto.ca> | 2020-02-02 15:55:15 -0500 |
---|---|---|
committer | Jan Edmund Lazo <jan.lazo@mail.utoronto.ca> | 2020-02-29 17:40:00 -0500 |
commit | 3c12ee333a519c5be1d8f63d7978b483a51a3da7 (patch) | |
tree | eacd0da0ae6a415dc3f2e3bb32dfb09cbaaa0c5b /test/functional/ex_cmds/echo_spec.lua | |
parent | 1656367b90bd29d84d5ebf1ccef560368a1973cf (diff) | |
download | rneovim-3c12ee333a519c5be1d8f63d7978b483a51a3da7.tar.gz rneovim-3c12ee333a519c5be1d8f63d7978b483a51a3da7.tar.bz2 rneovim-3c12ee333a519c5be1d8f63d7978b483a51a3da7.zip |
vim-patch:8.1.0619: :echomsg and :echoerr do not handle List and Dict
Problem: :echomsg and :echoerr do not handle List and Dict like :echo does.
(Daniel Hahler)
Solution: Be more tolerant about the expression result type.
https://github.com/vim/vim/commit/461a7fcfce3cd6414f990037e6468af3b5ccf119
Add lua functional tests for :echo,:echon,:echomsg,:echoerr
because nvim did not port "test_" functions from Vim
that modify internal state.
Testing :echoerr via try/catch is sufficient.
Diffstat (limited to 'test/functional/ex_cmds/echo_spec.lua')
-rw-r--r-- | test/functional/ex_cmds/echo_spec.lua | 167 |
1 files changed, 119 insertions, 48 deletions
diff --git a/test/functional/ex_cmds/echo_spec.lua b/test/functional/ex_cmds/echo_spec.lua index 10c7230896..408ce52b8c 100644 --- a/test/functional/ex_cmds/echo_spec.lua +++ b/test/functional/ex_cmds/echo_spec.lua @@ -11,31 +11,57 @@ local dedent = helpers.dedent local command = helpers.command local exc_exec = helpers.exc_exec local redir_exec = helpers.redir_exec +local matches = helpers.matches + +describe(':echo :echon :echomsg :echoerr', function() + local fn_tbl = {'String', 'StringN', 'StringMsg', 'StringErr'} + local function assert_same_echo_dump(expected, input, use_eval) + for _,v in pairs(fn_tbl) do + eq(expected, use_eval and eval(v..'('..input..')') or funcs[v](input)) + end + end + local function assert_matches_echo_dump(expected, input, use_eval) + for _,v in pairs(fn_tbl) do + matches(expected, use_eval and eval(v..'('..input..')') or funcs[v](input)) + end + end -describe(':echo', function() before_each(function() clear() source([[ function String(s) return execute('echo a:s')[1:] endfunction + function StringMsg(s) + return execute('echomsg a:s')[1:] + endfunction + function StringN(s) + return execute('echon a:s') + endfunction + function StringErr(s) + try + execute 'echoerr a:s' + catch + return substitute(v:exception, '^Vim(echoerr):', '', '') + endtry + endfunction ]]) end) describe('used to represent floating-point values', function() it('dumps NaN values', function() - eq('str2float(\'nan\')', eval('String(str2float(\'nan\'))')) + assert_same_echo_dump("str2float('nan')", "str2float('nan')", true) end) it('dumps infinite values', function() - eq('str2float(\'inf\')', eval('String(str2float(\'inf\'))')) - eq('-str2float(\'inf\')', eval('String(str2float(\'-inf\'))')) + assert_same_echo_dump("str2float('inf')", "str2float('inf')", true) + assert_same_echo_dump("-str2float('inf')", "str2float('-inf')", true) end) it('dumps regular values', function() - eq('1.5', funcs.String(1.5)) - eq('1.56e-20', funcs.String(1.56000e-020)) - eq('0.0', eval('String(0.0)')) + assert_same_echo_dump('1.5', 1.5) + assert_same_echo_dump('1.56e-20', 1.56000e-020) + assert_same_echo_dump('0.0', '0.0', true) end) it('dumps special v: values', function() @@ -45,69 +71,81 @@ describe(':echo', function() eq('v:true', funcs.String(true)) eq('v:false', funcs.String(false)) eq('v:null', funcs.String(NIL)) + eq('true', eval('StringMsg(v:true)')) + eq('false', eval('StringMsg(v:false)')) + eq('null', eval('StringMsg(v:null)')) + eq('true', funcs.StringMsg(true)) + eq('false', funcs.StringMsg(false)) + eq('null', funcs.StringMsg(NIL)) + eq('true', eval('StringErr(v:true)')) + eq('false', eval('StringErr(v:false)')) + eq('null', eval('StringErr(v:null)')) + eq('true', funcs.StringErr(true)) + eq('false', funcs.StringErr(false)) + eq('null', funcs.StringErr(NIL)) end) it('dumps values with at most six digits after the decimal point', function() - eq('1.234568e-20', funcs.String(1.23456789123456789123456789e-020)) - eq('1.234568', funcs.String(1.23456789123456789123456789)) + assert_same_echo_dump('1.234568e-20', 1.23456789123456789123456789e-020) + assert_same_echo_dump('1.234568', 1.23456789123456789123456789) end) it('dumps values with at most seven digits before the decimal point', function() - eq('1234567.891235', funcs.String(1234567.89123456789123456789)) - eq('1.234568e7', funcs.String(12345678.9123456789123456789)) + assert_same_echo_dump('1234567.891235', 1234567.89123456789123456789) + assert_same_echo_dump('1.234568e7', 12345678.9123456789123456789) end) it('dumps negative values', function() - eq('-1.5', funcs.String(-1.5)) - eq('-1.56e-20', funcs.String(-1.56000e-020)) - eq('-1.234568e-20', funcs.String(-1.23456789123456789123456789e-020)) - eq('-1.234568', funcs.String(-1.23456789123456789123456789)) - eq('-1234567.891235', funcs.String(-1234567.89123456789123456789)) - eq('-1.234568e7', funcs.String(-12345678.9123456789123456789)) + assert_same_echo_dump('-1.5', -1.5) + assert_same_echo_dump('-1.56e-20', -1.56000e-020) + assert_same_echo_dump('-1.234568e-20', -1.23456789123456789123456789e-020) + assert_same_echo_dump('-1.234568', -1.23456789123456789123456789) + assert_same_echo_dump('-1234567.891235', -1234567.89123456789123456789) + assert_same_echo_dump('-1.234568e7', -12345678.9123456789123456789) end) end) describe('used to represent numbers', function() it('dumps regular values', function() - eq('0', funcs.String(0)) - eq('-1', funcs.String(-1)) - eq('1', funcs.String(1)) + assert_same_echo_dump('0', 0) + assert_same_echo_dump('-1', -1) + assert_same_echo_dump('1', 1) end) it('dumps large values', function() - eq('2147483647', funcs.String(2^31-1)) - eq('-2147483648', funcs.String(-2^31)) + assert_same_echo_dump('2147483647', 2^31-1) + assert_same_echo_dump('-2147483648', -2^31) end) end) describe('used to represent strings', function() it('dumps regular strings', function() - eq('test', funcs.String('test')) + assert_same_echo_dump('test', 'test') end) it('dumps empty strings', function() - eq('', funcs.String('')) + assert_same_echo_dump('', '') end) - it('dumps strings with \' inside', function() - eq('\'\'\'', funcs.String('\'\'\'')) - eq('a\'b\'\'', funcs.String('a\'b\'\'')) - eq('\'b\'\'d', funcs.String('\'b\'\'d')) - eq('a\'b\'c\'d', funcs.String('a\'b\'c\'d')) + it("dumps strings with ' inside", function() + assert_same_echo_dump("'''", "'''") + assert_same_echo_dump("a'b''", "a'b''") + assert_same_echo_dump("'b''d", "'b''d") + assert_same_echo_dump("a'b'c'd", "a'b'c'd") end) it('dumps NULL strings', function() - eq('', eval('String($XXX_UNEXISTENT_VAR_XXX)')) + assert_same_echo_dump('', '$XXX_UNEXISTENT_VAR_XXX', true) end) it('dumps NULL lists', function() - eq('[]', eval('String(v:_null_list)')) + assert_same_echo_dump('[]', 'v:_null_list', true) end) it('dumps NULL dictionaries', function() - eq('{}', eval('String(v:_null_dict)')) + assert_same_echo_dump('{}', 'v:_null_dict', true) end) end) @@ -129,15 +167,27 @@ describe(':echo', function() it('dumps references to built-in functions', function() eq('function', eval('String(function("function"))')) + eq("function('function')", eval('StringMsg(function("function"))')) + eq("function('function')", eval('StringErr(function("function"))')) end) it('dumps references to user functions', function() eq('Test1', eval('String(function("Test1"))')) eq('g:Test3', eval('String(function("g:Test3"))')) + eq("function('Test1')", eval("StringMsg(function('Test1'))")) + eq("function('g:Test3')", eval("StringMsg(function('g:Test3'))")) + eq("function('Test1')", eval("StringErr(function('Test1'))")) + eq("function('g:Test3')", eval("StringErr(function('g:Test3'))")) end) it('dumps references to script functions', function() eq('<SNR>2_Test2', eval('String(Test2_f)')) + eq("function('<SNR>2_Test2')", eval('StringMsg(Test2_f)')) + eq("function('<SNR>2_Test2')", eval('StringErr(Test2_f)')) + end) + + it('dump references to lambdas', function() + assert_matches_echo_dump("function%('<lambda>%d+'%)", '{-> 1234}', true) end) it('dumps partials with self referencing a partial', function() @@ -156,19 +206,23 @@ describe(':echo', function() end) it('dumps automatically created partials', function() - eq('function(\'<SNR>2_Test2\', {\'f\': function(\'<SNR>2_Test2\')})', - eval('String({"f": Test2_f}.f)')) - eq('function(\'<SNR>2_Test2\', [1], {\'f\': function(\'<SNR>2_Test2\', [1])})', - eval('String({"f": function(Test2_f, [1])}.f)')) + assert_same_echo_dump( + "function('<SNR>2_Test2', {'f': function('<SNR>2_Test2')})", + '{"f": Test2_f}.f', + true) + assert_same_echo_dump( + "function('<SNR>2_Test2', [1], {'f': function('<SNR>2_Test2', [1])})", + '{"f": function(Test2_f, [1])}.f', + true) end) it('dumps manually created partials', function() - eq('function(\'Test3\', [1, 2], {})', - eval('String(function("Test3", [1, 2], {}))')) - eq('function(\'Test3\', {})', - eval('String(function("Test3", {}))')) - eq('function(\'Test3\', [1, 2])', - eval('String(function("Test3", [1, 2]))')) + assert_same_echo_dump("function('Test3', [1, 2], {})", + "function('Test3', [1, 2], {})", true) + assert_same_echo_dump("function('Test3', [1, 2])", + "function('Test3', [1, 2])", true) + assert_same_echo_dump("function('Test3', {})", + "function('Test3', {})", true) end) it('does not crash or halt when dumping partials with reference cycles in self', @@ -225,15 +279,19 @@ describe(':echo', function() describe('used to represent lists', function() it('dumps empty list', function() - eq('[]', funcs.String({})) + assert_same_echo_dump('[]', {}) + end) + + it('dumps non-empty list', function() + assert_same_echo_dump('[1, 2]', {1,2}) end) it('dumps nested lists', function() - eq('[[[[[]]]]]', funcs.String({{{{{}}}}})) + assert_same_echo_dump('[[[[[]]]]]', {{{{{}}}}}) end) it('dumps nested non-empty lists', function() - eq('[1, [[3, [[5], 4]], 2]]', funcs.String({1, {{3, {{5}, 4}}, 2}})) + assert_same_echo_dump('[1, [[3, [[5], 4]], 2]]', {1, {{3, {{5}, 4}}, 2}}) end) it('does not error when dumping recursive lists', function() @@ -252,18 +310,18 @@ describe(':echo', function() describe('used to represent dictionaries', function() it('dumps empty dictionary', function() - eq('{}', eval('String({})')) + assert_same_echo_dump('{}', '{}', true) end) it('dumps list with two same empty dictionaries, also in partials', function() command('let d = {}') - eq('[{}, {}]', eval('String([d, d])')) + assert_same_echo_dump('[{}, {}]', '[d, d]', true) eq('[function(\'tr\', {}), {}]', eval('String([function("tr", d), d])')) eq('[{}, function(\'tr\', {})]', eval('String([d, function("tr", d)])')) end) it('dumps non-empty dictionary', function() - eq('{\'t\'\'est\': 1}', funcs.String({['t\'est']=1})) + assert_same_echo_dump("{'t''est': 1}", {["t'est"]=1}) end) it('does not error when dumping recursive dictionaries', function() @@ -297,11 +355,20 @@ describe(':echo', function() eq('<8e>', funcs.String(chr(0x8e))) eq('<c2>', funcs.String(('«'):sub(1, 1))) eq('«', funcs.String(('«'):sub(1, 2))) + + eq('<80>', funcs.StringMsg(chr(0x80))) + eq('<81>', funcs.StringMsg(chr(0x81))) + eq('<8e>', funcs.StringMsg(chr(0x8e))) + eq('<c2>', funcs.StringMsg(('«'):sub(1, 1))) + eq('«', funcs.StringMsg(('«'):sub(1, 2))) end) it('displays ASCII control characters using ^X notation', function() eq('^C', funcs.String(ctrl('c'))) eq('^A', funcs.String(ctrl('a'))) eq('^F', funcs.String(ctrl('f'))) + eq('^C', funcs.StringMsg(ctrl('c'))) + eq('^A', funcs.StringMsg(ctrl('a'))) + eq('^F', funcs.StringMsg(ctrl('f'))) end) it('prints CR, NL and tab as-is', function() eq('\n', funcs.String('\n')) @@ -311,11 +378,15 @@ describe(':echo', function() it('prints non-printable UTF-8 in <> notation', function() -- SINGLE SHIFT TWO, unicode control eq('<8e>', funcs.String(funcs.nr2char(0x8E))) + eq('<8e>', funcs.StringMsg(funcs.nr2char(0x8E))) -- Surrogate pair: U+1F0A0 PLAYING CARD BACK is represented in UTF-16 as -- 0xD83C 0xDCA0. This is not valid in UTF-8. eq('<d83c>', funcs.String(funcs.nr2char(0xD83C))) eq('<dca0>', funcs.String(funcs.nr2char(0xDCA0))) eq('<d83c><dca0>', funcs.String(funcs.nr2char(0xD83C) .. funcs.nr2char(0xDCA0))) + eq('<d83c>', funcs.StringMsg(funcs.nr2char(0xD83C))) + eq('<dca0>', funcs.StringMsg(funcs.nr2char(0xDCA0))) + eq('<d83c><dca0>', funcs.StringMsg(funcs.nr2char(0xD83C) .. funcs.nr2char(0xDCA0))) end) end) end) |