Як відновити положення курсору після виконання звичайної команди?


13

Я намагаюся кодувати функцію, яка замінює символ у шостому стовпці мого поточного рядка символом долара ( $), але я хотів би, щоб мій курсор залишався на тому місці, яке було до виклику функції.

Тому я спробував зберегти поточний стовпець, виконати зміни та повернутися із наступною функцією:

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

Я, мабуть, щось не розумію щодо executeкоманди ... А може, я повинен створити рядок, що містить команду, яку я хочу виконати?

Відповіді:


19

Ви повинні використовувати getpos():

Щоб зберегти вашу позицію в змінній:

let save_pos = getpos(".")

getpos()бере як аргумент позначку, тут "."представлено поточне положення вашого курсору.

І відновити його:

call setpos('.', save_pos)

Тут перший аргумент вказує на те, що ви будете переміщувати позначку поточного положення курсору (звідси ваше поточне положення), а другий - куди поставити позначку (позицію, яку ви зберегли раніше).

Ваша функція виглядатиме так:

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

Детальніше див.: :h getpos()Та:h setpos()


Для отримання більш детальної інформації про ваше використання execute: ця функція займе рядок і виконає її. У вашому рядку можуть бути лише жорсткі коди між подвійними лапками або вмістом змінних.

Коли пишеш

execute col_number."|"

Якщо ви знаходитесь у 12-му стовпці, розширена рядок буде 12|. Execute спробує виконати цю команду, але вона не працюватиме, оскільки 12|це не функція vimscript, а команда звичайного режиму.

Щоб виконати його з vimscript, ви повинні сказати "виконати його так, як ніби я його набрав у звичайному режимі", саме для цього використовується звичайний.

Тож без виконання ви б написали:

normal 12|

Тепер, щоб ваш executeдзвінок працював, вам потрібно додати normalключове слово до розширеного рядка, наприклад:

execute "normal " . col_number . "|"

Дякую за це рішення (саме те, що я буду використовувати), але чи є інший спосіб, використовуючи мій змінний "col_number"? Це дозволило б мені краще зрозуміти, як виконувати / нормально працювати.
Feffe

1
@Feffe: Моє оновлення має уточнити це :-)
statox

3

Ця функція також зберігає ваш реєстр пошуку. Таким чином, ви можете передавати свою команду як аргумент по ній.

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

Деякі пояснення

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

Наприклад:

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

джерело: https://technotales.wordpress.com/2010/03/31/preserve-a-vim-function-that-keeps-your-state/


1
Ласкаво просимо на наш сайт! Відповідаючи, спробуйте дати пояснення у межах відповіді, а не лише посилання на інші сторінки. Посилання можуть загинути і можуть мати багато нерелевантної інформації для розбору.
Тумблер41

1
Як я вже говорив у дублікаті SO, відновлення має відбуватися в finallyблоці. В іншому випадку, якщо a:commandне вдасться, нічого не відновиться.
Люк Ермітт

Я щойно виправив свою функцію, як ви згадали @Luc Hermitte
SergioAraujo

Чудові приклади - дуже корисні.
Чарлі Далсасс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.