Comment restaurer la position du curseur après avoir exécuté une commande normale?

13

J'essaie de coder une fonction qui remplace le caractère dans la sixième colonne de ma ligne actuelle par un symbole dollar ( $), mais je voudrais que mon curseur reste à la position qu'il était avant d'appeler la fonction.

J'ai donc essayé de stocker la colonne en cours, d'exécuter mes modifications, puis de revenir avec la fonction suivante:

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

J'ai probablement mal compris quelque chose à propos de la executecommande ... Ou peut-être devrais-je créer une chaîne contenant la commande que je veux exécuter?

Feffe
la source

Réponses:

19

Vous devez utiliser getpos():

Pour enregistrer votre position dans une variable:

let save_pos = getpos(".")

getpos()prend comme argument une marque, "."représente ici la position actuelle de votre curseur.

Et pour le restaurer:

call setpos('.', save_pos)

Ici, le premier argument indique que vous allez déplacer la marque de la position actuelle de votre curseur (d'où votre position actuelle) et le second est l'endroit où placer la marque (la position que vous avez enregistrée précédemment).

Votre fonction ressemblerait à ceci:

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

Pour plus de détails, voir: :h getpos()et:h setpos()


Pour plus de détails sur votre utilisation de execute: cette fonction prendra une chaîne et l'exécutera. Votre chaîne ne peut être que des caractères codés en dur entre guillemets doubles ou le contenu des variables.

Quand tu écris

execute col_number."|"

Si vous êtes sur la 12e colonne, la chaîne développée sera 12|. Execute essaiera d'exécuter cette commande mais cela ne fonctionnera pas car il 12|ne s'agit pas d'une fonction vimscript mais d'une commande en mode normal.

Pour l'exécuter à partir d'un vimscript, vous devez dire "l'exécuter comme si je l'avais tapé en mode normal", c'est à cela que sert la normale.

Donc sans l'exécution, vous auriez écrit:

normal 12|

Maintenant, pour que votre executeappel fonctionne, vous devez ajouter le normalmot - clé à votre chaîne développée, comme ceci:

execute "normal " . col_number . "|"
statox
la source
Merci pour cette solution (c'est celle que j'utiliserai), mais existe-t-il un autre moyen d'utiliser ma variable "col_number"? Cela me permettrait de mieux comprendre comment exécuter / travailler normalement.
Feffe
1
@Feffe: Ma mise à jour devrait clarifier ceci :-)
statox
3

Cette fonction conserve également votre registre de recherche. Vous pouvez donc passer votre commande comme argument dessus.

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

Quelques explications

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

Par exemple:

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

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

SergioAraujo
la source
1
Bienvenue sur notre site! Lorsque vous répondez, essayez de donner des explications dans la réponse et pas seulement des liens vers d'autres pages. Les liens peuvent mourir et peuvent contenir de nombreuses informations non pertinentes.
Tumbler41
1
Comme je l'ai dit dans le SO-duplicate, la restauration doit avoir lieu dans un finallybloc. Sinon, en cas d' a:commandéchec, rien ne serait restauré.
Luc Hermitte
Je viens de corriger
SergioAraujo
Grands exemples - très utiles.
Charlie Dalsass