aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rw-r--r--test/functional/eval/timer_spec.lua129
-rw-r--r--test/functional/legacy/031_close_commands_spec.lua24
-rw-r--r--test/functional/legacy/061_undo_tree_spec.lua13
-rw-r--r--test/functional/legacy/068_text_formatting_spec.lua207
-rw-r--r--test/functional/legacy/108_backtrace_debug_commands_spec.lua177
-rw-r--r--test/functional/legacy/assert_spec.lua18
-rw-r--r--test/functional/legacy/breakindent_spec.lua211
-rw-r--r--test/functional/legacy/close_count_spec.lua133
-rw-r--r--test/functional/legacy/file_perm_spec.lua42
-rw-r--r--test/functional/legacy/increment_spec.lua25
-rw-r--r--test/functional/legacy/join_spec.lua20
-rw-r--r--test/functional/legacy/listlbr_spec.lua195
-rw-r--r--test/functional/legacy/quickfix_spec.lua296
-rw-r--r--test/functional/legacy/set_spec.lua15
-rw-r--r--test/functional/provider/python_spec.lua82
-rw-r--r--test/functional/terminal/buffer_spec.lua13
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua23
-rw-r--r--test/functional/terminal/highlight_spec.lua6
-rw-r--r--test/functional/terminal/tui_spec.lua4
-rw-r--r--test/functional/ui/highlight_spec.lua351
-rw-r--r--test/functional/ui/mouse_spec.lua17
-rw-r--r--test/functional/ui/screen.lua15
22 files changed, 1952 insertions, 64 deletions
diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua
new file mode 100644
index 0000000000..611113f560
--- /dev/null
+++ b/test/functional/eval/timer_spec.lua
@@ -0,0 +1,129 @@
+local helpers = require('test.functional.helpers')
+local Screen = require('test.functional.ui.screen')
+local ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval
+local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run
+local clear, execute, funcs = helpers.clear, helpers.execute, helpers.funcs
+
+describe('timers', function()
+ before_each(function()
+ clear()
+ source([[
+ let g:val = 0
+ func MyHandler(timer)
+ let g:val += 1
+ endfunc
+ ]])
+ end)
+
+ it('works one-shot', function()
+ execute("call timer_start(50, 'MyHandler')")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 200)
+ eq(1,eval("g:val"))
+ end)
+
+ it('works with repeat two', function()
+ execute("call timer_start(50, 'MyHandler', {'repeat': 2})")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ eq(2,eval("g:val"))
+ end)
+
+ it('are triggered during sleep', function()
+ execute("call timer_start(50, 'MyHandler', {'repeat': 2})")
+ nvim_async("command", "sleep 10")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ eq(2,eval("g:val"))
+ end)
+
+ it('can be started during sleep', function()
+ nvim_async("command", "sleep 10")
+ -- this also tests that remote requests works during sleep
+ eval("timer_start(50, 'MyHandler', {'repeat': 2})")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ eq(2,eval("g:val"))
+ end)
+
+ it('are paused when event processing is disabled', function()
+ -- this is not the intended behavior, but at least there will
+ -- not be a burst of queued up callbacks
+ execute("call timer_start(50, 'MyHandler', {'repeat': 2})")
+ run(nil, nil, nil, 100)
+ local count = eval("g:val")
+ nvim_async("command", "let g:c = getchar()")
+ run(nil, nil, nil, 300)
+ feed("c")
+ local diff = eval("g:val") - count
+ ok(0 <= diff and diff <= 2)
+ eq(99, eval("g:c"))
+ end)
+
+ it('can be stopped', function()
+ local t = eval("timer_start(50, 'MyHandler', {'repeat': -1})")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ funcs.timer_stop(t)
+ local count = eval("g:val")
+ run(nil, nil, nil, 300)
+ local count2 = eval("g:val")
+ ok(4 <= count and count <= 7)
+ -- when count is eval:ed after timer_stop this should be non-racy
+ eq(count, count2)
+ end)
+
+ it('can be stopped from the handler', function()
+ source([[
+ func! MyHandler(timer)
+ let g:val += 1
+ if g:val == 3
+ call timer_stop(a:timer)
+ " check double stop is ignored
+ call timer_stop(a:timer)
+ endif
+ endfunc
+ ]])
+ execute("call timer_start(50, 'MyHandler', {'repeat': -1})")
+ eq(0,eval("g:val"))
+ run(nil, nil, nil, 300)
+ eq(3,eval("g:val"))
+ end)
+
+ it('can have two timers', function()
+ source([[
+ let g:val2 = 0
+ func! MyHandler2(timer)
+ let g:val2 += 1
+ endfunc
+ ]])
+ execute("call timer_start(50, 'MyHandler', {'repeat': 3})")
+ execute("call timer_start(100, 'MyHandler2', {'repeat': 2})")
+ run(nil, nil, nil, 300)
+ eq(3,eval("g:val"))
+ eq(2,eval("g:val2"))
+ end)
+
+ it("doesn't mess up the cmdline", function()
+ local screen = Screen.new(40, 6)
+ screen:attach()
+ screen:set_default_attr_ignore({{bold=true, foreground=Screen.colors.Blue}})
+ source([[
+ func! MyHandler(timer)
+ echo "evil"
+ endfunc
+ ]])
+ execute("call timer_start(100, 'MyHandler', {'repeat': 1})")
+ feed(":good")
+ screen:sleep(200)
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ :good^ |
+ ]])
+ end)
+
+end)
diff --git a/test/functional/legacy/031_close_commands_spec.lua b/test/functional/legacy/031_close_commands_spec.lua
index 3597cba12a..b79b1903ba 100644
--- a/test/functional/legacy/031_close_commands_spec.lua
+++ b/test/functional/legacy/031_close_commands_spec.lua
@@ -10,7 +10,7 @@
-- :edit
local helpers = require('test.functional.helpers')
-local feed, insert = helpers.feed, helpers.insert
+local feed, insert, source = helpers.feed, helpers.insert, helpers.source
local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
describe('Commands that close windows and/or buffers', function()
@@ -84,6 +84,28 @@ describe('Commands that close windows and/or buffers', function()
feed('GA 4<Esc>:all!<CR>')
execute('1wincmd w')
expect('testtext 2 2 2')
+
+ -- Test ":q!" and hidden buffer.
+ execute('bw! Xtest1 Xtest2 Xtest3 Xtest4')
+ execute('sp Xtest1')
+ execute('wincmd w')
+ execute('bw!')
+ execute('set modified')
+ execute('bot sp Xtest2')
+ execute('set modified')
+ execute('bot sp Xtest3')
+ execute('set modified')
+ execute('wincmd t')
+ execute('hide')
+ execute('q!')
+ expect('testtext 3')
+ execute('q!')
+ feed('<CR>')
+ expect('testtext 1')
+ source([[
+ q!
+ " Now nvim should have exited
+ throw "Oh, Not finished yet."]])
end)
teardown(function()
diff --git a/test/functional/legacy/061_undo_tree_spec.lua b/test/functional/legacy/061_undo_tree_spec.lua
index 6db37bf1ff..350a77b2c5 100644
--- a/test/functional/legacy/061_undo_tree_spec.lua
+++ b/test/functional/legacy/061_undo_tree_spec.lua
@@ -1,10 +1,9 @@
-- Tests for undo tree and :earlier and :later.
local helpers = require('test.functional.helpers')
-local feed, source, eq, eval, clear, execute, expect, wait, write_file =
- helpers.feed, helpers.source, helpers.eq, helpers.eval,
- helpers.clear, helpers.execute, helpers.expect, helpers.wait,
- helpers.write_file
+local expect, feed, source = helpers.expect, helpers.feed, helpers.source
+local eval, clear, execute = helpers.eval, helpers.clear, helpers.execute
+local write_file, command, eq = helpers.write_file, helpers.command, helpers.eq
local function expect_empty_buffer()
-- The space will be removed by helpers.dedent but is needed because dedent
@@ -57,8 +56,7 @@ describe('undo tree:', function()
-- Delete three other characters and go back in time step by step.
feed('$xxx')
expect_line('123456')
- execute('sleep 1')
- wait()
+ command('sleep 1')
feed('g-')
expect_line('1234567')
feed('g-')
@@ -79,8 +77,7 @@ describe('undo tree:', function()
expect_line('123456')
-- Delay for two seconds and go some seconds forward and backward.
- execute('sleep 2')
- wait()
+ command('sleep 2')
feed('Aa<esc>')
feed('Ab<esc>')
feed('Ac<esc>')
diff --git a/test/functional/legacy/068_text_formatting_spec.lua b/test/functional/legacy/068_text_formatting_spec.lua
new file mode 100644
index 0000000000..cac8be77f3
--- /dev/null
+++ b/test/functional/legacy/068_text_formatting_spec.lua
@@ -0,0 +1,207 @@
+local helpers = require('test.functional.helpers')
+local feed, insert = helpers.feed, helpers.insert
+local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
+
+describe('text formatting', function()
+ setup(clear)
+
+ it('is working', function()
+ -- The control character <C-A> (byte \x01) needs to be put in the buffer
+ -- directly. But the insert function sends the text to nvim in insert
+ -- mode so it has to be escaped with <C-V>.
+ insert([[
+ Results of test68:
+
+
+ {
+
+
+ }
+
+
+ {
+ a b
+
+ a
+ }
+
+
+ {
+ a 
+ }
+
+
+ {
+ a b
+ #a b
+ }
+
+
+ {
+ 1 a
+ # 1 a
+ }
+
+
+ {
+
+ x a
+ b
+ c
+
+ }
+
+
+ {
+ # 1 a b
+ }
+
+
+ {
+ # x
+ # a b
+ }
+
+
+ {
+ 1aa
+ 2bb
+ }
+
+
+ /* abc def ghi jkl
+ * mno pqr stu
+ */
+
+
+ # 1 xxxxx
+ ]])
+
+ execute('/^{/+1')
+ execute('set noai tw=2 fo=t')
+ feed('gRa b<esc>')
+
+ execute('/^{/+1')
+ execute('set ai tw=2 fo=tw')
+ feed('gqgqjjllab<esc>')
+
+ execute('/^{/+1')
+ execute('set tw=3 fo=t')
+ feed('gqgqo<cr>')
+ feed('a <C-V><C-A><esc><esc>')
+
+ execute('/^{/+1')
+ execute('set tw=2 fo=tcq1 comments=:#')
+ feed('gqgqjgqgqo<cr>')
+ feed('a b<cr>')
+ feed('#a b<esc>')
+
+ execute('/^{/+1')
+ execute('set tw=5 fo=tcn comments=:#')
+ feed('A b<esc>jA b<esc>')
+
+ execute('/^{/+3')
+ execute('set tw=5 fo=t2a si')
+ feed('i <esc>A_<esc>')
+
+ execute('/^{/+1')
+ execute('set tw=5 fo=qn comments=:#')
+ feed('gwap<cr>')
+
+ execute('/^{/+1')
+ execute('set tw=5 fo=q2 comments=:#')
+ feed('gwap<cr>')
+
+ execute('/^{/+2')
+ execute('set tw& fo=a')
+ feed('I^^<esc><esc>')
+
+ execute('/mno pqr/')
+ execute('setl tw=20 fo=an12wcq comments=s1:/*,mb:*,ex:*/')
+ feed('A vwx yz<esc>')
+
+ execute('/^#/')
+ execute('setl tw=12 fo=tqnc comments=:#')
+ feed('A foobar<esc>')
+
+ -- Assert buffer contents.
+ expect([[
+ Results of test68:
+
+
+ {
+ a
+ b
+ }
+
+
+ {
+ a
+ b
+
+ a
+ b
+ }
+
+
+ {
+ a
+ 
+
+ a
+ 
+ }
+
+
+ {
+ a b
+ #a b
+
+ a b
+ #a b
+ }
+
+
+ {
+ 1 a
+ b
+ # 1 a
+ # b
+ }
+
+
+ {
+
+ x a
+ b_
+ c
+
+ }
+
+
+ {
+ # 1 a
+ # b
+ }
+
+
+ {
+ # x a
+ # b
+ }
+
+
+ { 1aa ^^2bb }
+
+
+ /* abc def ghi jkl
+ * mno pqr stu
+ * vwx yz
+ */
+
+
+ # 1 xxxxx
+ # foobar
+ ]])
+ end)
+end)
diff --git a/test/functional/legacy/108_backtrace_debug_commands_spec.lua b/test/functional/legacy/108_backtrace_debug_commands_spec.lua
new file mode 100644
index 0000000000..6df645d255
--- /dev/null
+++ b/test/functional/legacy/108_backtrace_debug_commands_spec.lua
@@ -0,0 +1,177 @@
+-- Tests for backtrace debug commands.
+
+local helpers = require('test.functional.helpers')
+local feed, clear = helpers.feed, helpers.clear
+local execute, expect = helpers.execute, helpers.expect
+
+describe('108', function()
+ before_each(clear)
+
+ it('is working', function()
+ execute('lang mess C')
+ execute('function! Foo()')
+ execute(' let var1 = 1')
+ execute(' let var2 = Bar(var1) + 9')
+ execute(' return var2')
+ execute('endfunction')
+ execute('function! Bar(var)')
+ execute(' let var1 = 2 + a:var')
+ execute(' let var2 = Bazz(var1) + 4')
+ execute(' return var2')
+ execute('endfunction')
+ execute('function! Bazz(var)')
+ execute(' let var1 = 3 + a:var')
+ execute(' let var3 = "another var"')
+ execute(' return var1')
+ execute('endfunction')
+ execute('new')
+ execute('debuggreedy')
+ execute('redir => out')
+ execute('debug echo Foo()')
+ feed('step<cr>')
+ feed('step<cr>')
+ feed('step<cr>')
+ feed('step<cr>')
+ feed('step<cr>')
+ feed('step<cr>')
+ feed([[echo "- show backtrace:\n"<cr>]])
+ feed('backtrace<cr>')
+ feed([[echo "\nshow variables on different levels:\n"<cr>]])
+ feed('echo var1<cr>')
+ feed('up<cr>')
+ feed('back<cr>')
+ feed('echo var1<cr>')
+ feed('u<cr>')
+ feed('bt<cr>')
+ feed('echo var1<cr>')
+ feed([[echo "\n- undefined vars:\n"<cr>]])
+ feed('step<cr>')
+ feed('frame 2<cr>')
+ feed('echo "undefined var3 on former level:"<cr>')
+ feed('echo var3<cr>')
+ feed('fr 0<cr>')
+ feed([[echo "here var3 is defined with \"another var\":"<cr>]])
+ feed('echo var3<cr>')
+ feed('step<cr>')
+ feed('step<cr>')
+ feed('step<cr>')
+ feed('up<cr>')
+ feed([[echo "\nundefined var2 on former level"<cr>]])
+ feed('echo var2<cr>')
+ feed('down<cr>')
+ feed('echo "here var2 is defined with 10:"<cr>')
+ feed('echo var2<cr>')
+ feed([[echo "\n- backtrace movements:\n"<cr>]])
+ feed('b<cr>')
+ feed([[echo "\nnext command cannot go down, we are on bottom\n"<cr>]])
+ feed('down<cr>')
+ feed('up<cr>')
+ feed([[echo "\nnext command cannot go up, we are on top\n"<cr>]])
+ feed('up<cr>')
+ feed('b<cr>')
+ feed('echo "fil is not frame or finish, it is file"<cr>')
+ feed('fil<cr>')
+ feed([[echo "\n- relative backtrace movement\n"<cr>]])
+ feed('fr -1<cr>')
+ feed('frame<cr>')
+ feed('fra +1<cr>')
+ feed('fram<cr>')
+ feed([[echo "\n- go beyond limits does not crash\n"<cr>]])
+ feed('fr 100<cr>')
+ feed('fra<cr>')
+ feed('frame -40<cr>')
+ feed('fram<cr>')
+ feed([[echo "\n- final result 19:"<cr>]])
+ feed('cont<cr>')
+ execute('0debuggreedy')
+ execute('redir END')
+ execute('$put =out')
+
+ -- Assert buffer contents.
+ expect([=[
+
+
+
+ - show backtrace:
+
+ 2 function Foo[2]
+ 1 Bar[2]
+ ->0 Bazz
+ line 2: let var3 = "another var"
+
+ show variables on different levels:
+
+ 6
+ 2 function Foo[2]
+ ->1 Bar[2]
+ 0 Bazz
+ line 2: let var3 = "another var"
+ 3
+ ->2 function Foo[2]
+ 1 Bar[2]
+ 0 Bazz
+ line 2: let var3 = "another var"
+ 1
+
+ - undefined vars:
+
+ undefined var3 on former level:
+ Error detected while processing function Foo[2]..Bar[2]..Bazz:
+ line 3:
+ E121: Undefined variable: var3
+ E15: Invalid expression: var3
+ here var3 is defined with "another var":
+ another var
+
+ undefined var2 on former level
+ Error detected while processing function Foo[2]..Bar:
+ line 3:
+ E121: Undefined variable: var2
+ E15: Invalid expression: var2
+ here var2 is defined with 10:
+ 10
+
+ - backtrace movements:
+
+ 1 function Foo[2]
+ ->0 Bar
+ line 3: End of function
+
+ next command cannot go down, we are on bottom
+
+ frame is zero
+
+ next command cannot go up, we are on top
+
+ frame at highest level: 1
+ ->1 function Foo[2]
+ 0 Bar
+ line 3: End of function
+ fil is not frame or finish, it is file
+ "[No Name]" --No lines in buffer--
+
+ - relative backtrace movement
+
+ 1 function Foo[2]
+ ->0 Bar
+ line 3: End of function
+ ->1 function Foo[2]
+ 0 Bar
+ line 3: End of function
+
+ - go beyond limits does not crash
+
+ frame at highest level: 1
+ ->1 function Foo[2]
+ 0 Bar
+ line 3: End of function
+ frame is zero
+ 1 function Foo[2]
+ ->0 Bar
+ line 3: End of function
+
+ - final result 19:
+ 19
+ ]=])
+ end)
+end)
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index 1ce665360d..63699387c1 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -142,4 +142,22 @@ describe('assert function:', function()
})
end)
end)
+
+ -- assert_fails({cmd}, [, {error}])
+ describe('assert_fails', function()
+ it('should change v:errors when error does not match v:errmsg', function()
+ execute([[call assert_fails('xxx', {})]])
+ expected_errors({"Expected {} but got 'E731: using Dictionary as a String'"})
+ end)
+
+ it('should not change v:errors when cmd errors', function()
+ call('assert_fails', 'NonexistentCmd')
+ expected_empty()
+ end)
+
+ it('should change v:errors when cmd succeeds', function()
+ call('assert_fails', 'call empty("")')
+ expected_errors({'command did not fail: call empty("")'})
+ end)
+ end)
end)
diff --git a/test/functional/legacy/breakindent_spec.lua b/test/functional/legacy/breakindent_spec.lua
new file mode 100644
index 0000000000..a12d4add10
--- /dev/null
+++ b/test/functional/legacy/breakindent_spec.lua
@@ -0,0 +1,211 @@
+-- Test for breakindent
+
+local helpers = require('test.functional.helpers')
+local feed, insert = helpers.feed, helpers.insert
+local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
+
+describe('breakindent', function()
+ setup(clear)
+
+ it('is working', function()
+ insert('dummy text')
+
+ execute('set wildchar=^E')
+ execute('10new')
+ execute('vsp')
+ execute('vert resize 20')
+ execute([[put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\"]])
+ execute('set ts=4 sw=4 sts=4 breakindent')
+ execute('fu! ScreenChar(line, width)')
+ execute(' let c=""')
+ execute(' for i in range(1,a:width)')
+ execute(' let c.=nr2char(screenchar(a:line, i))')
+ execute(' endfor')
+ execute([[ let c.="\n"]])
+ execute(' for i in range(1,a:width)')
+ execute(' let c.=nr2char(screenchar(a:line+1, i))')
+ execute(' endfor')
+ execute([[ let c.="\n"]])
+ execute(' for i in range(1,a:width)')
+ execute(' let c.=nr2char(screenchar(a:line+2, i))')
+ execute(' endfor')
+ execute(' return c')
+ execute('endfu')
+ execute('fu DoRecordScreen()')
+ execute(' wincmd l')
+ execute([[ $put =printf(\"\n%s\", g:test)]])
+ execute(' $put =g:line1')
+ execute(' wincmd p')
+ execute('endfu')
+ execute('set briopt=min:0')
+ execute('let g:test="Test 1: Simple breakindent"')
+ execute('let line1=ScreenChar(line("."),8)')
+ execute('call DoRecordScreen()')
+ execute('let g:test="Test 2: Simple breakindent + sbr=>>"')
+ execute('set sbr=>>')
+ execute('let line1=ScreenChar(line("."),8)')
+ execute('call DoRecordScreen()')
+ execute('let g:test ="Test 3: Simple breakindent + briopt:sbr"')
+ execute('set briopt=sbr,min:0 sbr=++')
+ execute('let line1=ScreenChar(line("."),8)')
+ execute('call DoRecordScreen()')
+ execute('let g:test ="Test 4: Simple breakindent + min width: 18"')
+ execute('set sbr= briopt=min:18')
+ execute('let line1=ScreenChar(line("."),8)')
+ execute('call DoRecordScreen()')
+ execute('let g:test =" Test 5: Simple breakindent + shift by 2"')
+ execute('set briopt=shift:2,min:0')
+ execute('let line1=ScreenChar(line("."),8)')
+ execute('call DoRecordScreen()')
+ execute('let g:test=" Test 6: Simple breakindent + shift by -1"')
+ execute('set briopt=shift:-1,min:0')
+ execute('let line1=ScreenChar(line("."),8)')
+ execute('call DoRecordScreen()')
+ execute('let g:test=" Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr"')
+ execute('set briopt=shift:1,sbr,min:0 nu sbr=? nuw=4')
+ execute('let line1=ScreenChar(line("."),10)')
+ execute('call DoRecordScreen()')
+ execute('let g:test=" Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr"')
+ execute('set briopt=shift:1,sbr,min:0 nu sbr=# list lcs&vi')
+ execute('let line1=ScreenChar(line("."),10)')
+ execute('call DoRecordScreen()')
+ execute([[let g:test=" Test 9: breakindent + shift by +1 + 'nu' + sbr=# list"]])
+ execute('set briopt-=sbr')
+ execute('let line1=ScreenChar(line("."),10)')
+ execute('call DoRecordScreen()')
+ execute([[let g:test=" Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n"]])
+ execute('set cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0')
+ execute('let line1=ScreenChar(line("."),10)')
+ execute('call DoRecordScreen()')
+ execute('wincmd p')
+ execute([[let g:test="\n Test 11: strdisplaywidth when breakindent is on"]])
+ execute('set cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4')
+ -- Skip leading tab when calculating text width.
+ execute('let text=getline(2)')
+ -- Text wraps 3 times.
+ execute('let width = strlen(text[1:])+indent(2)*4+strlen(&sbr)*3')
+ execute('$put =g:test')
+ execute([[$put =printf(\"strdisplaywidth: %d == calculated: %d\", strdisplaywidth(text), width)]])
+ execute([[let g:str="\t\t\t\t\t{"]])
+ execute('let g:test=" Test 12: breakindent + long indent"')
+ execute('wincmd p')
+ execute('set all& breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4')
+ execute('$put =g:str')
+ feed('zt')
+ execute('let line1=ScreenChar(1,10)')
+ execute('wincmd p')
+ execute('call DoRecordScreen()')
+
+ -- Test, that the string " a\tb\tc\td\te" is correctly displayed in a
+ -- 20 column wide window (see bug report
+ -- https://groups.google.com/d/msg/vim_dev/ZOdg2mc9c9Y/TT8EhFjEy0IJ ).
+ execute('only')
+ execute('vert 20new')
+ execute('set all& breakindent briopt=min:10')
+ execute([[call setline(1, [" a\tb\tc\td\te", " z y x w v"])]])
+ execute([[/^\s*a]])
+ feed('fbgjyl')
+ execute('let line1 = @0')
+ execute([[?^\s*z]])
+ feed('fygjyl')
+ execute('let line2 = @0')
+ execute('quit!')
+ execute([[$put ='Test 13: breakindent with wrapping Tab']])
+ execute('$put =line1')
+ execute('$put =line2')
+
+ execute('let g:test="Test 14: breakindent + visual blockwise delete #1"')
+ execute('set all& breakindent shada+=nX-test-breakindent.shada')
+ execute('30vnew')
+ execute('normal! 3a1234567890')
+ execute('normal! a abcde')
+ execute([[exec "normal! 0\<C-V>tex"]])
+ execute('let line1=ScreenChar(line("."),8)')
+ execute('call DoRecordScreen()')
+
+ execute('let g:test="Test 15: breakindent + visual blockwise delete #2"')
+ execute('%d')
+ execute('normal! 4a1234567890')
+ execute([[exec "normal! >>\<C-V>3f0x"]])
+ execute('let line1=ScreenChar(line("."),20)')
+ execute('call DoRecordScreen()')
+ execute('quit!')
+
+ -- Assert buffer contents.
+ expect([[
+
+ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP
+
+ Test 1: Simple breakindent
+ abcd
+ qrst
+ GHIJ
+
+ Test 2: Simple breakindent + sbr=>>
+ abcd
+ >>qr
+ >>EF
+
+ Test 3: Simple breakindent + briopt:sbr
+ abcd
+ ++ qrst
+ ++ GHIJ
+
+ Test 4: Simple breakindent + min width: 18
+ abcd
+ qrstuv
+ IJKLMN
+
+ Test 5: Simple breakindent + shift by 2
+ abcd
+ qr
+ EF
+
+ Test 6: Simple breakindent + shift by -1
+ abcd
+ qrstu
+ HIJKL
+
+ Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr
+ 2 ab
+ ? m
+ ? x
+
+ Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr
+ 2 ^Iabcd
+ # opq
+ # BCD
+
+ Test 9: breakindent + shift by +1 + 'nu' + sbr=# list
+ 2 ^Iabcd
+ #op
+ #AB
+
+ Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n
+ 2 ab
+ ~ mn
+ ~ yz
+
+ Test 11: strdisplaywidth when breakindent is on
+ strdisplaywidth: 46 == calculated: 64
+ {
+
+ Test 12: breakindent + long indent
+ 56
+
+ ~
+ Test 13: breakindent with wrapping Tab
+ d
+ w
+
+ Test 14: breakindent + visual blockwise delete #1
+ e
+ ~
+ ~
+
+ Test 15: breakindent + visual blockwise delete #2
+ 1234567890
+ ~
+ ~ ]])
+ end)
+end)
diff --git a/test/functional/legacy/close_count_spec.lua b/test/functional/legacy/close_count_spec.lua
new file mode 100644
index 0000000000..ee6b29c618
--- /dev/null
+++ b/test/functional/legacy/close_count_spec.lua
@@ -0,0 +1,133 @@
+-- Tests for :[count]close! and :[count]hide
+
+local helpers = require('test.functional.helpers')
+local feed, eval, eq, clear, execute =
+ helpers.feed, helpers.eval, helpers.eq, helpers.clear, helpers.execute
+
+describe('close_count', function()
+ setup(clear)
+
+ it('is working', function()
+ execute('let tests = []')
+ execute('for i in range(5)')
+ execute('new')
+ execute('endfor')
+ execute('4wincmd w')
+ execute('close!')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({6, 5, 4, 2, 1}, eval('buffers'))
+ execute('1close!')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({5, 4, 2, 1}, eval('buffers'))
+ execute('$close!')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({5, 4, 2}, eval('buffers'))
+ execute('1wincmd w')
+ execute('2close!')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({5, 2}, eval('buffers'))
+ execute('1wincmd w')
+ execute('new')
+ execute('new')
+ execute('2wincmd w')
+ execute('-1close!')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({7, 5, 2}, eval('buffers'))
+ execute('2wincmd w')
+ execute('+1close!')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({7, 5}, eval('buffers'))
+ execute('only!')
+ execute('b1')
+ execute('let tests = []')
+ execute('for i in range(5)')
+ execute('new')
+ execute('endfor')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({13, 12, 11, 10, 9, 1}, eval('buffers'))
+ execute('4wincmd w')
+ execute('.hide')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({13, 12, 11, 9, 1}, eval('buffers'))
+ execute('1hide')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({12, 11, 9, 1}, eval('buffers'))
+ execute('$hide')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({12, 11, 9}, eval('buffers'))
+ execute('1wincmd w')
+ execute('2hide')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({12, 9}, eval('buffers'))
+ execute('1wincmd w')
+ execute('new')
+ execute('new')
+ execute('3wincmd w')
+ execute('-hide')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({15, 12, 9}, eval('buffers'))
+ execute('2wincmd w')
+ execute('+hide')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({15, 12}, eval('buffers'))
+ execute('only!')
+ execute('b1')
+ execute('let tests = []')
+ execute('set hidden')
+ execute('for i in range(5)')
+ execute('new')
+ execute('endfor')
+ execute('1wincmd w')
+ execute('$ hide')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({20, 19, 18, 17, 16}, eval('buffers'))
+ execute('$-1 close!')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({20, 19, 18, 16}, eval('buffers'))
+ execute('1wincmd w')
+ execute('.+close!')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({20, 18, 16}, eval('buffers'))
+ execute('only!')
+ execute('b1')
+ execute('let tests = []')
+ execute('set hidden')
+ execute('for i in range(5)')
+ execute('new')
+ execute('endfor')
+ execute('4wincmd w')
+ feed('<C-W>c<cr>')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({25, 24, 23, 21, 1}, eval('buffers'))
+ feed('1<C-W>c<cr>')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({24, 23, 21, 1}, eval('buffers'))
+ feed('9<C-W>c<cr>')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({24, 23, 21}, eval('buffers'))
+ execute('1wincmd w')
+ feed('2<C-W>c<cr>')
+ execute('let buffers = []')
+ execute('windo call add(buffers, bufnr("%"))')
+ eq({24, 21}, eval('buffers'))
+ end)
+end)
diff --git a/test/functional/legacy/file_perm_spec.lua b/test/functional/legacy/file_perm_spec.lua
new file mode 100644
index 0000000000..cabeecdc9c
--- /dev/null
+++ b/test/functional/legacy/file_perm_spec.lua
@@ -0,0 +1,42 @@
+-- Test getting and setting file permissions.
+require('os')
+
+local helpers = require('test.functional.helpers')
+local clear, call, eq = helpers.clear, helpers.call, helpers.eq
+local neq, exc_exec = helpers.neq, helpers.exc_exec
+
+describe('Test getting and setting file permissions', function()
+ local tempfile = os.tmpname()
+
+ before_each(function()
+ os.remove(tempfile)
+ clear()
+ end)
+
+ it('file permissions', function()
+ eq('', call('getfperm', tempfile))
+ eq(0, call('setfperm', tempfile, 'r------'))
+
+ call('writefile', {'one'}, tempfile)
+ eq(9, call('len', call('getfperm', tempfile)))
+
+ eq(1, call('setfperm', tempfile, 'rwx------'))
+ if helpers.os_name == 'windows' then
+ eq('rw-rw-rw-', call('getfperm', tempfile))
+ else
+ eq('rwx------', call('getfperm', tempfile))
+ end
+
+ eq(1, call('setfperm', tempfile, 'r--r--r--'))
+ eq('r--r--r--', call('getfperm', tempfile))
+
+ local err = exc_exec(('call setfperm("%s", "---")'):format(tempfile))
+ neq(err:find('E475:'), nil)
+
+ eq(1, call('setfperm', tempfile, 'rwx------'))
+ end)
+
+ after_each(function()
+ os.remove(tempfile)
+ end)
+end)
diff --git a/test/functional/legacy/increment_spec.lua b/test/functional/legacy/increment_spec.lua
index 6139ec0b67..4aa24c0d53 100644
--- a/test/functional/legacy/increment_spec.lua
+++ b/test/functional/legacy/increment_spec.lua
@@ -708,6 +708,25 @@ describe('Ctrl-A/Ctrl-X on visual selections', function()
call assert_equal(["20"], getline(1, '$'))
call assert_equal([0, 1, 2, 0], getpos('.'))
endfunc
+
+ " Test what patch 7.3.414 fixed. Ctrl-A on "000" drops the leading zeros.
+ func Test_normal_increment_01()
+ call setline(1, "000")
+ exec "norm! gg0\<C-A>"
+ call assert_equal("001", getline(1))
+
+ call setline(1, "000")
+ exec "norm! gg$\<C-A>"
+ call assert_equal("001", getline(1))
+
+ call setline(1, "001")
+ exec "norm! gg0\<C-A>"
+ call assert_equal("002", getline(1))
+
+ call setline(1, "001")
+ exec "norm! gg$\<C-A>"
+ call assert_equal("002", getline(1))
+ endfunc
]=])
end)
@@ -720,4 +739,10 @@ describe('Ctrl-A/Ctrl-X on visual selections', function()
eq({}, nvim.get_vvar('errors'))
end)
end
+
+ it('does not drop leading zeroes', function()
+ execute('set nrformats&vi') -- &vi makes Vim compatible
+ call('Test_normal_increment_01')
+ eq({}, nvim.get_vvar('errors'))
+ end)
end)
diff --git a/test/functional/legacy/join_spec.lua b/test/functional/legacy/join_spec.lua
new file mode 100644
index 0000000000..17ff2e71ad
--- /dev/null
+++ b/test/functional/legacy/join_spec.lua
@@ -0,0 +1,20 @@
+-- Test for joining lines
+
+local helpers = require('test.functional.helpers')
+local clear, eq = helpers.clear, helpers.eq
+local eval, execute = helpers.eval, helpers.execute
+
+describe('joining lines', function()
+ before_each(clear)
+
+ it('is working', function()
+ execute('new')
+ execute([[call setline(1, ['one', 'two', 'three', 'four'])]])
+ execute('normal J')
+ eq('one two', eval('getline(1)'))
+ execute('%del')
+ execute([[call setline(1, ['one', 'two', 'three', 'four'])]])
+ execute('normal 10J')
+ eq('one two three four', eval('getline(1)'))
+ end)
+end)
diff --git a/test/functional/legacy/listlbr_spec.lua b/test/functional/legacy/listlbr_spec.lua
new file mode 100644
index 0000000000..6601a922ef
--- /dev/null
+++ b/test/functional/legacy/listlbr_spec.lua
@@ -0,0 +1,195 @@
+-- Test for linebreak and list option (non-utf8)
+
+local helpers = require('test.functional.helpers')
+local feed, insert, source = helpers.feed, helpers.insert, helpers.source
+local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
+
+describe('listlbr', function()
+ setup(clear)
+
+ it('is working', function()
+ insert([[
+ dummy text]])
+
+ execute('set wildchar=^E')
+ execute('10new')
+ execute('vsp')
+ execute('vert resize 20')
+ execute([[put =\"\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP \"]])
+ execute('norm! zt')
+ execute('set ts=4 sw=4 sts=4 linebreak sbr=+ wrap')
+ source([[
+ fu! ScreenChar(width)
+ let c=''
+ for j in range(1,4)
+ for i in range(1,a:width)
+ let c.=nr2char(screenchar(j, i))
+ endfor
+ let c.="\n"
+ endfor
+ return c
+ endfu
+ fu! DoRecordScreen()
+ wincmd l
+ $put =printf(\"\n%s\", g:test)
+ $put =g:line
+ wincmd p
+ endfu
+ ]])
+ execute('let g:test="Test 1: set linebreak"')
+ execute('redraw!')
+ execute('let line=ScreenChar(winwidth(0))')
+ execute('call DoRecordScreen()')
+
+ execute('let g:test="Test 2: set linebreak + set list"')
+ execute('set linebreak list listchars=')
+ execute('redraw!')
+ execute('let line=ScreenChar(winwidth(0))')
+ execute('call DoRecordScreen()')
+
+ execute('let g:test ="Test 3: set linebreak nolist"')
+ execute('set nolist linebreak')
+ execute('redraw!')
+ execute('let line=ScreenChar(winwidth(0))')
+ execute('call DoRecordScreen()')
+
+ execute('let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!"')
+ execute('set nolist linebreak ts=8')
+ execute([[let line="1\t".repeat('a', winwidth(0)-2)]])
+ execute('$put =line')
+ execute('$')
+ execute('norm! zt')
+ execute('redraw!')
+ execute('let line=ScreenChar(winwidth(0))')
+ execute('call DoRecordScreen()')
+ execute([[let line="_S_\t bla"]])
+ execute('$put =line')
+ execute('$')
+ execute('norm! zt')
+
+ execute('let g:test ="Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)"')
+ execute('set cpo&vim list linebreak conceallevel=2 concealcursor=nv listchars=tab:ab')
+ execute('syn match ConcealVar contained /_/ conceal')
+ execute('syn match All /.*/ contains=ConcealVar')
+ execute('let line=ScreenChar(winwidth(0))')
+ execute('call DoRecordScreen()')
+ execute('set cpo&vim linebreak')
+
+ execute('let g:test ="Test 6: set linebreak with visual block mode"')
+ execute('let line="REMOVE: this not"')
+ execute('$put =g:test')
+ execute('$put =line')
+ execute('let line="REMOVE: aaaaaaaaaaaaa"')
+ execute('$put =line')
+ execute('1/^REMOVE:')
+ feed('0<C-V>jf x')
+ execute('$put')
+ execute('set cpo&vim linebreak')
+
+ execute('let g:test ="Test 7: set linebreak with visual block mode and v_b_A"')
+ execute('$put =g:test')
+ feed('Golong line: <esc>40afoobar <esc>aTARGET at end<esc>')
+ execute([[exe "norm! $3B\<C-v>eAx\<Esc>"]])
+ execute('set cpo&vim linebreak sbr=')
+
+ execute('let g:test ="Test 8: set linebreak with visual char mode and changing block"')
+ execute('$put =g:test')
+ feed('Go1111-1111-1111-11-1111-1111-1111<esc>0f-lv3lc2222<esc>bgj.')
+
+ execute('let g:test ="Test 9: using redo after block visual mode"')
+ execute('$put =g:test')
+ feed('Go<CR>')
+ feed('aaa<CR>')
+ feed('aaa<CR>')
+ feed('a<ESC>2k<C-V>2j~e.<CR>')
+
+ execute('let g:test ="Test 10: using normal commands after block-visual"')
+ execute('$put =g:test')
+ execute('set linebreak')
+ feed('Go<cr>')
+ feed('abcd{ef<cr>')
+ feed('ghijklm<cr>')
+ feed('no}pqrs<esc>2k0f{<C-V><C-V>c%<esc>')
+
+ execute('let g:test ="Test 11: using block replace mode after wrapping"')
+ execute('$put =g:test')
+ execute('set linebreak wrap')
+ feed('Go<esc>150aa<esc>yypk147|<C-V>jr0<cr>')
+
+ execute('let g:test ="Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$"')
+ execute('set list listchars=space:_,trail:-,tab:>-,eol:$')
+ execute('$put =g:test')
+ execute([[let line="a aaaaaaaaaaaaaaaaaaaaaa\ta "]])
+ execute('$put =line')
+ execute('$')
+ execute('norm! zt')
+ execute('redraw!')
+ execute('let line=ScreenChar(winwidth(0))')
+ execute('call DoRecordScreen()')
+
+ -- Assert buffer contents.
+ expect([[
+
+ abcdef hijklmn pqrstuvwxyz_1060ABCDEFGHIJKLMNOP
+
+ Test 1: set linebreak
+ abcdef
+ +hijklmn
+ +pqrstuvwxyz_1060ABC
+ +DEFGHIJKLMNOP
+
+ Test 2: set linebreak + set list
+ ^Iabcdef hijklmn^I
+ +pqrstuvwxyz_1060ABC
+ +DEFGHIJKLMNOP
+
+
+ Test 3: set linebreak nolist
+ abcdef
+ +hijklmn
+ +pqrstuvwxyz_1060ABC
+ +DEFGHIJKLMNOP
+ 1 aaaaaaaaaaaaaaaaaa
+
+ Test 4: set linebreak with tab and 1 line as long as screen: should break!
+ 1
+ +aaaaaaaaaaaaaaaaaa
+ ~
+ ~
+ _S_ bla
+
+ Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)
+ Sabbbbbb bla
+ ~
+ ~
+ ~
+ Test 6: set linebreak with visual block mode
+ this not
+ aaaaaaaaaaaaa
+ REMOVE:
+ REMOVE:
+ Test 7: set linebreak with visual block mode and v_b_A
+ long line: foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar TARGETx at end
+ Test 8: set linebreak with visual char mode and changing block
+ 1111-2222-1111-11-1111-2222-1111
+ Test 9: using redo after block visual mode
+
+ AaA
+ AaA
+ A
+ Test 10: using normal commands after block-visual
+
+ abcdpqrs
+ Test 11: using block replace mode after wrapping
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa
+ Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$
+ a aaaaaaaaaaaaaaaaaaaaaa a
+
+ Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$
+ a_
+ aaaaaaaaaaaaaaaaaaaa
+ aa>-----a-$
+ ~ ]])
+ end)
+end)
diff --git a/test/functional/legacy/quickfix_spec.lua b/test/functional/legacy/quickfix_spec.lua
index 88f86815b3..315b8ca682 100644
--- a/test/functional/legacy/quickfix_spec.lua
+++ b/test/functional/legacy/quickfix_spec.lua
@@ -2,11 +2,264 @@
local helpers = require('test.functional.helpers')
local source, clear = helpers.source, helpers.clear
+local eq, nvim, call = helpers.eq, helpers.meths, helpers.call
+
+local function expected_empty()
+ eq({}, nvim.get_vvar('errors'))
+end
describe('helpgrep', function()
- before_each(clear)
+ before_each(function()
+ clear()
- it('works', function()
+ source([[
+ " Tests for the :clist and :llist commands
+ function XlistTests(cchar)
+ let Xlist = a:cchar . 'list'
+ let Xgetexpr = a:cchar . 'getexpr'
+
+ " With an empty list, command should return error
+ exe Xgetexpr . ' []'
+ exe 'silent! ' . Xlist
+ call assert_true(v:errmsg ==# 'E42: No Errors')
+
+ " Populate the list and then try
+ exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1',
+ \ 'non-error 2', 'Xtestfile2:2:2:Line2',
+ \ 'non-error 3', 'Xtestfile3:3:1:Line3']"
+
+ " List only valid entries
+ redir => result
+ exe 'silent ' . Xlist
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
+ \ ' 4 Xtestfile2:2 col 2: Line2',
+ \ ' 6 Xtestfile3:3 col 1: Line3'], l)
+
+ " List all the entries
+ redir => result
+ exe 'silent ' . Xlist . "!"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
+ \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
+ \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
+
+ " List a range of errors
+ redir => result
+ exe 'silent '. Xlist . " 3,6"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
+ \ ' 6 Xtestfile3:3 col 1: Line3'], l)
+
+ redir => result
+ exe 'silent ' . Xlist . "! 3,4"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
+
+ redir => result
+ exe 'silent ' . Xlist . " -6,-4"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
+
+ redir => result
+ exe 'silent ' . Xlist . "! -5,-3"
+ redir END
+ let l = split(result, "\n")
+ call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
+ \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
+ endfunction
+
+ " Tests for the :colder, :cnewer, :lolder and :lnewer commands
+ " Note that this test assumes that a quickfix/location list is
+ " already set by the caller
+ function XageTests(cchar)
+ let Xolder = a:cchar . 'older'
+ let Xnewer = a:cchar . 'newer'
+ let Xgetexpr = a:cchar . 'getexpr'
+ if a:cchar == 'c'
+ let Xgetlist = 'getqflist()'
+ else
+ let Xgetlist = 'getloclist(0)'
+ endif
+
+ " Jumping to a non existent list should return error
+ exe 'silent! ' . Xolder . ' 99'
+ call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
+
+ exe 'silent! ' . Xnewer . ' 99'
+ call assert_true(v:errmsg ==# 'E381: At top of quickfix stack')
+
+ " Add three quickfix/location lists
+ exe Xgetexpr . " ['Xtestfile1:1:3:Line1']"
+ exe Xgetexpr . " ['Xtestfile2:2:2:Line2']"
+ exe Xgetexpr . " ['Xtestfile3:3:1:Line3']"
+
+ " Go back two lists
+ exe Xolder
+ exe 'let l = ' . Xgetlist
+ call assert_equal('Line2', l[0].text)
+
+ " Go forward two lists
+ exe Xnewer
+ exe 'let l = ' . Xgetlist
+ call assert_equal('Line3', l[0].text)
+
+ " Test for the optional count argument
+ exe Xolder . ' 2'
+ exe 'let l = ' . Xgetlist
+ call assert_equal('Line1', l[0].text)
+
+ exe Xnewer . ' 2'
+ exe 'let l = ' . Xgetlist
+ call assert_equal('Line3', l[0].text)
+ endfunction
+
+ " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
+ " commands
+ function XwindowTests(cchar)
+ let Xwindow = a:cchar . 'window'
+ let Xclose = a:cchar . 'close'
+ let Xopen = a:cchar . 'open'
+ let Xgetexpr = a:cchar . 'getexpr'
+
+ " Create a list with no valid entries
+ exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']"
+
+ " Quickfix/Location window should not open with no valid errors
+ exe Xwindow
+ call assert_true(winnr('$') == 1)
+
+ " Create a list with valid entries
+ exe Xgetexpr . " ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
+ \ 'Xtestfile3:3:1:Line3']"
+
+ " Open the window
+ exe Xwindow
+ call assert_true(winnr('$') == 2 && winnr() == 2 &&
+ \ getline('.') ==# 'Xtestfile1|1 col 3| Line1')
+
+ " Close the window
+ exe Xclose
+ call assert_true(winnr('$') == 1)
+
+ " Create a list with no valid entries
+ exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']"
+
+ " Open the window
+ exe Xopen . ' 5'
+ call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1'
+ \ && winheight('.') == 5)
+
+ " Opening the window again, should move the cursor to that window
+ wincmd t
+ exe Xopen . ' 7'
+ call assert_true(winnr('$') == 2 && winnr() == 2 &&
+ \ winheight('.') == 7 &&
+ \ getline('.') ==# '|| non-error 1')
+
+
+ " Calling cwindow should close the quickfix window with no valid errors
+ exe Xwindow
+ call assert_true(winnr('$') == 1)
+ endfunction
+
+ " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
+ " commands.
+ function XfileTests(cchar)
+ let Xfile = a:cchar . 'file'
+ let Xgetfile = a:cchar . 'getfile'
+ let Xaddfile = a:cchar . 'addfile'
+ if a:cchar == 'c'
+ let Xgetlist = 'getqflist()'
+ else
+ let Xgetlist = 'getloclist(0)'
+ endif
+
+ call writefile(['Xtestfile1:700:10:Line 700',
+ \ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1')
+
+ enew!
+ exe Xfile . ' Xqftestfile1'
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 2 &&
+ \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
+ \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
+
+ " Run cfile/lfile from a modified buffer
+ enew!
+ silent! put ='Quickfix'
+ exe 'silent! ' . Xfile . ' Xqftestfile1'
+ call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)')
+
+ call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1')
+ exe Xaddfile . ' Xqftestfile1'
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 3 &&
+ \ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900')
+
+ call writefile(['Xtestfile1:222:77:Line 222',
+ \ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1')
+
+ enew!
+ exe Xgetfile . ' Xqftestfile1'
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 2 &&
+ \ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' &&
+ \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
+
+ call delete('Xqftestfile1')
+ endfunction
+
+ " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
+ " :lgetbuffer commands.
+ function XbufferTests(cchar)
+ let Xbuffer = a:cchar . 'buffer'
+ let Xgetbuffer = a:cchar . 'getbuffer'
+ let Xaddbuffer = a:cchar . 'addbuffer'
+ if a:cchar == 'c'
+ let Xgetlist = 'getqflist()'
+ else
+ let Xgetlist = 'getloclist(0)'
+ endif
+
+ enew!
+ silent! call setline(1, ['Xtestfile7:700:10:Line 700',
+ \ 'Xtestfile8:800:15:Line 800'])
+ exe Xbuffer . "!"
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 2 &&
+ \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' &&
+ \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800')
+
+ enew!
+ silent! call setline(1, ['Xtestfile9:900:55:Line 900',
+ \ 'Xtestfile10:950:66:Line 950'])
+ exe Xgetbuffer
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 2 &&
+ \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' &&
+ \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950')
+
+ enew!
+ silent! call setline(1, ['Xtestfile11:700:20:Line 700',
+ \ 'Xtestfile12:750:25:Line 750'])
+ exe Xaddbuffer
+ exe 'let l = ' . Xgetlist
+ call assert_true(len(l) == 4 &&
+ \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' &&
+ \ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' &&
+ \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
+
+ endfunction
+ ]])
+ end)
+
+ it('copen/cclose work', function()
source([[
helpgrep quickfix
copen
@@ -14,4 +267,43 @@ describe('helpgrep', function()
cclose
]])
end)
+
+ it('clist/llist work', function()
+ call('XlistTests', 'c')
+ expected_empty()
+ call('XlistTests', 'l')
+ expected_empty()
+ end)
+
+ it('colder/cnewer and lolder/lnewer work', function()
+ local list = {{bufnr = 1, lnum = 1}}
+ call('setqflist', list)
+ call('XageTests', 'c')
+ expected_empty()
+
+ call('setloclist', 0, list)
+ call('XageTests', 'l')
+ expected_empty()
+ end)
+
+ it('quickfix/location list window commands work', function()
+ call('XwindowTests', 'c')
+ expected_empty()
+ call('XwindowTests', 'l')
+ expected_empty()
+ end)
+
+ it('quickfix/location list file commands work', function()
+ call('XfileTests', 'c')
+ expected_empty()
+ call('XfileTests', 'l')
+ expected_empty()
+ end)
+
+ it('quickfix/location list buffer commands work', function()
+ call('XbufferTests', 'c')
+ expected_empty()
+ call('XbufferTests', 'l')
+ expected_empty()
+ end)
end)
diff --git a/test/functional/legacy/set_spec.lua b/test/functional/legacy/set_spec.lua
index f81fcd3700..f2c907084e 100644
--- a/test/functional/legacy/set_spec.lua
+++ b/test/functional/legacy/set_spec.lua
@@ -7,6 +7,21 @@ local clear, execute, eval, eq =
describe(':set', function()
before_each(clear)
+ it('handles backslash properly', function()
+ execute('set iskeyword=a,b,c')
+ execute('set iskeyword+=d')
+ eq('a,b,c,d', eval('&iskeyword'))
+
+ execute([[set iskeyword+=\\,e]])
+ eq([[a,b,c,d,\,e]], eval('&iskeyword'))
+
+ execute('set iskeyword-=e')
+ eq([[a,b,c,d,\]], eval('&iskeyword'))
+
+ execute([[set iskeyword-=\]])
+ eq('a,b,c,d', eval('&iskeyword'))
+ end)
+
it('recognizes a trailing comma with +=', function()
execute('set wildignore=*.png,')
execute('set wildignore+=*.jpg')
diff --git a/test/functional/provider/python_spec.lua b/test/functional/provider/python_spec.lua
index da45d6aa00..06fdbef669 100644
--- a/test/functional/provider/python_spec.lua
+++ b/test/functional/provider/python_spec.lua
@@ -1,12 +1,22 @@
local helpers = require('test.functional.helpers')
-local eval, command, feed = helpers.eval, helpers.command, helpers.feed
-local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert
-local expect, write_file = helpers.expect, helpers.write_file
+
+local eq = helpers.eq
+local neq = helpers.neq
+local feed = helpers.feed
+local clear = helpers.clear
+local funcs = helpers.funcs
+local meths = helpers.meths
+local insert = helpers.insert
+local expect = helpers.expect
+local command = helpers.command
+local exc_exec = helpers.exc_exec
+local write_file = helpers.write_file
+local curbufmeths = helpers.curbufmeths
do
clear()
command('let [g:interp, g:errors] = provider#pythonx#Detect(2)')
- local errors = eval('g:errors')
+ local errors = meths.get_var('errors')
if errors ~= '' then
pending(
'Python 2 (or the Python 2 neovim module) is broken or missing:\n' .. errors,
@@ -15,49 +25,58 @@ do
end
end
-describe('python commands and functions', function()
- before_each(function()
- clear()
- command('python import vim')
- end)
+before_each(function()
+ clear()
+ command('python import vim')
+end)
- it('feature test', function()
- eq(1, eval('has("python")'))
+describe('python feature test', function()
+ it('works', function()
+ eq(1, funcs.has('python'))
end)
+end)
- it('python_execute', function()
+describe(':python command', function()
+ it('works with a line', function()
command('python vim.vars["set_by_python"] = [100, 0]')
- eq({100, 0}, eval('g:set_by_python'))
+ eq({100, 0}, meths.get_var('set_by_python'))
end)
- it('python_execute with nested commands', function()
+ -- TODO(ZyX-I): works with << EOF
+ -- TODO(ZyX-I): works with execute 'python' line1."\n".line2."\n"…
+
+ it('supports nesting', function()
command([[python vim.command('python vim.command("python vim.command(\'let set_by_nested_python = 555\')")')]])
- eq(555, eval('g:set_by_nested_python'))
+ eq(555, meths.get_var('set_by_nested_python'))
end)
- it('python_execute with range', function()
+ it('supports range', function()
insert([[
line1
line2
line3
line4]])
feed('ggjvj:python vim.vars["range"] = vim.current.range[:]<CR>')
- eq({'line2', 'line3'}, eval('g:range'))
+ eq({'line2', 'line3'}, meths.get_var('range'))
end)
+end)
- it('pyfile', function()
+describe(':pyfile command', function()
+ it('works', function()
local fname = 'pyfile.py'
write_file(fname, 'vim.command("let set_by_pyfile = 123")')
command('pyfile pyfile.py')
- eq(123, eval('g:set_by_pyfile'))
+ eq(123, meths.get_var('set_by_pyfile'))
os.remove(fname)
end)
+end)
- it('pydo', function()
+describe(':pydo command', function()
+ it('works', function()
-- :pydo 42 returns None for all lines,
-- the buffer should not be changed
command('normal :pydo 42')
- eq(0, eval('&mod'))
+ eq(false, curbufmeths.get_option('modified'))
-- insert some text
insert('abc\ndef\nghi')
expect([[
@@ -71,8 +90,25 @@ describe('python commands and functions', function()
2
ghi]])
end)
+end)
+
+describe('pyeval()', function()
+ it('works', function()
+ eq({1, 2, {['key'] = 'val'}}, funcs.pyeval('[1, 2, {"key": "val"}]'))
+ end)
+
+ it('errors out when given non-string', function()
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(10)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_dict)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_list)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(0.0)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(function("tr"))'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:true)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:false)'))
+ eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:null)'))
+ end)
- it('pyeval', function()
- eq({1, 2, {['key'] = 'val'}}, eval([[pyeval('[1, 2, {"key": "val"}]')]]))
+ it('accepts NULL string', function()
+ neq(0, exc_exec('call pyeval($XXX_NONEXISTENT_VAR_XXX)'))
end)
end)
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 55ef254a63..cefb603a7e 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -158,8 +158,7 @@ describe('terminal buffer', function()
end)
it('handles loss of focus gracefully', function()
- -- Temporarily change the statusline to avoid printing the file name, which
- -- varies be where the test is run.
+ -- Change the statusline to avoid printing the file name, which varies.
nvim('set_option', 'statusline', '==========')
execute('set laststatus=0')
@@ -195,5 +194,15 @@ describe('terminal buffer', function()
execute('set laststatus=1') -- Restore laststatus to the default.
end)
+
+ it('term_close() use-after-free #4393', function()
+ if eval("executable('yes')") == 0 then
+ pending('missing "yes" command')
+ return
+ end
+ execute('terminal yes')
+ feed([[<C-\><C-n>]])
+ execute('bdelete!')
+ end)
end)
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 493539b4d3..d89092ff27 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -1,15 +1,15 @@
local helpers = require('test.functional.helpers')
local Screen = require('test.functional.ui.screen')
local clear, wait, nvim = helpers.clear, helpers.wait, helpers.nvim
-local nvim_dir = helpers.nvim_dir
-local execute = helpers.execute
+local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq
+local execute, eval = helpers.execute, helpers.eval
describe(':terminal', function()
local screen
before_each(function()
clear()
- screen = Screen.new(50, 7)
+ screen = Screen.new(50, 4)
screen:attach(false)
nvim('set_option', 'shell', nvim_dir..'/shell-test')
nvim('set_option', 'shellcmdflag', 'EXE')
@@ -23,9 +23,6 @@ describe(':terminal', function()
ready $ |
[Process exited 0] |
|
- |
- |
- |
-- TERMINAL -- |
]])
end)
@@ -37,9 +34,6 @@ describe(':terminal', function()
ready $ echo hi |
|
[Process exited 0] |
- |
- |
- |
-- TERMINAL -- |
]])
end)
@@ -51,10 +45,15 @@ describe(':terminal', function()
ready $ echo 'hello' \ "world" |
|
[Process exited 0] |
- |
- |
- |
-- TERMINAL -- |
]])
end)
+
+ it('ex_terminal() double-free #4554', function()
+ source([[
+ autocmd BufNew * set shell=foo
+ terminal]])
+ -- Verify that BufNew actually fired (else the test is invalid).
+ eq('foo', eval('&shell'))
+ end)
end)
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
index 045f5aa42f..97875c5147 100644
--- a/test/functional/terminal/highlight_spec.lua
+++ b/test/functional/terminal/highlight_spec.lua
@@ -25,7 +25,7 @@ describe('terminal window highlighting', function()
[5] = {background = 11},
[6] = {foreground = 130},
[7] = {reverse = true},
- [8] = {background = 11}
+ [8] = {background = 11},
})
screen:attach(false)
execute('enew | call termopen(["'..nvim_dir..'/tty-test"]) | startinsert')
@@ -121,7 +121,7 @@ describe('terminal window highlighting with custom palette', function()
clear()
screen = Screen.new(50, 7)
screen:set_default_attr_ids({
- [1] = {foreground = 1193046}
+ [1] = {foreground = 1193046, special = Screen.colors.Black}
})
screen:set_default_attr_ignore({
[1] = {bold = true},
@@ -130,7 +130,7 @@ describe('terminal window highlighting with custom palette', function()
[5] = {background = 11},
[6] = {foreground = 130},
[7] = {reverse = true},
- [8] = {background = 11}
+ [8] = {background = 11},
})
screen:attach(true)
nvim('set_var', 'terminal_color_3', '#123456')
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 48376a344f..364ca327a4 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -154,9 +154,7 @@ describe('tui', function()
for i = 1, 3000 do
t[i] = 'item ' .. tostring(i)
end
- feed('i\027[200~')
- feed(table.concat(t, '\n'))
- feed('\027[201~')
+ feed('i\027[200~'..table.concat(t, '\n')..'\027[201~')
screen:expect([[
item 2997 |
item 2998 |
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 06139277b2..85fca4d7ca 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')
local Screen = require('test.functional.ui.screen')
local os = require('os')
-local clear, feed = helpers.clear, helpers.feed
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local execute, request, eq = helpers.execute, helpers.request, helpers.eq
@@ -302,4 +302,353 @@ describe('Default highlight groups', function()
{1:-- INSERT --} |
]], {[1] = {foreground = Screen.colors.Red, background = Screen.colors.Green}})
end)
+ it('can be cleared by assigning NONE', function()
+ execute('syn keyword TmpKeyword neovim')
+ execute('hi link TmpKeyword ErrorMsg')
+ insert('neovim')
+ screen:expect([[
+ {1:neovi^m} |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], {
+ [1] = {foreground = Screen.colors.White, background = Screen.colors.Red}
+ })
+ execute("hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE"
+ .. " gui=NONE guifg=NONE guibg=NONE guisp=NONE")
+ screen:expect([[
+ neovi^m |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], {})
+ end)
+end)
+
+describe('guisp (special/undercurl)', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(25,10)
+ screen:attach()
+ screen:set_default_attr_ignore({
+ [1] = {bold = true, foreground = Screen.colors.Blue},
+ [2] = {bold = true}
+ })
+ end)
+
+ it('can be set and is applied like foreground or background', function()
+ execute('syntax on')
+ execute('syn keyword TmpKeyword neovim')
+ execute('syn keyword TmpKeyword1 special')
+ execute('syn keyword TmpKeyword2 specialwithbg')
+ execute('syn keyword TmpKeyword3 specialwithfg')
+ execute('hi! Awesome guifg=red guibg=yellow guisp=red')
+ execute('hi! Awesome1 guisp=red')
+ execute('hi! Awesome2 guibg=yellow guisp=red')
+ execute('hi! Awesome3 guifg=red guisp=red')
+ execute('hi link TmpKeyword Awesome')
+ execute('hi link TmpKeyword1 Awesome1')
+ execute('hi link TmpKeyword2 Awesome2')
+ execute('hi link TmpKeyword3 Awesome3')
+ insert([[
+ neovim
+ awesome neovim
+ wordcontainingneovim
+ special
+ specialwithbg
+ specialwithfg
+ ]])
+ feed('Go<tab>neovim tabbed')
+ screen:expect([[
+ {1:neovim} |
+ awesome {1:neovim} |
+ wordcontainingneovim |
+ {2:special} |
+ {3:specialwithbg} |
+ {4:specialwithfg} |
+ |
+ {1:neovim} tabbed^ |
+ ~ |
+ -- INSERT -- |
+ ]],{
+ [1] = {background = Screen.colors.Yellow, foreground = Screen.colors.Red,
+ special = Screen.colors.Red},
+ [2] = {special = Screen.colors.Red},
+ [3] = {special = Screen.colors.Red, background = Screen.colors.Yellow},
+ [4] = {foreground = Screen.colors.Red, special = Screen.colors.Red},
+ })
+
+ end)
+end)
+
+describe("'cursorline' with 'listchars'", function()
+ local screen
+
+ local hlgroup_colors = {
+ NonText = Screen.colors.Blue,
+ Cursorline = Screen.colors.Grey90,
+ SpecialKey = Screen.colors.Red,
+ Visual = Screen.colors.LightGrey,
+ }
+
+ before_each(function()
+ clear()
+ screen = Screen.new(20,5)
+ screen:attach()
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ it("'cursorline' and 'cursorcolumn'", function()
+ screen:set_default_attr_ids({[1] = {background=hlgroup_colors.Cursorline}})
+ screen:set_default_attr_ignore( {{bold=true, foreground=hlgroup_colors.NonText}} )
+ execute('highlight clear ModeMsg')
+ execute('set cursorline')
+ feed('i')
+ screen:expect([[
+ {1:^ }|
+ ~ |
+ ~ |
+ ~ |
+ -- INSERT -- |
+ ]])
+ feed('abcdefg<cr>kkasdf')
+ screen:expect([[
+ abcdefg |
+ {1:kkasdf^ }|
+ ~ |
+ ~ |
+ -- INSERT -- |
+ ]])
+ feed('<esc>')
+ screen:expect([[
+ abcdefg |
+ {1:kkasd^f }|
+ ~ |
+ ~ |
+ |
+ ]])
+ execute('set nocursorline')
+ screen:expect([[
+ abcdefg |
+ kkasd^f |
+ ~ |
+ ~ |
+ :set nocursorline |
+ ]])
+ feed('k')
+ screen:expect([[
+ abcde^fg |
+ kkasdf |
+ ~ |
+ ~ |
+ :set nocursorline |
+ ]])
+ feed('jjji<cr><cr><cr><esc>')
+ screen:expect([[
+ kkasd |
+ |
+ |
+ ^f |
+ |
+ ]])
+ execute('set cursorline')
+ execute('set cursorcolumn')
+ feed('kkiabcdefghijk<esc>hh')
+ screen:expect([[
+ kkasd {1: } |
+ {1:abcdefgh^ijk }|
+ {1: } |
+ f {1: } |
+ |
+ ]])
+ feed('khh')
+ screen:expect([[
+ {1:kk^asd }|
+ ab{1:c}defghijk |
+ {1: } |
+ f {1: } |
+ |
+ ]])
+ end)
+
+ it("'cursorline' and with 'listchar' option: space, eol, tab, and trail", function()
+ screen:set_default_attr_ids({
+ [1] = {background=hlgroup_colors.Cursorline},
+ [2] = {
+ foreground=hlgroup_colors.SpecialKey,
+ background=hlgroup_colors.Cursorline,
+ },
+ [3] = {
+ background=hlgroup_colors.Cursorline,
+ foreground=hlgroup_colors.NonText,
+ bold=true,
+ },
+ [4] = {
+ foreground=hlgroup_colors.NonText,
+ bold=true,
+ },
+ [5] = {
+ foreground=hlgroup_colors.SpecialKey,
+ },
+ })
+ execute('highlight clear ModeMsg')
+ execute('highlight SpecialKey guifg=#FF0000')
+ execute('set cursorline')
+ execute('set tabstop=8')
+ execute('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
+ feed('i\t abcd <cr>\t abcd <cr><esc>k')
+ screen:expect([[
+ {5:>-------.}abcd{5:*}{4:¬} |
+ {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }|
+ {4:¬} |
+ {4:~ }|
+ |
+ ]])
+ feed('k')
+ screen:expect([[
+ {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }|
+ {5:>-------.}abcd{5:*}{4:¬} |
+ {4:¬} |
+ {4:~ }|
+ |
+ ]])
+ execute('set nocursorline')
+ screen:expect([[
+ {5:^>-------.}abcd{5:*}{4:¬} |
+ {5:>-------.}abcd{5:*}{4:¬} |
+ {4:¬} |
+ {4:~ }|
+ :set nocursorline |
+ ]])
+ execute('set nowrap')
+ feed('ALorem ipsum dolor sit amet<ESC>0')
+ screen:expect([[
+ {5:^>-------.}abcd{5:.}Lorem{4:>}|
+ {5:>-------.}abcd{5:*}{4:¬} |
+ {4:¬} |
+ {4:~ }|
+ |
+ ]])
+ execute('set cursorline')
+ screen:expect([[
+ {2:^>-------.}{1:abcd}{2:.}{1:Lorem}{4:>}|
+ {5:>-------.}abcd{5:*}{4:¬} |
+ {4:¬} |
+ {4:~ }|
+ :set cursorline |
+ ]])
+ feed('$')
+ screen:expect([[
+ {4:<}{1:r}{2:.}{1:sit}{2:.}{1:ame^t}{3:¬}{1: }|
+ {4:<} |
+ {4:<} |
+ {4:~ }|
+ :set cursorline |
+ ]])
+ feed('G')
+ screen:expect([[
+ {5:>-------.}abcd{5:.}Lorem{4:>}|
+ {5:>-------.}abcd{5:*}{4:¬} |
+ {3:^¬}{1: }|
+ {4:~ }|
+ :set cursorline |
+ ]])
+ end)
+
+ it("'listchar' in visual mode", function()
+ screen:set_default_attr_ids({
+ [1] = {background=hlgroup_colors.Cursorline},
+ [2] = {
+ foreground=hlgroup_colors.SpecialKey,
+ background=hlgroup_colors.Cursorline,
+ },
+ [3] = {
+ background=hlgroup_colors.Cursorline,
+ foreground=hlgroup_colors.NonText,
+ bold=true,
+ },
+ [4] = {
+ foreground=hlgroup_colors.NonText,
+ bold=true,
+ },
+ [5] = {
+ foreground=hlgroup_colors.SpecialKey,
+ },
+ [6] = {
+ background=hlgroup_colors.Visual,
+ },
+ [7] = {
+ background=hlgroup_colors.Visual,
+ foreground=hlgroup_colors.SpecialKey,
+ },
+ [8] = {
+ background=hlgroup_colors.Visual,
+ foreground=hlgroup_colors.NonText,
+ bold=true,
+ },
+ })
+ execute('highlight clear ModeMsg')
+ execute('highlight SpecialKey guifg=#FF0000')
+ execute('set cursorline')
+ execute('set tabstop=8')
+ execute('set nowrap')
+ execute('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
+ feed('i\t abcd <cr>\t abcd Lorem ipsum dolor sit amet<cr><esc>kkk0')
+ screen:expect([[
+ {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }|
+ {5:>-------.}abcd{5:.}Lorem{4:>}|
+ {4:¬} |
+ {4:~ }|
+ |
+ ]])
+ feed('lllvj')
+ screen:expect([[
+ {5:>-------.}a{6:bcd}{7:*}{8:¬} |
+ {7:>-------.}{6:a}^bcd{5:.}Lorem{4:>}|
+ {4:¬} |
+ {4:~ }|
+ -- VISUAL -- |
+ ]])
+ feed('<esc>V')
+ screen:expect([[
+ {5:>-------.}abcd{5:*}{4:¬} |
+ {7:>-------.}{6:a}^b{6:cd}{7:.}{6:Lorem}{4:>}|
+ {4:¬} |
+ {4:~ }|
+ -- VISUAL LINE -- |
+ ]])
+ feed('<esc>$')
+ screen:expect([[
+ {4:<} |
+ {4:<}{1:r}{2:.}{1:sit}{2:.}{1:ame^t}{3:¬}{1: }|
+ {4:<} |
+ {4:~ }|
+ |
+ ]])
+ end)
end)
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index d0d791308b..993bbd5b0e 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -23,7 +23,12 @@ describe('Mouse input', function()
screen:attach()
screen:set_default_attr_ids({
[1] = {background = hlgroup_colors.Visual},
- [2] = {bold = true}
+ [2] = {bold = true},
+ [3] = {
+ foreground = hlgroup_colors.NonText,
+ background = hlgroup_colors.Visual,
+ bold = true,
+ },
})
screen:set_default_attr_ignore( {{bold=true, foreground=hlgroup_colors.NonText}} )
feed('itesting<cr>mouse<cr>support and selection<esc>')
@@ -225,14 +230,14 @@ describe('Mouse input', function()
feed('<LeftDrag><2,2>')
screen:expect([[
testing |
- mo{1:use } |
+ mo{1:use}{3: } |
{1:su}^pport and selection |
~ |
{2:-- VISUAL --} |
]])
feed('<LeftDrag><0,0>')
screen:expect([[
- ^t{1:esting } |
+ ^t{1:esting}{3: } |
{1:mou}se |
support and selection |
~ |
@@ -293,7 +298,7 @@ describe('Mouse input', function()
screen:expect([[
testing |
mouse |
- {1:su}^p{1:port and selection } |
+ {1:su}^p{1:port and selection}{3: } |
~ |
{2:-- VISUAL LINE --} |
]])
@@ -321,8 +326,8 @@ describe('Mouse input', function()
]])
feed('<RightMouse><2,2>')
screen:expect([[
- {1:testing } |
- {1:mouse } |
+ {1:testing}{3: } |
+ {1:mouse}{3: } |
{1:su}^pport and selection |
~ |
{2:-- VISUAL --} |
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index a11fab18a2..99b85caf10 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -290,6 +290,10 @@ If everything else fails, use Screen:redraw_debug to help investigate what is
end
end
+function Screen:sleep(ms)
+ pcall(function() self:wait(function() return "error" end, ms) end)
+end
+
function Screen:_redraw(updates)
for _, update in ipairs(updates) do
-- print('--')
@@ -425,6 +429,10 @@ function Screen:_handle_update_bg(bg)
self._bg = bg
end
+function Screen:_handle_update_sp(sp)
+ self._sp = sp
+end
+
function Screen:_handle_suspend()
self.suspended = true
end
@@ -497,7 +505,7 @@ end
function Screen:snapshot_util(attrs, ignore)
-- util to generate screen test
- pcall(function() self:wait(function() return "error" end, 250) end)
+ self:sleep(250)
self:print_snapshot(attrs, ignore)
end
@@ -573,7 +581,7 @@ function Screen:_pprint_attrs(attrs)
local items = {}
for f, v in pairs(attrs) do
local desc = tostring(v)
- if f == "foreground" or f == "background" then
+ if f == "foreground" or f == "background" or f == "special" then
if Screen.colornames[v] ~= nil then
desc = "Screen.colors."..Screen.colornames[v]
end
@@ -614,7 +622,8 @@ function Screen:_equal_attrs(a, b)
a.underline == b.underline and a.undercurl == b.undercurl and
a.italic == b.italic and a.reverse == b.reverse and
a.foreground == b.foreground and
- a.background == b.background
+ a.background == b.background and
+ a.special == b.special
end
function Screen:_attr_index(attrs, attr)