aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin/shada_spec.lua
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/plugin/shada_spec.lua')
-rw-r--r--test/functional/plugin/shada_spec.lua2833
1 files changed, 2833 insertions, 0 deletions
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
new file mode 100644
index 0000000000..407f13a55b
--- /dev/null
+++ b/test/functional/plugin/shada_spec.lua
@@ -0,0 +1,2833 @@
+local helpers = require('test.functional.helpers')
+local eq, nvim_eval, nvim_command, nvim, exc_exec, funcs, nvim_feed, curbuf =
+ helpers.eq, helpers.eval, helpers.command, helpers.nvim, helpers.exc_exec,
+ helpers.funcs, helpers.feed, helpers.curbuf
+local neq = helpers.neq
+
+local msgpack = require('MessagePack')
+
+local plugin_helpers = require('test.functional.plugin.helpers')
+local reset = plugin_helpers.reset
+
+local shada_helpers = require('test.functional.shada.helpers')
+local get_shada_rw = shada_helpers.get_shada_rw
+local read_shada_file = shada_helpers.read_shada_file
+
+local mpack_eq = function(expected, mpack_result)
+ local mpack_keys = {'type', 'timestamp', 'length', 'value'}
+
+ local unpacker = msgpack.unpacker(mpack_result)
+ local actual = {}
+ local cur
+ local i = 0
+ while true do
+ local off, val = unpacker()
+ if not off then break end
+ 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('In 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
+
+ local st_meta = {
+ __pairs=function(table)
+ local ret = {}
+ local next_key = nil
+ local num_keys = 0
+ while true do
+ next_key = next(table, next_key)
+ if next_key == nil then
+ break
+ end
+ num_keys = num_keys + 1
+ ret[num_keys] = {next_key, table[next_key]}
+ end
+ table.sort(ret, function(a, b)
+ return a[1] < b[1]
+ end)
+ local state = {i=0}
+ return (function(state, var)
+ state.i = state.i + 1
+ if ret[state.i] then
+ return table.unpack(ret[state.i])
+ end
+ end), state
+ end
+ }
+
+ local st = function(table)
+ return setmetatable(table, st_meta)
+ 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, funcs['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=st({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',
+ ' + rw block width 10',
+ ' + 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},
+ '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'],
+ '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',
+ ' + 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',
+ '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',
+ ' + 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',
+ ' + 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',
+ ' + 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},
+ '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',
+ ' + 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',
+ ' + 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},
+ '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',
+ ' + 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,
+ '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', ''))
+ 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',
+ }, ([[ [{'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',
+ }, ([[ [{'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',
+ }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ 'n': 0x20,
+ 'rc': ["abc", "def"],
+ }}] ]]):gsub('\n', ''))
+ sd2strings_eq({
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + n name \' \'',
+ ' + rc contents @',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' + rw block width 0',
+ ' + rt type CHARACTERWISE',
+ }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ 'n': 0x20,
+ 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
+ }}] ]]):gsub('\n', ''))
+ sd2strings_eq({
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + n name \' \'',
+ ' + rc contents @',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' + rw block width 0',
+ ' + rt type CHARACTERWISE',
+ }, ([[ [{'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',
+ }, ([[ [{'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',
+ }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ 'n': 0x20,
+ 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
+ 'rw': "",
+ 'rt': 2,
+ }}] ]]):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',
+ }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ 'n': 0x20,
+ 'rc': 0,
+ 'rw': -1,
+ 'rt': 10,
+ }}] ]]):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 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)
+ 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
+ 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
+
+ assert:set_parameter('TableFormatLevel', 100)
+
+ 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 = funcs['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()
+ getbstrings_eq({{timestamp='current', type=1, value={
+ generator='shada.vim',
+ version=704,
+ }}}, {})
+ getbstrings_eq({
+ {timestamp='current', type=1, value={
+ generator='shada.vim', version=704
+ }},
+ {timestamp=0, type=1, value={generator='test'}}
+ }, {
+ 'Header with timestamp ' .. epoch .. ':',
+ ' % Key______ Value',
+ ' + generator "test"',
+ })
+ nvim('set_var', 'shada#add_own_header', 1)
+ getbstrings_eq({{timestamp='current', type=1, value={
+ generator='shada.vim',
+ version=704,
+ }}}, {})
+ getbstrings_eq({
+ {timestamp='current', type=1, value={
+ generator='shada.vim', version=704
+ }},
+ {timestamp=0, type=1, value={generator='test'}}
+ }, {
+ 'Header with timestamp ' .. epoch .. ':',
+ ' % Key______ Value',
+ ' + generator "test"',
+ })
+ 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"',
+ })
+ 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('In plugin/shada.vim', function()
+ local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
+ before_each(function()
+ reset()
+ os.remove(fname)
+ os.remove(fname .. '.tst')
+ os.remove(fname_tmp)
+ end)
+
+ local shada_eq = function(expected, fname)
+ local fd = io.open(fname)
+ local mpack_result = fd:read('*a')
+ fd:close()
+ mpack_eq(expected, mpack_result)
+ end
+
+ describe('event BufReadCmd', function()
+ it('works', function()
+ wshada('\004\000\009\147\000\196\002ab\196\001a')
+ wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
+ nvim_command('edit ' .. fname)
+ eq({
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type CMD',
+ ' - contents "ab"',
+ ' - "a"',
+ }, nvim_eval('getline(1, "$")'))
+ eq(false, curbuf('get_option', 'modified'))
+ eq('shada', curbuf('get_option', '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, curbuf('get_option', 'modified'))
+ eq('shada', curbuf('get_option', '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, curbuf('get_option', 'modified'))
+ end)
+ end)
+
+ describe('event FileReadCmd', function()
+ it('works', function()
+ 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, curbuf('get_option', 'modified'))
+ neq('shada', curbuf('get_option', '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, curbuf('get_option', 'modified'))
+ neq('shada', curbuf('get_option', 'filetype'))
+ curbuf('set_option', '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, curbuf('get_option', 'modified'))
+ end)
+ end)
+
+ describe('event BufWriteCmd', function()
+ it('works', function()
+ nvim('set_var', 'shada#add_own_header', 0)
+ curbuf('set_line_slice', 0, 0, true, 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',
+ }, '\n') .. '\n', io.open(fname .. '.tst'):read('*a'))
+ 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)
+ end)
+
+ describe('event FileWriteCmd', function()
+ it('works', function()
+ nvim('set_var', 'shada#add_own_header', 0)
+ curbuf('set_line_slice', 0, 0, true, 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\'',
+ }, '\n') .. '\n', io.open(fname .. '.tst'):read('*a'))
+ shada_eq({{
+ timestamp=0,
+ type=8,
+ value={n=('A'):byte()},
+ }}, fname)
+ shada_eq({{
+ timestamp=0,
+ type=8,
+ value={n=('A'):byte()},
+ }}, fname_tmp)
+ end)
+ end)
+
+ describe('event FileAppendCmd', function()
+ it('works', function()
+ nvim('set_var', 'shada#add_own_header', 0)
+ curbuf('set_line_slice', 0, 0, true, 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',
+ })
+ funcs.writefile({''}, fname .. '.tst', 'b')
+ funcs.writefile({''}, fname, 'b')
+ funcs.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',
+ }, '\n') .. '\n', io.open(fname .. '.tst'):read('*a'))
+ 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)
+ end)
+
+ describe('event SourceCmd', function()
+ before_each(function()
+ reset(fname)
+ end)
+ it('works', function()
+ 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', funcs.histget(':', -1))
+ eq('ab', funcs.histget(':', -2))
+ end)
+ 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')
+ funcs.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',
+ }, funcs.getline(1, funcs.line('$')))
+ end)
+
+ it('sets options correctly', function()
+ nvim_command('filetype plugin indent on')
+ nvim_command('setlocal filetype=shada')
+ eq(true, curbuf('get_option', 'expandtab'))
+ eq(2, curbuf('get_option', 'tabstop'))
+ eq(2, curbuf('get_option', 'softtabstop'))
+ eq(2, curbuf('get_option', 'shiftwidth'))
+ end)
+
+ it('sets indentkeys correctly', function()
+ nvim_command('filetype plugin indent on')
+ nvim_command('setlocal filetype=shada')
+ funcs.setline(1, ' Replacement with timestamp ' .. epoch)
+ nvim_feed('ggA:\027')
+ eq('Replacement with timestamp ' .. epoch .. ':', curbuf('get_line', 0))
+ nvim_feed('o-\027')
+ eq(' -', curbuf('get_line', 1))
+ nvim_feed('ggO+\027')
+ eq('+', curbuf('get_line', 0))
+ nvim_feed('GO*\027')
+ eq(' *', curbuf('get_line', 2))
+ nvim_feed('ggO /\027')
+ eq(' /', curbuf('get_line', 0))
+ nvim_feed('ggOx\027')
+ eq('x', curbuf('get_line', 0))
+ 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')
+ curbuf('set_line_slice', 0, 0, true, 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',
+ })
+ 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
+ local mses = function(s) return {{'ShaDaEntryMapShort',
+ 'ShaDaEntryMapShortEntryStart'}, s} end
+ local mles = function(s) return {{'ShaDaEntryMapLong',
+ 'ShaDaEntryMapLongEntryStart'}, s} end
+ local act = funcs.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'},
+ },
+ {
+ {{'ShaDaEntryArrayEntryStart'}, ' - '},
+ {{'ShaDaEntryArrayDescription'}, ':s replacement string '},
+ {{'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'),
+ },
+ {
+ {{'ShaDaEntryMapLongEntryStart'}, ' + '},
+ {{'ShaDaEntryMapLongKey'}, 'se '},
+ {{'ShaDaEntryMapLongDescription'}, 'place cursor at end '},
+ {{'ShaDaMsgpackKeyword'}, 'TRUE'},
+ },
+ }
+ eq(exp, act)
+ end)
+end)