neovim/test/functional/plugin/shada_spec.lua
2024-04-10 15:53:50 +01:00

3620 lines
115 KiB
Lua

local t = require('test.functional.testutil')()
local Screen = require('test.functional.ui.screen')
local clear = t.clear
local eq, api, nvim_eval, nvim_command, exc_exec, fn, nvim_feed =
t.eq, t.api, t.eval, t.command, t.exc_exec, t.fn, t.feed
local neq = t.neq
local read_file = t.read_file
local t_shada = require('test.functional.shada.testutil')
local get_shada_rw = t_shada.get_shada_rw
local function reset(shada_file)
clear { args = { '-u', 'NORC', '-i', shada_file or 'NONE' } }
end
local mpack_eq = function(expected, mpack_result)
local mpack_keys = { 'type', 'timestamp', 'length', 'value' }
local unpack = vim.mpack.Unpacker()
local actual = {}
local cur, val
local i = 0
local off = 1
while off <= #mpack_result do
val, off = unpack(mpack_result, off)
if i % 4 == 0 then
cur = {}
actual[#actual + 1] = cur
end
local key = mpack_keys[(i % 4) + 1]
if key ~= 'length' then
if key == 'timestamp' and math.abs(val - os.time()) < 2 then
val = 'current'
end
cur[key] = val
end
i = i + 1
end
eq(expected, actual)
end
local wshada, _, fname = get_shada_rw('Xtest-functional-plugin-shada.shada')
local wshada_tmp, _, fname_tmp = get_shada_rw('Xtest-functional-plugin-shada.shada.tmp.f')
describe('autoload/shada.vim', function()
local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
before_each(function()
reset()
nvim_command([[
function ModifyVal(val)
if type(a:val) == type([])
if len(a:val) == 2 && type(a:val[0]) == type('') && a:val[0][0] is# '!' && has_key(v:msgpack_types, a:val[0][1:])
return {'_TYPE': v:msgpack_types[ a:val[0][1:] ], '_VAL': a:val[1]}
else
return map(copy(a:val), 'ModifyVal(v:val)')
endif
elseif type(a:val) == type({})
let keys = sort(keys(a:val))
let ret = {'_TYPE': v:msgpack_types.map, '_VAL': []}
for key in keys
let k = {'_TYPE': v:msgpack_types.string, '_VAL': split(key, "\n", 1)}
let v = ModifyVal(a:val[key])
call add(ret._VAL, [k, v])
unlet v
endfor
return ret
elseif type(a:val) == type('')
return {'_TYPE': v:msgpack_types.binary, '_VAL': split(a:val, "\n", 1)}
else
return a:val
endif
endfunction
]])
end)
local sp = function(typ, val)
return ('{"_TYPE": v:msgpack_types.%s, "_VAL": %s}'):format(typ, val)
end
describe('function shada#mpack_to_sd', function()
local mpack2sd = function(arg)
return ('shada#mpack_to_sd(%s)'):format(arg)
end
it('works', function()
eq({}, nvim_eval(mpack2sd('[]')))
eq({ { type = 1, timestamp = 5, length = 1, data = 7 } }, nvim_eval(mpack2sd('[1, 5, 1, 7]')))
eq({
{ type = 1, timestamp = 5, length = 1, data = 7 },
{ type = 1, timestamp = 10, length = 1, data = 5 },
}, nvim_eval(mpack2sd('[1, 5, 1, 7, 1, 10, 1, 5]')))
eq(
'zero-uint:Entry 1 has type element which is zero',
exc_exec('call ' .. mpack2sd('[0, 5, 1, 7]'))
)
eq(
'zero-uint:Entry 1 has type element which is zero',
exc_exec('call ' .. mpack2sd(('[%s, 5, 1, 7]'):format(sp('integer', '[1, 0, 0, 0]'))))
)
eq(
'not-uint:Entry 1 has timestamp element which is not an unsigned integer',
exc_exec('call ' .. mpack2sd('[1, -1, 1, 7]'))
)
eq(
'not-uint:Entry 1 has length element which is not an unsigned integer',
exc_exec('call ' .. mpack2sd('[1, 1, -1, 7]'))
)
eq(
'not-uint:Entry 1 has type element which is not an unsigned integer',
exc_exec('call ' .. mpack2sd('["", 1, -1, 7]'))
)
end)
end)
describe('function shada#sd_to_strings', function()
local sd2strings_eq = function(expected, arg)
if type(arg) == 'table' then
eq(expected, fn['shada#sd_to_strings'](arg))
else
eq(expected, nvim_eval(('shada#sd_to_strings(%s)'):format(arg)))
end
end
it('works with empty input', function()
sd2strings_eq({}, '[]')
end)
it('works with unknown items', function()
sd2strings_eq({
'Unknown (0x64) with timestamp ' .. epoch .. ':',
' = 100',
}, { { type = 100, timestamp = 0, length = 1, data = 100 } })
sd2strings_eq(
{
'Unknown (0x4000001180000006) with timestamp ' .. epoch .. ':',
' = 100',
},
('[{"type": %s, "timestamp": 0, "length": 1, "data": 100}]'):format(
sp('integer', '[1, 1, 35, 6]')
)
)
end)
it('works with multiple unknown items', function()
sd2strings_eq({
'Unknown (0x64) with timestamp ' .. epoch .. ':',
' = 100',
'Unknown (0x65) with timestamp ' .. epoch .. ':',
' = 500',
}, {
{ type = 100, timestamp = 0, length = 1, data = 100 },
{ type = 101, timestamp = 0, length = 1, data = 500 },
})
end)
it('works with header items', function()
sd2strings_eq({
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
}, { { type = 1, timestamp = 0, data = { generator = 'test' } } })
sd2strings_eq({
'Header with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + a 1',
' + b 2',
' + c column 3',
' + d 4',
}, { { type = 1, timestamp = 0, data = { a = 1, b = 2, c = 3, d = 4 } } })
sd2strings_eq({
'Header with timestamp ' .. epoch .. ':',
' % Key Value',
' + t "test"',
}, { { type = 1, timestamp = 0, data = { t = 'test' } } })
sd2strings_eq({
'Header with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}, { { type = 1, timestamp = 0, data = { 1, 2, 3 } } })
end)
it('processes standard keys correctly, even in header', function()
sd2strings_eq(
{
'Header with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + c column 0',
' + f file name "/tmp/foo"',
' + l line number 10',
" + n name '@'",
' + rc contents ["abc", "def"]',
' + rt type CHARACTERWISE',
' + ru is_unnamed FALSE',
' + rw block width 10',
' + sb search backward TRUE',
' + sc smartcase value FALSE',
' + se place cursor at end TRUE',
' + sh v:hlsearch value TRUE',
' + sl has line offset FALSE',
' + sm magic value TRUE',
' + so offset value 10',
' + sp pattern "100"',
' + ss is :s pattern TRUE',
' + su is last used FALSE',
},
([[ [{'type': 1, 'timestamp': 0, 'data': {
'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'so': 10,
'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'sp': '100',
'rt': 0,
'rw': 10,
'rc': ['abc', 'def'],
'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'n': 0x40,
'l': 10,
'c': 0,
'f': '/tmp/foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Header with timestamp ' .. epoch .. ':',
' % Key Description____ Value',
' # Expected integer',
' + c column "abc"',
' # Expected no NUL bytes',
' + f file name "abc\\0def"',
' # Value is negative',
' + l line number -10',
' # Value is negative',
' + n name -64',
' # Expected array value',
' + rc contents "10"',
' # Unexpected enum value: expected one of '
.. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
' + rt type 10',
' # Expected boolean',
' + ru is_unnamed 10',
' # Expected boolean',
' + sc smartcase value NIL',
' # Expected boolean',
' + sm magic value "TRUE"',
' # Expected integer',
' + so offset value "TRUE"',
' # Expected binary string',
' + sp pattern ="abc"',
},
([[ [{'type': 1, 'timestamp': 0, 'data': {
'sm': 'TRUE',
'sc': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
'so': 'TRUE',
'sp': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]},
'rt': 10,
'rc': '10',
'ru': 10,
'n': -0x40,
'l': -10,
'c': 'abc',
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Header with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected no NUL bytes',
' + f file name "abc\\0def"',
' # Expected array of binary strings',
' + rc contents ["abc", ="abc"]',
' # Expected integer',
' + rt type "ABC"',
},
([[ [{'type': 1, 'timestamp': 0, 'data': {
'rt': 'ABC',
'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}],
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Header with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected no NUL bytes',
' + rc contents ["abc", "a\\nd\\0"]',
},
([[ [{'type': 1, 'timestamp': 0, 'data': {
'rc': ["abc", {'_TYPE': v:msgpack_types.binary, '_VAL': ["a", "d\n"]}],
}}] ]]):gsub('\n', '')
)
end)
it('works with search pattern items', function()
sd2strings_eq({
'Search pattern with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}, { { type = 2, timestamp = 0, data = { 1, 2, 3 } } })
sd2strings_eq(
{
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern "abc"',
' + sh v:hlsearch value FALSE',
' + ss is :s pattern FALSE',
' + sb search backward FALSE',
' + sm magic value TRUE',
' + sc smartcase value FALSE',
' + sl has line offset FALSE',
' + se place cursor at end FALSE',
' + so offset value 0',
' + su is last used TRUE',
},
([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': 'abc',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern "abc"',
' + sh v:hlsearch value FALSE',
' + ss is :s pattern FALSE',
' + sb search backward FALSE',
' + sm magic value TRUE',
' + sc smartcase value FALSE',
' + sl has line offset FALSE',
' + se place cursor at end FALSE',
' + so offset value 0',
' + su is last used TRUE',
' + sX NIL',
' + sY NIL',
' + sZ NIL',
},
([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': 'abc',
'sZ': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
'sY': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
'sX': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern "abc"',
' + sh v:hlsearch value FALSE',
' + ss is :s pattern FALSE',
' + sb search backward FALSE',
' + sm magic value TRUE',
' + sc smartcase value FALSE',
' + sl has line offset FALSE',
' + se place cursor at end FALSE',
' + so offset value 0',
' + su is last used TRUE',
},
([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': 'abc',
'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'so': 0,
'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' # Required key missing: sp',
' + sh v:hlsearch value FALSE',
' + ss is :s pattern FALSE',
' + sb search backward FALSE',
' + sm magic value TRUE',
' + sc smartcase value FALSE',
' + sl has line offset FALSE',
' + se place cursor at end FALSE',
' + so offset value 0',
' + su is last used TRUE',
},
([[ [{'type': 2, 'timestamp': 0, 'data': {
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern ""',
' + sh v:hlsearch value TRUE',
' + ss is :s pattern TRUE',
' + sb search backward TRUE',
' + sm magic value FALSE',
' + sc smartcase value TRUE',
' + sl has line offset TRUE',
' + se place cursor at end TRUE',
' + so offset value -10',
' + su is last used FALSE',
},
([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': '',
'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'so': -10,
'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' # Expected binary string',
' + sp pattern 0',
' # Expected boolean',
' + sh v:hlsearch value 0',
' # Expected boolean',
' + ss is :s pattern 0',
' # Expected boolean',
' + sb search backward 0',
' # Expected boolean',
' + sm magic value 0',
' # Expected boolean',
' + sc smartcase value 0',
' # Expected boolean',
' + sl has line offset 0',
' # Expected boolean',
' + se place cursor at end 0',
' # Expected integer',
' + so offset value ""',
' # Expected boolean',
' + su is last used 0',
},
([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': 0,
'sh': 0,
'ss': 0,
'sb': 0,
'sm': 0,
'sc': 0,
'sl': 0,
'se': 0,
'so': '',
'su': 0,
}}] ]]):gsub('\n', '')
)
end)
it('works with replacement string items', function()
sd2strings_eq({
'Replacement string with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
}, { { type = 3, timestamp = 0, data = { a = { 10 } } } })
sd2strings_eq(
{
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' # Expected more elements in list',
},
([[ [{'type': 3, 'timestamp': 0, 'data': [
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' # Expected binary string',
' - :s replacement string 0',
},
([[ [{'type': 3, 'timestamp': 0, 'data': [
0,
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' # Expected no NUL bytes',
' - :s replacement string "abc\\0def"',
},
([[ [{'type': 3, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]},
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
},
([[ [{'type': 3, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc", "def"]},
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
' - 0',
},
([[ [{'type': 3, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc", "def"]},
0,
]}] ]]):gsub('\n', '')
)
end)
it('works with history entry items', function()
sd2strings_eq({
'History entry with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
}, { { type = 4, timestamp = 0, data = { a = { 10 } } } })
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Expected more elements in list',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Expected integer',
' - history type ""',
' # Expected more elements in list',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
'',
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
.. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
' - history type 5',
' - contents ""',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
5,
''
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
.. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
' - history type 5',
' - contents ""',
' - 32',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
5,
'',
0x20
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents ""',
' - 32',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
0,
'',
0x20
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type SEARCH',
' - contents ""',
" - separator ' '",
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'',
0x20
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type SEARCH',
' - contents ""',
' # Expected more elements in list',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'',
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type EXPR',
' - contents ""',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
2,
'',
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type INPUT',
' - contents ""',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
3,
'',
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type DEBUG',
' - contents ""',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
4,
'',
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type DEBUG',
' # Expected binary string',
' - contents 10',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
4,
10,
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type DEBUG',
' # Expected no NUL bytes',
' - contents "abc\\0def"',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
4,
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]},
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type SEARCH',
' - contents "abc"',
' # Expected integer',
' - separator ""',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'abc',
'',
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type SEARCH',
' - contents "abc"',
' # Value is negative',
' - separator -1',
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'abc',
-1,
]}] ]]):gsub('\n', '')
)
-- Regression: NUL separator must be properly supported
sd2strings_eq(
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type SEARCH',
' - contents ""',
" - separator '\\0'",
},
([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'',
0x0
]}] ]]):gsub('\n', '')
)
end)
it('works with register items', function()
sd2strings_eq({
'Register with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}, { { type = 5, timestamp = 0, data = { 1, 2, 3 } } })
sd2strings_eq(
{
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: n',
' # Required key missing: rc',
' + rw block width 0',
' + rt type CHARACTERWISE',
' + ru is_unnamed FALSE',
},
([[ [{'type': 5, 'timestamp': 0, 'data': {
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' # Required key missing: rc',
' + rw block width 0',
' + rt type CHARACTERWISE',
' + ru is_unnamed FALSE',
},
([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents ["abc", "def"]',
' + rw block width 0',
' + rt type CHARACTERWISE',
' + ru is_unnamed FALSE',
},
([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ["abc", "def"],
'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 0',
' + rt type CHARACTERWISE',
' + ru is_unnamed TRUE',
},
([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 0',
' + rt type CHARACTERWISE',
' + ru is_unnamed FALSE',
},
([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'rw': 0,
'rt': 0,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 5',
' + rt type LINEWISE',
' + ru is_unnamed FALSE',
},
([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'rw': 5,
'rt': 1,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' # Expected integer',
' + rw block width ""',
' + rt type BLOCKWISE',
' # Expected boolean',
' + ru is_unnamed ""',
},
([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'rw': "",
'rt': 2,
'ru': ""
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' # Expected array value',
' + rc contents 0',
' # Value is negative',
' + rw block width -1',
' # Unexpected enum value: expected one of 0 (CHARACTERWISE), '
.. '1 (LINEWISE), 2 (BLOCKWISE)',
' + rt type 10',
' # Expected boolean',
' + ru is_unnamed ["abc", "def"]',
},
([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': 0,
'rw': -1,
'rt': 10,
'ru': ['abc', 'def'],
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 5',
' + rt type LINEWISE',
' # Expected boolean',
' + ru is_unnamed 0',
},
([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'rw': 5,
'rt': 1,
'ru': 0,
}}] ]]):gsub('\n', '')
)
end)
it('works with variable items', function()
sd2strings_eq({
'Variable with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
}, { { type = 6, timestamp = 0, data = { a = { 10 } } } })
sd2strings_eq(
{
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' # Expected more elements in list',
},
([[ [{'type': 6, 'timestamp': 0, 'data': [
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' # Expected binary string',
' - name 1',
' # Expected more elements in list',
},
([[ [{'type': 6, 'timestamp': 0, 'data': [
1
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' # Expected no NUL bytes',
' - name "\\0"',
' # Expected more elements in list',
},
([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' - name "foo"',
' # Expected more elements in list',
},
([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]},
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' - name "foo"',
' - value NIL',
},
([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]},
{'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
]}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' - name "foo"',
' - value NIL',
' - NIL',
},
([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]},
{'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
{'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
]}] ]]):gsub('\n', '')
)
end)
it('works with global mark items', function()
sd2strings_eq({
'Global mark with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}, { { type = 7, timestamp = 0, data = { 1, 2, 3 } } })
sd2strings_eq(
{
'Global mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: n',
' # Required key missing: f',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 7, 'timestamp': 0, 'data': {
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Global mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected integer',
' + n name "foo"',
' # Required key missing: f',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': 'foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Global mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: n',
' + f file name "foo"',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 7, 'timestamp': 0, 'data': {
'f': 'foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Global mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Value is negative',
' + n name -10',
' # Expected no NUL bytes',
' + f file name "\\0"',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Global mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name '\\20'",
' + f file name "foo"',
' # Value is negative',
' + l line number -10',
' # Value is negative',
' + c column -10',
},
([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': 20,
'f': 'foo',
'l': -10,
'c': -10,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Global mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + n name 128',
' + f file name "foo"',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': 128,
'f': 'foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Global mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name '\\20'",
' + f file name "foo"',
' # Expected integer',
' + l line number "FOO"',
' # Expected integer',
' + c column "foo"',
' + mX 10',
},
([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': 20,
'f': 'foo',
'l': 'FOO',
'c': 'foo',
'mX': 10,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Global mark with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
},
([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': char2nr('A'),
'f': 'foo',
'l': 2,
'c': 200,
'mX': 10,
'mYYYYYYYYYY': 10,
}}] ]]):gsub('\n', '')
)
end)
it('works with jump items', function()
sd2strings_eq({
'Jump with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}, { { type = 8, timestamp = 0, data = { 1, 2, 3 } } })
sd2strings_eq(
{
'Jump with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 8, 'timestamp': 0, 'data': {
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Jump with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' + l line number 1',
' + c column 0',
' # Expected integer',
' + n name "foo"',
},
([[ [{'type': 8, 'timestamp': 0, 'data': {
'n': 'foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Jump with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "foo"',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 8, 'timestamp': 0, 'data': {
'f': 'foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Jump with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected no NUL bytes',
' + f file name "\\0"',
' + l line number 1',
' + c column 0',
' # Value is negative',
' + n name -10',
},
([[ [{'type': 8, 'timestamp': 0, 'data': {
'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Jump with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "foo"',
' # Value is negative',
' + l line number -10',
' # Value is negative',
' + c column -10',
},
([[ [{'type': 8, 'timestamp': 0, 'data': {
'f': 'foo',
'l': -10,
'c': -10,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Jump with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "foo"',
' # Expected integer',
' + l line number "FOO"',
' # Expected integer',
' + c column "foo"',
' + mX 10',
},
([[ [{'type': 8, 'timestamp': 0, 'data': {
'f': 'foo',
'l': 'FOO',
'c': 'foo',
'mX': 10,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
' + f file name "foo"',
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
" + n name ' '",
},
([[ [{'type': 8, 'timestamp': 0, 'data': {
'n': 0x20,
'f': 'foo',
'l': 2,
'c': 200,
'mX': 10,
'mYYYYYYYYYY': 10,
}}] ]]):gsub('\n', '')
)
end)
it('works with buffer list items', function()
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
}, { { type = 9, timestamp = 0, data = { a = { 10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps',
' = [[], []]',
}, { { type = 9, timestamp = 0, data = { {}, {} } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps',
' = [{="a": 10}, []]',
}, { { type = 9, timestamp = 0, data = { { a = 10 }, {} } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' + l line number 1',
' + c column 0',
' + a 10',
}, { { type = 9, timestamp = 0, data = { { a = 10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' # Expected integer',
' + l line number "10"',
' # Expected integer',
' + c column "10"',
' + a 10',
}, { { type = 9, timestamp = 0, data = { { l = '10', c = '10', a = 10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' + l line number 10',
' + c column 10',
' + a 10',
}, { { type = 9, timestamp = 0, data = { { l = 10, c = 10, a = 10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' # Value is negative',
' + l line number -10',
' # Value is negative',
' + c column -10',
}, { { type = 9, timestamp = 0, data = { { l = -10, c = -10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "abc"',
' + l line number 1',
' + c column 0',
}, { { type = 9, timestamp = 0, data = { { f = 'abc' } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected binary string',
' + f file name 10',
' + l line number 1',
' + c column 0',
'',
' % Key Description Value',
' # Expected binary string',
' + f file name 20',
' + l line number 1',
' + c column 0',
}, { { type = 9, timestamp = 0, data = { { f = 10 }, { f = 20 } } } })
sd2strings_eq(
{
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected binary string',
' + f file name 10',
' + l line number 1',
' + c column 0',
'',
' % Key Description Value',
' # Expected no NUL bytes',
' + f file name "\\0"',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 9, 'timestamp': 0, 'data': [
{'f': 10},
{'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}},
]}] ]]):gsub('\n', '')
)
end)
it('works with local mark items', function()
sd2strings_eq({
'Local mark with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}, { { type = 10, timestamp = 0, data = { 1, 2, 3 } } })
sd2strings_eq(
{
'Local mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
" + n name '\"'",
' + l line number 1',
' + c column 0',
},
([[ [{'type': 10, 'timestamp': 0, 'data': {
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Local mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' # Expected integer',
' + n name "foo"',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': 'foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Local mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "foo"',
" + n name '\"'",
' + l line number 1',
' + c column 0',
},
([[ [{'type': 10, 'timestamp': 0, 'data': {
'f': 'foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Local mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected no NUL bytes',
' + f file name "\\0"',
' # Value is negative',
' + n name -10',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Local mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "foo"',
" + n name '\\20'",
' # Value is negative',
' + l line number -10',
' # Value is negative',
' + c column -10',
},
([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': 20,
'f': 'foo',
'l': -10,
'c': -10,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Local mark with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "foo"',
" + n name '\\20'",
' # Expected integer',
' + l line number "FOO"',
' # Expected integer',
' + c column "foo"',
' + mX 10',
},
([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': 20,
'f': 'foo',
'l': 'FOO',
'c': 'foo',
'mX': 10,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Local mark with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
' + f file name "foo"',
" + n name 'a'",
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
},
([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': char2nr('a'),
'f': 'foo',
'l': 2,
'c': 200,
'mX': 10,
'mYYYYYYYYYY': 10,
}}] ]]):gsub('\n', '')
)
end)
it('works with change items', function()
sd2strings_eq({
'Change with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}, { { type = 11, timestamp = 0, data = { 1, 2, 3 } } })
sd2strings_eq(
{
'Change with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 11, 'timestamp': 0, 'data': {
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Change with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' + l line number 1',
' + c column 0',
' # Expected integer',
' + n name "foo"',
},
([[ [{'type': 11, 'timestamp': 0, 'data': {
'n': 'foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Change with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "foo"',
' + l line number 1',
' + c column 0',
},
([[ [{'type': 11, 'timestamp': 0, 'data': {
'f': 'foo',
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Change with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected no NUL bytes',
' + f file name "\\0"',
' + l line number 1',
' + c column 0',
' # Value is negative',
' + n name -10',
},
([[ [{'type': 11, 'timestamp': 0, 'data': {
'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Change with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "foo"',
' # Value is negative',
' + l line number -10',
' # Value is negative',
' + c column -10',
},
([[ [{'type': 11, 'timestamp': 0, 'data': {
'f': 'foo',
'l': -10,
'c': -10,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Change with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "foo"',
' # Expected integer',
' + l line number "FOO"',
' # Expected integer',
' + c column "foo"',
' + mX 10',
},
([[ [{'type': 11, 'timestamp': 0, 'data': {
'f': 'foo',
'l': 'FOO',
'c': 'foo',
'mX': 10,
}}] ]]):gsub('\n', '')
)
sd2strings_eq(
{
'Change with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
' + f file name "foo"',
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
" + n name ' '",
},
([[ [{'type': 11, 'timestamp': 0, 'data': {
'n': 0x20,
'f': 'foo',
'l': 2,
'c': 200,
'mX': 10,
'mYYYYYYYYYY': 10,
}}] ]]):gsub('\n', '')
)
end)
end)
describe('function shada#get_strings', function()
it('works', function()
eq({
'Header with timestamp ' .. epoch .. ':',
' % Key Value',
}, nvim_eval('shada#get_strings(msgpackdump([1, 0, 0, {}]))'))
end)
end)
describe('function shada#strings_to_sd', function()
local strings2sd_eq = function(expected, input)
api.nvim_set_var('__input', input)
nvim_command(
'let g:__actual = map(shada#strings_to_sd(g:__input), '
.. '"filter(v:val, \\"v:key[0] isnot# \'_\' '
.. '&& v:key isnot# \'length\'\\")")'
)
-- print()
if type(expected) == 'table' then
api.nvim_set_var('__expected', expected)
nvim_command('let g:__expected = ModifyVal(g:__expected)')
expected = 'g:__expected'
-- print(nvim_eval('msgpack#string(g:__expected)'))
end
-- print(nvim_eval('msgpack#string(g:__actual)'))
eq(1, nvim_eval(('msgpack#equal(%s, g:__actual)'):format(expected)))
if type(expected) == 'table' then
nvim_command('unlet g:__expected')
end
nvim_command('unlet g:__input')
nvim_command('unlet g:__actual')
end
it('works with multiple items', function()
strings2sd_eq({
{
type = 11,
timestamp = 0,
data = {
f = 'foo',
l = 2,
c = 200,
mX = 10,
mYYYYYYYYYY = 10,
n = (' '):byte(),
},
},
{
type = 1,
timestamp = 0,
data = {
c = 'abc',
f = { '!binary', { 'abc\ndef' } },
l = -10,
n = -64,
rc = '10',
rt = 10,
sc = { '!nil', 0 },
sm = 'TRUE',
so = 'TRUE',
sp = { '!string', { 'abc' } },
},
},
}, {
'Change with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
' + f file name "foo"',
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
" + n name ' '",
'Header with timestamp ' .. epoch .. ':',
' % Key Description____ Value',
' # Expected integer',
' + c column "abc"',
' # Expected no NUL bytes',
' + f file name "abc\\0def"',
' # Value is negative',
' + l line number -10',
' # Value is negative',
' + n name -64',
' # Expected array value',
' + rc contents "10"',
' # Unexpected enum value: expected one of '
.. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
' + rt type 10',
' # Expected boolean',
' + sc smartcase value NIL',
' # Expected boolean',
' + sm magic value "TRUE"',
' # Expected integer',
' + so offset value "TRUE"',
' # Expected binary string',
' + sp pattern ="abc"',
})
end)
it('works with empty list', function()
strings2sd_eq({}, {})
end)
it('works with header items', function()
strings2sd_eq({ { type = 1, timestamp = 0, data = {
generator = 'test',
} } }, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
strings2sd_eq(
{ { type = 1, timestamp = 0, data = {
1,
2,
3,
} } },
{
'Header with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}
)
strings2sd_eq({
{
type = 1,
timestamp = 0,
data = {
a = 1,
b = 2,
c = 3,
d = 4,
},
},
}, {
'Header with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + a 1',
' + b 2',
' + c column 3',
' + d 4',
})
strings2sd_eq({
{
type = 1,
timestamp = 0,
data = {
c = 'abc',
f = { '!binary', { 'abc\ndef' } },
l = -10,
n = -64,
rc = '10',
rt = 10,
sc = { '!nil', 0 },
sm = 'TRUE',
so = 'TRUE',
sp = { '!string', { 'abc' } },
},
},
}, {
'Header with timestamp ' .. epoch .. ':',
' % Key Description____ Value',
' # Expected integer',
' + c column "abc"',
' # Expected no NUL bytes',
' + f file name "abc\\0def"',
' # Value is negative',
' + l line number -10',
' # Value is negative',
' + n name -64',
' # Expected array value',
' + rc contents "10"',
' # Unexpected enum value: expected one of '
.. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
' + rt type 10',
' # Expected boolean',
' + sc smartcase value NIL',
' # Expected boolean',
' + sm magic value "TRUE"',
' # Expected integer',
' + so offset value "TRUE"',
' # Expected binary string',
' + sp pattern ="abc"',
})
end)
it('works with search pattern items', function()
strings2sd_eq(
{ { type = 2, timestamp = 0, data = {
1,
2,
3,
} } },
{
'Search pattern with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}
)
strings2sd_eq({ { type = 2, timestamp = 0, data = {
sp = 'abc',
} } }, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern "abc"',
' + sh v:hlsearch value FALSE',
' + ss is :s pattern FALSE',
' + sm magic value TRUE',
' + sc smartcase value FALSE',
' + sl has line offset FALSE',
' + se place cursor at end FALSE',
' + so offset value 0',
' + su is last used TRUE',
})
strings2sd_eq({
{
type = 2,
timestamp = 0,
data = {
sp = 'abc',
sX = { '!nil', 0 },
sY = { '!nil', 0 },
sZ = { '!nil', 0 },
},
},
}, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern "abc"',
' + sh v:hlsearch value FALSE',
' + ss is :s pattern FALSE',
' + sm magic value TRUE',
' + sc smartcase value FALSE',
' + sl has line offset FALSE',
' + se place cursor at end FALSE',
' + so offset value 0',
' + su is last used TRUE',
' + sX NIL',
' + sY NIL',
' + sZ NIL',
})
strings2sd_eq({ { type = 2, timestamp = 0, data = { '!map', {} } } }, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' # Required key missing: sp',
' + sh v:hlsearch value FALSE',
' + ss is :s pattern FALSE',
' + sm magic value TRUE',
' + sc smartcase value FALSE',
' + sl has line offset FALSE',
' + se place cursor at end FALSE',
' + so offset value 0',
' + su is last used TRUE',
})
strings2sd_eq({
{
type = 2,
timestamp = 0,
data = {
sp = '',
sh = { '!boolean', 1 },
ss = { '!boolean', 1 },
sc = { '!boolean', 1 },
sl = { '!boolean', 1 },
se = { '!boolean', 1 },
sm = { '!boolean', 0 },
su = { '!boolean', 0 },
so = -10,
},
},
}, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern ""',
' + sh v:hlsearch value TRUE',
' + ss is :s pattern TRUE',
' + sm magic value FALSE',
' + sc smartcase value TRUE',
' + sl has line offset TRUE',
' + se place cursor at end TRUE',
' + so offset value -10',
' + su is last used FALSE',
})
strings2sd_eq({
{
type = 2,
timestamp = 0,
data = {
sp = 0,
sh = 0,
ss = 0,
sc = 0,
sl = 0,
se = 0,
sm = 0,
su = 0,
so = '',
},
},
}, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' # Expected binary string',
' + sp pattern 0',
' # Expected boolean',
' + sh v:hlsearch value 0',
' # Expected boolean',
' + ss is :s pattern 0',
' # Expected boolean',
' + sm magic value 0',
' # Expected boolean',
' + sc smartcase value 0',
' # Expected boolean',
' + sl has line offset 0',
' # Expected boolean',
' + se place cursor at end 0',
' # Expected integer',
' + so offset value ""',
' # Expected boolean',
' + su is last used 0',
})
end)
it('works with replacement string items', function()
strings2sd_eq({ { type = 3, timestamp = 0, data = {
a = { 10 },
} } }, {
'Replacement string with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
})
strings2sd_eq({ { type = 3, timestamp = 0, data = {} } }, {
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' # Expected more elements in list',
})
strings2sd_eq({ { type = 3, timestamp = 0, data = {
0,
} } }, {
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' # Expected binary string',
' - :s replacement string 0',
})
strings2sd_eq(
{ { type = 3, timestamp = 0, data = {
'abc\ndef',
0,
} } },
{
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
' - 0',
}
)
strings2sd_eq({ { type = 3, timestamp = 0, data = {
'abc\ndef',
} } }, {
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
})
end)
it('works with history entry items', function()
strings2sd_eq({ { type = 4, timestamp = 0, data = {
a = { 10 },
} } }, {
'History entry with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
})
strings2sd_eq({ { type = 4, timestamp = 0, data = {} } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Expected more elements in list',
})
strings2sd_eq({ { type = 4, timestamp = 0, data = {
'',
} } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Expected integer',
' - history type ""',
' # Expected more elements in list',
})
strings2sd_eq({ { type = 4, timestamp = 0, data = {
5,
'',
} } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
.. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
' - history type 5',
' - contents ""',
})
strings2sd_eq(
{ { type = 4, timestamp = 0, data = {
5,
'',
32,
} } },
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
.. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
' - history type 5',
' - contents ""',
' - 32',
}
)
strings2sd_eq(
{ { type = 4, timestamp = 0, data = {
0,
'',
32,
} } },
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents ""',
' - 32',
}
)
strings2sd_eq(
{ { type = 4, timestamp = 0, data = {
1,
'',
32,
} } },
{
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type SEARCH',
' - contents ""',
" - separator ' '",
}
)
strings2sd_eq({ { type = 4, timestamp = 0, data = {
1,
'',
} } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type SEARCH',
' - contents ""',
' # Expected more elements in list',
})
strings2sd_eq({ { type = 4, timestamp = 0, data = {
2,
'',
} } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type EXPR',
' - contents ""',
})
strings2sd_eq({ { type = 4, timestamp = 0, data = {
3,
'',
} } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type INPUT',
' - contents ""',
})
strings2sd_eq({ { type = 4, timestamp = 0, data = {
4,
'',
} } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type DEBUG',
' - contents ""',
})
end)
it('works with register items', function()
strings2sd_eq(
{ { type = 5, timestamp = 0, data = {
1,
2,
3,
} } },
{
'Register with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}
)
strings2sd_eq({ { type = 5, timestamp = 0, data = { '!map', {} } } }, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: n',
' # Required key missing: rc',
' + rw block width 0',
' + rt type CHARACTERWISE',
})
strings2sd_eq({ { type = 5, timestamp = 0, data = {
n = (' '):byte(),
} } }, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' # Required key missing: rc',
' + rw block width 0',
' + rt type CHARACTERWISE',
})
strings2sd_eq({
{
type = 5,
timestamp = 0,
data = {
n = (' '):byte(),
rc = { 'abc', 'def' },
},
},
}, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents ["abc", "def"]',
' + rw block width 0',
' + rt type CHARACTERWISE',
})
strings2sd_eq({
{
type = 5,
timestamp = 0,
data = {
n = (' '):byte(),
rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
},
},
}, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 0',
' + rt type CHARACTERWISE',
})
strings2sd_eq({
{
type = 5,
timestamp = 0,
data = {
n = (' '):byte(),
rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
rw = 5,
rt = 1,
},
},
}, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 5',
' + rt type LINEWISE',
})
strings2sd_eq({
{
type = 5,
timestamp = 0,
data = {
n = (' '):byte(),
rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
rw = 5,
rt = 2,
},
},
}, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 5',
' + rt type BLOCKWISE',
})
strings2sd_eq({
{
type = 5,
timestamp = 0,
data = {
n = (' '):byte(),
rc = 0,
rw = -1,
rt = 10,
},
},
}, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' # Expected array value',
' + rc contents 0',
' # Value is negative',
' + rw block width -1',
' # Unexpected enum value: expected one of 0 (CHARACTERWISE), '
.. '1 (LINEWISE), 2 (BLOCKWISE)',
' + rt type 10',
})
end)
it('works with variable items', function()
strings2sd_eq({ { type = 6, timestamp = 0, data = {
a = { 10 },
} } }, {
'Variable with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
})
strings2sd_eq({ { type = 6, timestamp = 0, data = {} } }, {
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' # Expected more elements in list',
})
strings2sd_eq({ { type = 6, timestamp = 0, data = {
'foo',
} } }, {
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' - name "foo"',
' # Expected more elements in list',
})
strings2sd_eq({
{
type = 6,
timestamp = 0,
data = {
'foo',
{ '!nil', 0 },
},
},
}, {
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' - name "foo"',
' - value NIL',
})
strings2sd_eq({
{
type = 6,
timestamp = 0,
data = {
'foo',
{ '!nil', 0 },
{ '!nil', 0 },
},
},
}, {
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' - name "foo"',
' - value NIL',
' - NIL',
})
end)
it('works with global mark items', function()
strings2sd_eq(
{ { type = 7, timestamp = 0, data = {
1,
2,
3,
} } },
{
'Global mark with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}
)
strings2sd_eq({
{
type = 7,
timestamp = 0,
data = {
n = ('A'):byte(),
f = 'foo',
l = 2,
c = 200,
mX = 10,
mYYYYYYYYYY = 10,
},
},
}, {
'Global mark with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
})
end)
it('works with jump items', function()
strings2sd_eq(
{ { type = 8, timestamp = 0, data = {
1,
2,
3,
} } },
{
'Jump with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}
)
strings2sd_eq({
{
type = 8,
timestamp = 0,
data = {
n = ('A'):byte(),
f = 'foo',
l = 2,
c = 200,
mX = 10,
mYYYYYYYYYY = 10,
},
},
}, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
})
end)
it('works with buffer list items', function()
strings2sd_eq({ { type = 9, timestamp = 0, data = {
a = { 10 },
} } }, {
'Buffer list with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
})
strings2sd_eq(
{ { type = 9, timestamp = 0, data = {
{ a = 10 },
{},
} } },
{
'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps',
' = [{="a": 10}, []]',
}
)
strings2sd_eq({ { type = 9, timestamp = 0, data = {
{ a = 10 },
} } }, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' + l line number 1',
' + c column 0',
' + a 10',
})
strings2sd_eq({
{
type = 9,
timestamp = 0,
data = {
{ l = '10', c = '10', a = 10 },
},
},
}, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' # Expected integer',
' + l line number "10"',
' # Expected integer',
' + c column "10"',
' + a 10',
})
strings2sd_eq(
{ { type = 9, timestamp = 0, data = {
{ l = 10, c = 10, a = 10 },
} } },
{
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' + l line number 10',
' + c column 10',
' + a 10',
}
)
strings2sd_eq(
{ { type = 9, timestamp = 0, data = {
{ l = -10, c = -10 },
} } },
{
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
' # Value is negative',
' + l line number -10',
' # Value is negative',
' + c column -10',
}
)
strings2sd_eq({ { type = 9, timestamp = 0, data = {
{ f = 'abc' },
} } }, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "abc"',
' + l line number 1',
' + c column 0',
})
strings2sd_eq({
{
type = 9,
timestamp = 0,
data = {
{ f = 10 },
{ f = 20 },
},
},
}, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected binary string',
" + f file name '\\10'",
' + l line number 1',
' + c column 0',
'',
' % Key Description Value',
' # Expected binary string',
" + f file name '\\20'",
' + l line number 1',
' + c column 0',
})
strings2sd_eq({
{
type = 9,
timestamp = 0,
data = {
{ f = 10 },
{ f = { '!binary', { '\n' } } },
},
},
}, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected binary string',
" + f file name '\\10'",
' + l line number 1',
' + c column 0',
'',
' % Key Description Value',
' # Expected no NUL bytes',
' + f file name "\\0"',
' + l line number 1',
' + c column 0',
})
end)
it('works with local mark items', function()
strings2sd_eq(
{ { type = 10, timestamp = 0, data = {
1,
2,
3,
} } },
{
'Local mark with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}
)
strings2sd_eq({
{
type = 10,
timestamp = 0,
data = {
n = ('A'):byte(),
f = 'foo',
l = 2,
c = 200,
mX = 10,
mYYYYYYYYYY = 10,
},
},
}, {
'Local mark with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
})
end)
it('works with change items', function()
strings2sd_eq(
{ { type = 11, timestamp = 0, data = {
1,
2,
3,
} } },
{
'Change with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
}
)
strings2sd_eq({
{
type = 11,
timestamp = 0,
data = {
n = ('A'):byte(),
f = 'foo',
l = 2,
c = 200,
mX = 10,
mYYYYYYYYYY = 10,
},
},
}, {
'Change with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
})
end)
end)
describe('function shada#get_binstrings', function()
local getbstrings_eq = function(expected, input)
local result = fn['shada#get_binstrings'](input)
for i, s in ipairs(result) do
result[i] = s:gsub('\n', '\0')
end
local mpack_result = table.concat(result, '\n')
return mpack_eq(expected, mpack_result)
end
it('works', function()
local version = api.nvim_get_vvar('version')
getbstrings_eq({
{
timestamp = 'current',
type = 1,
value = {
generator = 'shada.vim',
version = version,
},
},
}, {})
getbstrings_eq({
{
timestamp = 'current',
type = 1,
value = {
generator = 'shada.vim',
version = version,
},
},
{ timestamp = 0, type = 1, value = { generator = 'test' } },
}, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
api.nvim_set_var('shada#add_own_header', 1)
getbstrings_eq({
{
timestamp = 'current',
type = 1,
value = {
generator = 'shada.vim',
version = version,
},
},
}, {})
getbstrings_eq({
{
timestamp = 'current',
type = 1,
value = {
generator = 'shada.vim',
version = version,
},
},
{ timestamp = 0, type = 1, value = { generator = 'test' } },
}, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
api.nvim_set_var('shada#add_own_header', 0)
getbstrings_eq({}, {})
getbstrings_eq({ { timestamp = 0, type = 1, value = { generator = 'test' } } }, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
api.nvim_set_var('shada#keep_old_header', 0)
getbstrings_eq({}, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
getbstrings_eq({
{ type = 3, timestamp = 0, value = { 'abc\ndef' } },
{ type = 3, timestamp = 0, value = { 'abc\ndef' } },
{ type = 3, timestamp = 0, value = { 'abc\ndef' } },
}, {
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
})
end)
end)
end)
describe('plugin/shada.vim', function()
local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
local eol = t.is_os('win') and '\r\n' or '\n'
before_each(function()
-- Note: reset() is called explicitly in each test.
os.remove(fname)
os.remove(fname .. '.tst')
os.remove(fname_tmp)
end)
teardown(function()
os.remove(fname)
os.remove(fname .. '.tst')
os.remove(fname_tmp)
end)
local shada_eq = function(expected, fname_)
local mpack_result = read_file(fname_)
mpack_eq(expected, mpack_result)
end
it('event BufReadCmd', function()
reset()
wshada('\004\000\009\147\000\196\002ab\196\001a')
wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
local bufread_commands =
api.nvim_get_autocmds({ group = 'ShaDaCommands', event = 'BufReadCmd' })
eq(2, #bufread_commands--[[, vim.inspect(bufread_commands) ]])
-- Need to set nohidden so that the buffer containing 'fname' is not unloaded
-- after loading 'fname_tmp', otherwise the '++opt not supported' test below
-- won't work since the BufReadCmd autocmd won't be triggered.
nvim_command('set nohidden')
nvim_command('edit ' .. fname)
eq({
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents "ab"',
' - "a"',
}, nvim_eval('getline(1, "$")'))
eq(false, api.nvim_get_option_value('modified', {}))
eq('shada', api.nvim_get_option_value('filetype', {}))
nvim_command('edit ' .. fname_tmp)
eq({
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents "ab"',
' - "b"',
}, nvim_eval('getline(1, "$")'))
eq(false, api.nvim_get_option_value('modified', {}))
eq('shada', api.nvim_get_option_value('filetype', {}))
eq('++opt not supported', exc_exec('edit ++enc=latin1 ' .. fname))
neq({
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents "ab"',
' - "a"',
}, nvim_eval('getline(1, "$")'))
neq(true, api.nvim_get_option_value('modified', {}))
end)
it('event FileReadCmd', function()
reset()
wshada('\004\000\009\147\000\196\002ab\196\001a')
wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
nvim_command('$read ' .. fname)
eq({
'',
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents "ab"',
' - "a"',
}, nvim_eval('getline(1, "$")'))
eq(true, api.nvim_get_option_value('modified', {}))
neq('shada', api.nvim_get_option_value('filetype', {}))
nvim_command('1,$read ' .. fname_tmp)
eq({
'',
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents "ab"',
' - "a"',
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents "ab"',
' - "b"',
}, nvim_eval('getline(1, "$")'))
eq(true, api.nvim_get_option_value('modified', {}))
neq('shada', api.nvim_get_option_value('filetype', {}))
api.nvim_set_option_value('modified', false, {})
eq('++opt not supported', exc_exec('$read ++enc=latin1 ' .. fname))
eq({
'',
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents "ab"',
' - "a"',
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type CMD',
' - contents "ab"',
' - "b"',
}, nvim_eval('getline(1, "$")'))
neq(true, api.nvim_get_option_value('modified', {}))
end)
it('event BufWriteCmd', function()
reset()
api.nvim_set_var('shada#add_own_header', 0)
api.nvim_buf_set_lines(0, 0, 1, true, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
})
nvim_command('w ' .. fname .. '.tst')
nvim_command('w ' .. fname)
nvim_command('w ' .. fname_tmp)
eq('++opt not supported', exc_exec('w! ++enc=latin1 ' .. fname))
eq(table.concat({
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
}, eol) .. eol, read_file(fname .. '.tst'))
shada_eq({
{
timestamp = 0,
type = 8,
value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
},
{
timestamp = 0,
type = 8,
value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
},
}, fname)
shada_eq({
{
timestamp = 0,
type = 8,
value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
},
{
timestamp = 0,
type = 8,
value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
},
}, fname_tmp)
end)
it('event FileWriteCmd', function()
reset()
api.nvim_set_var('shada#add_own_header', 0)
api.nvim_buf_set_lines(0, 0, 1, true, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
})
nvim_command('1,3w ' .. fname .. '.tst')
nvim_command('1,3w ' .. fname)
nvim_command('1,3w ' .. fname_tmp)
eq('++opt not supported', exc_exec('1,3w! ++enc=latin1 ' .. fname))
eq(table.concat({
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
}, eol) .. eol, read_file(fname .. '.tst'))
shada_eq(
{ {
timestamp = 0,
type = 8,
value = { n = ('A'):byte() },
} },
fname
)
shada_eq(
{ {
timestamp = 0,
type = 8,
value = { n = ('A'):byte() },
} },
fname_tmp
)
end)
it('event FileAppendCmd', function()
reset()
api.nvim_set_var('shada#add_own_header', 0)
api.nvim_buf_set_lines(0, 0, 1, true, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
})
fn.writefile({ '' }, fname .. '.tst', 'b')
fn.writefile({ '' }, fname, 'b')
fn.writefile({ '' }, fname_tmp, 'b')
nvim_command('1,3w >> ' .. fname .. '.tst')
nvim_command('1,3w >> ' .. fname)
nvim_command('1,3w >> ' .. fname_tmp)
nvim_command('w >> ' .. fname .. '.tst')
nvim_command('w >> ' .. fname)
nvim_command('w >> ' .. fname_tmp)
eq('++opt not supported', exc_exec('1,3w! ++enc=latin1 >> ' .. fname))
eq(table.concat({
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
}, eol) .. eol, read_file(fname .. '.tst'))
shada_eq({
{
timestamp = 0,
type = 8,
value = { n = ('A'):byte() },
},
{
timestamp = 0,
type = 8,
value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
},
{
timestamp = 0,
type = 8,
value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
},
}, fname)
shada_eq({
{
timestamp = 0,
type = 8,
value = { n = ('A'):byte() },
},
{
timestamp = 0,
type = 8,
value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
},
{
timestamp = 0,
type = 8,
value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
},
}, fname_tmp)
end)
it('event SourceCmd', function()
reset(fname)
finally(function()
nvim_command('set shadafile=NONE') -- Avoid writing shada file on exit
end)
wshada('\004\000\006\146\000\196\002ab')
wshada_tmp('\004\001\006\146\000\196\002bc')
eq(0, exc_exec('source ' .. fname))
eq(0, exc_exec('source ' .. fname_tmp))
eq('bc', fn.histget(':', -1))
eq('ab', fn.histget(':', -2))
end)
end)
describe('ftplugin/shada.vim', function()
local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
before_each(reset)
it('sets indentexpr correctly', function()
nvim_command('filetype plugin indent on')
nvim_command('setlocal filetype=shada')
fn.setline(1, {
'Jump with timestamp ' .. epoch .. ':',
'% Key________ Description Value',
"+ n name 'A'",
'+ f file name "foo"',
'+ l line number 2',
'+ c column 200',
'+ mX 10',
'+ mYYYYYYYYYY 10',
'Register with timestamp ' .. epoch .. ':',
'% Key Description Value',
"+ n name ' '",
'+ rc contents @',
'| - "abcdefghijklmnopqrstuvwxyz"',
'| - "abcdefghijklmnopqrstuvwxyz"',
'+ rw block width 0',
'+ rt type CHARACTERWISE',
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
' Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps',
'= [{="a": 10}, []]',
' Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected binary string',
'+ f file name 10',
' + l line number 1',
' + c column 0',
'',
' % Key Description Value',
' # Expected binary string',
' + f file name 20',
'+ l line number 1',
' + c column 0',
})
nvim_command('normal! gg=G')
eq({
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
" + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 0',
' + rt type CHARACTERWISE',
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps',
' = [{="a": 10}, []]',
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected binary string',
' + f file name 10',
' + l line number 1',
' + c column 0',
'',
' % Key Description Value',
' # Expected binary string',
' + f file name 20',
' + l line number 1',
' + c column 0',
}, fn.getline(1, fn.line('$')))
end)
it('sets options correctly', function()
nvim_command('filetype plugin indent on')
nvim_command('setlocal filetype=shada')
eq(true, api.nvim_get_option_value('expandtab', {}))
eq(2, api.nvim_get_option_value('tabstop', {}))
eq(2, api.nvim_get_option_value('softtabstop', {}))
eq(2, api.nvim_get_option_value('shiftwidth', {}))
end)
it('sets indentkeys correctly', function()
nvim_command('filetype plugin indent on')
nvim_command('setlocal filetype=shada')
fn.setline(1, ' Replacement with timestamp ' .. epoch)
nvim_feed('ggA:\027')
eq('Replacement with timestamp ' .. epoch .. ':', api.nvim_buf_get_lines(0, 0, 1, true)[1])
nvim_feed('o-\027')
eq({ ' -' }, api.nvim_buf_get_lines(0, 1, 2, true))
nvim_feed('ggO+\027')
eq({ '+' }, api.nvim_buf_get_lines(0, 0, 1, true))
nvim_feed('GO*\027')
eq({ ' *' }, api.nvim_buf_get_lines(0, 2, 3, true))
nvim_feed('ggO /\027')
eq({ ' /' }, api.nvim_buf_get_lines(0, 0, 1, true))
nvim_feed('ggOx\027')
eq({ 'x' }, api.nvim_buf_get_lines(0, 0, 1, true))
end)
end)
describe('syntax/shada.vim', function()
local epoch = os.date('!%Y-%m-%dT%H:%M:%S', 0)
before_each(reset)
it('works', function()
nvim_command('syntax on')
nvim_command('setlocal syntax=shada')
nvim_command('set laststatus&')
local screen = Screen.new(60, 37)
screen:set_default_attr_ids {
[1] = { bold = true, foreground = Screen.colors.Brown },
[2] = { foreground = tonumber('0x6a0dad') },
[3] = { foreground = Screen.colors.Fuchsia },
[4] = { foreground = Screen.colors.Blue1 },
[5] = { bold = true, foreground = Screen.colors.SeaGreen4 },
[6] = { foreground = Screen.colors.SlateBlue },
[7] = { bold = true, reverse = true },
[8] = { bold = true, foreground = Screen.colors.Blue },
}
screen:attach()
api.nvim_buf_set_lines(0, 0, 1, true, {
'Header with timestamp ' .. epoch .. ':',
' % Key Value',
' + t "test"',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
" + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + rc contents @',
' | - {"abcdefghijklmnopqrstuvwxyz": 1.0}',
' + rt type CHARACTERWISE',
' + rt type LINEWISE',
' + rt type BLOCKWISE',
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string CMD',
' - :s replacement string SEARCH',
' - :s replacement string EXPR',
' - :s replacement string INPUT',
' - :s replacement string DEBUG',
'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps',
' = [{="a": +(10)"ac\\0df\\ngi\\"tt\\.", TRUE: FALSE}, [NIL, +(-10)""]]',
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
'',
' % Key Description Value',
'Header with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + se place cursor at end TRUE',
})
screen:expect {
grid = [=[
{1:^Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{2: % Key Value} |
{1: +} {3:t } {1:"}{3:test}{1:"} |
{1:Jump} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{2: % Key________ Description Value} |
{1: +} {3:n } {4:name } {3:'A'} |
{1: +} {3:f } {4:file name } {1:["}{3:foo}{1:"]} |
{1: +} {3:l } {4:line number} {3:2} |
{1: +} {3:c } {4:column } {3:-200} |
{1:Register} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{2: % Key Description Value} |
{1: +} {3:rc } {4:contents } {1:@} |
{1: | -} {1:{"}{3:abcdefghijklmnopqrstuvwxyz}{1:":} {3:1.0}{1:}} |
{1: +} {3:rt } {4:type } {1:CHARACTERWISE} |
{1: +} {3:rt } {4:type } {1:LINEWISE} |
{1: +} {3:rt } {4:type } {1:BLOCKWISE} |
{1:Replacement string} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{2: @ Description__________ Value} |
{1: -} {4::s replacement string} {1:CMD} |
{1: -} {4::s replacement string} {1:SEARCH} |
{1: -} {4::s replacement string} {1:EXPR} |
{1: -} {4::s replacement string} {1:INPUT} |
{1: -} {4::s replacement string} {1:DEBUG} |
{1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{4: # Expected array of maps} |
= {1:[{="}{3:a}{1:":} {1:+(}{5:10}{1:)"}{3:ac}{6:\0}{3:df}{6:\n}{3:gi}{6:\"}{3:tt\.}{1:",} {1:TRUE:} {1:FALSE},} {1:[NIL,} {1:+(}{5:-}|
{5:10}{1:)""]]} |
{1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{2: % Key Description Value} |
|
{2: % Key Description Value} |
{1:Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{2: % Key Description________ Value} |
{1: +} {3:se } {4:place cursor at end} {1:TRUE} |
{8:~ }|
{7:[No Name] [+] }|
|
]=],
}
nvim_command([[
function GetSyntax()
let lines = []
for l in range(1, line('$'))
let columns = []
let line = getline(l)
for c in range(1, col([l, '$']) - 1)
let synstack = map(synstack(l, c), 'synIDattr(v:val, "name")')
if !empty(columns) && columns[-1][0] ==# synstack
let columns[-1][1] .= line[c - 1]
else
call add(columns, [ synstack, line[c - 1] ])
endif
endfor
call add(lines, columns)
endfor
return lines
endfunction
]])
local hname = function(s)
return { { 'ShaDaEntryHeader', 'ShaDaEntryName' }, s }
end
local h = function(s)
return { { 'ShaDaEntryHeader' }, s }
end
local htsnum = function(s)
return {
{ 'ShaDaEntryHeader', 'ShaDaEntryTimestamp', 'ShaDaEntryTimestampNumber' },
s,
}
end
local synhtssep = function(s)
return { { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp' }, s }
end
local synepoch = {
year = htsnum(os.date('%Y', 0)),
month = htsnum(os.date('%m', 0)),
day = htsnum(os.date('%d', 0)),
hour = htsnum(os.date('!%H', 0)),
minute = htsnum(os.date('%M', 0)),
second = htsnum(os.date('%S', 0)),
}
local msh = function(s)
return {
{ 'ShaDaEntryMapShort', 'ShaDaEntryMapHeader' },
s,
}
end
local mlh = function(s)
return { { 'ShaDaEntryMapLong', 'ShaDaEntryMapHeader' }, s }
end
local ah = function(s)
return { { 'ShaDaEntryArray', 'ShaDaEntryArrayHeader' }, s }
end
-- luacheck: ignore
local mses = function(s)
return {
{
'ShaDaEntryMapShort',
'ShaDaEntryMapShortEntryStart',
},
s,
}
end
local mles = function(s)
return {
{ 'ShaDaEntryMapLong', 'ShaDaEntryMapLongEntryStart' },
s,
}
end
local act = fn.GetSyntax()
local ms = function(syn)
return {
{ 'ShaDaEntryMap' .. syn, 'ShaDaEntryMap' .. syn .. 'EntryStart' },
' + ',
}
end
local as = function()
return { { 'ShaDaEntryArray', 'ShaDaEntryArrayEntryStart' }, ' - ' }
end
local ad = function(s)
return {
{ 'ShaDaEntryArray', 'ShaDaEntryArrayDescription' },
s,
}
end
local mbas = function(syn)
return {
{ 'ShaDaEntryMap' .. syn, 'ShaDaEntryMapBinArrayStart' },
' | - ',
}
end
local msk = function(s)
return {
{ 'ShaDaEntryMapShort', 'ShaDaEntryMapShortKey' },
s,
}
end
local mlk = function(s)
return {
{ 'ShaDaEntryMapLong', 'ShaDaEntryMapLongKey' },
s,
}
end
local mld = function(s)
return {
{ 'ShaDaEntryMapLong', 'ShaDaEntryMapLongDescription' },
s,
}
end
local c = function(s)
return { { 'ShaDaComment' }, s }
end
local exp = {
{
hname('Header'),
h(' with timestamp '),
synepoch.year,
synhtssep('-'),
synepoch.month,
synhtssep('-'),
synepoch.day,
synhtssep('T'),
synepoch.hour,
synhtssep(':'),
synepoch.minute,
synhtssep(':'),
synepoch.second,
h(':'),
},
{
msh(' % Key Value'),
},
{
ms('Short'),
msk('t '),
{
{ 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString', 'ShaDaMsgpackStringQuotes' },
'"',
},
{ { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString' }, 'test' },
{ { 'ShaDaEntryMapShort', 'ShaDaMsgpackStringQuotes' }, '"' },
},
{
hname('Jump'),
h(' with timestamp '),
synepoch.year,
synhtssep('-'),
synepoch.month,
synhtssep('-'),
synepoch.day,
synhtssep('T'),
synepoch.hour,
synhtssep(':'),
synepoch.minute,
synhtssep(':'),
synepoch.second,
h(':'),
},
{
mlh(' % Key________ Description Value'),
},
{
ms('Long'),
mlk('n '),
mld('name '),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackCharacter' }, "'A'" },
},
{
ms('Long'),
mlk('f '),
mld('file name '),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
{
{
'ShaDaEntryMapLong',
'ShaDaMsgpackArray',
'ShaDaMsgpackBinaryString',
'ShaDaMsgpackStringQuotes',
},
'"',
},
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString' }, 'foo' },
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' },
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackArrayBraces' }, ']' },
},
{
ms('Long'),
mlk('l '),
mld('line number '),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '2' },
},
{
ms('Long'),
mlk('c '),
mld('column '),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '-200' },
},
{
hname('Register'),
h(' with timestamp '),
synepoch.year,
synhtssep('-'),
synepoch.month,
synhtssep('-'),
synepoch.day,
synhtssep('T'),
synepoch.hour,
synhtssep(':'),
synepoch.minute,
synhtssep(':'),
synepoch.second,
h(':'),
},
{
mlh(' % Key Description Value'),
},
{
ms('Long'),
mlk('rc '),
mld('contents '),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackMultilineArray' }, '@' },
},
{
mbas('Long'),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' },
{
{
'ShaDaEntryMapLong',
'ShaDaMsgpackMap',
'ShaDaMsgpackBinaryString',
'ShaDaMsgpackStringQuotes',
},
'"',
},
{
{ 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' },
'abcdefghijklmnopqrstuvwxyz',
},
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap' }, ' ' },
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackFloat' }, '1.0' },
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackMapBraces' }, '}' },
},
{
ms('Long'),
mlk('rt '),
mld('type '),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'CHARACTERWISE' },
},
{
ms('Long'),
mlk('rt '),
mld('type '),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'LINEWISE' },
},
{
ms('Long'),
mlk('rt '),
mld('type '),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'BLOCKWISE' },
},
{
hname('Replacement string'),
h(' with timestamp '),
synepoch.year,
synhtssep('-'),
synepoch.month,
synhtssep('-'),
synepoch.day,
synhtssep('T'),
synepoch.hour,
synhtssep(':'),
synepoch.minute,
synhtssep(':'),
synepoch.second,
h(':'),
},
{
ah(' @ Description__________ Value'),
},
{
as(),
ad(':s replacement string '),
{ { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'CMD' },
},
{
as(),
ad(':s replacement string '),
{ { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'SEARCH' },
},
{
as(),
ad(':s replacement string '),
{ { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'EXPR' },
},
{
as(),
ad(':s replacement string '),
{ { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'INPUT' },
},
{
as(),
ad(':s replacement string '),
{ { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'DEBUG' },
},
{
hname('Buffer list'),
h(' with timestamp '),
synepoch.year,
synhtssep('-'),
synepoch.month,
synhtssep('-'),
synepoch.day,
synhtssep('T'),
synepoch.hour,
synhtssep(':'),
synepoch.minute,
synhtssep(':'),
synepoch.second,
h(':'),
},
{
c(' # Expected array of maps'),
},
{
{ { 'ShaDaEntryRawMsgpack' }, ' = ' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackString' }, '=' },
{
{
'ShaDaMsgpackArray',
'ShaDaMsgpackMap',
'ShaDaMsgpackBinaryString',
'ShaDaMsgpackStringQuotes',
},
'"',
},
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'a' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, '+(' },
{
{
'ShaDaMsgpackArray',
'ShaDaMsgpackMap',
'ShaDaMsgpackExt',
'ShaDaMsgpackExtType',
},
'10',
},
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, ')' },
{
{
'ShaDaMsgpackArray',
'ShaDaMsgpackMap',
'ShaDaMsgpackBinaryString',
'ShaDaMsgpackStringQuotes',
},
'"',
},
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'ac' },
{
{
'ShaDaMsgpackArray',
'ShaDaMsgpackMap',
'ShaDaMsgpackBinaryString',
'ShaDaMsgpackBinaryStringEscape',
},
'\\0',
},
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'df' },
{
{
'ShaDaMsgpackArray',
'ShaDaMsgpackMap',
'ShaDaMsgpackBinaryString',
'ShaDaMsgpackBinaryStringEscape',
},
'\\n',
},
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'gi' },
{
{
'ShaDaMsgpackArray',
'ShaDaMsgpackMap',
'ShaDaMsgpackBinaryString',
'ShaDaMsgpackBinaryStringEscape',
},
'\\"',
},
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'tt\\.' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackComma' }, ',' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'TRUE' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'FALSE' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackMapBraces' }, '}' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' },
{ { 'ShaDaMsgpackArray' }, ' ' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackKeyword' }, 'NIL' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray' }, ' ' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, '+(' },
{
{
'ShaDaMsgpackArray',
'ShaDaMsgpackArray',
'ShaDaMsgpackExt',
'ShaDaMsgpackExtType',
},
'-10',
},
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, ')' },
{
{
'ShaDaMsgpackArray',
'ShaDaMsgpackArray',
'ShaDaMsgpackBinaryString',
'ShaDaMsgpackStringQuotes',
},
'"',
},
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' },
{ { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, ']' },
{ { 'ShaDaMsgpackArrayBraces' }, ']' },
},
{
hname('Buffer list'),
h(' with timestamp '),
synepoch.year,
synhtssep('-'),
synepoch.month,
synhtssep('-'),
synepoch.day,
synhtssep('T'),
synepoch.hour,
synhtssep(':'),
synepoch.minute,
synhtssep(':'),
synepoch.second,
h(':'),
},
{
mlh(' % Key Description Value'),
},
{},
{
mlh(' % Key Description Value'),
},
{
hname('Header'),
h(' with timestamp '),
synepoch.year,
synhtssep('-'),
synepoch.month,
synhtssep('-'),
synepoch.day,
synhtssep('T'),
synepoch.hour,
synhtssep(':'),
synepoch.minute,
synhtssep(':'),
synepoch.second,
h(':'),
},
{
mlh(' % Key Description________ Value'),
},
{
mles(' + '),
mlk('se '),
mld('place cursor at end '),
{ { 'ShaDaEntryMapLong', 'ShaDaMsgpackKeyword' }, 'TRUE' },
},
}
eq(exp, act)
end)
end)