1

I am looking for a way to save and restore marks at the beginning and end of my custom Vimscript function. I am writing a plugin and I don't want my plugin to change any of the user's marks, so I would like to save the state at the beginning of my function, execute some commands which create marks, and then at the end restore the original state of the marks. Similar how we can do

let l:old_value = getreg("q")
--- some work ---
setreg("q", l:old_value)

I've read the docs and googled around, but couldn't find any way of saving and restoring a mark in this way.

8
  • 1
    You need to use getpos(), setpos(), and/or getmarklist() Jul 20, 2023 at 9:34
  • @ChristianBrabandt the issue with getpos() and setpos() is that it doesn't get updated if some text is inserted/deleted above the mark. However, getmarklist() seems to be what I was looking for. Do you know if there's a builtin way to create a mark from a dictionary entry in getmarklist() or do I have to parse it manually, go to the position, create mark, and then go back to previous position?
    – matko031
    Jul 20, 2023 at 11:18
  • 1
    You are supposed to use setpos().
    – romainl
    Jul 20, 2023 at 11:28
  • I cannot reproduce the issue that getpos() is not updated, after inserting/deleting text above a mark. Jul 20, 2023 at 12:01
  • 1
    I think it is clear from the OP that matko031 knows the difference; they used register functions as an example of the thing they'd like to do with marks. So I'm going to delete the comments trying to clarify the difference.
    – D. Ben Knoble
    Jul 20, 2023 at 16:41

1 Answer 1

3

To get a list of all marks, you can use the getmarklist() Vimscript function. It allows to either return global marks (when no buffer argument is given) or return buffer specific marks when a bufnr number is given as argument.

To set the position of a mark, you can use the setpos() function. And for getting the position of a mark, you can use the getpos() function.

So knowing all this, you can do:

let mymarks = getmarklist(bufnr('%'))
" Do your work
" [...]
" restore the marks
for item in mymarks 
    " filter out the marks you changed in your function
    call setpos(item.mark, item.pos)
endfor
" or in a slightly more compact way:
call mymarks->map({_, val -> setpos(val.mark, val.pos)})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.