aboutsummaryrefslogtreecommitdiff
path: root/test/functional/options
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/options')
-rw-r--r--test/functional/options/autochdir_spec.lua31
-rw-r--r--test/functional/options/cursorbind_spec.lua91
-rw-r--r--test/functional/options/defaults_spec.lua107
-rw-r--r--test/functional/options/keymap_spec.lua22
-rw-r--r--test/functional/options/mousescroll_spec.lua151
-rw-r--r--test/functional/options/num_options_spec.lua2
-rw-r--r--test/functional/options/pastetoggle_spec.lua86
7 files changed, 427 insertions, 63 deletions
diff --git a/test/functional/options/autochdir_spec.lua b/test/functional/options/autochdir_spec.lua
index 2fce0a5ed9..74959a8e76 100644
--- a/test/functional/options/autochdir_spec.lua
+++ b/test/functional/options/autochdir_spec.lua
@@ -1,7 +1,9 @@
+local lfs = require('lfs')
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
-local getcwd = helpers.funcs.getcwd
+local funcs = helpers.funcs
+local command = helpers.command
describe("'autochdir'", function()
it('given on the shell gets processed properly', function()
@@ -9,11 +11,34 @@ describe("'autochdir'", function()
-- By default 'autochdir' is off, thus getcwd() returns the repo root.
clear(targetdir..'/tty-test.c')
- local rootdir = getcwd()
+ local rootdir = funcs.getcwd()
local expected = rootdir .. '/' .. targetdir
-- With 'autochdir' on, we should get the directory of tty-test.c.
clear('--cmd', 'set autochdir', targetdir..'/tty-test.c')
- eq(helpers.iswin() and expected:gsub('/', '\\') or expected, getcwd())
+ eq(helpers.iswin() and expected:gsub('/', '\\') or expected, funcs.getcwd())
+ end)
+
+ it('is not overwritten by getwinvar() call #17609',function()
+ local curdir = string.gsub(lfs.currentdir(), '\\', '/')
+ local dir_a = curdir..'/Xtest-functional-options-autochdir.dir_a'
+ local dir_b = curdir..'/Xtest-functional-options-autochdir.dir_b'
+ lfs.mkdir(dir_a)
+ lfs.mkdir(dir_b)
+ clear()
+ command('set shellslash')
+ command('set autochdir')
+ command('edit '..dir_a..'/file1')
+ eq(dir_a, funcs.getcwd())
+ command('lcd '..dir_b)
+ eq(dir_b, funcs.getcwd())
+ command('botright vnew ../file2')
+ eq(curdir, funcs.getcwd())
+ command('wincmd w')
+ eq(dir_a, funcs.getcwd())
+ funcs.getwinvar(2, 'foo')
+ eq(dir_a, funcs.getcwd())
+ helpers.rmdir(dir_a)
+ helpers.rmdir(dir_b)
end)
end)
diff --git a/test/functional/options/cursorbind_spec.lua b/test/functional/options/cursorbind_spec.lua
new file mode 100644
index 0000000000..1a03ed099a
--- /dev/null
+++ b/test/functional/options/cursorbind_spec.lua
@@ -0,0 +1,91 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local command = helpers.command
+local exec = helpers.exec
+local feed = helpers.feed
+
+before_each(clear)
+
+describe("'cursorbind'", function()
+ it("behaves consistently whether 'cursorline' is set or not vim-patch:8.2.4795", function()
+ local screen = Screen.new(60, 8)
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [2] = {bold = true, reverse = true}, -- StatusLine
+ [3] = {reverse = true}, -- StatusLineNC
+ [4] = {background = Screen.colors.Grey90}, -- CursorLine, CursorColumn
+ })
+ screen:attach()
+ exec([[
+ call setline(1, 'aa bb cc dd ee ff gg hh ii jj kk ll mm' ..
+ \ ' nn oo pp qq rr ss tt uu vv ww xx yy zz')
+ set nowrap
+ " The following makes the cursor apparent on the screen dump
+ set sidescroll=1 cursorcolumn
+ " add empty lines, required for cursorcolumn
+ call append(1, ['','','',''])
+ 20vsp
+ windo :set cursorbind
+ ]])
+ feed('20l')
+ screen:expect([[
+ a bb cc dd ee ff gg │aa bb cc dd ee ff gg^ hh ii jj kk ll mm |
+ {4: }│ {4: } |
+ {4: }│ {4: } |
+ {4: }│ {4: } |
+ {4: }│ {4: } |
+ {1:~ }│{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ feed('10l')
+ screen:expect([[
+ hh ii jj kk ll mm n│aa bb cc dd ee ff gg hh ii jj ^kk ll mm |
+ {4: } │ {4: } |
+ {4: } │ {4: } |
+ {4: } │ {4: } |
+ {4: } │ {4: } |
+ {1:~ }│{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ command('windo :set cursorline')
+ feed('0')
+ feed('20l')
+ screen:expect([[
+ {4:a bb cc dd ee ff gg }│{4:aa bb cc dd ee ff gg^ hh ii jj kk ll mm }|
+ {4: }│ {4: } |
+ {4: }│ {4: } |
+ {4: }│ {4: } |
+ {4: }│ {4: } |
+ {1:~ }│{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ feed('10l')
+ screen:expect([[
+ {4: hh ii jj kk ll mm n}│{4:aa bb cc dd ee ff gg hh ii jj ^kk ll mm }|
+ {4: } │ {4: } |
+ {4: } │ {4: } |
+ {4: } │ {4: } |
+ {4: } │ {4: } |
+ {1:~ }│{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ command('windo :set nocursorline nocursorcolumn')
+ feed('0')
+ feed('40l')
+ screen:expect([[
+ kk ll mm nn oo pp qq│ bb cc dd ee ff gg hh ii jj kk ll mm n^n|
+ │ |
+ │ |
+ │ |
+ │ |
+ {1:~ }│{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ end)
+end)
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index 6620c9acef..9244ca0974 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -9,6 +9,7 @@ local clear = helpers.clear
local exc_exec = helpers.exc_exec
local eval = helpers.eval
local eq = helpers.eq
+local ok = helpers.ok
local funcs = helpers.funcs
local insert = helpers.insert
local iswin = helpers.iswin
@@ -17,6 +18,7 @@ local mkdir = helpers.mkdir
local rmdir = helpers.rmdir
local alter_slashes = helpers.alter_slashes
local tbl_contains = helpers.tbl_contains
+local expect_exit = helpers.expect_exit
describe('startup defaults', function()
describe(':filetype', function()
@@ -163,7 +165,7 @@ describe('startup defaults', function()
end)
it("'shadafile' ('viminfofile')", function()
- local env = {XDG_DATA_HOME='Xtest-userdata', XDG_CONFIG_HOME='Xtest-userconfig'}
+ local env = {XDG_DATA_HOME='Xtest-userdata', XDG_STATE_HOME='Xtest-userstate', XDG_CONFIG_HOME='Xtest-userconfig'}
clear{args={}, args_rm={'-i'}, env=env}
-- Default 'shadafile' is empty.
-- This means use the default location. :help shada-file-name
@@ -174,11 +176,11 @@ describe('startup defaults', function()
command('write')
local f = eval('fnamemodify(@%,":p")')
assert(string.len(f) > 3)
- command('qall')
+ expect_exit(command, 'qall')
clear{args={}, args_rm={'-i'}, env=env}
eq({ f }, eval('v:oldfiles'))
os.remove('Xtest-foo')
- rmdir('Xtest-userdata')
+ rmdir('Xtest-userstate')
-- Handles viminfo/viminfofile as alias for shada/shadafile.
eq('\n shadafile=', eval('execute("set shadafile?")'))
@@ -206,7 +208,7 @@ describe('startup defaults', function()
describe('$NVIM_LOG_FILE', function()
local xdgdir = 'Xtest-startup-xdg-logpath'
- local xdgcachedir = xdgdir..'/nvim'
+ local xdgstatedir = iswin() and xdgdir..'/nvim-data' or xdgdir..'/nvim'
after_each(function()
os.remove('Xtest-logpath')
rmdir(xdgdir)
@@ -218,26 +220,26 @@ describe('startup defaults', function()
}})
eq('Xtest-logpath', eval('$NVIM_LOG_FILE'))
end)
- it('defaults to stdpath("cache")/log if empty', function()
- eq(true, mkdir(xdgdir) and mkdir(xdgcachedir))
+ it('defaults to stdpath("log")/log if empty', function()
+ eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
clear({env={
- XDG_CACHE_HOME=xdgdir,
+ XDG_STATE_HOME=xdgdir,
NVIM_LOG_FILE='', -- Empty is invalid.
}})
- eq(xdgcachedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
+ eq(xdgstatedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
end)
- it('defaults to stdpath("cache")/log if invalid', function()
- eq(true, mkdir(xdgdir) and mkdir(xdgcachedir))
+ it('defaults to stdpath("log")/log if invalid', function()
+ eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
clear({env={
- XDG_CACHE_HOME=xdgdir,
+ XDG_STATE_HOME=xdgdir,
NVIM_LOG_FILE='.', -- Any directory is invalid.
}})
- eq(xdgcachedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
+ eq(xdgstatedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
end)
end)
end)
-describe('XDG-based defaults', function()
+describe('XDG defaults', function()
-- Need separate describe() blocks to not run clear() twice.
-- Do not put before_each() here for the same reasons.
@@ -264,6 +266,7 @@ describe('XDG-based defaults', function()
XDG_CONFIG_HOME=nil,
XDG_DATA_HOME=nil,
XDG_CACHE_HOME=nil,
+ XDG_STATE_HOME=nil,
XDG_RUNTIME_DIR=nil,
XDG_CONFIG_DIRS=nil,
XDG_DATA_DIRS=nil,
@@ -280,6 +283,7 @@ describe('XDG-based defaults', function()
eq('.', meths.get_option('viewdir'))
eq('.', meths.get_option('directory'))
eq('.', meths.get_option('undodir'))
+ ok((funcs.tempname()):len() > 4)
end)
end)
@@ -293,6 +297,7 @@ describe('XDG-based defaults', function()
local env_sep = iswin() and ';' or ':'
local data_dir = iswin() and 'nvim-data' or 'nvim'
+ local state_dir = iswin() and 'nvim-data' or 'nvim'
local root_path = iswin() and 'C:' or ''
describe('with too long XDG variables', function()
@@ -303,6 +308,8 @@ describe('XDG-based defaults', function()
.. env_sep.. root_path .. ('/b'):rep(2048)
.. (env_sep .. root_path .. '/c'):rep(512)),
XDG_DATA_HOME=(root_path .. ('/X'):rep(4096)),
+ XDG_RUNTIME_DIR=(root_path .. ('/X'):rep(4096)),
+ XDG_STATE_HOME=(root_path .. ('/X'):rep(4096)),
XDG_DATA_DIRS=(root_path .. ('/A'):rep(2048)
.. env_sep .. root_path .. ('/B'):rep(2048)
.. (env_sep .. root_path .. '/C'):rep(512)),
@@ -355,13 +362,13 @@ describe('XDG-based defaults', function()
.. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after'
.. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after'
):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. data_dir .. '/backup//',
+ eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. state_dir .. '/backup//',
(meths.get_option('backupdir'):gsub('\\', '/')))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/swap//',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/swap//',
(meths.get_option('directory')):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/undo//',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/undo//',
(meths.get_option('undodir')):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view//',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/view//',
(meths.get_option('viewdir')):gsub('\\', '/'))
end)
end)
@@ -372,6 +379,8 @@ describe('XDG-based defaults', function()
XDG_CONFIG_HOME='$XDG_DATA_HOME',
XDG_CONFIG_DIRS='$XDG_DATA_DIRS',
XDG_DATA_HOME='$XDG_CONFIG_HOME',
+ XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR',
+ XDG_STATE_HOME='$XDG_CONFIG_HOME',
XDG_DATA_DIRS='$XDG_CONFIG_DIRS',
}})
end)
@@ -405,13 +414,13 @@ describe('XDG-based defaults', function()
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'),
+ eq(('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
meths.get_option('backupdir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
meths.get_option('directory'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
meths.get_option('undodir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
meths.get_option('viewdir'):gsub('\\', '/'))
meths.command('set all&')
eq(('$XDG_DATA_HOME/nvim'
@@ -425,14 +434,15 @@ describe('XDG-based defaults', function()
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
):gsub('\\', '/'), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'),
+ eq(('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
meths.get_option('backupdir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
meths.get_option('directory'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
meths.get_option('undodir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'),
+ eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
meths.get_option('viewdir'):gsub('\\', '/'))
+ eq(nil, (funcs.tempname()):match('XDG_RUNTIME_DIR'))
end)
end)
@@ -442,6 +452,7 @@ describe('XDG-based defaults', function()
XDG_CONFIG_HOME=', , ,',
XDG_CONFIG_DIRS=',-,-,' .. env_sep .. '-,-,-',
XDG_DATA_HOME=',=,=,',
+ XDG_STATE_HOME=',=,=,',
XDG_DATA_DIRS=',≡,≡,' .. env_sep .. '≡,≡,≡',
}})
end)
@@ -484,13 +495,13 @@ describe('XDG-based defaults', function()
.. ',\\,-\\,-\\,' .. path_sep ..'nvim' .. path_sep ..'after'
.. ',\\, \\, \\,' .. path_sep ..'nvim' .. path_sep ..'after'
), meths.get_option('runtimepath'))
- eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup' .. (path_sep):rep(2),
+ eq('.,\\,=\\,=\\,' .. path_sep .. state_dir .. '' .. path_sep ..'backup' .. (path_sep):rep(2),
meths.get_option('backupdir'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2),
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2),
meths.get_option('directory'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'undo' .. (path_sep):rep(2),
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'undo' .. (path_sep):rep(2),
meths.get_option('undodir'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view' .. (path_sep):rep(2),
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'view' .. (path_sep):rep(2),
meths.get_option('viewdir'))
end)
end)
@@ -499,8 +510,9 @@ end)
describe('stdpath()', function()
-- Windows appends 'nvim-data' instead of just 'nvim' to prevent collisions
- -- due to XDG_CONFIG_HOME and XDG_DATA_HOME being the same.
+ -- due to XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_STATE_HOME being the same.
local datadir = iswin() and 'nvim-data' or 'nvim'
+ local statedir = iswin() and 'nvim-data' or 'nvim'
local env_sep = iswin() and ';' or ':'
it('acceptance', function()
@@ -509,8 +521,10 @@ describe('stdpath()', function()
eq('nvim', funcs.fnamemodify(funcs.stdpath('cache'), ':t'))
eq('nvim', funcs.fnamemodify(funcs.stdpath('config'), ':t'))
eq(datadir, funcs.fnamemodify(funcs.stdpath('data'), ':t'))
+ eq(statedir, funcs.fnamemodify(funcs.stdpath('state'), ':t'))
eq('table', type(funcs.stdpath('config_dirs')))
eq('table', type(funcs.stdpath('data_dirs')))
+ eq('string', type(funcs.stdpath('run')))
assert_alive() -- Check for crash. #8393
end)
@@ -582,6 +596,39 @@ describe('stdpath()', function()
end)
end)
+ describe('with "state"' , function ()
+ it('knows XDG_STATE_HOME', function()
+ clear({env={
+ XDG_STATE_HOME=alter_slashes('/home/docwhat/.local'),
+ }})
+ eq(alter_slashes('/home/docwhat/.local/'..statedir), funcs.stdpath('state'))
+ end)
+
+ it('handles changes during runtime', function()
+ clear({env={
+ XDG_STATE_HOME=alter_slashes('/home/original'),
+ }})
+ eq(alter_slashes('/home/original/'..statedir), funcs.stdpath('state'))
+ command("let $XDG_STATE_HOME='"..alter_slashes('/home/new').."'")
+ eq(alter_slashes('/home/new/'..statedir), funcs.stdpath('state'))
+ end)
+
+ it("doesn't expand $VARIABLES", function()
+ clear({env={
+ XDG_STATE_HOME='$VARIABLES',
+ VARIABLES='this-should-not-happen',
+ }})
+ eq(alter_slashes('$VARIABLES/'..statedir), funcs.stdpath('state'))
+ end)
+
+ it("doesn't expand ~/", function()
+ clear({env={
+ XDG_STATE_HOME=alter_slashes('~/frobnitz'),
+ }})
+ eq(alter_slashes('~/frobnitz/'..statedir), funcs.stdpath('state'))
+ end)
+ end)
+
describe('with "cache"' , function ()
it('knows XDG_CACHE_HOME', function()
clear({env={
diff --git a/test/functional/options/keymap_spec.lua b/test/functional/options/keymap_spec.lua
index 52a714f7a8..a814c35a39 100644
--- a/test/functional/options/keymap_spec.lua
+++ b/test/functional/options/keymap_spec.lua
@@ -120,9 +120,9 @@ describe("'keymap' / :lmap", function()
it("Can be toggled with <C-^> in insert mode", function()
feed('i<C-^>l<C-^>l<esc>')
expect('lalllaaa')
- eq(eval('&iminsert'), 1)
+ eq(1, eval('&iminsert'))
feed('i<C-^><esc>')
- eq(eval('&iminsert'), 0)
+ eq(0, eval('&iminsert'))
end)
end)
describe("'imsearch' option", function()
@@ -136,36 +136,36 @@ describe("'keymap' / :lmap", function()
expect('aaa')
end)
it("Can be toggled with C-^", function()
- eq(eval('&imsearch'), 1)
+ eq(1, eval('&imsearch'))
feed('/<C-^>lll<cr>3x')
expect('aaa')
- eq(eval('&imsearch'), 0)
+ eq(0, eval('&imsearch'))
feed('u0/<C-^>lll<cr>3x')
expect('lll')
- eq(eval('&imsearch'), 1)
+ eq(1, eval('&imsearch'))
end)
it("can follow 'iminsert'", function()
command('set imsearch=-1')
feed('/lll<cr>3x')
expect('lll')
- eq(eval('&imsearch'), -1)
- eq(eval('&iminsert'), 1)
+ eq(-1, eval('&imsearch'))
+ eq(1, eval('&iminsert'))
feed('u/<C-^>lll<cr>3x')
expect('aaa')
- eq(eval('&imsearch'), -1)
- eq(eval('&iminsert'), 0)
+ eq(-1, eval('&imsearch'))
+ eq(0, eval('&iminsert'))
end)
end)
it(":lmap not applied to macros", function()
command("call setreg('a', 'il')")
feed('@a')
expect('llllaaa')
- eq(call('getreg', 'a'), 'il')
+ eq('il', call('getreg', 'a'))
end)
it(":lmap applied to macro recording", function()
feed('qail<esc>q@a')
expect('aalllaaa')
- eq(call('getreg', 'a'), 'ia')
+ eq('ia', call('getreg', 'a'))
end)
it(":lmap not applied to mappings", function()
command('imap t l')
diff --git a/test/functional/options/mousescroll_spec.lua b/test/functional/options/mousescroll_spec.lua
new file mode 100644
index 0000000000..2c9b2d175e
--- /dev/null
+++ b/test/functional/options/mousescroll_spec.lua
@@ -0,0 +1,151 @@
+local helpers = require('test.functional.helpers')(after_each)
+local command = helpers.command
+local clear = helpers.clear
+local eval = helpers.eval
+local eq = helpers.eq
+local exc_exec = helpers.exc_exec
+local feed = helpers.feed
+
+local scroll = function(direction)
+ return helpers.request('nvim_input_mouse', 'wheel', direction, '', 0, 2, 2)
+end
+
+local screenrow = function()
+ return helpers.call('screenrow')
+end
+
+local screencol = function()
+ return helpers.call('screencol')
+end
+
+describe("'mousescroll'", function()
+ local invalid_arg = 'Vim(set):E474: Invalid argument: mousescroll='
+ local digit_expected = 'Vim(set):E548: digit expected: mousescroll='
+
+ local function should_fail(val, errorstr)
+ eq(errorstr..val, exc_exec('set mousescroll='..val))
+ end
+
+ local function should_succeed(val)
+ eq(0, exc_exec('set mousescroll='..val))
+ end
+
+ before_each(function()
+ clear()
+ command('set nowrap lines=20 columns=20 virtualedit=all')
+ feed('100o<Esc>50G10|')
+ end)
+
+ it('handles invalid values', function()
+ should_fail('', invalid_arg) -- empty string
+ should_fail('foo:123', invalid_arg) -- unknown direction
+ should_fail('hor:1,hor:2', invalid_arg) -- duplicate direction
+ should_fail('ver:99999999999999999999', invalid_arg) -- integer overflow
+ should_fail('ver:bar', digit_expected) -- expected digit
+ should_fail('ver:-1', digit_expected) -- negative count
+ end)
+
+ it('handles valid values', function()
+ should_succeed('hor:1,ver:1') -- both directions set
+ should_succeed('hor:1') -- only horizontal
+ should_succeed('ver:1') -- only vertical
+ should_succeed('hor:0,ver:0') -- zero
+ should_succeed('hor:2147483647') -- large count
+ end)
+
+ it('default set correctly', function()
+ eq('ver:3,hor:6', eval('&mousescroll'))
+
+ eq(10, screenrow())
+ scroll('up')
+ eq(13, screenrow())
+ scroll('down')
+ eq(10, screenrow())
+
+ eq(10, screencol())
+ scroll('right')
+ eq(4, screencol())
+ scroll('left')
+ eq(10, screencol())
+ end)
+
+ it('vertical scrolling falls back to default value', function()
+ command('set mousescroll=hor:1')
+ eq(10, screenrow())
+ scroll('up')
+ eq(13, screenrow())
+ end)
+
+ it('horizontal scrolling falls back to default value', function()
+ command('set mousescroll=ver:1')
+ eq(10, screencol())
+ scroll('right')
+ eq(4, screencol())
+ end)
+
+ it('count of zero disables mouse scrolling', function()
+ command('set mousescroll=hor:0,ver:0')
+
+ eq(10, screenrow())
+ scroll('up')
+ eq(10, screenrow())
+ scroll('down')
+ eq(10, screenrow())
+
+ eq(10, screencol())
+ scroll('right')
+ eq(10, screencol())
+ scroll('left')
+ eq(10, screencol())
+ end)
+
+ local test_vertical_scrolling = function()
+ eq(10, screenrow())
+
+ command('set mousescroll=ver:1')
+ scroll('up')
+ eq(11, screenrow())
+
+ command('set mousescroll=ver:2')
+ scroll('down')
+ eq(9, screenrow())
+
+ command('set mousescroll=ver:5')
+ scroll('up')
+ eq(14, screenrow())
+ end
+
+ it('controls vertical scrolling in normal mode', function()
+ test_vertical_scrolling()
+ end)
+
+ it('controls vertical scrolling in insert mode', function()
+ feed('i')
+ test_vertical_scrolling()
+ end)
+
+ local test_horizontal_scrolling = function()
+ eq(10, screencol())
+
+ command('set mousescroll=hor:1')
+ scroll('right')
+ eq(9, screencol())
+
+ command('set mousescroll=hor:3')
+ scroll('right')
+ eq(6, screencol())
+
+ command('set mousescroll=hor:2')
+ scroll('left')
+ eq(8, screencol())
+ end
+
+ it('controls horizontal scrolling in normal mode', function()
+ test_horizontal_scrolling()
+ end)
+
+ it('controls horizontal scrolling in insert mode', function()
+ feed('i')
+ test_horizontal_scrolling()
+ end)
+end)
diff --git a/test/functional/options/num_options_spec.lua b/test/functional/options/num_options_spec.lua
index 4754c14f5b..f343e2da75 100644
--- a/test/functional/options/num_options_spec.lua
+++ b/test/functional/options/num_options_spec.lua
@@ -54,7 +54,7 @@ describe(':set validation', function()
should_fail('iminsert', 3, 'E474')
should_fail('imsearch', 3, 'E474')
should_fail('titlelen', -1, 'E487')
- should_fail('cmdheight', 0, 'E487')
+ should_fail('cmdheight', -1, 'E487')
should_fail('updatecount', -1, 'E487')
should_fail('textwidth', -1, 'E487')
should_fail('tabstop', 0, 'E487')
diff --git a/test/functional/options/pastetoggle_spec.lua b/test/functional/options/pastetoggle_spec.lua
index a1f86f73ff..40c14fa187 100644
--- a/test/functional/options/pastetoggle_spec.lua
+++ b/test/functional/options/pastetoggle_spec.lua
@@ -4,16 +4,14 @@ local clear = helpers.clear
local feed = helpers.feed
local command = helpers.command
local eq = helpers.eq
+local expect = helpers.expect
local eval = helpers.eval
+local insert = helpers.insert
+local meths = helpers.meths
local sleep = helpers.sleep
-local expect = helpers.expect
describe("'pastetoggle' option", function()
- before_each(function()
- clear()
- command('set nopaste')
- end)
-
+ before_each(clear)
it("toggles 'paste'", function()
command('set pastetoggle=a')
eq(0, eval('&paste'))
@@ -22,19 +20,71 @@ describe("'pastetoggle' option", function()
feed('j')
eq(1, eval('&paste'))
end)
+ describe("multiple key 'pastetoggle'", function()
+ before_each(function()
+ eq(0, eval('&paste'))
+ command('set timeoutlen=1 ttimeoutlen=10000')
+ end)
+ it('is waited for when chars are typed', function()
+ local pastetoggle = 'lllll'
+ command('set pastetoggle=' .. pastetoggle)
+ feed(pastetoggle:sub(0, 2))
+ -- sleep() for long enough that vgetorpeek() is gotten into, but short
+ -- enough that ttimeoutlen is not reached.
+ sleep(200)
+ feed(pastetoggle:sub(3, -1))
+ -- Need another key so that the vgetorpeek() function returns.
+ feed('j')
+ eq(1, eval('&paste'))
+ end)
+ it('is not waited for when there are no typed chars after mapped chars', function()
+ command('set pastetoggle=abc')
+ command('imap d a')
+ meths.feedkeys('id', 't', true)
+ -- sleep() for long enough that vgetorpeek() is gotten into, but short
+ -- enough that ttimeoutlen is not reached.
+ sleep(200)
+ feed('bc')
+ -- Need another key so that the vgetorpeek() function returns.
+ feed('j')
+ -- 'ttimeoutlen' should NOT apply
+ eq(0, eval('&paste'))
+ end)
- it('does not wait for timeout', function()
- command('set pastetoggle=abc')
- command('set ttimeoutlen=9999999')
- eq(0, eval('&paste'))
- -- n.b. need <esc> to return from vgetorpeek()
- feed('abc<esc>')
- eq(1, eval('&paste'))
- feed('ab')
- sleep(10)
- feed('c<esc>')
- expect('bc')
- eq(1, eval('&paste'))
+ it('is waited for when there are typed chars after mapped chars', function()
+ command('set pastetoggle=abc')
+ command('imap d a')
+ meths.feedkeys('idb', 't', true)
+ -- sleep() for long enough that vgetorpeek() is gotten into, but short
+ -- enough that ttimeoutlen is not reached.
+ sleep(200)
+ feed('c')
+ -- Need another key so that the vgetorpeek() function returns.
+ feed('j')
+ -- 'ttimeoutlen' should apply
+ eq(1, eval('&paste'))
+ end)
+
+ it('is waited for when there are typed chars after noremapped chars', function()
+ command('set pastetoggle=abc')
+ command('inoremap d a')
+ meths.feedkeys('idb', 't', true)
+ -- sleep() for long enough that vgetorpeek() is gotten into, but short
+ -- enough that ttimeoutlen is not reached.
+ sleep(200)
+ feed('c')
+ -- Need another key so that the vgetorpeek() function returns.
+ feed('j')
+ -- 'ttimeoutlen' should apply
+ eq(1, eval('&paste'))
+ end)
+ end)
+ it('does not interfere with character-find', function()
+ insert('foo,bar')
+ feed('0')
+ command('set pastetoggle=,sp')
+ feed('dt,')
+ expect(',bar')
end)
end)