Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to make vim marks remember the relative position of the line in the current window?

Tags:

vim

I'm using (a modified version) of the solution proposed in http://www.thegeekstuff.com/2008/12/vi-and-vim-autocommand-3-steps-to-add-custom-header-to-your-file/ to create and update headers for my source codes automatically.

As explained in the above-mentioned page, upon invoking a write command in vim, the following sequence of commands are executed:

  1. A mark is set at the current position of the file.
  2. The "Last Modified" filed is updated. This moves the cursor to the beginning of the file (where the search-and-replace takes places).
  3. The cursor is returned to previously marked position.

This is fine, but there is a slightly annoying issue: Suppose we're editing a line close to the bottom of the window. If at that point we save the file, because of the cursor moves (for updating the header) the line we were editing jumps so that it is positioned in the middle of the window.

To my understanding 'a moves the cursor to the place marked by mark a and adjusts the window contents such that the current line appears in the middle of the window. I was wondering if there is a way to make "marks" remember also the exact relative position of the marked line in the window and maintain this position when jumping back to the mark?

like image 617
MikeL Avatar asked Jul 18 '17 09:07

MikeL


2 Answers

It's in the docs: Restoring the cursor position.

   :map <F2> msHmt…'tzt`s

(I skipped irrelevant parts with ellipsis).

ms  store cursor position in the 's' mark
H   go to the first line in the window
mt  store this position in the 't' mark

Breaking up restoring the position:

't  go to the line previously at the top of the window
zt  scroll to move this line to the top of the window
`s  jump to the original position of the cursor
like image 52
phd Avatar answered Sep 16 '22 18:09

phd


The mark itself only stores the position itself; the view (what's shown in the current window) isn't part of that.

What you're looking for is the pair of winsaveview() and winrestview() functions. These store the cursor position (like marks, but without adapting automatically to changes in the buffer; something that you probably won't need for the updating of headers), and the details of what is currently shown in the window. Use of these is recommended over marks; in custom mappings or commands it also has the benefit of not clobbering a mark.


If you use :substitute to update the header, you also may change the current search pattern (unless using a :function), and the search history. Undoing all of that is hard; I know because I've written such a plugin (AutoAdapt plugin) myself. You may want to have a look at its implementation for further tips (or start using it altogether). (The plugin page also has links to various alternative plugins.)

like image 36
Ingo Karkat Avatar answered Sep 20 '22 18:09

Ingo Karkat