11

I am trying to code a function that replaces the character in the sixth column of my current line with a dollar symbol ($), but I would like my cursor to remain at the position it was before calling the function.

So I tried to store the current column, execute my changes, and then come back with the following function :

function! DollarSplit()
   let col_number=col(".")     "stores the current column number of the cursor
   normal! 6|r$                " replaces the 6th caracter in line with a $
   execute col_number."|" 
endfunction

I am probably misunderstanding something about the execute command... Or maybe I should create a string containing the command I want to be executed ?

17

You should use getpos():

To save you position in a variable:

let save_pos = getpos(".")

getpos() takes as argument a mark, here "." represents the current position of your cursor.

And to restore it:

call setpos('.', save_pos)

Here the first argument indicate that you will move the mark of the current position of your cursor (hence your current position) and the second is where to put the mark (the position that you saved earlier).

Your function would look like this:

function! DollarSplit()
   let save_pos = getpos(".")
   normal! 6|r$                " replaces the 6th caracter in line with a $
   call setpos(".", save_pos)
endfunction

For more details see: :h getpos() and :h setpos()


For more details about your usage of execute: this function will take a string and execute it. Your string can be only hardcoded characters between double quotes or the contents of variables.

When you write

execute col_number."|"

If you are on the 12th column the expanded string will be 12|. Execute will try to execute this command but it won't work because 12| is not a vimscript function but a normal mode command.

To execute it from a vimscript you have to say "execute it as if I had typed it in normal mode`, that's what normal is used for.

So without the execute you would have wrote:

normal 12|

Now to make your execute call work you have to add the normal keyword to your expanded string, like this:

execute "normal " . col_number . "|"
  • Thanks for this solution (it is the one I will use), but is there any other way around, using my "col_number" variable ? That would allow me to understand better how execute/normal work. – Feffe May 12 '16 at 15:29
  • 1
    @Feffe: My update should clarify this :-) – statox May 12 '16 at 15:36
3

This function keeps also your search register. So you can pass your command as argument on it.

if !exists('*Preserve')
    function! Preserve(command)
        try
            " Preparation: save last search, and cursor position.
            let l:win_view = winsaveview()
            let l:old_query = getreg('/')
            silent! execute 'keepjumps' . a:command
        finally
            " try restore / reg and cursor position
            call winrestview(l:win_view)
            call setreg('/', l:old_query)
        endtry
    endfunction
endif

Some explanation

let .......... used to set a variable
l:somevar .... local variable
winsaveview()  get information about window view
winrestview(lwinview) restores window view to its last status
getreg('/')    used to store the last search in a variable
keepjumps      used to performe any change without change jumplis
. a:command    concatenates any given command with keepjumps

For example:

"Reident file without moving cursor position
:call Preserve('normal! gg=G')

"If you have any change log at your file header
:call Preserve('1,5s/Last Change: \zs.*/\=strftime("%c")/e')

source: https://technotales.wordpress.com/2010/03/31/preserve-a-vim-function-that-keeps-your-state/

  • Welcome to our site! When answering try to give some explanation within the answer and not just links to other pages. Links can die, and may have a lot of irrelevant information to sort through. – Tumbler41 Dec 21 '16 at 23:12
  • 1
    As I said in the SO-duplicate, the restoration should happen in a finally block. Otherwise, if the a:command fails, nothing would be restored. – Luc Hermitte Sep 1 '17 at 14:32
  • I have just fixed my function as you mentioned @Luc Hermitte – SergioAraujo Jan 2 '18 at 12:34
  • Great examples - very useful. – Charlie Dalsass Jul 12 '18 at 19:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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