neovim

Restore cursor position in Neovim when opening multiple files


I am currently trying to migrate from Vim to Neovim.

With Vim I have cursor position restoration via the following autocmd:

" Return to last edit position when opening files (You want this!)
autocmd BufReadPost *
    \ if line("'\"") > 0 && line("'\"") <= line("$") |
    \   exe "normal! g`\"" |
    \ endif

Maybe this is also relevant:

set viminfo^=%

When opening a file, scrolling to line 100, closing the file and re-opening it again I am on line 100 like where I was before closing the file.

I would like to have the same with Neovim too. In theory this is working, but only when opening files one by one. When opening multiple files at once (nvim <file> <file>) the cursor position is only restored for the first file.

I already tried...

But it is always the same issue that the cursor position is only restored for the first file, not for all of them.

With the following autocmd, I see that Neovim emits the BufReadPost for all files and it knows about the correct cursor position for all of them:

vim.api.nvim_create_autocmd("BufReadPost", {
  callback = function(args)
    local mark = vim.api.nvim_buf_get_mark(args.buf, '"')
    local line = mark[1]
    local col = mark[2]
    local line_count = vim.api.nvim_buf_line_count(args.buf)
    vim.print("Line: " .. line .. " / Column: " .. col .. " / Lines: " .. line_count)
  end
})

When opening two files (nvim foo bar) it shows me the following:

[foo] Line: 23 / Column: 2 / Lines: 100
[bar] Line: 2 / Column: 0 / Lines: 12

Solution

  • my nvim repo - I use this:

    
    local autocmd = vim.api.nvim_create_autocmd
    
    -- @returns a "clear = true" augroup
    local function augroup(name) return vim.api.nvim_create_augroup('sergio-lazyvim_' .. name, { clear = true }) end
    
    autocmd('BufReadPost', {
      group = augroup('restore_position'),
      callback = function()
        local exclude = { 'gitcommit' }
        local buf = vim.api.nvim_get_current_buf()
        if vim.tbl_contains(exclude, vim.bo[buf].filetype) then return end
    
        local mark = vim.api.nvim_buf_get_mark(buf, '"')
        local line_count = vim.api.nvim_buf_line_count(buf)
        if mark[1] > 0 and mark[1] <= line_count then
          pcall(vim.api.nvim_win_set_cursor, 0, mark)
          vim.api.nvim_feedkeys('zvzz', 'n', true)
        end
      end,
      desc = 'Restore cursor position after reopening file',
    })