diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/functional/api/vim_spec.lua | 23 | ||||
-rw-r--r-- | test/functional/eval/backtick_expansion_spec.lua | 16 | ||||
-rw-r--r-- | test/functional/eval/execute_spec.lua | 9 | ||||
-rw-r--r-- | test/functional/ex_cmds/bang_filter_spec.lua | 51 | ||||
-rw-r--r-- | test/functional/fixtures/shell-test.c | 23 | ||||
-rw-r--r-- | test/functional/fixtures/shell_data.txt | bin | 0 -> 50 bytes | |||
-rw-r--r-- | test/functional/legacy/arglist_spec.lua | 11 | ||||
-rw-r--r-- | test/functional/legacy/edit_spec.lua | 25 | ||||
-rw-r--r-- | test/functional/legacy/search_spec.lua | 110 | ||||
-rw-r--r-- | test/functional/plugin/man_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/terminal/ex_terminal_spec.lua | 50 | ||||
-rw-r--r-- | test/functional/terminal/tui_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/ui/bufhl_spec.lua | 15 | ||||
-rw-r--r-- | test/functional/ui/highlight_spec.lua | 1 | ||||
-rw-r--r-- | test/functional/ui/mouse_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/ui/output_spec.lua | 179 | ||||
-rw-r--r-- | test/functional/ui/screen.lua | 3 | ||||
-rw-r--r-- | test/functional/ui/spell_spec.lua | 49 | ||||
-rw-r--r-- | test/helpers.lua | 23 | ||||
-rw-r--r-- | test/unit/viml/expressions/parser_tests.lua | 60 |
20 files changed, 517 insertions, 141 deletions
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 39db831fe3..1faed4e9b1 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -11,6 +11,7 @@ local funcs = helpers.funcs local request = helpers.request local meth_pcall = helpers.meth_pcall local command = helpers.command +local iswin = helpers.iswin local intchar2lua = global_helpers.intchar2lua local format_string = global_helpers.format_string @@ -99,8 +100,9 @@ describe('api', function() [[echo nvim_command_output('echo "nested1\nnested2"') | ls]])) end) - it('does not return shell |:!| output', function() - eq(':!echo "foo"\r\n', nvim('command_output', [[!echo "foo"]])) + it('returns shell |:!| output', function() + local win_lf = iswin() and '\r' or '' + eq(':!echo foo\r\n\nfoo'..win_lf..'\n', nvim('command_output', [[!echo foo]])) end) it("parse error: fails (specific error), does NOT update v:errmsg", function() @@ -951,9 +953,20 @@ describe('api', function() end end) if not err then - msg = format_string('Error while processing test (%r, %s):\n%s', - str, FLAGS_TO_STR[flags], msg) - error(msg) + 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)) end end end diff --git a/test/functional/eval/backtick_expansion_spec.lua b/test/functional/eval/backtick_expansion_spec.lua index 81e8e295fa..b1b44cfa8b 100644 --- a/test/functional/eval/backtick_expansion_spec.lua +++ b/test/functional/eval/backtick_expansion_spec.lua @@ -21,11 +21,19 @@ describe("backtick expansion", function() end) it("with default 'shell'", function() - if helpers.pending_win32(pending) then return end -- Need win32 shell fixes - command(":silent args `echo ***2`") + if helpers.iswin() then + command(":silent args `dir /b *2`") + else + command(":silent args `echo ***2`") + end eq({ "file2", }, eval("argv()")) - command(":silent args `echo */*4`") - eq({ "subdir/file4", }, eval("argv()")) + if helpers.iswin() then + command(":silent args `dir /s/b *4`") + eq({ "subdir\\file4", }, eval("map(argv(), 'fnamemodify(v:val, \":.\")')")) + else + command(":silent args `echo */*4`") + eq({ "subdir/file4", }, eval("argv()")) + end end) it("with shell=fish", function() diff --git a/test/functional/eval/execute_spec.lua b/test/functional/eval/execute_spec.lua index 91966ed3dd..183884a51e 100644 --- a/test/functional/eval/execute_spec.lua +++ b/test/functional/eval/execute_spec.lua @@ -9,6 +9,7 @@ local funcs = helpers.funcs local Screen = require('test.functional.ui.screen') local command = helpers.command local feed = helpers.feed +local iswin = helpers.iswin describe('execute()', function() before_each(clear) @@ -118,9 +119,11 @@ describe('execute()', function() feed('<CR>') end) - -- This matches Vim behavior. - it('does not capture shell-command output', function() - eq('\n:!echo "foo"\13\n', funcs.execute('!echo "foo"')) + -- This deviates from vim behavior, but is consistent + -- with how nvim currently displays the output. + it('does capture shell-command output', function() + local win_lf = iswin() and '\13' or '' + eq('\n:!echo foo\r\n\nfoo'..win_lf..'\n', funcs.execute('!echo foo')) end) describe('{silent} argument', function() diff --git a/test/functional/ex_cmds/bang_filter_spec.lua b/test/functional/ex_cmds/bang_filter_spec.lua deleted file mode 100644 index aaec983b73..0000000000 --- a/test/functional/ex_cmds/bang_filter_spec.lua +++ /dev/null @@ -1,51 +0,0 @@ --- Specs for bang/filter commands - -local helpers = require('test.functional.helpers')(after_each) -local feed, command, clear = helpers.feed, helpers.command, helpers.clear -local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir - -if helpers.pending_win32(pending) then return end - -local Screen = require('test.functional.ui.screen') - - -describe('issues', function() - local screen - - before_each(function() - clear() - rmdir('bang_filter_spec') - mkdir('bang_filter_spec') - write_file('bang_filter_spec/f1', 'f1') - write_file('bang_filter_spec/f2', 'f2') - write_file('bang_filter_spec/f3', 'f3') - screen = Screen.new() - screen:attach() - end) - - after_each(function() - rmdir('bang_filter_spec') - end) - - it('#3269 Last line of shell output is not truncated', function() - command([[nnoremap <silent>\l :!ls bang_filter_spec<cr>]]) - feed([[\l]]) - screen:expect([[ - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | - :!ls bang_filter_spec | - | - f1 | - f2 | - f3 | - Press ENTER or type command to continue^ | - ]]) - end) - -end) diff --git a/test/functional/fixtures/shell-test.c b/test/functional/fixtures/shell-test.c index 8dbec2aaee..38695ce76b 100644 --- a/test/functional/fixtures/shell-test.c +++ b/test/functional/fixtures/shell-test.c @@ -4,6 +4,13 @@ #include <stdio.h> #include <string.h> #include <stdint.h> +#include <unistd.h> + +static void wait(void) +{ + fflush(stdout); + usleep(10*1000); +} static void help(void) { @@ -61,6 +68,22 @@ int main(int argc, char **argv) for (uint8_t i = 0; i < number; i++) { printf("%d: %s\n", (int) i, argv[3]); } + } else if (strcmp(argv[1], "UTF-8") == 0) { + // test split-up UTF-8 sequence + printf("\xc3"); wait(); + printf("\xa5\n"); wait(); + + // split up a 2+2 grapheme clusters all possible ways + printf("ref: \xc3\xa5\xcc\xb2\n"); wait(); + + printf("1: \xc3"); wait(); + printf("\xa5\xcc\xb2\n"); wait(); + + printf("2: \xc3\xa5"); wait(); + printf("\xcc\xb2\n"); wait(); + + printf("3: \xc3\xa5\xcc"); wait(); + printf("\xb2\n"); wait(); } else { fprintf(stderr, "Unknown first argument\n"); return 3; diff --git a/test/functional/fixtures/shell_data.txt b/test/functional/fixtures/shell_data.txt Binary files differnew file mode 100644 index 0000000000..ef3506c5b1 --- /dev/null +++ b/test/functional/fixtures/shell_data.txt diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua index 191f145095..ec754a533b 100644 --- a/test/functional/legacy/arglist_spec.lua +++ b/test/functional/legacy/arglist_spec.lua @@ -222,20 +222,19 @@ describe('argument list commands', function() eq({'a', 'b'}, eval('argv()')) eq('b', eval('expand("%:t")')) command('argedit a') - eq({'a', 'b'}, eval('argv()')) + eq({'a', 'b', 'a'}, eval('argv()')) eq('a', eval('expand("%:t")')) command('argedit c') - eq({'a', 'c', 'b'}, eval('argv()')) + eq({'a', 'b', 'a', 'c'}, eval('argv()')) command('0argedit x') - eq({'x', 'a', 'c', 'b'}, eval('argv()')) + eq({'x', 'a', 'b', 'a', 'c'}, eval('argv()')) command('enew! | set modified') assert_fails('argedit y', 'E37:') command('argedit! y') - eq({'x', 'y', 'a', 'c', 'b'}, eval('argv()')) + eq({'x', 'y', 'y', 'a', 'b', 'a', 'c'}, eval('argv()')) command('%argd') - -- Nvim allows unescaped spaces in filename on all platforms. #6010 command('argedit a b') - eq({'a b'}, eval('argv()')) + eq({'a', 'b'}, eval('argv()')) end) it('test for :argdelete command', function() diff --git a/test/functional/legacy/edit_spec.lua b/test/functional/legacy/edit_spec.lua new file mode 100644 index 0000000000..91d602924c --- /dev/null +++ b/test/functional/legacy/edit_spec.lua @@ -0,0 +1,25 @@ +-- Test for edit functions +-- See also: src/nvim/testdir/test_edit.vim + +local helpers = require('test.functional.helpers')(after_each) +local source = helpers.source +local eq, eval = helpers.eq, helpers.eval +local funcs = helpers.funcs +local clear = helpers.clear + +describe('edit', function() + before_each(clear) + + it('reset insertmode from i_ctrl-r_=', function() + source([=[ + call setline(1, ['abc']) + call cursor(1, 4) + call feedkeys(":set im\<cr>ZZZ\<c-r>=setbufvar(1,'&im', 0)\<cr>",'tnix') + ]=]) + eq({'abZZZc'}, funcs.getline(1,'$')) + eq({0, 1, 1, 0}, funcs.getpos('.')) + eq(0, eval('&im')) + end) + +end) + diff --git a/test/functional/legacy/search_spec.lua b/test/functional/legacy/search_spec.lua index 5f71861821..277d8d6c7f 100644 --- a/test/functional/legacy/search_spec.lua +++ b/test/functional/legacy/search_spec.lua @@ -6,6 +6,7 @@ local eq = helpers.eq local eval = helpers.eval local feed = helpers.feed local funcs = helpers.funcs +local wait = helpers.wait describe('search cmdline', function() local screen @@ -471,4 +472,113 @@ describe('search cmdline', function() coladd = 0, skipcol = 0, curswant = 0}, funcs.winsaveview()) end) + + it("CTRL-G with 'incsearch' and ? goes in the right direction", function() + -- oldtest: Test_search_cmdline4(). + screen:detach() + screen = Screen.new(40, 4) + screen:attach() + screen:set_default_attr_ids({ + inc = {reverse = true}, + err = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, + more = { bold = true, foreground = Screen.colors.SeaGreen4 }, + tilde = { bold = true, foreground = Screen.colors.Blue1 }, + }) + command('enew!') + funcs.setline(1, {' 1 the first', ' 2 the second', ' 3 the third'}) + command('set laststatus=0 shortmess+=s') + command('set incsearch') + command('$') + -- Send the input in chunks, so the cmdline logic regards it as + -- "interactive". This mimics Vim's test_override("char_avail"). + -- (See legacy test: test_search.vim) + feed('?the') + wait() + feed('<c-g>') + wait() + feed('<cr>') + screen:expect([[ + 1 the first | + 2 the second | + 3 ^the third | + ?the | + ]]) + + command('$') + feed('?the') + wait() + feed('<c-g>') + wait() + feed('<c-g>') + wait() + feed('<cr>') + screen:expect([[ + 1 ^the first | + 2 the second | + 3 the third | + ?the | + ]]) + + command('$') + feed('?the') + wait() + feed('<c-g>') + wait() + feed('<c-g>') + wait() + feed('<c-g>') + wait() + feed('<cr>') + screen:expect([[ + 1 the first | + 2 ^the second | + 3 the third | + ?the | + ]]) + + command('$') + feed('?the') + wait() + feed('<c-t>') + wait() + feed('<cr>') + screen:expect([[ + 1 ^the first | + 2 the second | + 3 the third | + ?the | + ]]) + + command('$') + feed('?the') + wait() + feed('<c-t>') + wait() + feed('<c-t>') + wait() + feed('<cr>') + screen:expect([[ + 1 the first | + 2 the second | + 3 ^the third | + ?the | + ]]) + + command('$') + feed('?the') + wait() + feed('<c-t>') + wait() + feed('<c-t>') + wait() + feed('<c-t>') + wait() + feed('<cr>') + screen:expect([[ + 1 the first | + 2 ^the second | + 3 the third | + ?the | + ]]) + end) end) diff --git a/test/functional/plugin/man_spec.lua b/test/functional/plugin/man_spec.lua index dc189b8f8e..e5da7932a5 100644 --- a/test/functional/plugin/man_spec.lua +++ b/test/functional/plugin/man_spec.lua @@ -66,13 +66,13 @@ describe(':Man', function() ithis <C-v><ESC>[1mis <C-v><ESC>[3ma <C-v><ESC>[4mtest<C-v><ESC>[0m <C-v><ESC>[4mwith<C-v><ESC>[24m <C-v><ESC>[4mescaped<C-v><ESC>[24m <C-v><ESC>[4mtext<C-v><ESC>[24m<ESC>]]) - screen:expect([[ + screen:expect([=[ this ^[[1mis ^[[3ma ^[[4mtest^[[0m | ^[[4mwith^[[24m ^[[4mescaped^[[24m ^[[4mtext^[[24^m | ~ | ~ | | - ]]) + ]=]) eval('man#init_pager()') diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua index ee92ba6865..0a30b9bb02 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_spec.lua @@ -2,8 +2,11 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, wait, nvim = helpers.clear, helpers.wait, helpers.nvim local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq +local feed = helpers.feed local feed_command, eval = helpers.feed_command, helpers.eval +local funcs = helpers.funcs local retry = helpers.retry +local ok = helpers.ok local iswin = helpers.iswin describe(':terminal', function() @@ -24,13 +27,16 @@ describe(':terminal', function() ]]) -- Invoke a command that emits frequent terminal activity. if iswin() then - feed_command([[terminal for /L \\%I in (1,0,2) do echo \\%I]]) + feed_command([[terminal for /L \%I in (1,0,2) do echo \%I]]) else feed_command([[terminal while true; do echo X; done]]) end - helpers.feed([[<C-\><C-N>]]) + feed([[<C-\><C-N>]]) wait() - screen:sleep(10) -- Let some terminal activity happen. + -- Wait for some terminal activity. + retry(nil, 4000, function() + ok(funcs.line('$') > 6) + end) feed_command("messages") screen:expect([[ msg1 | @@ -46,7 +52,7 @@ describe(':terminal', function() else feed_command([[terminal while true; do echo foo; sleep .1; done]]) end - helpers.feed([[<C-\><C-N>M]]) -- move cursor away from last line + feed([[<C-\><C-N>M]]) -- move cursor away from last line wait() eq(3, eval("line('$')")) -- window height eq(2, eval("line('.')")) -- cursor is in the middle @@ -56,6 +62,32 @@ describe(':terminal', function() eq(2, eval("line('.')")) -- cursor stays where we put it end) + it('Enter/Leave does not increment jumplist #3723', function() + feed_command('terminal') + local function enter_and_leave() + local lines_before = funcs.line('$') + -- Create a new line (in the shell). For a normal buffer this + -- increments the jumplist; for a terminal-buffer it should not. #3723 + feed('i') + wait() + feed('<CR><CR><CR><CR>') + wait() + feed([[<C-\><C-N>]]) + wait() + -- Wait for >=1 lines to be created. + retry(nil, 4000, function() + ok(funcs.line('$') > lines_before) + end) + end + enter_and_leave() + enter_and_leave() + enter_and_leave() + ok(funcs.line('$') > 6) -- Verify assumption. + local jumps = funcs.split(funcs.execute('jumps'), '\n') + eq(' jump line col file/text', jumps[1]) + eq(3, #jumps) + end) + end) describe(':terminal (with fake shell)', function() @@ -151,12 +183,12 @@ describe(':terminal (with fake shell)', function() it('ignores writes if the backing stream closes', function() terminal_with_fake_shell() - helpers.feed('iiXXXXXXX') + feed('iiXXXXXXX') wait() -- Race: Though the shell exited (and streams were closed by SIGCHLD -- handler), :terminal cleanup is pending on the main-loop. -- This write should be ignored (not crash, #5445). - helpers.feed('iiYYYYYYY') + feed('iiYYYYYYY') eq(2, eval("1+1")) -- Still alive? end) @@ -175,7 +207,7 @@ describe(':terminal (with fake shell)', function() :terminal | ]]) eq('term://', string.match(eval('bufname("%")'), "^term://")) - helpers.feed([[<C-\><C-N>]]) + feed([[<C-\><C-N>]]) feed_command([[find */shadacat.py]]) if iswin() then eq('scripts\\shadacat.py', eval('bufname("%")')) @@ -192,9 +224,9 @@ describe(':terminal (with fake shell)', function() [Process exited 0] | :terminal echo "scripts/shadacat.py" | ]]) - helpers.feed([[<C-\><C-N>]]) + feed([[<C-\><C-N>]]) eq('term://', string.match(eval('bufname("%")'), "^term://")) - helpers.feed([[ggf"lgf]]) + feed([[ggf"lgf]]) eq('scripts/shadacat.py', eval('bufname("%")')) end) diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index a62c03b70f..171745eb57 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -242,7 +242,7 @@ describe('tui', function() {9:~ }| {9:~ }| {3:[No Name] [+] }| - | + :set termguicolors | {4:-- TERMINAL --} | ]]) @@ -253,7 +253,7 @@ describe('tui', function() {2:~ }| {2:~ }| {3:[No Name] [+] }| - | + :set notermguicolors | {4:-- TERMINAL --} | ]]) end) diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua index 091c45596d..5b38921e50 100644 --- a/test/functional/ui/bufhl_spec.lua +++ b/test/functional/ui/bufhl_spec.lua @@ -2,11 +2,11 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command, request, neq = helpers.command, helpers.request, helpers.neq +local command, neq = helpers.command, helpers.neq +local curbufmeths = helpers.curbufmeths describe('Buffer highlighting', function() local screen - local curbuf before_each(function() clear() @@ -25,21 +25,14 @@ describe('Buffer highlighting', function() [9] = {foreground = Screen.colors.SlateBlue, underline = true}, [10] = {foreground = Screen.colors.Red} }) - curbuf = request('nvim_get_current_buf') end) after_each(function() screen:detach() end) - local function add_hl(...) - return request('nvim_buf_add_highlight', curbuf, ...) - end - - local function clear_hl(...) - return request('nvim_buf_clear_highlight', curbuf, ...) - end - + local add_hl = curbufmeths.add_highlight + local clear_hl = curbufmeths.clear_highlight it('works', function() insert([[ diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 2252e3580f..95fb2ce21c 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -905,6 +905,7 @@ describe("'winhighlight' highlight", function() end) it('background applies also to non-text', function() + command('set sidescroll=0') insert('Lorem ipsum dolor sit amet ') command('set shiftwidth=2') feed('>>') diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index 13820af3b8..e5708d51ef 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen') local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths local insert, feed_command = helpers.insert, helpers.feed_command local eq, funcs = helpers.eq, helpers.funcs +local command = helpers.command describe('ui/mouse/input', function() local screen @@ -706,6 +707,7 @@ describe('ui/mouse/input', function() end) it('horizontal scrolling', function() + command('set sidescroll=0') feed("<esc>:set nowrap<cr>") feed("a <esc>20Ab<esc>") diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua index c6d564e8dc..4246020fab 100644 --- a/test/functional/ui/output_spec.lua +++ b/test/functional/ui/output_spec.lua @@ -1,14 +1,24 @@ -local session = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local helpers = require('test.functional.helpers')(after_each) local child_session = require('test.functional.terminal.helpers') - -if session.pending_win32(pending) then return end +local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir +local eq = helpers.eq +local eval = helpers.eval +local feed = helpers.feed +local feed_command = helpers.feed_command +local iswin = helpers.iswin +local clear = helpers.clear +local command = helpers.command +local nvim_dir = helpers.nvim_dir describe("shell command :!", function() + if helpers.pending_win32(pending) then return end + local screen before_each(function() - session.clear() - screen = child_session.screen_setup(0, '["'..session.nvim_prog.. - '", "-u", "NONE", "-i", "NONE", "--cmd", "'..session.nvim_set..'"]') + clear() + screen = child_session.screen_setup(0, '["'..helpers.nvim_prog.. + '", "-u", "NONE", "-i", "NONE", "--cmd", "'..helpers.nvim_set..'"]') screen:expect([[ {1: } | {4:~ }| @@ -33,15 +43,15 @@ describe("shell command :!", function() {4:~ }| {4:~ }| {4:~ }| + {4:~ }| :!printf foo; sleep 200 | - | foo | {3:-- TERMINAL --} | ]]) end) it("throttles shell-command output greater than ~10KB", function() - if os.getenv("TRAVIS") and session.os_name() == "osx" then + if os.getenv("TRAVIS") and helpers.os_name() == "osx" then pending("[Unreliable on Travis macOS.]", function() end) return end @@ -56,13 +66,164 @@ describe("shell command :!", function() -- Final chunk of output should always be displayed, never skipped. -- (Throttling is non-deterministic, this test is merely a sanity check.) screen:expect([[ - XXXXXXXXXX 2996 | XXXXXXXXXX 2997 | XXXXXXXXXX 2998 | XXXXXXXXXX 2999 | XXXXXXXXXX 3000 | + | {10:Press ENTER or type command to continue}{1: } | {3:-- TERMINAL --} | ]]) end) end) + +describe("shell command :!", function() + before_each(function() + clear() + end) + + it("cat a binary file #4142", function() + feed(":exe 'silent !cat '.shellescape(v:progpath)<CR>") + eq(2, eval('1+1')) -- Still alive? + end) + + it([[display \x08 char #4142]], function() + feed(":silent !echo \08<CR>") + eq(2, eval('1+1')) -- Still alive? + end) + + it([[handles control codes]], function() + if iswin() then + pending('missing printf', function() end) + return + end + local screen = Screen.new(50, 4) + screen:attach() + -- Print TAB chars. #2958 + feed([[:!printf '1\t2\t3'<CR>]]) + screen:expect([[ + ~ | + :!printf '1\t2\t3' | + 1 2 3 | + Press ENTER or type command to continue^ | + ]]) + feed([[<CR>]]) + -- Print BELL control code. #4338 + screen.bell = false + feed([[:!printf '\x07\x07\x07\x07text'<CR>]]) + screen:expect([[ + ~ | + :!printf '\x07\x07\x07\x07text' | + text | + Press ENTER or type command to continue^ | + ]], nil, nil, function() + eq(true, screen.bell) + end) + feed([[<CR>]]) + -- Print BS control code. + feed([[:echo system('printf ''\x08\n''')<CR>]]) + screen:expect([[ + ~ | + ^H | + | + Press ENTER or type command to continue^ | + ]]) + feed([[<CR>]]) + -- Print LF control code. + feed([[:!printf '\n'<CR>]]) + screen:expect([[ + :!printf '\n' | + | + | + Press ENTER or type command to continue^ | + ]]) + feed([[<CR>]]) + end) + + describe('', function() + local screen + before_each(function() + rmdir('bang_filter_spec') + mkdir('bang_filter_spec') + write_file('bang_filter_spec/f1', 'f1') + write_file('bang_filter_spec/f2', 'f2') + write_file('bang_filter_spec/f3', 'f3') + screen = Screen.new(53,10) + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Blue1}, + [2] = {foreground = Screen.colors.Blue1}, + [3] = {bold = true, foreground = Screen.colors.SeaGreen4}, + }) + screen:attach() + end) + + after_each(function() + rmdir('bang_filter_spec') + end) + + it("doesn't truncate Last line of shell output #3269", function() + command(helpers.iswin() + and [[nnoremap <silent>\l :!dir /b bang_filter_spec<cr>]] + or [[nnoremap <silent>\l :!ls bang_filter_spec<cr>]]) + local result = (helpers.iswin() + and [[:!dir /b bang_filter_spec]] + or [[:!ls bang_filter_spec ]]) + feed([[\l]]) + screen:expect([[ + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]..result..[[ | + f1 | + f2 | + f3 | + | + {3:Press ENTER or type command to continue}^ | + ]]) + end) + + it('handles binary and multibyte data', function() + feed_command('!cat test/functional/fixtures/shell_data.txt') + screen.bell = false + screen:expect([[ + {1:~ }| + {1:~ }| + {1:~ }| + :!cat test/functional/fixtures/shell_data.txt | + {2:^@^A^B^C^D^E^F^H} | + {2:^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_} | + ö 한글 {2:<a5><c3>} | + t {2:<ff>} | + | + {3:Press ENTER or type command to continue}^ | + ]], nil, nil, function() + eq(true, screen.bell) + end) + end) + + it('handles multibyte sequences split over buffer boundaries', function() + command('cd '..nvim_dir) + local cmd + if iswin() then + cmd = '!shell-test UTF-8 ' + else + cmd = '!./shell-test UTF-8' + end + feed_command(cmd) + -- Note: only the first example of split composed char works + screen:expect([[ + {1:~ }| + {1:~ }| + :]]..cmd..[[ | + å | + ref: å̲ | + 1: å̲ | + 2: å ̲ | + 3: å ̲ | + | + {3:Press ENTER or type command to continue}^ | + ]]) + end) + end) +end) diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 696feabeed..52e108f389 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -455,6 +455,9 @@ function Screen:_handle_visual_bell() self.visual_bell = true end +function Screen:_handle_default_colors_set() +end + function Screen:_handle_update_fg(fg) self._fg = fg end diff --git a/test/functional/ui/spell_spec.lua b/test/functional/ui/spell_spec.lua new file mode 100644 index 0000000000..913f1b9bed --- /dev/null +++ b/test/functional/ui/spell_spec.lua @@ -0,0 +1,49 @@ +-- Test for scenarios involving 'spell' + +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear = helpers.clear +local feed = helpers.feed +local feed_command = helpers.feed_command +local insert = helpers.insert + +describe("'spell'", function() + local screen + + before_each(function() + clear() + screen = Screen.new(80, 8) + screen:attach() + screen:set_default_attr_ids( { + [0] = {bold=true, foreground=Screen.colors.Blue}, + [1] = {special = Screen.colors.Red, undercurl = true} + }) + end) + + after_each(function() + screen:detach() + end) + + it('joins long lines #7937', function() + feed_command('set spell') + insert([[ + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat + non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + ]]) + feed('ggJJJJJJ0') + screen:expect([[ + {1:^Lorem} {1:ipsum} dolor sit {1:amet}, {1:consectetur} {1:adipiscing} {1:elit}, {1:sed} do {1:eiusmod} {1:tempor} {1:i}| + {1:ncididunt} {1:ut} {1:labore} {1:et} {1:dolore} {1:magna} {1:aliqua}. {1:Ut} {1:enim} ad minim {1:veniam}, {1:quis} {1:nostru}| + {1:d} {1:exercitation} {1:ullamco} {1:laboris} {1:nisi} {1:ut} {1:aliquip} ex ea {1:commodo} {1:consequat}. {1:Duis} {1:aut}| + {1:e} {1:irure} dolor in {1:reprehenderit} in {1:voluptate} {1:velit} {1:esse} {1:cillum} {1:dolore} {1:eu} {1:fugiat} {1:n}| + {1:ulla} {1:pariatur}. {1:Excepteur} {1:sint} {1:occaecat} {1:cupidatat} non {1:proident}, {1:sunt} in culpa {1:qui}| + {1:officia} {1:deserunt} {1:mollit} {1:anim} id est {1:laborum}. | + {0:~ }| + | + ]]) + end) +end) diff --git a/test/helpers.lua b/test/helpers.lua index faf5c8e7f2..1c64f41b65 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -423,11 +423,13 @@ format_luav = function(v, indent, opts) if opts.literal_strings then ret = v else - ret = tostring(v):gsub('[\'\\]', '\\%0'):gsub( - '[%z\1-\31]', function(match) - return SUBTBL[match:byte() + 1] - end) - ret = '\'' .. ret .. '\'' + local quote = opts.dquote_strings and '"' or '\'' + ret = quote .. tostring(v):gsub( + opts.dquote_strings and '["\\]' or '[\'\\]', + '\\%0'):gsub( + '[%z\1-\31]', function(match) + return SUBTBL[match:byte() + 1] + end) .. quote end elseif type(v) == 'table' then if v == REMOVE_THIS then @@ -490,11 +492,14 @@ local function format_string(fmt, ...) if subfmt:sub(-1) ~= '%' then arg = getarg() end - if subfmt:sub(-1) == 'r' then - -- %r is like %q, but it is supposed to single-quote strings and not - -- double-quote them, and also work not only for strings. + if subfmt:sub(-1) == 'r' or subfmt:sub(-1) == 'q' then + -- %r is like built-in %q, but it is supposed to single-quote strings and + -- not double-quote them, and also work not only for strings. + -- Builtin %q is replaced here as it gives invalid and inconsistent with + -- luajit results for e.g. "\e" on lua: luajit transforms that into `\27`, + -- lua leaves as-is. + arg = format_luav(arg, nil, {dquote_strings = (subfmt:sub(-1) == 'q')}) subfmt = subfmt:sub(1, -2) .. 's' - arg = format_luav(arg) end if subfmt == '%e' then return format_float(arg) diff --git a/test/unit/viml/expressions/parser_tests.lua b/test/unit/viml/expressions/parser_tests.lua index e085d7e932..da61672bb1 100644 --- a/test/unit/viml/expressions/parser_tests.lua +++ b/test/unit/viml/expressions/parser_tests.lua @@ -5025,7 +5025,7 @@ return function(itp, _check_parsing, hl, fmtn) -- 0123456789012345 -- 0 1 ast = { - [[DoubleQuotedString(val="\8\27\12\13\9\\"):0:0:"\b\e\f\r\t\\"]], + [[DoubleQuotedString(val="\008\027\012\r\t\\"):0:0:"\b\e\f\r\t\\"]], }, }, { hl('DoubleQuote', '"'), @@ -5040,7 +5040,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\n\n"', { -- 01234 ast = { - fmtn('DoubleQuotedString', 'val="\\\n\\\n"', ':0:0:"\\n\n"'), + fmtn('DoubleQuotedString', 'val="\\n\\n"', ':0:0:"\\n\n"'), }, }, { hl('DoubleQuote', '"'), @@ -5051,7 +5051,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\x00"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\0"', ':0:0:"\\x00"'), + fmtn('DoubleQuotedString', 'val="\\000"', ':0:0:"\\x00"'), }, }, { hl('DoubleQuote', '"'), @@ -5071,7 +5071,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\xF"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\15"', ':0:0:"\\xF"'), + fmtn('DoubleQuotedString', 'val="\\015"', ':0:0:"\\xF"'), }, }, { hl('DoubleQuote', '"'), @@ -5126,7 +5126,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\xF', { -- 0123 ast = { - fmtn('DoubleQuotedString', 'val="\\15"', ':0:0:"\\xF'), + fmtn('DoubleQuotedString', 'val="\\015"', ':0:0:"\\xF'), }, err = { arg = '"\\xF', @@ -5190,7 +5190,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\xFX"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\15X"', ':0:0:"\\xFX"'), + fmtn('DoubleQuotedString', 'val="\\015X"', ':0:0:"\\xFX"'), }, }, { hl('DoubleQuote', '"'), @@ -5202,7 +5202,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\XFX"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\15X"', ':0:0:"\\XFX"'), + fmtn('DoubleQuotedString', 'val="\\015X"', ':0:0:"\\XFX"'), }, }, { hl('DoubleQuote', '"'), @@ -5262,7 +5262,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\x0X"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\x0X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\x0X"'), }, }, { hl('DoubleQuote', '"'), @@ -5274,7 +5274,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\X0X"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\X0X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\X0X"'), }, }, { hl('DoubleQuote', '"'), @@ -5286,7 +5286,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\u0X"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\u0X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\u0X"'), }, }, { hl('DoubleQuote', '"'), @@ -5298,7 +5298,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\U0X"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\U0X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U0X"'), }, }, { hl('DoubleQuote', '"'), @@ -5310,7 +5310,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\x00X"', { -- 0123456 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\x00X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\x00X"'), }, }, { hl('DoubleQuote', '"'), @@ -5322,7 +5322,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\X00X"', { -- 0123456 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\X00X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\X00X"'), }, }, { hl('DoubleQuote', '"'), @@ -5334,7 +5334,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\u00X"', { -- 0123456 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\u00X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\u00X"'), }, }, { hl('DoubleQuote', '"'), @@ -5346,7 +5346,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\U00X"', { -- 0123456 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\U00X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U00X"'), }, }, { hl('DoubleQuote', '"'), @@ -5358,7 +5358,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\u000X"', { -- 01234567 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\u000X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\u000X"'), }, }, { hl('DoubleQuote', '"'), @@ -5370,7 +5370,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\U000X"', { -- 01234567 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\U000X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U000X"'), }, }, { hl('DoubleQuote', '"'), @@ -5382,7 +5382,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\u0000X"', { -- 012345678 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\u0000X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\u0000X"'), }, }, { hl('DoubleQuote', '"'), @@ -5394,7 +5394,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\U0000X"', { -- 012345678 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\U0000X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U0000X"'), }, }, { hl('DoubleQuote', '"'), @@ -5406,7 +5406,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\U00000X"', { -- 0123456789 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\U00000X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U00000X"'), }, }, { hl('DoubleQuote', '"'), @@ -5419,7 +5419,7 @@ return function(itp, _check_parsing, hl, fmtn) -- 01234567890 -- 0 1 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\U000000X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U000000X"'), }, }, { hl('DoubleQuote', '"'), @@ -5432,7 +5432,7 @@ return function(itp, _check_parsing, hl, fmtn) -- 012345678901 -- 0 1 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\U0000000X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U0000000X"'), }, }, { hl('DoubleQuote', '"'), @@ -5445,7 +5445,7 @@ return function(itp, _check_parsing, hl, fmtn) -- 0123456789012 -- 0 1 ast = { - fmtn('DoubleQuotedString', 'val="\\0X"', ':0:0:"\\U00000000X"'), + fmtn('DoubleQuotedString', 'val="\\000X"', ':0:0:"\\U00000000X"'), }, }, { hl('DoubleQuote', '"'), @@ -5506,7 +5506,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\0"', { -- 0123 ast = { - fmtn('DoubleQuotedString', 'val="\\0"', ':0:0:"\\0"'), + fmtn('DoubleQuotedString', 'val="\\000"', ':0:0:"\\0"'), }, }, { hl('DoubleQuote', '"'), @@ -5517,7 +5517,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\00"', { -- 01234 ast = { - fmtn('DoubleQuotedString', 'val="\\0"', ':0:0:"\\00"'), + fmtn('DoubleQuotedString', 'val="\\000"', ':0:0:"\\00"'), }, }, { hl('DoubleQuote', '"'), @@ -5528,7 +5528,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\000"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\0"', ':0:0:"\\000"'), + fmtn('DoubleQuotedString', 'val="\\000"', ':0:0:"\\000"'), }, }, { hl('DoubleQuote', '"'), @@ -5620,7 +5620,7 @@ return function(itp, _check_parsing, hl, fmtn) check_parsing('"\\<C-u>"', { -- 012345 ast = { - fmtn('DoubleQuotedString', 'val="\\21"', ':0:0:"\\<C-u>"'), + fmtn('DoubleQuotedString', 'val="\\021"', ':0:0:"\\<C-u>"'), }, }, { hl('DoubleQuote', '"'), @@ -7119,7 +7119,7 @@ return function(itp, _check_parsing, hl, fmtn) 'Or:0:0:|', children = { 'Missing:0:0:', - fmtn('DoubleQuotedString', 'val="\\27"', ':0:1:"\\e"'), + fmtn('DoubleQuotedString', 'val="\\027"', ':0:1:"\\e"'), }, }, }, @@ -7180,9 +7180,9 @@ return function(itp, _check_parsing, hl, fmtn) hl('InvalidDoubleQuotedUnknownEscape', '\\<'), }) check_parsing('"\\1', { - -- 012 + -- 01 2 ast = { - fmtn('DoubleQuotedString', 'val="\\1"', ':0:0:"\\1'), + fmtn('DoubleQuotedString', 'val="\\001"', ':0:0:"\\1'), }, err = { arg = '"\\1', |