aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/lua/iter_spec.lua425
-rw-r--r--test/functional/lua/vim_spec.lua421
-rw-r--r--test/functional/vimscript/eval_spec.lua31
-rw-r--r--test/old/testdir/test_assert.vim10
-rw-r--r--test/old/testdir/test_charsearch.vim2
-rw-r--r--test/old/testdir/test_cmdline.vim2
-rw-r--r--test/old/testdir/test_expr.vim2
-rw-r--r--test/old/testdir/test_functions.vim476
-rw-r--r--test/old/testdir/test_listdict.vim2
-rw-r--r--test/old/testdir/test_maparg.vim2
-rw-r--r--test/old/testdir/test_matchfuzzy.vim8
-rw-r--r--test/old/testdir/test_partial.vim2
-rw-r--r--test/old/testdir/test_search_stat.vim2
-rw-r--r--test/old/testdir/test_signs.vim14
-rw-r--r--test/old/testdir/test_tagjump.vim8
-rw-r--r--test/old/testdir/test_timers.vim12
-rw-r--r--test/old/testdir/test_window_cmd.vim6
17 files changed, 951 insertions, 474 deletions
diff --git a/test/functional/lua/iter_spec.lua b/test/functional/lua/iter_spec.lua
new file mode 100644
index 0000000000..6e1ecc2f7e
--- /dev/null
+++ b/test/functional/lua/iter_spec.lua
@@ -0,0 +1,425 @@
+local helpers = require('test.functional.helpers')(after_each)
+local eq = helpers.eq
+local matches = helpers.matches
+local pcall_err = helpers.pcall_err
+
+describe('vim.iter', function()
+ it('filter()', function()
+ local function odd(v)
+ return v % 2 ~= 0
+ end
+
+ local t = { 1, 2, 3, 4, 5 }
+ eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable())
+ eq({ 2, 4 }, vim.iter(t):filter(function(v) return not odd(v) end):totable())
+ eq({}, vim.iter(t):filter(function(v) return v > 5 end):totable())
+
+ do
+ local it = vim.iter(ipairs(t))
+ it:filter(function(i, v) return i > 1 and v < 5 end)
+ it:map(function(_, v) return v * 2 end)
+ eq({ 4, 6, 8 }, it:totable())
+ end
+
+ local it = vim.iter(string.gmatch('the quick brown fox', '%w+'))
+ eq({'the', 'fox'}, it:filter(function(s) return #s <= 3 end):totable())
+ end)
+
+ it('map()', function()
+ local t = { 1, 2, 3, 4, 5 }
+ eq(
+ { 2, 4, 6, 8, 10 },
+ vim
+ .iter(t)
+ :map(function(v)
+ return 2 * v
+ end)
+ :totable()
+ )
+
+ local it = vim.gsplit(
+ [[
+ Line 1
+ Line 2
+ Line 3
+ Line 4
+ ]],
+ '\n'
+ )
+
+ eq(
+ { 'Lion 2', 'Lion 4' },
+ vim
+ .iter(it)
+ :map(function(s)
+ local lnum = s:match('(%d+)')
+ if lnum and tonumber(lnum) % 2 == 0 then
+ return vim.trim(s:gsub('Line', 'Lion'))
+ end
+ end)
+ :totable()
+ )
+ end)
+
+ it('for loops', function()
+ local t = {1, 2, 3, 4, 5}
+ local acc = 0
+ for v in vim.iter(t):map(function(v) return v * 3 end) do
+ acc = acc + v
+ end
+ eq(45, acc)
+ end)
+
+ it('totable()', function()
+ do
+ local it = vim.iter({1, 2, 3}):map(function(v) return v, v*v end)
+ eq({{1, 1}, {2, 4}, {3, 9}}, it:totable())
+ end
+
+ do
+ local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber)
+ eq({1, 4, 17, 2, 9, 3}, it:totable())
+ end
+ end)
+
+ it('next()', function()
+ local it = vim.iter({1, 2, 3}):map(function(v) return 2 * v end)
+ eq(2, it:next())
+ eq(4, it:next())
+ eq(6, it:next())
+ eq(nil, it:next())
+ end)
+
+ it('rev()', function()
+ eq({3, 2, 1}, vim.iter({1, 2, 3}):rev():totable())
+
+ local it = vim.iter(string.gmatch("abc", "%w"))
+ matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it))
+ end)
+
+ it('skip()', function()
+ do
+ local t = {4, 3, 2, 1}
+ eq(t, vim.iter(t):skip(0):totable())
+ eq({3, 2, 1}, vim.iter(t):skip(1):totable())
+ eq({2, 1}, vim.iter(t):skip(2):totable())
+ eq({1}, vim.iter(t):skip(#t - 1):totable())
+ eq({}, vim.iter(t):skip(#t):totable())
+ eq({}, vim.iter(t):skip(#t + 1):totable())
+ end
+
+ do
+ local function skip(n)
+ return vim.iter(vim.gsplit('a|b|c|d', '|')):skip(n):totable()
+ end
+ eq({'a', 'b', 'c', 'd'}, skip(0))
+ eq({'b', 'c', 'd'}, skip(1))
+ eq({'c', 'd'}, skip(2))
+ eq({'d'}, skip(3))
+ eq({}, skip(4))
+ eq({}, skip(5))
+ end
+ end)
+
+ it('skipback()', function()
+ do
+ local t = {4, 3, 2, 1}
+ eq(t, vim.iter(t):skipback(0):totable())
+ eq({4, 3, 2}, vim.iter(t):skipback(1):totable())
+ eq({4, 3}, vim.iter(t):skipback(2):totable())
+ eq({4}, vim.iter(t):skipback(#t - 1):totable())
+ eq({}, vim.iter(t):skipback(#t):totable())
+ eq({}, vim.iter(t):skipback(#t + 1):totable())
+ end
+
+ local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
+ matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0))
+ end)
+
+ it('slice()', function()
+ local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+ eq({3, 4, 5, 6, 7}, vim.iter(t):slice(3, 7):totable())
+ eq({}, vim.iter(t):slice(6, 5):totable())
+ eq({}, vim.iter(t):slice(0, 0):totable())
+ eq({1}, vim.iter(t):slice(1, 1):totable())
+ eq({1, 2}, vim.iter(t):slice(1, 2):totable())
+ eq({10}, vim.iter(t):slice(10, 10):totable())
+ eq({8, 9, 10}, vim.iter(t):slice(8, 11):totable())
+ end)
+
+ it('nth()', function()
+ do
+ local t = {4, 3, 2, 1}
+ eq(nil, vim.iter(t):nth(0))
+ eq(4, vim.iter(t):nth(1))
+ eq(3, vim.iter(t):nth(2))
+ eq(2, vim.iter(t):nth(3))
+ eq(1, vim.iter(t):nth(4))
+ eq(nil, vim.iter(t):nth(5))
+ end
+
+ do
+ local function nth(n)
+ return vim.iter(vim.gsplit('a|b|c|d', '|')):nth(n)
+ end
+ eq(nil, nth(0))
+ eq('a', nth(1))
+ eq('b', nth(2))
+ eq('c', nth(3))
+ eq('d', nth(4))
+ eq(nil, nth(5))
+ end
+ end)
+
+ it('nthback()', function()
+ do
+ local t = {4, 3, 2, 1}
+ eq(nil, vim.iter(t):nthback(0))
+ eq(1, vim.iter(t):nthback(1))
+ eq(2, vim.iter(t):nthback(2))
+ eq(3, vim.iter(t):nthback(3))
+ eq(4, vim.iter(t):nthback(4))
+ eq(nil, vim.iter(t):nthback(5))
+ end
+
+ local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
+ matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1))
+ end)
+
+ it('any()', function()
+ local function odd(v)
+ return v % 2 ~= 0
+ end
+
+ do
+ local t = { 4, 8, 9, 10 }
+ eq(true, vim.iter(t):any(odd))
+ end
+
+ do
+ local t = { 4, 8, 10 }
+ eq(false, vim.iter(t):any(odd))
+ end
+
+ do
+ eq(true, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'd' end))
+ eq(false, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'e' end))
+ end
+ end)
+
+ it('all()', function()
+ local function odd(v)
+ return v % 2 ~= 0
+ end
+
+ do
+ local t = { 3, 5, 7, 9 }
+ eq(true, vim.iter(t):all(odd))
+ end
+
+ do
+ local t = { 3, 5, 7, 10 }
+ eq(false, vim.iter(t):all(odd))
+ end
+
+ do
+ eq(true, vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s) return s == 'a' end))
+ eq(false, vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s) return s == 'a' end))
+ end
+ end)
+
+ it('last()', function()
+ local s = 'abcdefghijklmnopqrstuvwxyz'
+ eq('z', vim.iter(vim.split(s, '')):last())
+ eq('z', vim.iter(vim.gsplit(s, '')):last())
+ end)
+
+ it('enumerate()', function()
+ local it = vim.iter(vim.gsplit('abc', '')):enumerate()
+ eq({1, 'a'}, {it:next()})
+ eq({2, 'b'}, {it:next()})
+ eq({3, 'c'}, {it:next()})
+ eq({}, {it:next()})
+ end)
+
+ it('peek()', function()
+ do
+ local it = vim.iter({ 3, 6, 9, 12 })
+ eq(3, it:peek())
+ eq(3, it:peek())
+ eq(3, it:next())
+ end
+
+ do
+ local it = vim.iter(vim.gsplit('hi', ''))
+ matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it))
+ end
+ end)
+
+ it('find()', function()
+ local t = {3, 6, 9, 12}
+ eq(12, vim.iter(t):find(12))
+ eq(nil, vim.iter(t):find(15))
+ eq(12, vim.iter(t):find(function(v) return v % 4 == 0 end))
+
+ do
+ local it = vim.iter(t)
+ local pred = function(v) return v % 3 == 0 end
+ eq(3, it:find(pred))
+ eq(6, it:find(pred))
+ eq(9, it:find(pred))
+ eq(12, it:find(pred))
+ eq(nil, it:find(pred))
+ end
+
+ do
+ local it = vim.iter(vim.gsplit('AbCdE', ''))
+ local pred = function(s) return s:match('[A-Z]') end
+ eq('A', it:find(pred))
+ eq('C', it:find(pred))
+ eq('E', it:find(pred))
+ eq(nil, it:find(pred))
+ end
+ end)
+
+ it('rfind()', function()
+ local t = {1, 2, 3, 2, 1}
+ do
+ local it = vim.iter(t)
+ eq(1, it:rfind(1))
+ eq(1, it:rfind(1))
+ eq(nil, it:rfind(1))
+ end
+
+ do
+ local it = vim.iter(t):enumerate()
+ local pred = function(i) return i % 2 ~= 0 end
+ eq({5, 1}, {it:rfind(pred)})
+ eq({3, 3}, {it:rfind(pred)})
+ eq({1, 1}, {it:rfind(pred)})
+ eq(nil, it:rfind(pred))
+ end
+
+ do
+ local it = vim.iter(vim.gsplit('AbCdE', ''))
+ matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E'))
+ end
+ end)
+
+ it('nextback()', function()
+ do
+ local it = vim.iter({ 1, 2, 3, 4 })
+ eq(4, it:nextback())
+ eq(3, it:nextback())
+ eq(2, it:nextback())
+ eq(1, it:nextback())
+ eq(nil, it:nextback())
+ eq(nil, it:nextback())
+ end
+
+ do
+ local it = vim.iter(vim.gsplit('hi', ''))
+ matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it))
+ end
+ end)
+
+ it('peekback()', function()
+ do
+ local it = vim.iter({ 1, 2, 3, 4 })
+ eq(4, it:peekback())
+ eq(4, it:peekback())
+ eq(4, it:nextback())
+ end
+
+ do
+ local it = vim.iter(vim.gsplit('hi', ''))
+ matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it))
+ end
+ end)
+
+ it('fold()', function()
+ local t = {1, 2, 3, 4, 5}
+ eq(115, vim.iter(t):fold(100, function(acc, v) return acc + v end))
+ eq({5, 4, 3, 2, 1}, vim.iter(t):fold({}, function(acc, v)
+ table.insert(acc, 1, v)
+ return acc
+ end))
+ end)
+
+ it('handles map-like tables', function()
+ local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v)
+ if v % 2 ~= 0 then
+ return k:upper(), v * 2
+ end
+ end)
+
+ local t = it:fold({}, function(t, k, v)
+ t[k] = v
+ return t
+ end)
+ eq({ A = 2, C = 6 }, t)
+ end)
+
+ it('handles table values mid-pipeline', function()
+ local map = {
+ item = {
+ file = 'test',
+ },
+ item_2 = {
+ file = 'test',
+ },
+ item_3 = {
+ file = 'test',
+ },
+ }
+
+ local output = vim.iter(map):map(function(key, value)
+ return { [key] = value.file }
+ end):totable()
+
+ table.sort(output, function(a, b)
+ return next(a) < next(b)
+ end)
+
+ eq({
+ { item = 'test' },
+ { item_2 = 'test' },
+ { item_3 = 'test' },
+ }, output)
+ end)
+
+ it('handles nil values', function()
+ local t = {1, 2, 3, 4, 5}
+ do
+ local it = vim.iter(t):enumerate():map(function(i, v)
+ if i % 2 == 0 then
+ return nil, v*v
+ end
+ return v, nil
+ end)
+ eq({
+ { [1] = 1 },
+ { [2] = 4 },
+ { [1] = 3 },
+ { [2] = 16 },
+ { [1] = 5 },
+ }, it:totable())
+ end
+
+ do
+ local it = vim.iter(ipairs(t)):map(function(i, v)
+ if i % 2 == 0 then
+ return nil, v*v
+ end
+ return v, nil
+ end)
+ eq({
+ { [1] = 1 },
+ { [2] = 4 },
+ { [1] = 3 },
+ { [2] = 16 },
+ { [1] = 5 },
+ }, it:totable())
+ end
+ end)
+end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 42927f7e1b..53c21fd668 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -3031,427 +3031,6 @@ describe('lua stdlib', function()
eq(false, if_nil(d, c))
eq(NIL, if_nil(a))
end)
-
- describe('vim.iter', function()
- it('filter()', function()
- local function odd(v)
- return v % 2 ~= 0
- end
-
- local t = { 1, 2, 3, 4, 5 }
- eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable())
- eq({ 2, 4 }, vim.iter(t):filter(function(v) return not odd(v) end):totable())
- eq({}, vim.iter(t):filter(function(v) if v > 5 then return v end end):totable())
-
- do
- local it = vim.iter(ipairs(t))
- it:filter(function(i, v) return i > 1 and v < 5 end)
- it:map(function(_, v) return v * 2 end)
- eq({ 4, 6, 8 }, it:totable())
- end
-
- local it = vim.iter(string.gmatch('the quick brown fox', '%w+'))
- eq({'the', 'fox'}, it:filter(function(s) return #s <= 3 end):totable())
- end)
-
- it('map()', function()
- local t = { 1, 2, 3, 4, 5 }
- eq(
- { 2, 4, 6, 8, 10 },
- vim
- .iter(t)
- :map(function(v)
- return 2 * v
- end)
- :totable()
- )
-
- local it = vim.gsplit(
- [[
- Line 1
- Line 2
- Line 3
- Line 4
- ]],
- '\n'
- )
-
- eq(
- { 'Lion 2', 'Lion 4' },
- vim
- .iter(it)
- :map(function(s)
- local lnum = s:match('(%d+)')
- if lnum and tonumber(lnum) % 2 == 0 then
- return vim.trim(s:gsub('Line', 'Lion'))
- end
- end)
- :totable()
- )
- end)
-
- it('for loops', function()
- local t = {1, 2, 3, 4, 5}
- local acc = 0
- for v in vim.iter(t):map(function(v) return v * 3 end) do
- acc = acc + v
- end
- eq(45, acc)
- end)
-
- it('totable()', function()
- do
- local it = vim.iter({1, 2, 3}):map(function(v) return v, v*v end)
- eq({{1, 1}, {2, 4}, {3, 9}}, it:totable())
- end
-
- do
- local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber)
- eq({1, 4, 17, 2, 9, 3}, it:totable())
- end
- end)
-
- it('next()', function()
- local it = vim.iter({1, 2, 3}):map(function(v) return 2 * v end)
- eq(2, it:next())
- eq(4, it:next())
- eq(6, it:next())
- eq(nil, it:next())
- end)
-
- it('rev()', function()
- eq({3, 2, 1}, vim.iter({1, 2, 3}):rev():totable())
-
- local it = vim.iter(string.gmatch("abc", "%w"))
- matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it))
- end)
-
- it('skip()', function()
- do
- local t = {4, 3, 2, 1}
- eq(t, vim.iter(t):skip(0):totable())
- eq({3, 2, 1}, vim.iter(t):skip(1):totable())
- eq({2, 1}, vim.iter(t):skip(2):totable())
- eq({1}, vim.iter(t):skip(#t - 1):totable())
- eq({}, vim.iter(t):skip(#t):totable())
- eq({}, vim.iter(t):skip(#t + 1):totable())
- end
-
- do
- local function skip(n)
- return vim.iter(vim.gsplit('a|b|c|d', '|')):skip(n):totable()
- end
- eq({'a', 'b', 'c', 'd'}, skip(0))
- eq({'b', 'c', 'd'}, skip(1))
- eq({'c', 'd'}, skip(2))
- eq({'d'}, skip(3))
- eq({}, skip(4))
- eq({}, skip(5))
- end
- end)
-
- it('skipback()', function()
- do
- local t = {4, 3, 2, 1}
- eq(t, vim.iter(t):skipback(0):totable())
- eq({4, 3, 2}, vim.iter(t):skipback(1):totable())
- eq({4, 3}, vim.iter(t):skipback(2):totable())
- eq({4}, vim.iter(t):skipback(#t - 1):totable())
- eq({}, vim.iter(t):skipback(#t):totable())
- eq({}, vim.iter(t):skipback(#t + 1):totable())
- end
-
- local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
- matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0))
- end)
-
- it('slice()', function()
- local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
- eq({3, 4, 5, 6, 7}, vim.iter(t):slice(3, 7):totable())
- eq({}, vim.iter(t):slice(6, 5):totable())
- eq({}, vim.iter(t):slice(0, 0):totable())
- eq({1}, vim.iter(t):slice(1, 1):totable())
- eq({1, 2}, vim.iter(t):slice(1, 2):totable())
- eq({10}, vim.iter(t):slice(10, 10):totable())
- eq({8, 9, 10}, vim.iter(t):slice(8, 11):totable())
- end)
-
- it('nth()', function()
- do
- local t = {4, 3, 2, 1}
- eq(nil, vim.iter(t):nth(0))
- eq(4, vim.iter(t):nth(1))
- eq(3, vim.iter(t):nth(2))
- eq(2, vim.iter(t):nth(3))
- eq(1, vim.iter(t):nth(4))
- eq(nil, vim.iter(t):nth(5))
- end
-
- do
- local function nth(n)
- return vim.iter(vim.gsplit('a|b|c|d', '|')):nth(n)
- end
- eq(nil, nth(0))
- eq('a', nth(1))
- eq('b', nth(2))
- eq('c', nth(3))
- eq('d', nth(4))
- eq(nil, nth(5))
- end
- end)
-
- it('nthback()', function()
- do
- local t = {4, 3, 2, 1}
- eq(nil, vim.iter(t):nthback(0))
- eq(1, vim.iter(t):nthback(1))
- eq(2, vim.iter(t):nthback(2))
- eq(3, vim.iter(t):nthback(3))
- eq(4, vim.iter(t):nthback(4))
- eq(nil, vim.iter(t):nthback(5))
- end
-
- local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
- matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1))
- end)
-
- it('any()', function()
- local function odd(v)
- return v % 2 ~= 0
- end
-
- do
- local t = { 4, 8, 9, 10 }
- eq(true, vim.iter(t):any(odd))
- end
-
- do
- local t = { 4, 8, 10 }
- eq(false, vim.iter(t):any(odd))
- end
-
- do
- eq(true, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'd' end))
- eq(false, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'e' end))
- end
- end)
-
- it('all()', function()
- local function odd(v)
- return v % 2 ~= 0
- end
-
- do
- local t = { 3, 5, 7, 9 }
- eq(true, vim.iter(t):all(odd))
- end
-
- do
- local t = { 3, 5, 7, 10 }
- eq(false, vim.iter(t):all(odd))
- end
-
- do
- eq(true, vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s) return s == 'a' end))
- eq(false, vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s) return s == 'a' end))
- end
- end)
-
- it('last()', function()
- local s = 'abcdefghijklmnopqrstuvwxyz'
- eq('z', vim.iter(vim.split(s, '')):last())
- eq('z', vim.iter(vim.gsplit(s, '')):last())
- end)
-
- it('enumerate()', function()
- local it = vim.iter(vim.gsplit('abc', '')):enumerate()
- eq({1, 'a'}, {it:next()})
- eq({2, 'b'}, {it:next()})
- eq({3, 'c'}, {it:next()})
- eq({}, {it:next()})
- end)
-
- it('peek()', function()
- do
- local it = vim.iter({ 3, 6, 9, 12 })
- eq(3, it:peek())
- eq(3, it:peek())
- eq(3, it:next())
- end
-
- do
- local it = vim.iter(vim.gsplit('hi', ''))
- matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it))
- end
- end)
-
- it('find()', function()
- local t = {3, 6, 9, 12}
- eq(12, vim.iter(t):find(12))
- eq(nil, vim.iter(t):find(15))
- eq(12, vim.iter(t):find(function(v) return v % 4 == 0 end))
-
- do
- local it = vim.iter(t)
- local pred = function(v) return v % 3 == 0 end
- eq(3, it:find(pred))
- eq(6, it:find(pred))
- eq(9, it:find(pred))
- eq(12, it:find(pred))
- eq(nil, it:find(pred))
- end
-
- do
- local it = vim.iter(vim.gsplit('AbCdE', ''))
- local pred = function(s) return s:match('[A-Z]') end
- eq('A', it:find(pred))
- eq('C', it:find(pred))
- eq('E', it:find(pred))
- eq(nil, it:find(pred))
- end
- end)
-
- it('rfind()', function()
- local t = {1, 2, 3, 2, 1}
- do
- local it = vim.iter(t)
- eq(1, it:rfind(1))
- eq(1, it:rfind(1))
- eq(nil, it:rfind(1))
- end
-
- do
- local it = vim.iter(t):enumerate()
- local pred = function(i) return i % 2 ~= 0 end
- eq({5, 1}, {it:rfind(pred)})
- eq({3, 3}, {it:rfind(pred)})
- eq({1, 1}, {it:rfind(pred)})
- eq(nil, it:rfind(pred))
- end
-
- do
- local it = vim.iter(vim.gsplit('AbCdE', ''))
- matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E'))
- end
- end)
-
- it('nextback()', function()
- do
- local it = vim.iter({ 1, 2, 3, 4 })
- eq(4, it:nextback())
- eq(3, it:nextback())
- eq(2, it:nextback())
- eq(1, it:nextback())
- eq(nil, it:nextback())
- eq(nil, it:nextback())
- end
-
- do
- local it = vim.iter(vim.gsplit('hi', ''))
- matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it))
- end
- end)
-
- it('peekback()', function()
- do
- local it = vim.iter({ 1, 2, 3, 4 })
- eq(4, it:peekback())
- eq(4, it:peekback())
- eq(4, it:peekback())
- end
-
- do
- local it = vim.iter(vim.gsplit('hi', ''))
- matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it))
- end
- end)
-
- it('fold()', function()
- local t = {1, 2, 3, 4, 5}
- eq(115, vim.iter(t):fold(100, function(acc, v) return acc + v end))
- eq({5, 4, 3, 2, 1}, vim.iter(t):fold({}, function(acc, v)
- table.insert(acc, 1, v)
- return acc
- end))
- end)
-
- it('handles map-like tables', function()
- local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v)
- if v % 2 ~= 0 then
- return k:upper(), v * 2
- end
- end)
-
- local t = it:fold({}, function(t, k, v)
- t[k] = v
- return t
- end)
- eq({ A = 2, C = 6 }, t)
- end)
-
- it('handles table values mid-pipeline', function()
- local map = {
- item = {
- file = 'test',
- },
- item_2 = {
- file = 'test',
- },
- item_3 = {
- file = 'test',
- },
- }
-
- local output = vim.iter(map):map(function(key, value)
- return { [key] = value.file }
- end):totable()
-
- table.sort(output, function(a, b)
- return next(a) < next(b)
- end)
-
- eq({
- { item = 'test' },
- { item_2 = 'test' },
- { item_3 = 'test' },
- }, output)
- end)
-
- it('handles nil values', function()
- local t = {1, 2, 3, 4, 5}
- do
- local it = vim.iter(t):enumerate():map(function(i, v)
- if i % 2 == 0 then
- return nil, v*v
- end
- return v, nil
- end)
- eq({
- { [1] = 1 },
- { [2] = 4 },
- { [1] = 3 },
- { [2] = 16 },
- { [1] = 5 },
- }, it:totable())
- end
-
- do
- local it = vim.iter(ipairs(t)):map(function(i, v)
- if i % 2 == 0 then
- return nil, v*v
- end
- return v, nil
- end)
- eq({
- { [1] = 1 },
- { [2] = 4 },
- { [1] = 3 },
- { [2] = 16 },
- { [1] = 5 },
- }, it:totable())
- end
- end)
- end)
end)
describe('lua: builtin modules', function()
diff --git a/test/functional/vimscript/eval_spec.lua b/test/functional/vimscript/eval_spec.lua
index b411b1e379..b3f2c1bfeb 100644
--- a/test/functional/vimscript/eval_spec.lua
+++ b/test/functional/vimscript/eval_spec.lua
@@ -191,11 +191,10 @@ describe('listing functions using :function', function()
endfunction]]):format(num), exec_capture(('function <lambda>%s'):format(num)))
end)
- -- FIXME: If the same function is deleted, the crash still happens. #20790
it('does not crash if another function is deleted while listing', function()
local screen = Screen.new(80, 24)
screen:attach()
- matches('Vim%(function%):E454: function list was modified', pcall_err(exec_lua, [=[
+ matches('Vim%(function%):E454: Function list was modified$', pcall_err(exec_lua, [=[
vim.cmd([[
func Func1()
endfunc
@@ -219,6 +218,34 @@ describe('listing functions using :function', function()
]=]))
assert_alive()
end)
+
+ it('does not crash if the same function is deleted while listing', function()
+ local screen = Screen.new(80, 24)
+ screen:attach()
+ matches('Vim%(function%):E454: Function list was modified$', pcall_err(exec_lua, [=[
+ vim.cmd([[
+ func Func1()
+ endfunc
+ func Func2()
+ endfunc
+ func Func3()
+ endfunc
+ ]])
+
+ local ns = vim.api.nvim_create_namespace('test')
+
+ vim.ui_attach(ns, { ext_messages = true }, function(event, _, content)
+ if event == 'msg_show' and content[1][2] == 'function Func1()' then
+ vim.cmd('delfunc Func2')
+ end
+ end)
+
+ vim.cmd('function')
+
+ vim.ui_detach(ns)
+ ]=]))
+ assert_alive()
+ end)
end)
it('no double-free in garbage collection #16287', function()
diff --git a/test/old/testdir/test_assert.vim b/test/old/testdir/test_assert.vim
index 431908e95c..4386492339 100644
--- a/test/old/testdir/test_assert.vim
+++ b/test/old/testdir/test_assert.vim
@@ -337,6 +337,16 @@ func Test_assert_with_msg()
call remove(v:errors, 0)
endfunc
+func Test_override()
+ throw 'Skipped: Nvim does not support test_override()'
+ call test_override('char_avail', 1)
+ eval 1->test_override('redraw')
+ call test_override('ALL', 0)
+ call assert_fails("call test_override('xxx', 1)", 'E475:')
+ call assert_fails("call test_override('redraw', 'yes')", 'E474:')
+ call assert_fails("call test_override('redraw', 'yes')", 'E1210:')
+endfunc
+
func Test_mouse_position()
let save_mouse = &mouse
set mouse=a
diff --git a/test/old/testdir/test_charsearch.vim b/test/old/testdir/test_charsearch.vim
index f8f3e958ca..8d6b405743 100644
--- a/test/old/testdir/test_charsearch.vim
+++ b/test/old/testdir/test_charsearch.vim
@@ -39,7 +39,7 @@ func Test_charsearch()
call setcharsearch({'char' : ''})
call assert_equal('', getcharsearch().char)
- call assert_fails("call setcharsearch([])", 'E715:')
+ call assert_fails("call setcharsearch([])", 'E1206:')
enew!
endfunc
diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim
index 9d506a66c0..9ed49b44c0 100644
--- a/test/old/testdir/test_cmdline.vim
+++ b/test/old/testdir/test_cmdline.vim
@@ -652,7 +652,7 @@ func Test_getcompletion()
call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:')
call assert_fails('call getcompletion("", "burp")', 'E475:')
- call assert_fails('call getcompletion("abc", [])', 'E475:')
+ call assert_fails('call getcompletion("abc", [])', 'E1174:')
endfunc
" Test for getcompletion() with "fuzzy" in 'wildoptions'
diff --git a/test/old/testdir/test_expr.vim b/test/old/testdir/test_expr.vim
index dee7266bb5..ff3dfb83cb 100644
--- a/test/old/testdir/test_expr.vim
+++ b/test/old/testdir/test_expr.vim
@@ -105,7 +105,7 @@ func Test_dict()
END
call CheckLegacyAndVim9Success(lines)
- call CheckLegacyAndVim9Failure(["VAR i = has_key([], 'a')"], ['E715:', 'E1013:', 'E1206:'])
+ call CheckLegacyAndVim9Failure(["VAR i = has_key([], 'a')"], ['E1206:', 'E1013:', 'E1206:'])
endfunc
func Test_strgetchar()
diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim
index 7d3d74caad..b934f7fac2 100644
--- a/test/old/testdir/test_functions.vim
+++ b/test/old/testdir/test_functions.vim
@@ -1064,19 +1064,14 @@ func Test_byte2line_line2byte()
bw!
endfunc
-" Test for byteidx() and byteidxcomp() functions
+" Test for byteidx() using a character index
func Test_byteidx()
let a = '.é.' " one char of two bytes
call assert_equal(0, byteidx(a, 0))
- call assert_equal(0, byteidxcomp(a, 0))
call assert_equal(1, byteidx(a, 1))
- call assert_equal(1, byteidxcomp(a, 1))
call assert_equal(3, byteidx(a, 2))
- call assert_equal(3, byteidxcomp(a, 2))
call assert_equal(4, byteidx(a, 3))
- call assert_equal(4, byteidxcomp(a, 3))
call assert_equal(-1, byteidx(a, 4))
- call assert_equal(-1, byteidxcomp(a, 4))
let b = '.é.' " normal e with composing char
call assert_equal(0, b->byteidx(0))
@@ -1084,18 +1079,184 @@ func Test_byteidx()
call assert_equal(4, b->byteidx(2))
call assert_equal(5, b->byteidx(3))
call assert_equal(-1, b->byteidx(4))
+
+ " string with multiple composing characters
+ let str = '-ą́-ą́'
+ call assert_equal(0, byteidx(str, 0))
+ call assert_equal(1, byteidx(str, 1))
+ call assert_equal(6, byteidx(str, 2))
+ call assert_equal(7, byteidx(str, 3))
+ call assert_equal(12, byteidx(str, 4))
+ call assert_equal(-1, byteidx(str, 5))
+
+ " empty string
+ call assert_equal(0, byteidx('', 0))
+ call assert_equal(-1, byteidx('', 1))
+
+ " error cases
call assert_fails("call byteidx([], 0)", 'E730:')
+ call assert_fails("call byteidx('abc', [])", 'E745:')
+endfunc
+
+" Test for byteidxcomp() using a character index
+func Test_byteidxcomp()
+ let a = '.é.' " one char of two bytes
+ call assert_equal(0, byteidxcomp(a, 0))
+ call assert_equal(1, byteidxcomp(a, 1))
+ call assert_equal(3, byteidxcomp(a, 2))
+ call assert_equal(4, byteidxcomp(a, 3))
+ call assert_equal(-1, byteidxcomp(a, 4))
+ let b = '.é.' " normal e with composing char
call assert_equal(0, b->byteidxcomp(0))
call assert_equal(1, b->byteidxcomp(1))
call assert_equal(2, b->byteidxcomp(2))
call assert_equal(4, b->byteidxcomp(3))
call assert_equal(5, b->byteidxcomp(4))
call assert_equal(-1, b->byteidxcomp(5))
+
+ " string with multiple composing characters
+ let str = '-ą́-ą́'
+ call assert_equal(0, byteidxcomp(str, 0))
+ call assert_equal(1, byteidxcomp(str, 1))
+ call assert_equal(2, byteidxcomp(str, 2))
+ call assert_equal(4, byteidxcomp(str, 3))
+ call assert_equal(6, byteidxcomp(str, 4))
+ call assert_equal(7, byteidxcomp(str, 5))
+ call assert_equal(8, byteidxcomp(str, 6))
+ call assert_equal(10, byteidxcomp(str, 7))
+ call assert_equal(12, byteidxcomp(str, 8))
+ call assert_equal(-1, byteidxcomp(str, 9))
+
+ " empty string
+ call assert_equal(0, byteidxcomp('', 0))
+ call assert_equal(-1, byteidxcomp('', 1))
+
+ " error cases
call assert_fails("call byteidxcomp([], 0)", 'E730:')
+ call assert_fails("call byteidxcomp('abc', [])", 'E745:')
endfunc
-" Test for charidx()
+" Test for byteidx() using a UTF-16 index
+func Test_byteidx_from_utf16_index()
+ " string with single byte characters
+ let str = "abc"
+ for i in range(3)
+ call assert_equal(i, byteidx(str, i, v:true))
+ endfor
+ call assert_equal(3, byteidx(str, 3, v:true))
+ call assert_equal(-1, byteidx(str, 4, v:true))
+
+ " string with two byte characters
+ let str = "a©©b"
+ call assert_equal(0, byteidx(str, 0, v:true))
+ call assert_equal(1, byteidx(str, 1, v:true))
+ call assert_equal(3, byteidx(str, 2, v:true))
+ call assert_equal(5, byteidx(str, 3, v:true))
+ call assert_equal(6, byteidx(str, 4, v:true))
+ call assert_equal(-1, byteidx(str, 5, v:true))
+
+ " string with two byte characters
+ let str = "a😊😊b"
+ call assert_equal(0, byteidx(str, 0, v:true))
+ call assert_equal(1, byteidx(str, 1, v:true))
+ call assert_equal(1, byteidx(str, 2, v:true))
+ call assert_equal(5, byteidx(str, 3, v:true))
+ call assert_equal(5, byteidx(str, 4, v:true))
+ call assert_equal(9, byteidx(str, 5, v:true))
+ call assert_equal(10, byteidx(str, 6, v:true))
+ call assert_equal(-1, byteidx(str, 7, v:true))
+
+ " string with composing characters
+ let str = '-á-b́'
+ call assert_equal(0, byteidx(str, 0, v:true))
+ call assert_equal(1, byteidx(str, 1, v:true))
+ call assert_equal(4, byteidx(str, 2, v:true))
+ call assert_equal(5, byteidx(str, 3, v:true))
+ call assert_equal(8, byteidx(str, 4, v:true))
+ call assert_equal(-1, byteidx(str, 5, v:true))
+
+ " string with multiple composing characters
+ let str = '-ą́-ą́'
+ call assert_equal(0, byteidx(str, 0, v:true))
+ call assert_equal(1, byteidx(str, 1, v:true))
+ call assert_equal(6, byteidx(str, 2, v:true))
+ call assert_equal(7, byteidx(str, 3, v:true))
+ call assert_equal(12, byteidx(str, 4, v:true))
+ call assert_equal(-1, byteidx(str, 5, v:true))
+
+ " empty string
+ call assert_equal(0, byteidx('', 0, v:true))
+ call assert_equal(-1, byteidx('', 1, v:true))
+
+ " error cases
+ call assert_fails('call byteidx(str, 0, [])', 'E745:')
+endfunc
+
+" Test for byteidxcomp() using a UTF-16 index
+func Test_byteidxcomp_from_utf16_index()
+ " string with single byte characters
+ let str = "abc"
+ for i in range(3)
+ call assert_equal(i, byteidxcomp(str, i, v:true))
+ endfor
+ call assert_equal(3, byteidxcomp(str, 3, v:true))
+ call assert_equal(-1, byteidxcomp(str, 4, v:true))
+
+ " string with two byte characters
+ let str = "a©©b"
+ call assert_equal(0, byteidxcomp(str, 0, v:true))
+ call assert_equal(1, byteidxcomp(str, 1, v:true))
+ call assert_equal(3, byteidxcomp(str, 2, v:true))
+ call assert_equal(5, byteidxcomp(str, 3, v:true))
+ call assert_equal(6, byteidxcomp(str, 4, v:true))
+ call assert_equal(-1, byteidxcomp(str, 5, v:true))
+
+ " string with two byte characters
+ let str = "a😊😊b"
+ call assert_equal(0, byteidxcomp(str, 0, v:true))
+ call assert_equal(1, byteidxcomp(str, 1, v:true))
+ call assert_equal(1, byteidxcomp(str, 2, v:true))
+ call assert_equal(5, byteidxcomp(str, 3, v:true))
+ call assert_equal(5, byteidxcomp(str, 4, v:true))
+ call assert_equal(9, byteidxcomp(str, 5, v:true))
+ call assert_equal(10, byteidxcomp(str, 6, v:true))
+ call assert_equal(-1, byteidxcomp(str, 7, v:true))
+
+ " string with composing characters
+ let str = '-á-b́'
+ call assert_equal(0, byteidxcomp(str, 0, v:true))
+ call assert_equal(1, byteidxcomp(str, 1, v:true))
+ call assert_equal(2, byteidxcomp(str, 2, v:true))
+ call assert_equal(4, byteidxcomp(str, 3, v:true))
+ call assert_equal(5, byteidxcomp(str, 4, v:true))
+ call assert_equal(6, byteidxcomp(str, 5, v:true))
+ call assert_equal(8, byteidxcomp(str, 6, v:true))
+ call assert_equal(-1, byteidxcomp(str, 7, v:true))
+ call assert_fails('call byteidxcomp(str, 0, [])', 'E745:')
+
+ " string with multiple composing characters
+ let str = '-ą́-ą́'
+ call assert_equal(0, byteidxcomp(str, 0, v:true))
+ call assert_equal(1, byteidxcomp(str, 1, v:true))
+ call assert_equal(2, byteidxcomp(str, 2, v:true))
+ call assert_equal(4, byteidxcomp(str, 3, v:true))
+ call assert_equal(6, byteidxcomp(str, 4, v:true))
+ call assert_equal(7, byteidxcomp(str, 5, v:true))
+ call assert_equal(8, byteidxcomp(str, 6, v:true))
+ call assert_equal(10, byteidxcomp(str, 7, v:true))
+ call assert_equal(12, byteidxcomp(str, 8, v:true))
+ call assert_equal(-1, byteidxcomp(str, 9, v:true))
+
+ " empty string
+ call assert_equal(0, byteidxcomp('', 0, v:true))
+ call assert_equal(-1, byteidxcomp('', 1, v:true))
+
+ " error cases
+ call assert_fails('call byteidxcomp(str, 0, [])', 'E745:')
+endfunc
+
+" Test for charidx() using a byte index
func Test_charidx()
let a = 'xáb́y'
call assert_equal(0, charidx(a, 0))
@@ -1104,22 +1265,256 @@ func Test_charidx()
call assert_equal(3, charidx(a, 7))
call assert_equal(-1, charidx(a, 8))
call assert_equal(-1, charidx(a, -1))
- call assert_equal(-1, charidx('', 0))
- call assert_equal(-1, charidx(v:_null_string, 0))
" count composing characters
- call assert_equal(0, charidx(a, 0, 1))
- call assert_equal(2, charidx(a, 2, 1))
- call assert_equal(3, charidx(a, 4, 1))
- call assert_equal(5, charidx(a, 7, 1))
- call assert_equal(-1, charidx(a, 8, 1))
+ call assert_equal(0, a->charidx(0, 1))
+ call assert_equal(2, a->charidx(2, 1))
+ call assert_equal(3, a->charidx(4, 1))
+ call assert_equal(5, a->charidx(7, 1))
+ call assert_equal(-1, a->charidx(8, 1))
+
+ " empty string
+ call assert_equal(-1, charidx('', 0))
call assert_equal(-1, charidx('', 0, 1))
- call assert_fails('let x = charidx([], 1)', 'E474:')
- call assert_fails('let x = charidx("abc", [])', 'E474:')
- call assert_fails('let x = charidx("abc", 1, [])', 'E474:')
- call assert_fails('let x = charidx("abc", 1, -1)', 'E1023:')
- call assert_fails('let x = charidx("abc", 1, 2)', 'E1023:')
+ " error cases
+ call assert_equal(-1, charidx(v:_null_string, 0))
+ call assert_fails('let x = charidx([], 1)', 'E1174:')
+ call assert_fails('let x = charidx("abc", [])', 'E1210:')
+ call assert_fails('let x = charidx("abc", 1, [])', 'E1212:')
+ call assert_fails('let x = charidx("abc", 1, -1)', 'E1212:')
+ call assert_fails('let x = charidx("abc", 1, 2)', 'E1212:')
+endfunc
+
+" Test for charidx() using a UTF-16 index
+func Test_charidx_from_utf16_index()
+ " string with single byte characters
+ let str = "abc"
+ for i in range(3)
+ call assert_equal(i, charidx(str, i, v:false, v:true))
+ endfor
+ call assert_equal(-1, charidx(str, 3, v:false, v:true))
+
+ " string with two byte characters
+ let str = "a©©b"
+ call assert_equal(0, charidx(str, 0, v:false, v:true))
+ call assert_equal(1, charidx(str, 1, v:false, v:true))
+ call assert_equal(2, charidx(str, 2, v:false, v:true))
+ call assert_equal(3, charidx(str, 3, v:false, v:true))
+ call assert_equal(-1, charidx(str, 4, v:false, v:true))
+
+ " string with four byte characters
+ let str = "a😊😊b"
+ call assert_equal(0, charidx(str, 0, v:false, v:true))
+ call assert_equal(1, charidx(str, 1, v:false, v:true))
+ call assert_equal(1, charidx(str, 2, v:false, v:true))
+ call assert_equal(2, charidx(str, 3, v:false, v:true))
+ call assert_equal(2, charidx(str, 4, v:false, v:true))
+ call assert_equal(3, charidx(str, 5, v:false, v:true))
+ call assert_equal(-1, charidx(str, 6, v:false, v:true))
+
+ " string with composing characters
+ let str = '-á-b́'
+ for i in str->strcharlen()->range()
+ call assert_equal(i, charidx(str, i, v:false, v:true))
+ endfor
+ call assert_equal(-1, charidx(str, 4, v:false, v:true))
+ for i in str->strchars()->range()
+ call assert_equal(i, charidx(str, i, v:true, v:true))
+ endfor
+ call assert_equal(-1, charidx(str, 6, v:true, v:true))
+
+ " string with multiple composing characters
+ let str = '-ą́-ą́'
+ for i in str->strcharlen()->range()
+ call assert_equal(i, charidx(str, i, v:false, v:true))
+ endfor
+ call assert_equal(-1, charidx(str, 4, v:false, v:true))
+ for i in str->strchars()->range()
+ call assert_equal(i, charidx(str, i, v:true, v:true))
+ endfor
+ call assert_equal(-1, charidx(str, 8, v:true, v:true))
+
+ " empty string
+ call assert_equal(-1, charidx('', 0, v:false, v:true))
+ call assert_equal(-1, charidx('', 0, v:true, v:true))
+
+ " error cases
+ call assert_equal(-1, charidx('', 0, v:false, v:true))
+ call assert_equal(-1, charidx('', 0, v:true, v:true))
+ call assert_equal(-1, charidx(v:_null_string, 0, v:false, v:true))
+ call assert_fails('let x = charidx("abc", 1, v:false, [])', 'E1212:')
+ call assert_fails('let x = charidx("abc", 1, v:true, [])', 'E1212:')
+endfunc
+
+" Test for utf16idx() using a byte index
+func Test_utf16idx_from_byteidx()
+ " UTF-16 index of a string with single byte characters
+ let str = "abc"
+ for i in range(3)
+ call assert_equal(i, utf16idx(str, i))
+ endfor
+ call assert_equal(-1, utf16idx(str, 3))
+
+ " UTF-16 index of a string with two byte characters
+ let str = 'a©©b'
+ call assert_equal(0, str->utf16idx(0))
+ call assert_equal(1, str->utf16idx(1))
+ call assert_equal(1, str->utf16idx(2))
+ call assert_equal(2, str->utf16idx(3))
+ call assert_equal(2, str->utf16idx(4))
+ call assert_equal(3, str->utf16idx(5))
+ call assert_equal(-1, str->utf16idx(6))
+
+ " UTF-16 index of a string with four byte characters
+ let str = 'a😊😊b'
+ call assert_equal(0, utf16idx(str, 0))
+ call assert_equal(2, utf16idx(str, 1))
+ call assert_equal(2, utf16idx(str, 2))
+ call assert_equal(2, utf16idx(str, 3))
+ call assert_equal(2, utf16idx(str, 4))
+ call assert_equal(4, utf16idx(str, 5))
+ call assert_equal(4, utf16idx(str, 6))
+ call assert_equal(4, utf16idx(str, 7))
+ call assert_equal(4, utf16idx(str, 8))
+ call assert_equal(5, utf16idx(str, 9))
+ call assert_equal(-1, utf16idx(str, 10))
+
+ " UTF-16 index of a string with composing characters
+ let str = '-á-b́'
+ call assert_equal(0, utf16idx(str, 0))
+ call assert_equal(1, utf16idx(str, 1))
+ call assert_equal(1, utf16idx(str, 2))
+ call assert_equal(1, utf16idx(str, 3))
+ call assert_equal(2, utf16idx(str, 4))
+ call assert_equal(3, utf16idx(str, 5))
+ call assert_equal(3, utf16idx(str, 6))
+ call assert_equal(3, utf16idx(str, 7))
+ call assert_equal(-1, utf16idx(str, 8))
+ call assert_equal(0, utf16idx(str, 0, v:true))
+ call assert_equal(1, utf16idx(str, 1, v:true))
+ call assert_equal(2, utf16idx(str, 2, v:true))
+ call assert_equal(2, utf16idx(str, 3, v:true))
+ call assert_equal(3, utf16idx(str, 4, v:true))
+ call assert_equal(4, utf16idx(str, 5, v:true))
+ call assert_equal(5, utf16idx(str, 6, v:true))
+ call assert_equal(5, utf16idx(str, 7, v:true))
+ call assert_equal(-1, utf16idx(str, 8, v:true))
+
+ " string with multiple composing characters
+ let str = '-ą́-ą́'
+ call assert_equal(0, utf16idx(str, 0))
+ call assert_equal(1, utf16idx(str, 1))
+ call assert_equal(1, utf16idx(str, 2))
+ call assert_equal(1, utf16idx(str, 3))
+ call assert_equal(1, utf16idx(str, 4))
+ call assert_equal(1, utf16idx(str, 5))
+ call assert_equal(2, utf16idx(str, 6))
+ call assert_equal(3, utf16idx(str, 7))
+ call assert_equal(3, utf16idx(str, 8))
+ call assert_equal(3, utf16idx(str, 9))
+ call assert_equal(3, utf16idx(str, 10))
+ call assert_equal(3, utf16idx(str, 11))
+ call assert_equal(-1, utf16idx(str, 12))
+ call assert_equal(0, utf16idx(str, 0, v:true))
+ call assert_equal(1, utf16idx(str, 1, v:true))
+ call assert_equal(2, utf16idx(str, 2, v:true))
+ call assert_equal(2, utf16idx(str, 3, v:true))
+ call assert_equal(3, utf16idx(str, 4, v:true))
+ call assert_equal(3, utf16idx(str, 5, v:true))
+ call assert_equal(4, utf16idx(str, 6, v:true))
+ call assert_equal(5, utf16idx(str, 7, v:true))
+ call assert_equal(6, utf16idx(str, 8, v:true))
+ call assert_equal(6, utf16idx(str, 9, v:true))
+ call assert_equal(7, utf16idx(str, 10, v:true))
+ call assert_equal(7, utf16idx(str, 11, v:true))
+ call assert_equal(-1, utf16idx(str, 12, v:true))
+
+ " empty string
+ call assert_equal(-1, utf16idx('', 0))
+ call assert_equal(-1, utf16idx('', 0, v:true))
+
+ " error cases
+ call assert_equal(-1, utf16idx("", 0))
+ call assert_equal(-1, utf16idx("abc", -1))
+ call assert_equal(-1, utf16idx(v:_null_string, 0))
+ call assert_fails('let l = utf16idx([], 0)', 'E1174:')
+ call assert_fails('let l = utf16idx("ab", [])', 'E1210:')
+ call assert_fails('let l = utf16idx("ab", 0, [])', 'E1212:')
+endfunc
+
+" Test for utf16idx() using a character index
+func Test_utf16idx_from_charidx()
+ let str = "abc"
+ for i in str->strcharlen()->range()
+ call assert_equal(i, utf16idx(str, i, v:false, v:true))
+ endfor
+ call assert_equal(-1, utf16idx(str, 3, v:false, v:true))
+
+ " UTF-16 index of a string with two byte characters
+ let str = "a©©b"
+ for i in str->strcharlen()->range()
+ call assert_equal(i, utf16idx(str, i, v:false, v:true))
+ endfor
+ call assert_equal(-1, utf16idx(str, 4, v:false, v:true))
+
+ " UTF-16 index of a string with four byte characters
+ let str = "a😊😊b"
+ call assert_equal(0, utf16idx(str, 0, v:false, v:true))
+ call assert_equal(2, utf16idx(str, 1, v:false, v:true))
+ call assert_equal(4, utf16idx(str, 2, v:false, v:true))
+ call assert_equal(5, utf16idx(str, 3, v:false, v:true))
+ call assert_equal(-1, utf16idx(str, 4, v:false, v:true))
+
+ " UTF-16 index of a string with composing characters
+ let str = '-á-b́'
+ for i in str->strcharlen()->range()
+ call assert_equal(i, utf16idx(str, i, v:false, v:true))
+ endfor
+ call assert_equal(-1, utf16idx(str, 4, v:false, v:true))
+ for i in str->strchars()->range()
+ call assert_equal(i, utf16idx(str, i, v:true, v:true))
+ endfor
+ call assert_equal(-1, utf16idx(str, 6, v:true, v:true))
+
+ " string with multiple composing characters
+ let str = '-ą́-ą́'
+ for i in str->strcharlen()->range()
+ call assert_equal(i, utf16idx(str, i, v:false, v:true))
+ endfor
+ call assert_equal(-1, utf16idx(str, 4, v:false, v:true))
+ for i in str->strchars()->range()
+ call assert_equal(i, utf16idx(str, i, v:true, v:true))
+ endfor
+ call assert_equal(-1, utf16idx(str, 8, v:true, v:true))
+
+ " empty string
+ call assert_equal(-1, utf16idx('', 0, v:false, v:true))
+ call assert_equal(-1, utf16idx('', 0, v:true, v:true))
+
+ " error cases
+ call assert_equal(-1, utf16idx(v:_null_string, 0, v:true, v:true))
+ call assert_fails('let l = utf16idx("ab", 0, v:false, [])', 'E1212:')
+endfunc
+
+" Test for strutf16len()
+func Test_strutf16len()
+ call assert_equal(3, strutf16len('abc'))
+ call assert_equal(3, 'abc'->strutf16len(v:true))
+ call assert_equal(4, strutf16len('a©©b'))
+ call assert_equal(4, strutf16len('a©©b', v:true))
+ call assert_equal(6, strutf16len('a😊😊b'))
+ call assert_equal(6, strutf16len('a😊😊b', v:true))
+ call assert_equal(4, strutf16len('-á-b́'))
+ call assert_equal(6, strutf16len('-á-b́', v:true))
+ call assert_equal(4, strutf16len('-ą́-ą́'))
+ call assert_equal(8, strutf16len('-ą́-ą́', v:true))
+ call assert_equal(0, strutf16len(''))
+
+ " error cases
+ call assert_fails('let l = strutf16len([])', 'E1174:')
+ call assert_fails('let l = strutf16len("a", [])', 'E1212:')
+ call assert_equal(0, strutf16len(v:_null_string))
endfunc
func Test_count()
@@ -1605,7 +2000,7 @@ func Test_trim()
call assert_fails('eval trim(" vim ", " ", [])', 'E745:')
call assert_fails('eval trim(" vim ", " ", -1)', 'E475:')
call assert_fails('eval trim(" vim ", " ", 3)', 'E475:')
- call assert_fails('eval trim(" vim ", 0)', 'E475:')
+ call assert_fails('eval trim(" vim ", 0)', 'E1174:')
let chars = join(map(range(1, 0x20) + [0xa0], {n -> n->nr2char()}), '')
call assert_equal("x", trim(chars . "x" . chars))
@@ -2007,7 +2402,7 @@ func Test_call()
endfunction
let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
eval mydict.len->call([], mydict)->assert_equal(4)
- call assert_fails("call call('Mylen', [], 0)", 'E715:')
+ call assert_fails("call call('Mylen', [], 0)", 'E1206:')
call assert_fails('call foo', 'E107:')
" These once caused a crash.
@@ -2567,7 +2962,7 @@ endfunc
" Test for gettext()
func Test_gettext()
- call assert_fails('call gettext(1)', 'E475:')
+ call assert_fails('call gettext(1)', 'E1174:')
endfunc
func Test_builtin_check()
@@ -2607,4 +3002,41 @@ func Test_builtin_check()
endfunc
+" Test for virtcol()
+func Test_virtcol()
+ enew!
+ call setline(1, "the\tquick\tbrown\tfox")
+ norm! 4|
+ call assert_equal(8, virtcol('.'))
+ call assert_equal(8, virtcol('.', v:false))
+ call assert_equal([4, 8], virtcol('.', v:true))
+ bwipe!
+endfunc
+
+func Test_delfunc_while_listing()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ set nocompatible
+ for i in range(1, 999)
+ exe 'func ' .. 'MyFunc' .. i .. '()'
+ endfunc
+ endfor
+ au CmdlineLeave : call timer_start(0, {-> execute('delfunc MyFunc622')})
+ END
+ call writefile(lines, 'Xfunctionclear', 'D')
+ let buf = RunVimInTerminal('-S Xfunctionclear', {'rows': 12})
+
+ " This was using freed memory. The height of the terminal must be so that
+ " the next function to be listed with "j" is the one that is deleted in the
+ " timer callback, tricky!
+ call term_sendkeys(buf, ":func /MyFunc\<CR>")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "j")
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "\<CR>")
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_listdict.vim b/test/old/testdir/test_listdict.vim
index cbed71bb0a..0ff3582da9 100644
--- a/test/old/testdir/test_listdict.vim
+++ b/test/old/testdir/test_listdict.vim
@@ -699,7 +699,7 @@ func Test_reverse_sort_uniq()
call assert_fails('call reverse("")', 'E899:')
call assert_fails('call uniq([1, 2], {x, y -> []})', 'E745:')
- call assert_fails("call sort([1, 2], function('min'), 1)", "E715:")
+ call assert_fails("call sort([1, 2], function('min'), 1)", "E1206:")
call assert_fails("call sort([1, 2], function('invalid_func'))", "E700:")
call assert_fails("call sort([1, 2], function('min'))", "E118:")
endfunc
diff --git a/test/old/testdir/test_maparg.vim b/test/old/testdir/test_maparg.vim
index 19130c1569..12670671dd 100644
--- a/test/old/testdir/test_maparg.vim
+++ b/test/old/testdir/test_maparg.vim
@@ -270,7 +270,7 @@ func Test_mapset()
bwipe!
call assert_fails('call mapset([], v:false, {})', 'E730:')
- call assert_fails('call mapset("i", 0, "")', 'E715:')
+ call assert_fails('call mapset("i", 0, "")', 'E1206:')
call assert_fails('call mapset("i", 0, {})', 'E460:')
endfunc
diff --git a/test/old/testdir/test_matchfuzzy.vim b/test/old/testdir/test_matchfuzzy.vim
index b46550fbc3..be5c629cf5 100644
--- a/test/old/testdir/test_matchfuzzy.vim
+++ b/test/old/testdir/test_matchfuzzy.vim
@@ -67,7 +67,7 @@ func Test_matchfuzzy()
call assert_equal([{'id' : 6, 'val' : 'camera'}], matchfuzzy(l, 'cam', {'key' : 'val'}))
call assert_equal([], matchfuzzy(l, 'day', {'text_cb' : {v -> v.val}}))
call assert_equal([], matchfuzzy(l, 'day', {'key' : 'val'}))
- call assert_fails("let x = matchfuzzy(l, 'cam', 'random')", 'E715:')
+ call assert_fails("let x = matchfuzzy(l, 'cam', 'random')", 'E1206:')
call assert_equal([], matchfuzzy(l, 'day', {'text_cb' : {v -> []}}))
call assert_equal([], matchfuzzy(l, 'day', {'text_cb' : {v -> 1}}))
call assert_fails("let x = matchfuzzy(l, 'day', {'text_cb' : {a, b -> 1}})", 'E119:')
@@ -76,7 +76,7 @@ func Test_matchfuzzy()
" call assert_fails("let x = matchfuzzy(l, 'cam', {'text_cb' : []})", 'E921:')
call assert_fails("let x = matchfuzzy(l, 'cam', {'text_cb' : []})", 'E6000:')
call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : []})", 'E730:')
- call assert_fails("let x = matchfuzzy(l, 'cam', v:_null_dict)", 'E715:')
+ call assert_fails("let x = matchfuzzy(l, 'cam', v:_null_dict)", 'E1297:')
call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : v:_null_string})", 'E475:')
" Nvim doesn't have null functions
" call assert_fails("let x = matchfuzzy(l, 'foo', {'text_cb' : test_null_function()})", 'E475:')
@@ -144,7 +144,7 @@ func Test_matchfuzzypos()
\ matchfuzzypos(l, 'cam', {'key' : 'val'}))
call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'text_cb' : {v -> v.val}}))
call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'key' : 'val'}))
- call assert_fails("let x = matchfuzzypos(l, 'cam', 'random')", 'E715:')
+ call assert_fails("let x = matchfuzzypos(l, 'cam', 'random')", 'E1206:')
call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'text_cb' : {v -> []}}))
call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'text_cb' : {v -> 1}}))
call assert_fails("let x = matchfuzzypos(l, 'day', {'text_cb' : {a, b -> 1}})", 'E119:')
@@ -153,7 +153,7 @@ func Test_matchfuzzypos()
" call assert_fails("let x = matchfuzzypos(l, 'cam', {'text_cb' : []})", 'E921:')
call assert_fails("let x = matchfuzzypos(l, 'cam', {'text_cb' : []})", 'E6000:')
call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : []})", 'E730:')
- call assert_fails("let x = matchfuzzypos(l, 'cam', v:_null_dict)", 'E715:')
+ call assert_fails("let x = matchfuzzypos(l, 'cam', v:_null_dict)", 'E1297:')
call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : v:_null_string})", 'E475:')
" Nvim doesn't have null functions
" call assert_fails("let x = matchfuzzypos(l, 'foo', {'text_cb' : test_null_function()})", 'E475:')
diff --git a/test/old/testdir/test_partial.vim b/test/old/testdir/test_partial.vim
index 302bc22d93..8b62e4a0e5 100644
--- a/test/old/testdir/test_partial.vim
+++ b/test/old/testdir/test_partial.vim
@@ -86,7 +86,7 @@ func Test_partial_dict()
call assert_equal("Hello", dict.tr())
call assert_fails("let F=function('setloclist', 10)", "E923:")
- call assert_fails("let F=function('setloclist', [], [])", "E922:")
+ call assert_fails("let F=function('setloclist', [], [])", "E1206:")
endfunc
func Test_partial_implicit()
diff --git a/test/old/testdir/test_search_stat.vim b/test/old/testdir/test_search_stat.vim
index 1b2d854829..8dfc850956 100644
--- a/test/old/testdir/test_search_stat.vim
+++ b/test/old/testdir/test_search_stat.vim
@@ -259,7 +259,7 @@ func Test_search_stat()
endfunc
func Test_searchcount_fails()
- call assert_fails('echo searchcount("boo!")', 'E715:')
+ call assert_fails('echo searchcount("boo!")', 'E1206:')
call assert_fails('echo searchcount({"timeout" : []})', 'E745:')
call assert_fails('echo searchcount({"maxcount" : []})', 'E745:')
call assert_fails('echo searchcount({"pattern" : []})', 'E730:')
diff --git a/test/old/testdir/test_signs.vim b/test/old/testdir/test_signs.vim
index 129f1c1a0c..1e972371a5 100644
--- a/test/old/testdir/test_signs.vim
+++ b/test/old/testdir/test_signs.vim
@@ -463,7 +463,7 @@ func Test_sign_funcs()
call assert_fails('call sign_define("sign4", {"text" : "===>"})', 'E239:')
" call assert_fails('call sign_define("sign5", {"text" : ""})', 'E239:')
call assert_fails('call sign_define({})', 'E731:')
- call assert_fails('call sign_define("sign6", [])', 'E715:')
+ call assert_fails('call sign_define("sign6", [])', 'E1206:')
" Tests for sign_getdefined()
call assert_equal([], sign_getdefined("none"))
@@ -490,8 +490,7 @@ func Test_sign_funcs()
" Tests for invalid arguments to sign_place()
call assert_fails('call sign_place([], "", "mySign", 1)', 'E745:')
call assert_fails('call sign_place(5, "", "mySign", -1)', 'E158:')
- call assert_fails('call sign_place(-1, "", "sign1", "Xsign", [])',
- \ 'E715:')
+ call assert_fails('call sign_place(-1, "", "sign1", "Xsign", [])', 'E1206:')
call assert_fails('call sign_place(-1, "", "sign1", "Xsign",
\ {"lnum" : 30})', 'E474:')
call assert_fails('call sign_place(10, "", "xsign1x", "Xsign",
@@ -526,7 +525,7 @@ func Test_sign_funcs()
call assert_fails("call sign_getplaced('dummy.sign')", 'E158:')
call assert_fails('call sign_getplaced("&")', 'E158:')
call assert_fails('call sign_getplaced(-1)', 'E158:')
- call assert_fails('call sign_getplaced("Xsign", [])', 'E715:')
+ call assert_fails('call sign_getplaced("Xsign", [])', 'E1206:')
call assert_equal([{'bufnr' : bufnr(''), 'signs' : []}],
\ sign_getplaced('Xsign', {'lnum' : 1000000}))
call assert_fails("call sign_getplaced('Xsign', {'lnum' : []})",
@@ -549,7 +548,7 @@ func Test_sign_funcs()
\ {'id' : 20, 'buffer' : '&'})", 'E158:')
call assert_fails("call sign_unplace('g1',
\ {'id' : 20, 'buffer' : 200})", 'E158:')
- call assert_fails("call sign_unplace('g1', 'mySign')", 'E715:')
+ call assert_fails("call sign_unplace('g1', 'mySign')", 'E1206:')
call sign_unplace('*')
@@ -701,7 +700,7 @@ func Test_sign_group()
call assert_equal([], sign_getplaced(bnum, {'group' : '*'})[0].signs)
" Error case
- call assert_fails("call sign_unplace({})", 'E474:')
+ call assert_fails("call sign_unplace({})", 'E1174:')
" Place a sign in the global group and try to delete it using a group
call assert_equal(5, sign_place(5, '', 'sign1', bnum, {'lnum' : 10}))
@@ -1568,8 +1567,7 @@ func Test_sign_priority()
\ s[0].signs)
" Error case
- call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign',
- \ [])", 'E715:')
+ call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign', [])", 'E1206:')
call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign',
\ {'priority' : []})", 'E745:')
call sign_unplace('*')
diff --git a/test/old/testdir/test_tagjump.vim b/test/old/testdir/test_tagjump.vim
index be60a3535c..f330bca125 100644
--- a/test/old/testdir/test_tagjump.vim
+++ b/test/old/testdir/test_tagjump.vim
@@ -405,10 +405,10 @@ func Test_getsettagstack()
" Error cases
call assert_equal({}, gettagstack(100))
call assert_equal(-1, settagstack(100, {'items' : []}))
- call assert_fails('call settagstack(1, [1, 10])', 'E715')
- call assert_fails("call settagstack(1, {'items' : 10})", 'E714')
- call assert_fails("call settagstack(1, {'items' : []}, 10)", 'E928')
- call assert_fails("call settagstack(1, {'items' : []}, 'b')", 'E962')
+ call assert_fails('call settagstack(1, [1, 10])', 'E1206:')
+ call assert_fails("call settagstack(1, {'items' : 10})", 'E714:')
+ call assert_fails("call settagstack(1, {'items' : []}, 10)", 'E1174:')
+ call assert_fails("call settagstack(1, {'items' : []}, 'b')", 'E962:')
call assert_equal(-1, settagstack(0, v:_null_dict))
set tags=Xtags
diff --git a/test/old/testdir/test_timers.vim b/test/old/testdir/test_timers.vim
index f94ee6c9f3..37226c7efb 100644
--- a/test/old/testdir/test_timers.vim
+++ b/test/old/testdir/test_timers.vim
@@ -93,7 +93,13 @@ func Test_timer_info()
call timer_stop(id)
call assert_equal([], timer_info(id))
- call assert_fails('call timer_info("abc")', 'E39:')
+ call assert_fails('call timer_info("abc")', 'E1210:')
+
+ " check repeat count inside the callback
+ let g:timer_repeat = []
+ let tid = timer_start(10, {tid -> execute("call add(g:timer_repeat, timer_info(tid)[0].repeat)")}, #{repeat: 3})
+ call WaitForAssert({-> assert_equal([2, 1, 0], g:timer_repeat)})
+ unlet g:timer_repeat
endfunc
func Test_timer_stopall()
@@ -228,9 +234,9 @@ func Test_timer_errors()
sleep 50m
call assert_equal(3, g:call_count)
- call assert_fails('call timer_start(100, "MyHandler", "abc")', 'E475:')
+ call assert_fails('call timer_start(100, "MyHandler", "abc")', 'E1206:')
call assert_fails('call timer_start(100, [])', 'E921:')
- call assert_fails('call timer_stop("abc")', 'E39:')
+ call assert_fails('call timer_stop("abc")', 'E1210:')
endfunc
func FuncWithCaughtError(timer)
diff --git a/test/old/testdir/test_window_cmd.vim b/test/old/testdir/test_window_cmd.vim
index 88135199fe..9320d67498 100644
--- a/test/old/testdir/test_window_cmd.vim
+++ b/test/old/testdir/test_window_cmd.vim
@@ -735,7 +735,7 @@ func Test_relative_cursor_position_in_one_line_window()
only!
bwipe!
- call assert_fails('call winrestview(v:_null_dict)', 'E474:')
+ call assert_fails('call winrestview(v:_null_dict)', 'E1297:')
endfunc
func Test_relative_cursor_position_after_move_and_resize()
@@ -936,7 +936,7 @@ func Test_winrestview()
call assert_equal(view, winsaveview())
bwipe!
- call assert_fails('call winrestview(v:_null_dict)', 'E474:')
+ call assert_fails('call winrestview(v:_null_dict)', 'E1297:')
endfunc
func Test_win_splitmove()
@@ -967,7 +967,7 @@ func Test_win_splitmove()
call assert_equal(bufname(winbufnr(2)), 'b')
call assert_equal(bufname(winbufnr(3)), 'a')
call assert_equal(bufname(winbufnr(4)), 'd')
- call assert_fails('call win_splitmove(winnr(), winnr("k"), v:_null_dict)', 'E474:')
+ call assert_fails('call win_splitmove(winnr(), winnr("k"), v:_null_dict)', 'E1297:')
only | bd
call assert_fails('call win_splitmove(winnr(), 123)', 'E957:')