Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/bugabinga/cursor_restore_spec.lua

Raw
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)