local auto = require('std.auto') local ignored = require('std.ignored') local behaviour = require('bugabinga.options.behaviour') local restore_cursor_handler = behaviour.restore_cursor_handler describe('cursor restore behaviour', function() after_each(function() pcall(vim.api.nvim_del_augroup_by_name, 'restore_cursor_position') pcall(vim.api.nvim_del_augroup_by_name, 'restore_cursor_stage2') for _, buf in ipairs(vim.api.nvim_list_bufs()) do pcall(vim.api.nvim_buf_delete, buf, { force = true }) end end) local function make_buffer_with_lines(buf, lines) vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) end local function set_shada_mark(buf, line, col) vim.api.nvim_set_current_buf(buf) vim.cmd.normal { string.format('%dG', line), bang = true } vim.cmd.normal { string.format('%dl', col - 1), bang = true } vim.cmd([[normal! m"]]) end describe('BufReadPost stage', function() it('should NOT create stage2 when buftype is nofile', function() local buf = vim.api.nvim_create_buf(false, false) vim.bo[buf].buftype = 'nofile' make_buffer_with_lines(buf, { 'line 1', 'line 2', 'line 3' }) set_shada_mark(buf, 3, 5) auto 'restore_cursor_position' { events = 'BufReadPost', command = restore_cursor_handler, } vim.api.nvim_exec_autocmds('BufReadPost', { buf = buf }) local ok, stage2 = pcall(vim.api.nvim_get_autocmds, { group = 'restore_cursor_stage2' }) if ok then assert.equal(0, #stage2) end end) it('should NOT create stage2 when filetype is help', function() local buf = vim.api.nvim_create_buf(false, false) vim.bo[buf].filetype = 'help' make_buffer_with_lines(buf, { 'line 1', 'line 2', 'line 3' }) set_shada_mark(buf, 3, 5) auto 'restore_cursor_position' { events = 'BufReadPost', command = restore_cursor_handler, } vim.api.nvim_exec_autocmds('BufReadPost', { buf = buf }) local ok, stage2 = pcall(vim.api.nvim_get_autocmds, { group = 'restore_cursor_stage2' }) if ok then assert.equal(0, #stage2) end end) it('should NOT create stage2 when cursor already at mark position', function() local buf = vim.api.nvim_create_buf(false, false) make_buffer_with_lines(buf, { 'line 1', 'line 2', 'line 3', 'line 4', 'line 5' }) set_shada_mark(buf, 3, 5) -- simulate nvim +3 file.lua - cursor already at line 3 (same as mark) vim.api.nvim_set_current_buf(buf) vim.cmd.normal { '3G' } auto 'restore_cursor_position' { events = 'BufReadPost', command = restore_cursor_handler, } vim.api.nvim_exec_autocmds('BufReadPost', { buf = buf }) local ok, stage2 = pcall(vim.api.nvim_get_autocmds, { group = 'restore_cursor_stage2' }) if ok then assert.equal(0, #stage2) end end) it('should create stage2 autocmd when conditions are met', function() local buf = vim.api.nvim_create_buf(false, false) make_buffer_with_lines(buf, { 'line 1', 'line 2', 'line 3', 'line 4', 'line 5' }) set_shada_mark(buf, 3, 5) -- cursor at line 1, mark at line 3 vim.api.nvim_set_current_buf(buf) vim.cmd.normal { 'gg' } auto 'restore_cursor_position' { events = 'BufReadPost', command = restore_cursor_handler, } vim.api.nvim_exec_autocmds('BufReadPost', { buf = buf }) local stage2 = vim.api.nvim_get_autocmds({ group = 'restore_cursor_stage2' }) assert.equal(1, #stage2) assert.equal(buf, stage2[1].buf) end) it('should only restore once per buffer, not on every read', function() local buf = vim.api.nvim_create_buf(false, false) make_buffer_with_lines(buf, { 'line 1', 'line 2', 'line 3', 'line 4', 'line 5' }) set_shada_mark(buf, 3, 5) vim.api.nvim_set_current_buf(buf) vim.cmd.normal { 'gg' } auto 'restore_cursor_position' { events = 'BufReadPost', command = restore_cursor_handler, } -- first read: opening the file vim.api.nvim_exec_autocmds('BufReadPost', { buf = buf }) assert.is_true(vim.b[buf].cursor_restored) pcall(vim.api.nvim_del_augroup_by_name, 'restore_cursor_stage2') -- second read: the file changed on disk and was reloaded. -- must not queue another jump to the shada mark. vim.cmd.normal { 'gg' } vim.api.nvim_exec_autocmds('BufReadPost', { buf = buf }) local ok, stage2 = pcall(vim.api.nvim_get_autocmds, { group = 'restore_cursor_stage2' }) if ok then assert.equal(0, #stage2) end end) end) describe('BufWinEnter stage', function() it('should restore cursor to shada position', function() local buf = vim.api.nvim_create_buf(false, false) make_buffer_with_lines(buf, { 'line 1', 'line 2', 'line 3', 'line 4', 'line 5' }) set_shada_mark(buf, 3, 5) -- create a window with this buffer vim.cmd.split() local win = vim.api.nvim_get_current_win() vim.api.nvim_win_set_buf(win, buf) vim.api.nvim_set_current_win(win) vim.cmd.normal { 'gg' } -- cursor at line 1 auto 'restore_cursor_position' { events = 'BufReadPost', command = restore_cursor_handler, } vim.api.nvim_exec_autocmds('BufReadPost', { buf = buf }) vim.api.nvim_exec_autocmds('BufWinEnter', { buf = buf }) local cursor = vim.api.nvim_win_get_cursor(win) assert.equal(3, cursor[1]) assert.equal(4, cursor[2]) end) end) end)