Jak przywrócić pozycję kursora po wykonaniu normalnego polecenia?

13

Próbuję zakodować funkcję, która zastępuje znak w szóstej kolumnie mojego bieżącego wiersza symbolem dolara ( $), ale chciałbym, aby mój kursor pozostał w pozycji, w której był przed wywołaniem funkcji.

Próbowałem więc zapisać bieżącą kolumnę, wykonać moje zmiany, a następnie wrócić z następującą funkcją:

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

Prawdopodobnie nie rozumiem czegoś na temat executepolecenia ... A może powinienem utworzyć ciąg zawierający polecenie, które chcę wykonać?

Feffe
źródło

Odpowiedzi:

19

Powinieneś użyć getpos():

Aby zapisać swoją pozycję w zmiennej:

let save_pos = getpos(".")

getpos()przyjmuje jako argument znak, tutaj "."reprezentuje bieżącą pozycję kursora.

I aby go przywrócić:

call setpos('.', save_pos)

Tutaj pierwszy argument wskazuje, że przesuniesz znak bieżącej pozycji kursora (stąd twoja aktualna pozycja), a drugi to miejsce, w którym umieścisz znak (pozycję zapisaną wcześniej).

Twoja funkcja wyglądałaby następująco:

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

Aby uzyskać więcej informacji zobacz: :h getpos()i:h setpos()


Aby uzyskać więcej informacji na temat korzystania z execute: ta funkcja pobierze ciąg i wykona go. Ciąg może być tylko zakodowanymi na stałe znakami między podwójnymi cudzysłowami lub zawartością zmiennych.

Kiedy piszesz

execute col_number."|"

Jeśli znajdujesz się w 12. kolumnie, będzie to rozwinięty ciąg 12|. Wykonaj spróbuje wykonać to polecenie, ale nie będzie działać, ponieważ 12|nie jest to funkcja vimscript, ale polecenie trybu normalnego.

Aby wykonać go z vimscript, musisz powiedzieć „wykonaj go tak, jakbym napisał go w trybie normalnym”, do tego właśnie służy normalny.

Bez wykonania napisałbyś:

normal 12|

Teraz, aby executezadzwonić, musisz dodać normalsłowo kluczowe do rozwiniętego ciągu, tak jak poniżej:

execute "normal " . col_number . "|"
statox
źródło
Dzięki za to rozwiązanie (tego użyję), ale czy jest jakiś inny sposób, używając mojej zmiennej „numer_kolumny”? To pozwoli mi lepiej zrozumieć, w jaki sposób wykonywać / normalną pracę.
Feffe
1
@Feffe: Moja aktualizacja powinna to wyjaśnić :-)
statox
3

Ta funkcja prowadzi również rejestr wyszukiwania. Możesz przekazać komendę jako argument.

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

Jakieś wyjaśnienie

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

Na przykład:

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

źródło: https://technotales.wordpress.com/2010/03/31/preserve-a-vim-function-that-keeps-your-state/

SergioAraujo
źródło
1
Witamy na naszej stronie! Odpowiadając, podaj wyjaśnienie w odpowiedzi, a nie tylko linki do innych stron. Linki mogą umrzeć i mogą mieć wiele nieistotnych informacji do posortowania.
Tumbler41,
1
Jak powiedziałem w duplikacie SO, przywrócenie powinno nastąpić w finallybloku. W przeciwnym razie, jeśli a:commandzawiedzie, nic nie zostanie przywrócone.
Luc Hermitte,
Właśnie poprawiłem
SergioAraujo
Świetne przykłady - bardzo przydatne.
Charlie Dalsass,