¿Cómo restaurar la posición del cursor después de ejecutar un comando normal?


13

Estoy tratando de codificar una función que reemplaza el carácter en la sexta columna de mi línea actual con un símbolo de dólar ( $), pero me gustaría que mi cursor permanezca en la posición que tenía antes de llamar a la función.

Así que intenté almacenar la columna actual, ejecutar mis cambios y luego regresar con la siguiente función:

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

Probablemente estoy malinterpretando algo sobre el executecomando ... ¿O tal vez debería crear una cadena que contiene el comando que quiero que se ejecute?

Respuestas:


19

Debes usar getpos():

Para guardar su posición en una variable:

let save_pos = getpos(".")

getpos()toma como argumento una marca, aquí "."representa la posición actual de su cursor.

Y para restaurarlo:

call setpos('.', save_pos)

Aquí el primer argumento indica que moverá la marca de la posición actual de su cursor (de ahí su posición actual) y el segundo es donde colocar la marca (la posición que guardó anteriormente).

Su función se vería así:

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

Para más detalles ver: :h getpos()y:h setpos()


Para obtener más detalles sobre su uso de execute: esta función tomará una cadena y la ejecutará. Su cadena puede ser solo caracteres codificados entre comillas dobles o el contenido de las variables.

Cuando escribes

execute col_number."|"

Si está en la columna 12, la cadena expandida estará 12|. Execute intentará ejecutar este comando pero no funcionará porque 12|no es una función vimscript sino un comando en modo normal.

Para ejecutarlo desde un vimscript tienes que decir "ejecutarlo como si lo hubiera escrito en modo normal", para eso se usa lo normal.

Entonces, sin la ejecución, habría escrito:

normal 12|

Ahora, para que su executellamada funcione, debe agregar la normalpalabra clave a su cadena expandida, como esta:

execute "normal " . col_number . "|"

Gracias por esta solución (es la que usaré), pero ¿hay alguna otra forma de usar mi variable "col_number"? Eso me permitiría entender mejor cómo ejecutar / trabajo normal.
Feffe

1
@Feffe: Mi actualización debería aclarar esto :-)
statox

3

Esta función también mantiene su registro de búsqueda. Entonces puede pasar su comando como argumento sobre él.

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

Alguna explicación

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

Por ejemplo:

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

"Reindent command using 'Preserve()'
command! -nargs=0 Reindent :call Preserve('exec "normal! gg=G"')

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

"Close all buffers but current one
" https://bitbucket.org/snippets/sergio/9nbyGy
command! BufOnly silent! call Preserve("exec '%bd|e#|bd#'")

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


1
¡Bienvenido a nuestro sitio! Cuando responda, intente dar alguna explicación dentro de la respuesta y no solo enlaces a otras páginas. Los enlaces pueden morir y pueden tener mucha información irrelevante para clasificar.
Tumbler41

1
Como dije en el duplicado SO, la restauración debería ocurrir en un finallybloque. De lo contrario, si a:commandfalla, no se restaurará nada.
Luc Hermitte

Acabo de arreglar mi función como mencionaste @Luc Hermitte
SergioAraujo

Grandes ejemplos, muy útiles.
Charlie Dalsass
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.