Как восстановить положение курсора после выполнения обычной команды?

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команде ... Или, может быть, мне нужно создать строку, содержащую команду, которую я хочу выполнить?

Feffe
источник

Ответы:

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 . "|"
statox
источник
Спасибо за это решение (это я буду использовать), но есть ли другой способ использования моей переменной "col_number"? Это позволило бы мне лучше понять, как выполнять / нормальную работу.
Фефе
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/

SergioAraujo
источник
1
Добро пожаловать на наш сайт! При ответе постарайтесь дать какое-то объяснение в ответе, а не просто ссылки на другие страницы. Ссылки могут умереть, и может иметь много несоответствующей информации, чтобы разобраться.
Tumbler41
1
Как я сказал в SO-дубликате, восстановление должно происходить в finallyблоке. Иначе, если a:commandне получится, ничего не будет восстановлено.
Люк Эрмитт
Я только что исправил свою функцию, как вы упомянули @Luc Hermitte
SergioAraujo
Прекрасные примеры - очень полезно.
Чарли Далсасс