neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

marks_spec.lua (13110B)


      1 -- ShaDa marks saving/reading support
      2 local t = require('test.testutil')
      3 local n = require('test.functional.testnvim')()
      4 local t_shada = require('test.functional.shada.testutil')
      5 
      6 local api, nvim_command, fn, eq = n.api, n.command, n.fn, t.eq
      7 local feed = n.feed
      8 local exc_exec, exec_capture = n.exc_exec, n.exec_capture
      9 local expect_exit = n.expect_exit
     10 
     11 local reset, clear = t_shada.reset, t_shada.clear
     12 
     13 local nvim_current_line = function()
     14  return api.nvim_win_get_cursor(0)[1]
     15 end
     16 
     17 describe('ShaDa support code', function()
     18  local testfilename = 'Xtestfile-functional-shada-marks'
     19  local testfilename_2 = 'Xtestfile-functional-shada-marks-2'
     20  local non_existent_testfilename = testfilename .. '.nonexistent'
     21  before_each(function()
     22    reset()
     23    os.remove(non_existent_testfilename)
     24    local fd = io.open(testfilename, 'w')
     25    fd:write('test\n')
     26    fd:write('test2\n')
     27    fd:close()
     28    fd = io.open(testfilename_2, 'w')
     29    fd:write('test3\n')
     30    fd:write('test4\n')
     31    fd:close()
     32  end)
     33  after_each(function()
     34    clear()
     35    os.remove(testfilename)
     36    os.remove(testfilename_2)
     37  end)
     38 
     39  it('is able to dump and read back global mark', function()
     40    nvim_command('edit ' .. testfilename)
     41    nvim_command('mark A')
     42    nvim_command('2')
     43    nvim_command('kB')
     44    nvim_command('wshada')
     45    reset()
     46    nvim_command('rshada')
     47    nvim_command('normal! `A')
     48    eq(testfilename, fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
     49    eq(1, nvim_current_line())
     50    nvim_command('normal! `B')
     51    eq(2, nvim_current_line())
     52  end)
     53 
     54  it('can dump and read back numbered marks', function()
     55    local function move(cmd)
     56      feed(cmd)
     57      nvim_command('wshada')
     58    end
     59    nvim_command('edit ' .. testfilename)
     60    move('l')
     61    move('l')
     62    move('j')
     63    move('l')
     64    move('l')
     65    nvim_command('edit ' .. testfilename_2)
     66    move('l')
     67    move('l')
     68    move('j')
     69    move('l')
     70    move('l')
     71    -- we have now populated marks 0 through 9
     72    nvim_command('edit ' .. testfilename)
     73    feed('gg0')
     74    -- during shada save on exit, mark 0 will become the current position,
     75    -- 9 will be removed, and all other marks shifted
     76    expect_exit(nvim_command, 'qall')
     77    reset()
     78    nvim_command('edit ' .. testfilename)
     79    nvim_command('edit ' .. testfilename_2)
     80    local marklist = fn.getmarklist()
     81    for _, mark in ipairs(marklist) do
     82      mark.file = fn.fnamemodify(mark.file, ':t')
     83    end
     84    eq({
     85      {
     86        file = testfilename,
     87        mark = "'0",
     88        pos = { 1, 1, 1, 0 },
     89      },
     90      {
     91        file = testfilename_2,
     92        mark = "'1",
     93        pos = { 2, 2, 5, 0 },
     94      },
     95      {
     96        file = testfilename_2,
     97        mark = "'2",
     98        pos = { 2, 2, 4, 0 },
     99      },
    100      {
    101        file = testfilename_2,
    102        mark = "'3",
    103        pos = { 2, 2, 3, 0 },
    104      },
    105      {
    106        file = testfilename_2,
    107        mark = "'4",
    108        pos = { 2, 1, 3, 0 },
    109      },
    110      {
    111        file = testfilename_2,
    112        mark = "'5",
    113        pos = { 2, 1, 2, 0 },
    114      },
    115      {
    116        file = testfilename,
    117        mark = "'6",
    118        pos = { 1, 2, 5, 0 },
    119      },
    120      {
    121        file = testfilename,
    122        mark = "'7",
    123        pos = { 1, 2, 4, 0 },
    124      },
    125      {
    126        file = testfilename,
    127        mark = "'8",
    128        pos = { 1, 2, 3, 0 },
    129      },
    130      {
    131        file = testfilename,
    132        mark = "'9",
    133        pos = { 1, 1, 3, 0 },
    134      },
    135    }, marklist)
    136  end)
    137 
    138  it('does not dump global or numbered marks with `f0` in shada', function()
    139    nvim_command('set shada+=f0')
    140    nvim_command('edit ' .. testfilename)
    141    nvim_command('mark A')
    142    nvim_command('2')
    143    nvim_command('wshada')
    144    reset()
    145    nvim_command('language C')
    146    eq('Vim(normal):E20: Mark not set', exc_exec('normal! `A'))
    147    eq('Vim(normal):E20: Mark not set', exc_exec('normal! `0'))
    148  end)
    149 
    150  it("restores global and numbered marks even with `'0` and `f0` in shada", function()
    151    nvim_command('edit ' .. testfilename)
    152    nvim_command('mark A')
    153    nvim_command('2')
    154    nvim_command('wshada')
    155    reset("set shada='0,f0")
    156    nvim_command('language C')
    157    nvim_command('normal! `A')
    158    eq(testfilename, fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    159    eq(1, nvim_current_line())
    160    nvim_command('normal! `0')
    161    eq(testfilename, fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    162    eq(2, nvim_current_line())
    163  end)
    164 
    165  it('is able to dump and read back local mark', function()
    166    nvim_command('edit ' .. testfilename)
    167    nvim_command('mark a')
    168    nvim_command('2')
    169    nvim_command('kb')
    170    expect_exit(nvim_command, 'qall')
    171    reset()
    172    nvim_command('edit ' .. testfilename)
    173    nvim_command('normal! `a')
    174    eq(testfilename, fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    175    eq(1, nvim_current_line())
    176    nvim_command('normal! `b')
    177    eq(2, nvim_current_line())
    178  end)
    179 
    180  it('is able to dump and read back mark "', function()
    181    nvim_command('edit ' .. testfilename)
    182    nvim_command('2')
    183    expect_exit(nvim_command, 'qall')
    184    reset()
    185    nvim_command('edit ' .. testfilename)
    186    nvim_command('normal! `"')
    187    eq(2, nvim_current_line())
    188  end)
    189 
    190  it('is able to dump and read back mark " from a closed tab', function()
    191    nvim_command('edit ' .. testfilename)
    192    nvim_command('tabedit ' .. testfilename_2)
    193    nvim_command('2')
    194    nvim_command('q!')
    195    expect_exit(nvim_command, 'qall')
    196    reset()
    197    nvim_command('edit ' .. testfilename_2)
    198    nvim_command('normal! `"')
    199    eq(2, nvim_current_line())
    200  end)
    201 
    202  it('is able to populate v:oldfiles', function()
    203    nvim_command('edit ' .. testfilename)
    204    local tf_full = api.nvim_buf_get_name(0)
    205    nvim_command('edit ' .. testfilename_2)
    206    local tf_full_2 = api.nvim_buf_get_name(0)
    207    expect_exit(nvim_command, 'qall')
    208    reset()
    209    local oldfiles = api.nvim_get_vvar('oldfiles')
    210    table.sort(oldfiles)
    211    eq(2, #oldfiles)
    212    eq(testfilename, oldfiles[1]:sub(-#testfilename))
    213    eq(testfilename_2, oldfiles[2]:sub(-#testfilename_2))
    214    eq(tf_full, oldfiles[1])
    215    eq(tf_full_2, oldfiles[2])
    216    nvim_command('rshada!')
    217    oldfiles = api.nvim_get_vvar('oldfiles')
    218    table.sort(oldfiles)
    219    eq(2, #oldfiles)
    220    eq(testfilename, oldfiles[1]:sub(-#testfilename))
    221    eq(testfilename_2, oldfiles[2]:sub(-#testfilename_2))
    222    eq(tf_full, oldfiles[1])
    223    eq(tf_full_2, oldfiles[2])
    224  end)
    225 
    226  it('is able to dump and restore jump list', function()
    227    nvim_command('edit ' .. testfilename_2)
    228    nvim_command('normal! G')
    229    nvim_command('normal! gg')
    230    nvim_command('edit ' .. testfilename)
    231    nvim_command('normal! G')
    232    nvim_command('normal! gg')
    233    nvim_command('enew')
    234    nvim_command('normal! gg')
    235    local saved = exec_capture('jumps')
    236    expect_exit(nvim_command, 'qall')
    237    reset()
    238    eq(saved, exec_capture('jumps'))
    239  end)
    240 
    241  it("does not dump jumplist if `'0` in shada", function()
    242    local empty_jumps = exec_capture('jumps')
    243    nvim_command("set shada='0")
    244    nvim_command('edit ' .. testfilename_2)
    245    nvim_command('normal! G')
    246    nvim_command('normal! gg')
    247    nvim_command('edit ' .. testfilename)
    248    nvim_command('normal! G')
    249    nvim_command('normal! gg')
    250    nvim_command('enew')
    251    nvim_command('normal! gg')
    252    expect_exit(nvim_command, 'qall')
    253    reset()
    254    eq(empty_jumps, exec_capture('jumps'))
    255  end)
    256 
    257  it("does read back jumplist even with `'0` in shada", function()
    258    nvim_command('edit ' .. testfilename_2)
    259    nvim_command('normal! G')
    260    nvim_command('normal! gg')
    261    nvim_command('edit ' .. testfilename)
    262    nvim_command('normal! G')
    263    nvim_command('normal! gg')
    264    nvim_command('enew')
    265    nvim_command('normal! gg')
    266    local saved = exec_capture('jumps')
    267    expect_exit(nvim_command, 'qall')
    268    reset("set shada='0")
    269    eq(saved, exec_capture('jumps'))
    270  end)
    271 
    272  it('when dumping jump list also dumps current position', function()
    273    nvim_command('edit ' .. testfilename)
    274    nvim_command('normal! G')
    275    nvim_command('split ' .. testfilename_2)
    276    nvim_command('normal! G')
    277    nvim_command('wshada')
    278    nvim_command('quit')
    279    nvim_command('rshada')
    280    nvim_command('normal! \15') -- <C-o>
    281    eq(testfilename_2, fn.bufname('%'))
    282    eq({ 2, 0 }, api.nvim_win_get_cursor(0))
    283  end)
    284 
    285  it('is able to dump and restore jump list with different times', function()
    286    nvim_command('edit ' .. testfilename_2)
    287    nvim_command('sleep 10m')
    288    nvim_command('normal! G')
    289    nvim_command('sleep 10m')
    290    nvim_command('normal! gg')
    291    nvim_command('sleep 10m')
    292    nvim_command('edit ' .. testfilename)
    293    nvim_command('sleep 10m')
    294    nvim_command('normal! G')
    295    nvim_command('sleep 10m')
    296    nvim_command('normal! gg')
    297    expect_exit(nvim_command, 'qall')
    298    reset()
    299    nvim_command('redraw')
    300    nvim_command('edit ' .. testfilename)
    301    eq(testfilename, fn.bufname('%'))
    302    eq(1, nvim_current_line())
    303    nvim_command('execute "normal! \\<C-o>"')
    304    eq(testfilename, fn.bufname('%'))
    305    eq(2, nvim_current_line())
    306    nvim_command('execute "normal! \\<C-o>"')
    307    eq(testfilename_2, fn.bufname('%'))
    308    eq(1, nvim_current_line())
    309    nvim_command('execute "normal! \\<C-o>"')
    310    eq(testfilename_2, fn.bufname('%'))
    311    eq(2, nvim_current_line())
    312    nvim_command('execute "normal! \\<C-o>"')
    313    eq(testfilename_2, fn.bufname('%'))
    314    eq(2, nvim_current_line())
    315  end)
    316 
    317  it('is able to dump and restore change list', function()
    318    nvim_command('edit ' .. testfilename)
    319    nvim_command('normal! Gra')
    320    nvim_command('normal! ggrb')
    321    expect_exit(nvim_command, 'qall!')
    322    reset()
    323    nvim_command('edit ' .. testfilename)
    324    nvim_command('normal! Gg;')
    325    -- Note: without “sync” “commands” test has good changes to fail for unknown
    326    -- reason (in first eq expected 1 is compared with 2). Any command inserted
    327    -- causes this to work properly.
    328    nvim_command('" sync')
    329    eq(1, nvim_current_line())
    330    nvim_command('normal! g;')
    331    nvim_command('" sync 2')
    332    eq(2, nvim_current_line())
    333  end)
    334 
    335  -- -c temporary sets lnum to zero to make `+/pat` work, so calling setpcmark()
    336  -- during -c used to add item with zero lnum to jump list.
    337  it('does not create incorrect file for non-existent buffers when writing from -c', function()
    338    local p = n.spawn_wait {
    339      args_rm = {
    340        '-i',
    341        '--embed', -- no --embed
    342      },
    343      args = {
    344        '-i',
    345        api.nvim_get_var('tmpname'), -- Use same shada file as parent.
    346        '--cmd',
    347        'silent edit ' .. non_existent_testfilename,
    348        '-c',
    349        'qall',
    350      },
    351    }
    352    eq('', p:output())
    353    eq(0, p.status)
    354    eq(0, exc_exec('rshada'))
    355  end)
    356 
    357  it('does not create incorrect file for non-existent buffers opened from -c', function()
    358    local p = n.spawn_wait {
    359      args_rm = {
    360        '-i',
    361        '--embed', -- no --embed
    362      },
    363      args = {
    364        '-i',
    365        api.nvim_get_var('tmpname'), -- Use same shada file as parent.
    366        '-c',
    367        'silent edit ' .. non_existent_testfilename,
    368        '-c',
    369        'autocmd VimEnter * qall',
    370      },
    371    }
    372    eq('', p:output())
    373    eq(0, p.status)
    374    eq(0, exc_exec('rshada'))
    375  end)
    376 
    377  it('updates deleted marks with :delmarks', function()
    378    nvim_command('edit ' .. testfilename)
    379 
    380    nvim_command('mark A')
    381    nvim_command('mark a')
    382    -- create a change to set the '.' mark,
    383    -- since it can't be set via :mark
    384    feed('ggifoobar<esc>')
    385    nvim_command('wshada')
    386 
    387    reset()
    388    nvim_command('edit ' .. testfilename)
    389    nvim_command('normal! `A`a`.')
    390    nvim_command('delmarks A a .')
    391    nvim_command('wshada')
    392 
    393    reset()
    394    nvim_command('edit ' .. testfilename)
    395    eq('Vim(normal):E20: Mark not set', exc_exec('normal! `A'))
    396    eq('Vim(normal):E20: Mark not set', exc_exec('normal! `a'))
    397    eq('Vim(normal):E20: Mark not set', exc_exec('normal! `.'))
    398  end)
    399 
    400  it('updates deleted marks with :delmarks!', function()
    401    nvim_command('edit ' .. testfilename)
    402 
    403    nvim_command('mark A')
    404    nvim_command('mark a')
    405    feed('ggifoobar<esc>')
    406    nvim_command('wshada')
    407 
    408    reset()
    409    nvim_command('edit ' .. testfilename)
    410    nvim_command('normal! `A`a`.')
    411    nvim_command('delmarks!')
    412    nvim_command('wshada')
    413 
    414    reset()
    415    nvim_command('edit ' .. testfilename)
    416    eq('Vim(normal):E20: Mark not set', exc_exec('normal! `a'))
    417    eq('Vim(normal):E20: Mark not set', exc_exec('normal! `.'))
    418    -- Make sure that uppercase marks aren't deleted.
    419    nvim_command('normal! `A')
    420  end)
    421 
    422  it('preserves marks after :bdelete #35770', function()
    423    nvim_command('edit foo')
    424    nvim_command('mark X')
    425    nvim_command('bdelete')
    426    nvim_command('wshada')
    427 
    428    reset()
    429    local mX = api.nvim_get_mark('X', {})
    430    t.matches(vim.pesc('foo'), mX[4])
    431 
    432    nvim_command('delmarks X')
    433    nvim_command('edit foo')
    434    nvim_command('mark X')
    435    nvim_command('edit bar')
    436    nvim_command('mark Y')
    437    nvim_command('bufdo bdelete')
    438    nvim_command('edit foo')
    439    nvim_command('wshada')
    440 
    441    reset()
    442    mX = api.nvim_get_mark('X', {})
    443    local mY = api.nvim_get_mark('Y', {})
    444    t.matches(vim.pesc('foo'), mX[4])
    445    t.matches(vim.pesc('bar'), mY[4])
    446  end)
    447 end)