Come ripristinare la posizione del cursore dopo aver eseguito un comando normale?


13

Sto cercando di codificare una funzione che sostituisce il carattere nella sesta colonna della mia riga corrente con un simbolo di dollaro ( $), ma vorrei che il mio cursore rimanesse nella posizione in cui si trovava prima di chiamare la funzione.

Quindi ho provato a memorizzare la colonna corrente, eseguire le mie modifiche e quindi tornare con la seguente funzione:

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

Probabilmente sto fraintendendo qualcosa sul executecomando ... O forse dovrei creare una stringa contenente il comando che voglio eseguire?

Risposte:


19

Dovresti usare getpos():

Per salvare la posizione in una variabile:

let save_pos = getpos(".")

getpos()prende come argomento un segno, qui "."rappresenta la posizione corrente del cursore.

E per ripristinarlo:

call setpos('.', save_pos)

Qui il primo argomento indica che si sposta il segno della posizione corrente del cursore (quindi la posizione corrente) e il secondo è dove posizionare il segno (la posizione salvata in precedenza).

La tua funzione sarebbe simile a questa:

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

Per maggiori dettagli vedi: :h getpos()e:h setpos()


Per maggiori dettagli sull'uso di execute: questa funzione prenderà una stringa ed eseguirà. La stringa può essere solo caratteri codificati tra virgolette doppie o il contenuto delle variabili.

Quando scrivi

execute col_number."|"

Se ti trovi sulla dodicesima colonna, sarà la stringa espansa 12|. Execute tenterà di eseguire questo comando ma non funzionerà perché 12|non è una funzione vimscript ma un comando in modalità normale.

Per eseguirlo da un vimscript devi dire "eseguilo come se lo avessi digitato in modalità normale`, ecco a cosa serve il normale.

Quindi senza l'esecuzione avresti scritto:

normal 12|

Ora per far funzionare la tua executechiamata devi aggiungere la normalparola chiave alla tua stringa espansa, in questo modo:

execute "normal " . col_number . "|"

Grazie per questa soluzione (è quella che userò), ma c'è un altro modo, usando la mia variabile "col_number"? Ciò mi consentirebbe di capire meglio come eseguire / il lavoro normale.
Feffe,

1
@Feffe: Il mio aggiornamento dovrebbe chiarire questo :-)
statox

3

Questa funzione mantiene anche il registro di ricerca. Quindi puoi passare il tuo comando come argomento su di esso.

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

Qualche spiegazione

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

Per esempio:

"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#'")

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


1
Benvenuti nel nostro sito! Quando rispondi prova a dare una spiegazione all'interno della risposta e non solo i collegamenti ad altre pagine. I collegamenti possono morire e possono contenere molte informazioni irrilevanti da riordinare.
Tumbler41,

1
Come ho detto nel duplicato di SO, il restauro dovrebbe avvenire in un finallyblocco. Altrimenti, se a:commandfallisce, nulla verrebbe ripristinato.
Luc Hermitte,

Ho appena corretto la mia funzione come hai menzionato @Luc Hermitte
SergioAraujo il

Grandi esempi - molto utili.
Charlie Dalsass,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.