Wie kann ich die Position des Cursors wiederherstellen, nachdem ich einen normalen Befehl ausgeführt habe?

13

Ich versuche, eine Funktion zu codieren, die das Zeichen in der sechsten Spalte meiner aktuellen Zeile durch ein Dollarsymbol ( $) ersetzt, möchte jedoch, dass der Cursor an der Stelle bleibt, an der er vor dem Aufrufen der Funktion war.

Daher habe ich versucht, die aktuelle Spalte zu speichern, meine Änderungen auszuführen und dann mit der folgenden Funktion zurückzukehren:

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

Ich habe wahrscheinlich ein Missverständnis mit dem executeBefehl ... Oder sollte ich einen String erstellen, der den Befehl enthält, den ich ausführen möchte?

Feffe
quelle

Antworten:

19

Sie sollten verwenden getpos():

So speichern Sie Ihre Position in einer Variablen:

let save_pos = getpos(".")

getpos()Nimmt als Argument eine Marke, "."repräsentiert hier die aktuelle Position Ihres Cursors.

Und um es wiederherzustellen:

call setpos('.', save_pos)

Hier zeigt das erste Argument an, dass Sie die Marke der aktuellen Position Ihres Cursors verschieben (daher Ihre aktuelle Position) und das zweite ist, wo die Marke platziert werden soll (die Position, die Sie zuvor gespeichert haben).

Ihre Funktion würde so aussehen:

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

Weitere Einzelheiten finden Sie unter: :h getpos()und:h setpos()


Für weitere Informationen zu Ihrer Verwendung von execute: Diese Funktion nimmt einen String und führt ihn aus. Ihre Zeichenfolge kann nur aus hartcodierten Zeichen zwischen doppelten Anführungszeichen oder dem Inhalt von Variablen bestehen.

Wenn du schreibst

execute col_number."|"

Wenn Sie sich in der 12. Spalte befinden, wird die erweiterte Zeichenfolge angezeigt 12|. Execute versucht, diesen Befehl 12|auszuführen, funktioniert aber nicht, da es sich nicht um eine Vimscript-Funktion handelt, sondern um einen Befehl im normalen Modus.

Um es von einem Vimscript auszuführen, muss man sagen "Führe es so aus, als hätte ich es im normalen Modus getippt", dafür wird normal verwendet.

Also ohne das Ausführen hättest du geschrieben:

normal 12|

Damit Ihr executeAnruf funktioniert, müssen Sie das normalSchlüsselwort wie folgt zu Ihrer erweiterten Zeichenfolge hinzufügen :

execute "normal " . col_number . "|"
statox
quelle
Vielen Dank für diese Lösung (die ich verwenden werde), aber gibt es eine andere Möglichkeit, meine Variable "col_number" zu verwenden? Das würde es mir ermöglichen, besser zu verstehen, wie Execute / Normal funktionieren.
Feffe
1
@Feffe: Mein Update sollte dies klarstellen :-)
statox
3

Diese Funktion führt auch Ihr Suchregister. So können Sie Ihren Befehl als Argument übergeben.

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

Eine Erklärung

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

Beispielsweise:

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

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

SergioAraujo
quelle
1
Willkommen auf unserer Webseite! Versuchen Sie bei der Beantwortung, eine Erklärung in der Antwort anzugeben und nicht nur auf andere Seiten zu verlinken. Links können absterben und viele irrelevante Informationen enthalten, die sortiert werden müssen.
Tumbler41
1
Wie ich im SO-Duplikat sagte, sollte die Wiederherstellung in einem finallyBlock erfolgen. Andernfalls wird a:commandnichts wiederhergestellt , wenn das fehlschlägt.
Luc Hermitte
Ich habe gerade meine Funktion festgelegt, als Sie @Luc Hermitte
SergioAraujo am
Tolle Beispiele - sehr nützlich.
Charlie Dalsass