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.lua3
-rw-r--r--test/functional/options/defaults_spec.lua706
-rw-r--r--test/functional/options/fillchars_spec.lua73
-rw-r--r--test/functional/options/keymap_spec.lua233
-rw-r--r--test/functional/options/num_options_spec.lua110
-rw-r--r--test/functional/options/pastetoggle_spec.lua40
-rw-r--r--test/functional/options/shortmess_spec.lua97
-rw-r--r--test/functional/options/tabstop_spec.lua23
8 files changed, 1227 insertions, 58 deletions
diff --git a/test/functional/options/autochdir_spec.lua b/test/functional/options/autochdir_spec.lua
index 0e293761ad..2fce0a5ed9 100644
--- a/test/functional/options/autochdir_spec.lua
+++ b/test/functional/options/autochdir_spec.lua
@@ -10,9 +10,10 @@ describe("'autochdir'", function()
-- By default 'autochdir' is off, thus getcwd() returns the repo root.
clear(targetdir..'/tty-test.c')
local rootdir = 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(rootdir..'/'..targetdir, getcwd())
+ eq(helpers.iswin() and expected:gsub('/', '\\') or expected, getcwd())
end)
end)
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index a36939b0bd..f6f3f02f45 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -1,80 +1,712 @@
local helpers = require('test.functional.helpers')(after_each)
+
local Screen = require('test.functional.ui.screen')
-local eval, eq = helpers.eval, helpers.eq
-local execute = helpers.execute
-
-local function init_session(...)
- local args = { helpers.nvim_prog, '-i', 'NONE', '--embed',
- '--cmd', 'set shortmess+=I background=light noswapfile noautoindent',
- '--cmd', 'set laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
- }
- for _, v in ipairs({...}) do
- table.insert(args, v)
- end
- helpers.set_session(helpers.spawn(args))
-end
+
+local meths = helpers.meths
+local command = helpers.command
+local clear = helpers.clear
+local exc_exec = helpers.exc_exec
+local eval = helpers.eval
+local eq = helpers.eq
+local funcs = helpers.funcs
+local insert = helpers.insert
+local iswin = helpers.iswin
+local neq = helpers.neq
+local mkdir = helpers.mkdir
+local rmdir = helpers.rmdir
+local alter_slashes = helpers.alter_slashes
describe('startup defaults', function()
describe(':filetype', function()
local function expect_filetype(expected)
- local screen = Screen.new(48, 4)
+ local screen = Screen.new(50, 4)
screen:attach()
- execute('filetype')
+ command('filetype')
screen:expect([[
- ^ |
- ~ |
- ~ |
+ ^ |
+ ~ |
+ ~ |
]]..expected
)
end
- it('enabled by `-u NORC`', function()
- init_session('-u', 'NORC')
+ it('all ON after `-u NORC`', function()
+ clear('-u', 'NORC')
expect_filetype(
- 'filetype detection:ON plugin:ON indent:ON |')
+ 'filetype detection:ON plugin:ON indent:ON |')
end)
- it('disabled by `-u NONE`', function()
- init_session('-u', 'NONE')
+ it('all ON after `:syntax …` #7765', function()
+ clear('-u', 'NORC', '--cmd', 'syntax on')
expect_filetype(
- 'filetype detection:OFF plugin:OFF indent:OFF |')
+ 'filetype detection:ON plugin:ON indent:ON |')
+ clear('-u', 'NORC', '--cmd', 'syntax off')
+ expect_filetype(
+ 'filetype detection:ON plugin:ON indent:ON |')
end)
- it('overridden by early `filetype on`', function()
- init_session('-u', 'NORC', '--cmd', 'filetype on')
+ it('all OFF after `-u NONE`', function()
+ clear('-u', 'NONE')
expect_filetype(
- 'filetype detection:ON plugin:OFF indent:OFF |')
+ 'filetype detection:OFF plugin:OFF indent:OFF |')
end)
- it('overridden by early `filetype plugin on`', function()
- init_session('-u', 'NORC', '--cmd', 'filetype plugin on')
+ it('explicit OFF stays OFF', function()
+ clear('-u', 'NORC', '--cmd',
+ 'syntax off | filetype off | filetype plugin indent off')
+ expect_filetype(
+ 'filetype detection:OFF plugin:OFF indent:OFF |')
+ clear('-u', 'NORC', '--cmd', 'syntax off | filetype plugin indent off')
+ expect_filetype(
+ 'filetype detection:ON plugin:OFF indent:OFF |')
+ clear('-u', 'NORC', '--cmd', 'filetype indent off')
+ expect_filetype(
+ 'filetype detection:ON plugin:ON indent:OFF |')
+ clear('-u', 'NORC', '--cmd', 'syntax off | filetype off')
expect_filetype(
- 'filetype detection:ON plugin:ON indent:OFF |')
+ 'filetype detection:OFF plugin:(on) indent:(on) |')
+ -- Swap the order.
+ clear('-u', 'NORC', '--cmd', 'filetype off | syntax off')
+ expect_filetype(
+ 'filetype detection:OFF plugin:(on) indent:(on) |')
end)
- it('overridden by early `filetype indent on`', function()
- init_session('-u', 'NORC', '--cmd', 'filetype indent on')
+ it('all ON after early `:filetype … on`', function()
+ -- `:filetype … on` should not change the defaults. #7765
+ -- Only an explicit `:filetype … off` sets OFF.
+
+ clear('-u', 'NORC', '--cmd', 'filetype on')
+ expect_filetype(
+ 'filetype detection:ON plugin:ON indent:ON |')
+ clear('-u', 'NORC', '--cmd', 'filetype plugin on')
+ expect_filetype(
+ 'filetype detection:ON plugin:ON indent:ON |')
+ clear('-u', 'NORC', '--cmd', 'filetype indent on')
expect_filetype(
- 'filetype detection:ON plugin:OFF indent:ON |')
+ 'filetype detection:ON plugin:ON indent:ON |')
+ end)
+
+ it('late `:filetype … off` stays OFF', function()
+ clear('-u', 'NORC', '-c', 'filetype off')
+ expect_filetype(
+ 'filetype detection:OFF plugin:(on) indent:(on) |')
+ clear('-u', 'NORC', '-c', 'filetype plugin off')
+ expect_filetype(
+ 'filetype detection:ON plugin:OFF indent:ON |')
+ clear('-u', 'NORC', '-c', 'filetype indent off')
+ expect_filetype(
+ 'filetype detection:ON plugin:ON indent:OFF |')
end)
end)
describe('syntax', function()
it('enabled by `-u NORC`', function()
- init_session('-u', 'NORC')
+ clear('-u', 'NORC')
eq(1, eval('g:syntax_on'))
end)
it('disabled by `-u NONE`', function()
- init_session('-u', 'NONE')
+ clear('-u', 'NONE')
eq(0, eval('exists("g:syntax_on")'))
end)
- it('overridden by early `syntax off`', function()
- init_session('-u', 'NORC', '--cmd', 'syntax off')
+ it('`:syntax off` stays off', function()
+ -- early
+ clear('-u', 'NORC', '--cmd', 'syntax off')
eq(0, eval('exists("g:syntax_on")'))
+ -- late
+ clear('-u', 'NORC', '-c', 'syntax off')
+ eq(0, eval('exists("g:syntax_on")'))
+ end)
+
+ it('":if 0|syntax on|endif" does not affect default #8728', function()
+ clear('-u', 'NORC', '--cmd', ':if 0|syntax on|endif')
+ eq(1, eval('exists("g:syntax_on")'))
+ clear('-u', 'NORC', '--cmd', ':if 0|syntax off|endif')
+ eq(1, eval('exists("g:syntax_on")'))
+ end)
+ end)
+
+ describe("'fillchars'", function()
+ it('vert/fold flags', function()
+ clear()
+ local screen = Screen.new(50, 5)
+ screen:attach()
+ command('set laststatus=0')
+ insert([[
+ 1
+ 2
+ 3
+ 4]])
+ command('normal! ggjzfj')
+ command('vsp')
+ screen:expect([[
+ 1 │1 |
+ ^+-- 2 lines: 2··········│+-- 2 lines: 2·········|
+ 4 │4 |
+ ~ │~ |
+ |
+ ]])
+
+ -- ambiwidth=double defaults to single-byte fillchars.
+ command('set ambiwidth=double')
+ screen:expect([[
+ 1 |1 |
+ ^+-- 2 lines: 2----------|+-- 2 lines: 2---------|
+ 4 |4 |
+ ~ |~ |
+ |
+ ]])
+ end)
+ end)
+
+ describe("'packpath'", function()
+ it('defaults to &runtimepath', function()
+ eq(meths.get_option('runtimepath'), meths.get_option('packpath'))
+ end)
+
+ it('does not follow modifications to runtimepath', function()
+ meths.command('set runtimepath+=foo')
+ neq(meths.get_option('runtimepath'), meths.get_option('packpath'))
+ meths.command('set packpath+=foo')
+ eq(meths.get_option('runtimepath'), meths.get_option('packpath'))
+ end)
+ end)
+
+ it('v:progpath is set to the absolute path', function()
+ eq(eval("fnamemodify(v:progpath, ':p')"), eval('v:progpath'))
+ end)
+
+ describe('$NVIM_LOG_FILE', function()
+ local datasubdir = iswin() and 'nvim-data' or 'nvim'
+ local xdgdir = 'Xtest-startup-xdg-logpath'
+ local xdgdatadir = xdgdir..'/'..datasubdir
+ after_each(function()
+ os.remove('Xtest-logpath')
+ rmdir(xdgdir)
+ end)
+
+ it('is used if expansion succeeds', function()
+ clear({env={
+ NVIM_LOG_FILE='Xtest-logpath',
+ }})
+ eq('Xtest-logpath', eval('$NVIM_LOG_FILE'))
+ end)
+ it('defaults to stdpath("data")/log if empty', function()
+ eq(true, mkdir(xdgdir) and mkdir(xdgdatadir))
+ clear({env={
+ XDG_DATA_HOME=xdgdir,
+ NVIM_LOG_FILE='', -- Empty is invalid.
+ }})
+ -- server_start() calls ELOG, which tickles log_path_init().
+ pcall(command, 'call serverstart(serverlist()[0])')
+
+ eq(xdgdir..'/'..datasubdir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
+ end)
+ it('defaults to stdpath("data")/log if invalid', function()
+ eq(true, mkdir(xdgdir) and mkdir(xdgdatadir))
+ clear({env={
+ XDG_DATA_HOME=xdgdir,
+ NVIM_LOG_FILE='.', -- Any directory is invalid.
+ }})
+ -- server_start() calls ELOG, which tickles log_path_init().
+ pcall(command, 'call serverstart(serverlist()[0])')
+
+ eq(xdgdir..'/'..datasubdir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
+ end)
+ it('defaults to .nvimlog if stdpath("data") is invalid', function()
+ clear({env={
+ XDG_DATA_HOME='Xtest-missing-xdg-dir',
+ NVIM_LOG_FILE='.', -- Any directory is invalid.
+ }})
+ -- server_start() calls ELOG, which tickles log_path_init().
+ pcall(command, 'call serverstart(serverlist()[0])')
+
+ eq('.nvimlog', eval('$NVIM_LOG_FILE'))
+ end)
+ end)
+end)
+
+describe('XDG-based defaults', function()
+ -- Need separate describe() blocks to not run clear() twice.
+ -- Do not put before_each() here for the same reasons.
+
+ describe('with empty/broken environment', function()
+ it('sets correct defaults', function()
+ clear({env={
+ XDG_CONFIG_HOME=nil,
+ XDG_DATA_HOME=nil,
+ XDG_CACHE_HOME=nil,
+ XDG_RUNTIME_DIR=nil,
+ XDG_CONFIG_DIRS=nil,
+ XDG_DATA_DIRS=nil,
+ LOCALAPPDATA=nil,
+ HOMEPATH=nil,
+ HOMEDRIVE=nil,
+ HOME=nil,
+ TEMP=nil,
+ VIMRUNTIME=nil,
+ USER=nil,
+ }})
+
+ eq('.', meths.get_option('backupdir'))
+ eq('.', meths.get_option('viewdir'))
+ eq('.', meths.get_option('directory'))
+ eq('.', meths.get_option('undodir'))
+ end)
+ end)
+
+ -- TODO(jkeyes): tests below fail on win32 because of path separator.
+ if helpers.pending_win32(pending) then return end
+
+ describe('with too long XDG variables', function()
+ before_each(function()
+ clear({env={
+ XDG_CONFIG_HOME=('/x'):rep(4096),
+ XDG_CONFIG_DIRS=(('/a'):rep(2048)
+ .. ':' .. ('/b'):rep(2048)
+ .. (':/c'):rep(512)),
+ XDG_DATA_HOME=('/X'):rep(4096),
+ XDG_DATA_DIRS=(('/A'):rep(2048)
+ .. ':' .. ('/B'):rep(2048)
+ .. (':/C'):rep(512)),
+ }})
+ end)
+
+ it('are correctly set', function()
+ eq((('/x'):rep(4096) .. '/nvim'
+ .. ',' .. ('/a'):rep(2048) .. '/nvim'
+ .. ',' .. ('/b'):rep(2048) .. '/nvim'
+ .. (',' .. '/c/nvim'):rep(512)
+ .. ',' .. ('/X'):rep(4096) .. '/nvim/site'
+ .. ',' .. ('/A'):rep(2048) .. '/nvim/site'
+ .. ',' .. ('/B'):rep(2048) .. '/nvim/site'
+ .. (',' .. '/C/nvim/site'):rep(512)
+ .. ',' .. eval('$VIMRUNTIME')
+ .. (',' .. '/C/nvim/site/after'):rep(512)
+ .. ',' .. ('/B'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. ('/A'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. ('/X'):rep(4096) .. '/nvim/site/after'
+ .. (',' .. '/c/nvim/after'):rep(512)
+ .. ',' .. ('/b'):rep(2048) .. '/nvim/after'
+ .. ',' .. ('/a'):rep(2048) .. '/nvim/after'
+ .. ',' .. ('/x'):rep(4096) .. '/nvim/after'
+ ), meths.get_option('runtimepath'))
+ meths.command('set runtimepath&')
+ meths.command('set backupdir&')
+ meths.command('set directory&')
+ meths.command('set undodir&')
+ meths.command('set viewdir&')
+ eq((('/x'):rep(4096) .. '/nvim'
+ .. ',' .. ('/a'):rep(2048) .. '/nvim'
+ .. ',' .. ('/b'):rep(2048) .. '/nvim'
+ .. (',' .. '/c/nvim'):rep(512)
+ .. ',' .. ('/X'):rep(4096) .. '/nvim/site'
+ .. ',' .. ('/A'):rep(2048) .. '/nvim/site'
+ .. ',' .. ('/B'):rep(2048) .. '/nvim/site'
+ .. (',' .. '/C/nvim/site'):rep(512)
+ .. ',' .. eval('$VIMRUNTIME')
+ .. (',' .. '/C/nvim/site/after'):rep(512)
+ .. ',' .. ('/B'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. ('/A'):rep(2048) .. '/nvim/site/after'
+ .. ',' .. ('/X'):rep(4096) .. '/nvim/site/after'
+ .. (',' .. '/c/nvim/after'):rep(512)
+ .. ',' .. ('/b'):rep(2048) .. '/nvim/after'
+ .. ',' .. ('/a'):rep(2048) .. '/nvim/after'
+ .. ',' .. ('/x'):rep(4096) .. '/nvim/after'
+ ), meths.get_option('runtimepath'))
+ eq('.,' .. ('/X'):rep(4096) .. '/nvim/backup',
+ meths.get_option('backupdir'))
+ eq(('/X'):rep(4096) .. '/nvim/swap//', meths.get_option('directory'))
+ eq(('/X'):rep(4096) .. '/nvim/undo', meths.get_option('undodir'))
+ eq(('/X'):rep(4096) .. '/nvim/view', meths.get_option('viewdir'))
+ end)
+ end)
+
+ describe('with XDG variables that can be expanded', function()
+ before_each(function()
+ clear({env={
+ XDG_CONFIG_HOME='$XDG_DATA_HOME',
+ XDG_CONFIG_DIRS='$XDG_DATA_DIRS',
+ XDG_DATA_HOME='$XDG_CONFIG_HOME',
+ XDG_DATA_DIRS='$XDG_CONFIG_DIRS',
+ }})
+ end)
+
+ it('are not expanded', function()
+ eq(('$XDG_DATA_HOME/nvim'
+ .. ',$XDG_DATA_DIRS/nvim'
+ .. ',$XDG_CONFIG_HOME/nvim/site'
+ .. ',$XDG_CONFIG_DIRS/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',$XDG_CONFIG_DIRS/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/nvim/site/after'
+ .. ',$XDG_DATA_DIRS/nvim/after'
+ .. ',$XDG_DATA_HOME/nvim/after'
+ ), meths.get_option('runtimepath'))
+ meths.command('set runtimepath&')
+ meths.command('set backupdir&')
+ meths.command('set directory&')
+ meths.command('set undodir&')
+ meths.command('set viewdir&')
+ eq(('$XDG_DATA_HOME/nvim'
+ .. ',$XDG_DATA_DIRS/nvim'
+ .. ',$XDG_CONFIG_HOME/nvim/site'
+ .. ',$XDG_CONFIG_DIRS/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',$XDG_CONFIG_DIRS/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/nvim/site/after'
+ .. ',$XDG_DATA_DIRS/nvim/after'
+ .. ',$XDG_DATA_HOME/nvim/after'
+ ), meths.get_option('runtimepath'))
+ eq('.,$XDG_CONFIG_HOME/nvim/backup', meths.get_option('backupdir'))
+ eq('$XDG_CONFIG_HOME/nvim/swap//', meths.get_option('directory'))
+ eq('$XDG_CONFIG_HOME/nvim/undo', meths.get_option('undodir'))
+ eq('$XDG_CONFIG_HOME/nvim/view', meths.get_option('viewdir'))
+ meths.command('set all&')
+ eq(('$XDG_DATA_HOME/nvim'
+ .. ',$XDG_DATA_DIRS/nvim'
+ .. ',$XDG_CONFIG_HOME/nvim/site'
+ .. ',$XDG_CONFIG_DIRS/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',$XDG_CONFIG_DIRS/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/nvim/site/after'
+ .. ',$XDG_DATA_DIRS/nvim/after'
+ .. ',$XDG_DATA_HOME/nvim/after'
+ ), meths.get_option('runtimepath'))
+ eq('.,$XDG_CONFIG_HOME/nvim/backup', meths.get_option('backupdir'))
+ eq('$XDG_CONFIG_HOME/nvim/swap//', meths.get_option('directory'))
+ eq('$XDG_CONFIG_HOME/nvim/undo', meths.get_option('undodir'))
+ eq('$XDG_CONFIG_HOME/nvim/view', meths.get_option('viewdir'))
+ end)
+ end)
+
+ describe('with commas', function()
+ before_each(function()
+ clear({env={
+ XDG_CONFIG_HOME=', , ,',
+ XDG_CONFIG_DIRS=',-,-,:-,-,-',
+ XDG_DATA_HOME=',=,=,',
+ XDG_DATA_DIRS=',≡,≡,:≡,≡,≡',
+ }})
+ end)
+
+ it('are escaped properly', function()
+ eq(('\\, \\, \\,/nvim'
+ .. ',\\,-\\,-\\,/nvim'
+ .. ',-\\,-\\,-/nvim'
+ .. ',\\,=\\,=\\,/nvim/site'
+ .. ',\\,≡\\,≡\\,/nvim/site'
+ .. ',≡\\,≡\\,≡/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',≡\\,≡\\,≡/nvim/site/after'
+ .. ',\\,≡\\,≡\\,/nvim/site/after'
+ .. ',\\,=\\,=\\,/nvim/site/after'
+ .. ',-\\,-\\,-/nvim/after'
+ .. ',\\,-\\,-\\,/nvim/after'
+ .. ',\\, \\, \\,/nvim/after'
+ ), meths.get_option('runtimepath'))
+ meths.command('set runtimepath&')
+ meths.command('set backupdir&')
+ meths.command('set directory&')
+ meths.command('set undodir&')
+ meths.command('set viewdir&')
+ eq(('\\, \\, \\,/nvim'
+ .. ',\\,-\\,-\\,/nvim'
+ .. ',-\\,-\\,-/nvim'
+ .. ',\\,=\\,=\\,/nvim/site'
+ .. ',\\,≡\\,≡\\,/nvim/site'
+ .. ',≡\\,≡\\,≡/nvim/site'
+ .. ',' .. eval('$VIMRUNTIME')
+ .. ',≡\\,≡\\,≡/nvim/site/after'
+ .. ',\\,≡\\,≡\\,/nvim/site/after'
+ .. ',\\,=\\,=\\,/nvim/site/after'
+ .. ',-\\,-\\,-/nvim/after'
+ .. ',\\,-\\,-\\,/nvim/after'
+ .. ',\\, \\, \\,/nvim/after'
+ ), meths.get_option('runtimepath'))
+ eq('.,\\,=\\,=\\,/nvim/backup', meths.get_option('backupdir'))
+ eq('\\,=\\,=\\,/nvim/swap//', meths.get_option('directory'))
+ eq('\\,=\\,=\\,/nvim/undo', meths.get_option('undodir'))
+ eq('\\,=\\,=\\,/nvim/view', meths.get_option('viewdir'))
end)
end)
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.
+ local datadir = iswin() and 'nvim-data' or 'nvim'
+
+ it('acceptance', function()
+ clear() -- Do not explicitly set any env vars.
+
+ 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('table', type(funcs.stdpath('config_dirs')))
+ eq('table', type(funcs.stdpath('data_dirs')))
+ -- Check for crash. #8393
+ eq(2, eval('1+1'))
+ end)
+
+ context('returns a String', function()
+
+ describe('with "config"' , function ()
+ it('knows XDG_CONFIG_HOME', function()
+ clear({env={
+ XDG_CONFIG_HOME=alter_slashes('/home/docwhat/.config'),
+ }})
+ eq(alter_slashes('/home/docwhat/.config/nvim'), funcs.stdpath('config'))
+ end)
+
+ it('handles changes during runtime', function()
+ clear({env={
+ XDG_CONFIG_HOME=alter_slashes('/home/original'),
+ }})
+ eq(alter_slashes('/home/original/nvim'), funcs.stdpath('config'))
+ command("let $XDG_CONFIG_HOME='"..alter_slashes('/home/new').."'")
+ eq(alter_slashes('/home/new/nvim'), funcs.stdpath('config'))
+ end)
+
+ it("doesn't expand $VARIABLES", function()
+ clear({env={
+ XDG_CONFIG_HOME='$VARIABLES',
+ VARIABLES='this-should-not-happen',
+ }})
+ eq(alter_slashes('$VARIABLES/nvim'), funcs.stdpath('config'))
+ end)
+
+ it("doesn't expand ~/", function()
+ clear({env={
+ XDG_CONFIG_HOME=alter_slashes('~/frobnitz'),
+ }})
+ eq(alter_slashes('~/frobnitz/nvim'), funcs.stdpath('config'))
+ end)
+ end)
+
+ describe('with "data"' , function ()
+ it('knows XDG_DATA_HOME', function()
+ clear({env={
+ XDG_DATA_HOME=alter_slashes('/home/docwhat/.local'),
+ }})
+ eq(alter_slashes('/home/docwhat/.local/'..datadir), funcs.stdpath('data'))
+ end)
+
+ it('handles changes during runtime', function()
+ clear({env={
+ XDG_DATA_HOME=alter_slashes('/home/original'),
+ }})
+ eq(alter_slashes('/home/original/'..datadir), funcs.stdpath('data'))
+ command("let $XDG_DATA_HOME='"..alter_slashes('/home/new').."'")
+ eq(alter_slashes('/home/new/'..datadir), funcs.stdpath('data'))
+ end)
+
+ it("doesn't expand $VARIABLES", function()
+ clear({env={
+ XDG_DATA_HOME='$VARIABLES',
+ VARIABLES='this-should-not-happen',
+ }})
+ eq(alter_slashes('$VARIABLES/'..datadir), funcs.stdpath('data'))
+ end)
+
+ it("doesn't expand ~/", function()
+ clear({env={
+ XDG_DATA_HOME=alter_slashes('~/frobnitz'),
+ }})
+ eq(alter_slashes('~/frobnitz/'..datadir), funcs.stdpath('data'))
+ end)
+ end)
+
+ describe('with "cache"' , function ()
+ it('knows XDG_CACHE_HOME', function()
+ clear({env={
+ XDG_CACHE_HOME=alter_slashes('/home/docwhat/.cache'),
+ }})
+ eq(alter_slashes('/home/docwhat/.cache/nvim'), funcs.stdpath('cache'))
+ end)
+
+ it('handles changes during runtime', function()
+ clear({env={
+ XDG_CACHE_HOME=alter_slashes('/home/original'),
+ }})
+ eq(alter_slashes('/home/original/nvim'), funcs.stdpath('cache'))
+ command("let $XDG_CACHE_HOME='"..alter_slashes('/home/new').."'")
+ eq(alter_slashes('/home/new/nvim'), funcs.stdpath('cache'))
+ end)
+
+ it("doesn't expand $VARIABLES", function()
+ clear({env={
+ XDG_CACHE_HOME='$VARIABLES',
+ VARIABLES='this-should-not-happen',
+ }})
+ eq(alter_slashes('$VARIABLES/nvim'), funcs.stdpath('cache'))
+ end)
+
+ it("doesn't expand ~/", function()
+ clear({env={
+ XDG_CACHE_HOME=alter_slashes('~/frobnitz'),
+ }})
+ eq(alter_slashes('~/frobnitz/nvim'), funcs.stdpath('cache'))
+ end)
+ end)
+ end)
+
+ context('returns a List', function()
+ -- Some OS specific variables the system would have set.
+ local function base_env()
+ if iswin() then
+ return {
+ HOME='C:\\Users\\docwhat', -- technically, is not a usual PATH
+ HOMEDRIVE='C:',
+ HOMEPATH='\\Users\\docwhat',
+ LOCALAPPDATA='C:\\Users\\docwhat\\AppData\\Local',
+ TEMP='C:\\Users\\docwhat\\AppData\\Local\\Temp',
+ TMPDIR='C:\\Users\\docwhat\\AppData\\Local\\Temp',
+ TMP='C:\\Users\\docwhat\\AppData\\Local\\Temp',
+ }
+ else
+ return {
+ HOME='/home/docwhat',
+ HOMEDRIVE='HOMEDRIVE-should-be-ignored',
+ HOMEPATH='HOMEPATH-should-be-ignored',
+ LOCALAPPDATA='LOCALAPPDATA-should-be-ignored',
+ TEMP='TEMP-should-be-ignored',
+ TMPDIR='TMPDIR-should-be-ignored',
+ TMP='TMP-should-be-ignored',
+ }
+ end
+ end
+
+ local function set_paths_via_system(var_name, paths)
+ local env = base_env()
+ env[var_name] = table.concat(paths, ':')
+ clear({env=env})
+ end
+
+ local function set_paths_at_runtime(var_name, paths)
+ clear({env=base_env()})
+ meths.set_var('env_val', table.concat(paths, ':'))
+ command(('let $%s=g:env_val'):format(var_name))
+ end
+
+ local function behaves_like_dir_list_env(msg, stdpath_arg, env_var_name, paths, expected_paths)
+ describe(msg, function()
+ it('set via system', function()
+ set_paths_via_system(env_var_name, paths)
+ eq(expected_paths, funcs.stdpath(stdpath_arg))
+ end)
+
+ it('set at runtime', function()
+ set_paths_at_runtime(env_var_name, paths)
+ eq(expected_paths, funcs.stdpath(stdpath_arg))
+ end)
+ end)
+ end
+
+ describe('with "config_dirs"' , function ()
+ behaves_like_dir_list_env(
+ 'handles XDG_CONFIG_DIRS with one path',
+ 'config_dirs', 'XDG_CONFIG_DIRS',
+ {
+ alter_slashes('/home/docwhat/.config')
+ },
+ {
+ alter_slashes('/home/docwhat/.config/nvim')
+ })
+
+ behaves_like_dir_list_env(
+ 'handles XDG_CONFIG_DIRS with two paths',
+ 'config_dirs', 'XDG_CONFIG_DIRS',
+ {
+ alter_slashes('/home/docwhat/.config'),
+ alter_slashes('/etc/config')
+ },
+ {
+ alter_slashes('/home/docwhat/.config/nvim'),
+ alter_slashes('/etc/config/nvim')
+ })
+
+ behaves_like_dir_list_env(
+ "doesn't expand $VAR and $IBLES",
+ 'config_dirs', 'XDG_CONFIG_DIRS',
+ { '$HOME', '$TMP' },
+ {
+ alter_slashes('$HOME/nvim'),
+ alter_slashes('$TMP/nvim')
+ })
+
+
+ behaves_like_dir_list_env(
+ "doesn't expand ~/",
+ 'config_dirs', 'XDG_CONFIG_DIRS',
+ {
+ alter_slashes('~/.oldconfig'),
+ alter_slashes('~/.olderconfig')
+ },
+ {
+ alter_slashes('~/.oldconfig/nvim'),
+ alter_slashes('~/.olderconfig/nvim')
+ })
+ end)
+
+ describe('with "data_dirs"' , function ()
+ behaves_like_dir_list_env(
+ 'knows XDG_DATA_DIRS with one path',
+ 'data_dirs', 'XDG_DATA_DIRS',
+ {
+ alter_slashes('/home/docwhat/.data')
+ },
+ {
+ alter_slashes('/home/docwhat/.data/nvim')
+ })
+
+ behaves_like_dir_list_env(
+ 'knows XDG_DATA_DIRS with two paths',
+ 'data_dirs', 'XDG_DATA_DIRS',
+ {
+ alter_slashes('/home/docwhat/.data'),
+ alter_slashes('/etc/local')
+ },
+ {
+ alter_slashes('/home/docwhat/.data/nvim'),
+ alter_slashes('/etc/local/nvim'),
+ })
+
+ behaves_like_dir_list_env(
+ "doesn't expand $VAR and $IBLES",
+ 'data_dirs', 'XDG_DATA_DIRS',
+ { '$HOME', '$TMP' },
+ {
+ alter_slashes('$HOME/nvim'),
+ alter_slashes('$TMP/nvim')
+ })
+
+ behaves_like_dir_list_env(
+ "doesn't expand ~/",
+ 'data_dirs', 'XDG_DATA_DIRS',
+ {
+ alter_slashes('~/.oldconfig'),
+ alter_slashes('~/.olderconfig')
+ },
+ {
+ alter_slashes('~/.oldconfig/nvim'),
+ alter_slashes('~/.olderconfig/nvim'),
+ })
+ end)
+ end)
+
+ describe('errors', function()
+ it('on unknown strings', function()
+ eq('Vim(call):E6100: "capybara" is not a valid stdpath', exc_exec('call stdpath("capybara")'))
+ eq('Vim(call):E6100: "" is not a valid stdpath', exc_exec('call stdpath("")'))
+ eq('Vim(call):E6100: "23" is not a valid stdpath', exc_exec('call stdpath(23)'))
+ end)
+
+ it('on non-strings', function()
+ eq('Vim(call):E731: using Dictionary as a String', exc_exec('call stdpath({"eris": 23})'))
+ eq('Vim(call):E730: using List as a String', exc_exec('call stdpath([23])'))
+ end)
+ end)
+end)
diff --git a/test/functional/options/fillchars_spec.lua b/test/functional/options/fillchars_spec.lua
new file mode 100644
index 0000000000..99177a11b4
--- /dev/null
+++ b/test/functional/options/fillchars_spec.lua
@@ -0,0 +1,73 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear, command = helpers.clear, helpers.command
+local eval = helpers.eval
+local eq = helpers.eq
+local exc_exec = helpers.exc_exec
+
+describe("'fillchars'", function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(25, 5)
+ screen:attach()
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ local function shouldfail(val,errval)
+ errval = errval or val
+ eq('Vim(set):E474: Invalid argument: fillchars='..errval,
+ exc_exec('set fillchars='..val))
+ end
+
+ describe('"eob" flag', function()
+ it("uses '~' by default", function()
+ eq('', eval('&fillchars'))
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]])
+ end)
+ it('supports whitespace', function()
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]])
+ command('set fillchars=eob:\\ ')
+ screen:expect([[
+ ^ |
+ |
+ |
+ |
+ |
+ ]])
+ end)
+ it('supports multibyte char', function()
+ command('set fillchars=eob:ñ')
+ screen:expect([[
+ ^ |
+ ñ |
+ ñ |
+ ñ |
+ |
+ ]])
+ end)
+ it('handles invalid values', function()
+ shouldfail('eob:') -- empty string
+ shouldfail('eob:馬') -- doublewidth char
+ shouldfail('eob:å̲') -- composing chars
+ shouldfail('eob:xy') -- two ascii chars
+ shouldfail('eob:\255', 'eob:<ff>') -- invalid UTF-8
+ end)
+ end)
+end)
diff --git a/test/functional/options/keymap_spec.lua b/test/functional/options/keymap_spec.lua
new file mode 100644
index 0000000000..7f6d623dc7
--- /dev/null
+++ b/test/functional/options/keymap_spec.lua
@@ -0,0 +1,233 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq
+local expect, command, eval = helpers.expect, helpers.command, helpers.eval
+local insert, call = helpers.insert, helpers.call
+local funcs, dedent = helpers.funcs, helpers.dedent
+
+-- First test it's implemented using the :lmap and :lnoremap commands, then
+-- check those mappings behave as expected.
+describe("'keymap' / :lmap", function()
+ clear()
+ before_each(function()
+ clear()
+ insert("lllaaa")
+ command('set iminsert=1')
+ command('set imsearch=1')
+ command('lmap l a')
+ feed('gg0')
+ end)
+
+ describe("'keymap' as :lmap", function()
+ -- Shows that 'keymap' sets language mappings that allows remapping.
+ -- This equivalence allows us to only test :lmap commands and assert they
+ -- behave the same as 'keymap' settings.
+ -- It does rely on the absence of special code that implements 'keymap'
+ -- and :lmap differently but shows mappings from the 'keymap' after
+ -- typing :lmap.
+ -- At the moment this is the case.
+ it("'keymap' mappings are shown with :lmap", function()
+ command('lmapclear')
+ command('lmapclear <buffer>')
+ command('set keymap=dvorak')
+ command('set nomore')
+ local bindings = funcs.nvim_command_output('lmap')
+ eq(dedent([[
+
+ l " @_
+ l ' @-
+ l + @}
+ l , @w
+ l - @[
+ l . @v
+ l / @z
+ l : @S
+ l ; @s
+ l < @W
+ l = @]
+ l > @V
+ l ? @Z
+ l A @A
+ l B @X
+ l C @J
+ l D @E
+ l E @>
+ l F @U
+ l G @I
+ l H @D
+ l I @C
+ l J @H
+ l K @T
+ l L @N
+ l M @M
+ l N @B
+ l O @R
+ l P @L
+ l Q @"
+ l R @P
+ l S @O
+ l T @Y
+ l U @G
+ l V @K
+ l W @<
+ l X @Q
+ l Y @F
+ l Z @:
+ l [ @/
+ l \ @\
+ l ] @=
+ l _ @{
+ l a @a
+ l b @x
+ l c @j
+ l d @e
+ l e @.
+ l f @u
+ l g @i
+ l h @d
+ l i @c
+ l j @h
+ l k @t
+ l l @n
+ l m @m
+ l n @b
+ l o @r
+ l p @l
+ l q @'
+ l r @p
+ l s @o
+ l t @y
+ l u @g
+ l v @k
+ l w @,
+ l x @q
+ l y @f
+ l z @;
+ l { @?
+ l | @|
+ l } @+]]), bindings)
+ end)
+ end)
+ describe("'iminsert' option", function()
+ it("Uses :lmap in insert mode when ON", function()
+ feed('il<esc>')
+ expect('alllaaa')
+ end)
+ it("Ignores :lmap in insert mode when OFF", function()
+ command('set iminsert=0')
+ feed('il<esc>')
+ expect('llllaaa')
+ end)
+ it("Can be toggled with <C-^> in insert mode", function()
+ feed('i<C-^>l<C-^>l<esc>')
+ expect('lalllaaa')
+ eq(eval('&iminsert'), 1)
+ feed('i<C-^><esc>')
+ eq(eval('&iminsert'), 0)
+ end)
+ end)
+ describe("'imsearch' option", function()
+ it("Uses :lmap at search prompt when ON", function()
+ feed('/lll<cr>3x')
+ expect('lll')
+ end)
+ it("Ignores :lmap at search prompt when OFF", function()
+ command('set imsearch=0')
+ feed('gg/lll<cr>3x')
+ expect('aaa')
+ end)
+ it("Can be toggled with C-^", function()
+ eq(eval('&imsearch'), 1)
+ feed('/<C-^>lll<cr>3x')
+ expect('aaa')
+ eq(eval('&imsearch'), 0)
+ feed('u0/<C-^>lll<cr>3x')
+ expect('lll')
+ eq(eval('&imsearch'), 1)
+ end)
+ it("can follow 'iminsert'", function()
+ command('set imsearch=-1')
+ feed('/lll<cr>3x')
+ expect('lll')
+ eq(eval('&imsearch'), -1)
+ eq(eval('&iminsert'), 1)
+ feed('u/<C-^>lll<cr>3x')
+ expect('aaa')
+ eq(eval('&imsearch'), -1)
+ eq(eval('&iminsert'), 0)
+ end)
+ end)
+ it(":lmap not applied to macros", function()
+ command("call setreg('a', 'il')")
+ feed('@a')
+ expect('llllaaa')
+ eq(call('getreg', 'a'), 'il')
+ end)
+ it(":lmap applied to macro recording", function()
+ feed('qail<esc>q@a')
+ expect('aalllaaa')
+ eq(call('getreg', 'a'), 'ia')
+ end)
+ it(":lmap not applied to mappings", function()
+ command('imap t l')
+ feed('it<esc>')
+ expect('llllaaa')
+ end)
+ it("mappings applied to keys created with :lmap", function()
+ command('imap a x')
+ feed('il<esc>')
+ expect('xlllaaa')
+ end)
+ it("mappings not applied to keys gotten with :lnoremap", function()
+ command('lmapclear')
+ command('lnoremap l a')
+ command('imap a x')
+ feed('il<esc>')
+ expect('alllaaa')
+ end)
+ -- This is a problem introduced when introducting :lmap and macro
+ -- compatibility. There are no plans to fix this as the complexity involved
+ -- seems too great.
+ pending('mappings not applied to macro replay of :lnoremap', function()
+ command('lmapclear')
+ command('lnoremap l a')
+ command('imap a x')
+ feed('qail<esc>q')
+ expect('alllaaa')
+ feed('@a')
+ expect('aalllaaa')
+ end)
+ it("is applied when using f/F t/T", function()
+ feed('flx')
+ expect('lllaa')
+ feed('0ia<esc>4lFlx')
+ expect('lllaa')
+ feed('tllx')
+ expect('llla')
+ feed('0ia<esc>4lTlhx')
+ expect('llla')
+ end)
+ it('takes priority over :imap mappings', function()
+ command('imap l x')
+ feed('il<esc>')
+ expect('alllaaa')
+ command('lmapclear')
+ command('lmap l a')
+ feed('il')
+ expect('aalllaaa')
+ end)
+ it('does not cause recursive mappings', function()
+ command('lmap a l')
+ feed('qaila<esc>q')
+ expect('allllaaa')
+ feed('u@a')
+ expect('allllaaa')
+ end)
+ it('can handle multicharacter mappings', function()
+ command("lmap 'a x")
+ command("lmap '' '")
+ feed("qai'a''a<esc>q")
+ expect("x'alllaaa")
+ feed('u@a')
+ expect("x'alllaaa")
+ end)
+end)
diff --git a/test/functional/options/num_options_spec.lua b/test/functional/options/num_options_spec.lua
new file mode 100644
index 0000000000..fb0559054d
--- /dev/null
+++ b/test/functional/options/num_options_spec.lua
@@ -0,0 +1,110 @@
+-- Tests for :setlocal and :setglobal
+
+local helpers = require('test.functional.helpers')(after_each)
+local clear, feed_command, eval, eq, meths =
+ helpers.clear, helpers.feed_command, helpers.eval, helpers.eq, helpers.meths
+
+local function should_fail(opt, value, errmsg)
+ feed_command('setglobal ' .. opt .. '=' .. value)
+ eq(errmsg, eval("v:errmsg"):match("E%d*"))
+ feed_command('let v:errmsg = ""')
+ feed_command('setlocal ' .. opt .. '=' .. value)
+ eq(errmsg, eval("v:errmsg"):match("E%d*"))
+ feed_command('let v:errmsg = ""')
+ local status, err = pcall(meths.set_option, opt, value)
+ eq(status, false)
+ eq(errmsg, err:match("E%d*"))
+ eq('', eval("v:errmsg"))
+end
+
+local function should_succeed(opt, value)
+ feed_command('setglobal ' .. opt .. '=' .. value)
+ feed_command('setlocal ' .. opt .. '=' .. value)
+ meths.set_option(opt, value)
+ eq(value, meths.get_option(opt))
+ eq('', eval("v:errmsg"))
+end
+
+describe(':setlocal', function()
+ before_each(clear)
+
+ it('setlocal sets only local value', function()
+ eq(0, meths.get_option('iminsert'))
+ feed_command('setlocal iminsert=1')
+ eq(0, meths.get_option('iminsert'))
+ eq(0, meths.get_option('imsearch'))
+ feed_command('setlocal imsearch=1')
+ eq(0, meths.get_option('imsearch'))
+ end)
+end)
+
+describe(':set validation', function()
+ before_each(clear)
+
+ it('setlocal and setglobal validate values', function()
+ should_fail('shiftwidth', -10, 'E487')
+ should_succeed('shiftwidth', 0)
+ should_fail('tabstop', -10, 'E487')
+ should_fail('winheight', -10, 'E487')
+ should_fail('winheight', 0, 'E487')
+ should_fail('winminheight', -1, 'E487')
+ should_succeed('winminheight', 0)
+ should_fail('winwidth', 0, 'E487')
+ should_fail('helpheight', -1, 'E487')
+ should_fail('iminsert', 3, 'E474')
+ should_fail('imsearch', 3, 'E474')
+ should_fail('titlelen', -1, 'E487')
+ should_fail('cmdheight', 0, 'E487')
+ should_fail('updatecount', -1, 'E487')
+ should_fail('textwidth', -1, 'E487')
+ should_fail('tabstop', 0, 'E487')
+ should_fail('timeoutlen', -1, 'E487')
+ should_fail('history', 1000000, 'E474')
+ should_fail('regexpengine', -1, 'E474')
+ should_fail('regexpengine', 3, 'E474')
+ should_succeed('regexpengine', 2)
+ should_fail('report', -1, 'E487')
+ should_succeed('report', 0)
+ should_fail('scrolloff', -1, 'E49')
+ should_fail('sidescrolloff', -1, 'E487')
+ should_fail('sidescroll', -1, 'E487')
+ should_fail('cmdwinheight', 0, 'E487')
+ should_fail('updatetime', -1, 'E487')
+
+ should_fail('foldlevel', -5, 'E487')
+ should_fail('foldcolumn', 13, 'E474')
+ should_fail('conceallevel', 4, 'E474')
+ should_fail('numberwidth', 11, 'E474')
+ should_fail('numberwidth', 0, 'E487')
+
+ -- If smaller than 1 this one is set to 'lines'-1
+ feed_command('setglobal window=-10')
+ meths.set_option('window', -10)
+ eq(23, meths.get_option('window'))
+ eq('', eval("v:errmsg"))
+ end)
+
+ it('set wmh/wh wmw/wiw checks', function()
+ feed_command('set winheight=2')
+ feed_command('set winminheight=3')
+ eq('E591', eval("v:errmsg"):match("E%d*"))
+
+ feed_command('set winwidth=2')
+ feed_command('set winminwidth=3')
+ eq('E592', eval("v:errmsg"):match("E%d*"))
+ end)
+
+ it('set maxcombine resets to 6', function()
+ local function setto(value)
+ feed_command('setglobal maxcombine=' .. value)
+ feed_command('setlocal maxcombine=' .. value)
+ meths.set_option('maxcombine', value)
+ eq(6, meths.get_option('maxcombine'))
+ eq('', eval("v:errmsg"))
+ end
+ setto(0)
+ setto(1)
+ setto(6)
+ setto(7)
+ end)
+end)
diff --git a/test/functional/options/pastetoggle_spec.lua b/test/functional/options/pastetoggle_spec.lua
new file mode 100644
index 0000000000..a1f86f73ff
--- /dev/null
+++ b/test/functional/options/pastetoggle_spec.lua
@@ -0,0 +1,40 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local feed = helpers.feed
+local command = helpers.command
+local eq = helpers.eq
+local eval = helpers.eval
+local sleep = helpers.sleep
+local expect = helpers.expect
+
+describe("'pastetoggle' option", function()
+ before_each(function()
+ clear()
+ command('set nopaste')
+ end)
+
+ it("toggles 'paste'", function()
+ command('set pastetoggle=a')
+ eq(0, eval('&paste'))
+ feed('a')
+ -- Need another key so that the vgetorpeek() function returns.
+ feed('j')
+ eq(1, 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'))
+ end)
+end)
diff --git a/test/functional/options/shortmess_spec.lua b/test/functional/options/shortmess_spec.lua
index d531e47e28..8ea9a19464 100644
--- a/test/functional/options/shortmess_spec.lua
+++ b/test/functional/options/shortmess_spec.lua
@@ -1,39 +1,96 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, execute = helpers.clear, helpers.execute
+local clear = helpers.clear
+local command = helpers.command
+local eq = helpers.eq
+local eval = helpers.eval
+local feed = helpers.feed
describe("'shortmess'", function()
local screen
before_each(function()
clear()
- screen = Screen.new(25, 5)
+ screen = Screen.new(42, 5)
screen:attach()
end)
- after_each(function()
- screen:detach()
- end)
-
describe('"F" flag', function()
- it('hides messages about the files read', function()
- execute('e test')
+ it('hides :edit fileinfo messages', function()
+ command('set hidden')
+ command('set shortmess-=F')
+ feed(':edit foo<CR>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ "foo" [New File] |
+ ]])
+ eq(1, eval('bufnr("%")'))
+
+ command('set shortmess+=F')
+ feed(':edit bar<CR>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ :edit bar |
+ ]])
+ eq(2, eval('bufnr("%")'))
+ end)
+
+ it('hides :bnext, :bprevious fileinfo messages', function()
+ command('set hidden')
+ command('set shortmess-=F')
+ feed(':edit foo<CR>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ "foo" [New File] |
+ ]])
+ eq(1, eval('bufnr("%")'))
+ feed(':edit bar<CR>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ "bar" [New File] |
+ ]])
+ eq(2, eval('bufnr("%")'))
+ feed(':bprevious<CR>')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ "foo" [New file] --No lines in buffer-- |
+ ]])
+ eq(1, eval('bufnr("%")'))
+
+ command('set shortmess+=F')
+ feed(':bnext<CR>')
screen:expect([[
- ^ |
- ~ |
- ~ |
- ~ |
- "test" is a directory |
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ :bnext |
]])
- execute('set shortmess=F')
- execute('e test')
+ eq(2, eval('bufnr("%")'))
+ feed(':bprevious<CR>')
screen:expect([[
- ^ |
- ~ |
- ~ |
- ~ |
- :e test |
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ :bprevious |
]])
+ eq(1, eval('bufnr("%")'))
end)
end)
end)
diff --git a/test/functional/options/tabstop_spec.lua b/test/functional/options/tabstop_spec.lua
new file mode 100644
index 0000000000..dc3ba38438
--- /dev/null
+++ b/test/functional/options/tabstop_spec.lua
@@ -0,0 +1,23 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local feed = helpers.feed
+local eq = helpers.eq
+local eval = helpers.eval
+
+describe("'tabstop' option", function()
+ before_each(function()
+ clear()
+ end)
+
+ -- NOTE: Setting 'tabstop' to a big number reproduces crash #2838.
+ -- Disallowing big 'tabstop' would not fix #2838, only hide it.
+ it("tabstop=<big-number> does not crash #2838", function()
+ -- Insert a <Tab> character for 'tabstop' to work with.
+ feed('i<Tab><Esc>')
+ -- Set 'tabstop' to a very high value.
+ -- Use feed(), not command(), to provoke crash.
+ feed(':set tabstop=3000000000<CR>')
+ eq(2, eval("1+1")) -- Still alive?
+ end)
+end)