1-- ShaDa marks saving/reading support
2local helpers = require('test.functional.helpers')(after_each)
3local meths, curwinmeths, curbufmeths, nvim_command, funcs, eq =
4  helpers.meths, helpers.curwinmeths, helpers.curbufmeths, helpers.command,
5  helpers.funcs, helpers.eq
6local exc_exec, exec_capture = helpers.exc_exec, helpers.exec_capture
7
8local shada_helpers = require('test.functional.shada.helpers')
9local reset, clear = shada_helpers.reset, shada_helpers.clear
10
11local nvim_current_line = function()
12  return curwinmeths.get_cursor()[1]
13end
14
15describe('ShaDa support code', function()
16  local testfilename = 'Xtestfile-functional-shada-marks'
17  local testfilename_2 = 'Xtestfile-functional-shada-marks-2'
18  local non_existent_testfilename = testfilename .. '.nonexistent'
19  before_each(function()
20    reset()
21    os.remove(non_existent_testfilename)
22    local fd = io.open(testfilename, 'w')
23    fd:write('test\n')
24    fd:write('test2\n')
25    fd:close()
26    fd = io.open(testfilename_2, 'w')
27    fd:write('test3\n')
28    fd:write('test4\n')
29    fd:close()
30  end)
31  after_each(function()
32    clear()
33    os.remove(testfilename)
34    os.remove(testfilename_2)
35  end)
36
37  it('is able to dump and read back global mark', function()
38    nvim_command('edit ' .. testfilename)
39    nvim_command('mark A')
40    nvim_command('2')
41    nvim_command('kB')
42    nvim_command('wshada')
43    reset()
44    nvim_command('rshada')
45    nvim_command('normal! `A')
46    eq(testfilename, funcs.fnamemodify(curbufmeths.get_name(), ':t'))
47    eq(1, nvim_current_line())
48    nvim_command('normal! `B')
49    eq(2, nvim_current_line())
50  end)
51
52  it('does not dump global mark with `f0` in shada', function()
53    nvim_command('set shada+=f0')
54    nvim_command('edit ' .. testfilename)
55    nvim_command('mark A')
56    nvim_command('2')
57    nvim_command('kB')
58    nvim_command('wshada')
59    reset()
60    nvim_command('language C')
61    eq('Vim(normal):E20: Mark not set', exc_exec('normal! `A'))
62  end)
63
64  it('does read back global mark even with `\'0` and `f0` in shada', function()
65    nvim_command('edit ' .. testfilename)
66    nvim_command('mark A')
67    nvim_command('2')
68    nvim_command('kB')
69    nvim_command('wshada')
70    reset('set shada=\'0,f0')
71    nvim_command('language C')
72    nvim_command('normal! `A')
73    eq(testfilename, funcs.fnamemodify(curbufmeths.get_name(), ':t'))
74    eq(1, nvim_current_line())
75  end)
76
77  it('is able to dump and read back local mark', function()
78    nvim_command('edit ' .. testfilename)
79    nvim_command('mark a')
80    nvim_command('2')
81    nvim_command('kb')
82    nvim_command('qall')
83    reset()
84    nvim_command('edit ' .. testfilename)
85    nvim_command('normal! `a')
86    eq(testfilename, funcs.fnamemodify(curbufmeths.get_name(), ':t'))
87    eq(1, nvim_current_line())
88    nvim_command('normal! `b')
89    eq(2, nvim_current_line())
90  end)
91
92  it('is able to dump and read back mark "', function()
93    nvim_command('edit ' .. testfilename)
94    nvim_command('2')
95    nvim_command('qall')
96    reset()
97    nvim_command('edit ' .. testfilename)
98    nvim_command('normal! `"')
99    eq(2, nvim_current_line())
100  end)
101
102  it('is able to dump and read back mark " from a closed tab', function()
103    nvim_command('edit ' .. testfilename)
104    nvim_command('tabedit ' .. testfilename_2)
105    nvim_command('2')
106    nvim_command('q!')
107    nvim_command('qall')
108    reset()
109    nvim_command('edit ' .. testfilename_2)
110    nvim_command('normal! `"')
111    eq(2, nvim_current_line())
112  end)
113
114  it('is able to populate v:oldfiles', function()
115    nvim_command('edit ' .. testfilename)
116    local tf_full = curbufmeths.get_name()
117    nvim_command('edit ' .. testfilename_2)
118    local tf_full_2 = curbufmeths.get_name()
119    nvim_command('qall')
120    reset()
121    local oldfiles = meths.get_vvar('oldfiles')
122    table.sort(oldfiles)
123    eq(2, #oldfiles)
124    eq(testfilename, oldfiles[1]:sub(-#testfilename))
125    eq(testfilename_2, oldfiles[2]:sub(-#testfilename_2))
126    eq(tf_full, oldfiles[1])
127    eq(tf_full_2, oldfiles[2])
128    nvim_command('rshada!')
129    oldfiles = meths.get_vvar('oldfiles')
130    table.sort(oldfiles)
131    eq(2, #oldfiles)
132    eq(testfilename, oldfiles[1]:sub(-#testfilename))
133    eq(testfilename_2, oldfiles[2]:sub(-#testfilename_2))
134    eq(tf_full, oldfiles[1])
135    eq(tf_full_2, oldfiles[2])
136  end)
137
138  it('is able to dump and restore jump list', function()
139    nvim_command('edit ' .. testfilename_2)
140    nvim_command('normal! G')
141    nvim_command('normal! gg')
142    nvim_command('edit ' .. testfilename)
143    nvim_command('normal! G')
144    nvim_command('normal! gg')
145    nvim_command('enew')
146    nvim_command('normal! gg')
147    local saved = exec_capture('jumps')
148    nvim_command('qall')
149    reset()
150    eq(saved, exec_capture('jumps'))
151  end)
152
153  it('when dumping jump list also dumps current position', function()
154    nvim_command('edit ' .. testfilename)
155    nvim_command('normal! G')
156    nvim_command('split ' .. testfilename_2)
157    nvim_command('normal! G')
158    nvim_command('wshada')
159    nvim_command('quit')
160    nvim_command('rshada')
161    nvim_command('normal! \15')  -- <C-o>
162    eq(testfilename_2, funcs.bufname('%'))
163    eq({2, 0}, curwinmeths.get_cursor())
164  end)
165
166  it('is able to dump and restore jump list with different times (slow!)',
167  function()
168    nvim_command('edit ' .. testfilename_2)
169    nvim_command('sleep 2')
170    nvim_command('normal! G')
171    nvim_command('sleep 2')
172    nvim_command('normal! gg')
173    nvim_command('sleep 2')
174    nvim_command('edit ' .. testfilename)
175    nvim_command('sleep 2')
176    nvim_command('normal! G')
177    nvim_command('sleep 2')
178    nvim_command('normal! gg')
179    nvim_command('qall')
180    reset()
181    nvim_command('redraw')
182    nvim_command('edit ' .. testfilename)
183    eq(testfilename, funcs.bufname('%'))
184    eq(1, nvim_current_line())
185    nvim_command('execute "normal! \\<C-o>"')
186    eq(testfilename, funcs.bufname('%'))
187    eq(2, nvim_current_line())
188    nvim_command('execute "normal! \\<C-o>"')
189    eq(testfilename_2, funcs.bufname('%'))
190    eq(1, nvim_current_line())
191    nvim_command('execute "normal! \\<C-o>"')
192    eq(testfilename_2, funcs.bufname('%'))
193    eq(2, nvim_current_line())
194    nvim_command('execute "normal! \\<C-o>"')
195    eq(testfilename_2, funcs.bufname('%'))
196    eq(2, nvim_current_line())
197  end)
198
199  it('is able to dump and restore change list', function()
200    nvim_command('edit ' .. testfilename)
201    nvim_command('normal! Gra')
202    nvim_command('normal! ggrb')
203    nvim_command('qall!')
204    reset()
205    nvim_command('edit ' .. testfilename)
206    nvim_command('normal! Gg;')
207    -- Note: without “sync” “commands” test has good changes to fail for unknown
208    -- reason (in first eq expected 1 is compared with 2). Any command inserted
209    -- causes this to work properly.
210    nvim_command('" sync')
211    eq(1, nvim_current_line())
212    nvim_command('normal! g;')
213    nvim_command('" sync 2')
214    eq(2, nvim_current_line())
215  end)
216
217  -- -c temporary sets lnum to zero to make `+/pat` work, so calling setpcmark()
218  -- during -c used to add item with zero lnum to jump list.
219  it('does not create incorrect file for non-existent buffers when writing from -c',
220  function()
221    local argv = helpers.new_argv{
222      args_rm={
223        '-i',
224        '--embed',  -- no --embed
225      },
226      args={
227        '-i', meths.get_var('tmpname'),  -- Use same shada file as parent.
228        '--cmd', 'silent edit '..non_existent_testfilename,
229        '-c', 'qall'},
230    }
231    eq('', funcs.system(argv))
232    eq(0, exc_exec('rshada'))
233  end)
234
235  it('does not create incorrect file for non-existent buffers opened from -c',
236  function()
237    local argv = helpers.new_argv{
238      args_rm={
239        '-i',
240        '--embed',  -- no --embed
241      },
242      args={
243        '-i', meths.get_var('tmpname'),  -- Use same shada file as parent.
244        '-c', 'silent edit '..non_existent_testfilename,
245        '-c', 'autocmd VimEnter * qall'},
246    }
247    eq('', funcs.system(argv))
248    eq(0, exc_exec('rshada'))
249  end)
250end)
251