Làm thế nào để khôi phục vị trí của con trỏ sau khi thực hiện một lệnh bình thường?


13

Tôi đang cố mã hóa một hàm thay thế ký tự trong cột thứ sáu của dòng hiện tại của tôi bằng ký hiệu đô la ( $), nhưng tôi muốn con trỏ của tôi giữ nguyên vị trí trước khi gọi hàm.

Vì vậy, tôi đã cố gắng lưu trữ cột hiện tại, thực hiện các thay đổi của mình và sau đó quay lại với chức năng sau:

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

Tôi có lẽ đang hiểu nhầm điều gì đó về executelệnh ... Hoặc có lẽ tôi nên tạo một chuỗi chứa lệnh tôi muốn được thực thi?

Câu trả lời:


19

Bạn nên sử dụng getpos():

Để tiết kiệm vị trí của bạn trong một biến:

let save_pos = getpos(".")

getpos()lấy làm đối số một dấu, ở đây "."đại diện cho vị trí hiện tại của con trỏ của bạn.

Và để khôi phục nó:

call setpos('.', save_pos)

Ở đây, đối số đầu tiên chỉ ra rằng bạn sẽ di chuyển dấu của vị trí hiện tại của con trỏ (do đó là vị trí hiện tại của bạn) và thứ hai là nơi đặt dấu (vị trí mà bạn đã lưu trước đó).

Chức năng của bạn sẽ trông như thế này:

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

Để biết thêm chi tiết, xem: :h getpos():h setpos()


Để biết thêm chi tiết về việc sử dụng của bạn execute: chức năng này sẽ lấy một chuỗi và thực hiện nó. Chuỗi của bạn chỉ có thể là các ký tự được mã hóa cứng giữa các dấu ngoặc kép hoặc nội dung của các biến.

Khi bạn viết

execute col_number."|"

Nếu bạn ở cột thứ 12, chuỗi mở rộng sẽ là 12|. Execute sẽ cố gắng thực thi lệnh này nhưng nó sẽ không hoạt động vì 12|không phải là hàm vimscript mà là lệnh chế độ bình thường.

Để thực thi nó từ một vimscript bạn phải nói "thực thi nó như thể tôi đã gõ nó ở chế độ bình thường", đó là những gì bình thường được sử dụng cho.

Vì vậy, nếu không thực hiện, bạn sẽ viết:

normal 12|

Bây giờ để thực hiện executecuộc gọi của bạn, bạn phải thêm normaltừ khóa vào chuỗi mở rộng của mình, như thế này:

execute "normal " . col_number . "|"

Cảm ơn giải pháp này (đó là giải pháp tôi sẽ sử dụng), nhưng có cách nào khác không, sử dụng biến "col_number" của tôi? Điều đó sẽ cho phép tôi hiểu rõ hơn cách thực hiện / công việc bình thường.
Feffe

1
@Feffe: Bản cập nhật của tôi sẽ làm rõ điều này :-)
statox

3

Chức năng này cũng giữ đăng ký tìm kiếm của bạn. Vì vậy, bạn có thể truyền lệnh của bạn như là đối số trên nó.

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

Một số giải thích

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

Ví dụ:

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

nguồn: https://technotales.wordpress.com/2010/03/31/preserve-a-vim-feft-that-keeps-your-state/


1
Chào mừng đến với trang web của chúng tôi! Khi trả lời hãy cố gắng đưa ra một số lời giải thích trong câu trả lời và không chỉ liên kết đến các trang khác. Liên kết có thể chết và có thể có nhiều thông tin không liên quan để sắp xếp.
Tumbler41

1
Như tôi đã nói trong bản sao SO, việc khôi phục sẽ diễn ra trong một finallykhối. Nếu không, nếu a:commandthất bại, không có gì sẽ được khôi phục.
Luc Hermitte

Tôi vừa sửa chức năng của mình như bạn đã đề cập @Luc Hermitte
SergioAraujo

Ví dụ tuyệt vời - rất hữu ích.
Charlie Dalsass
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.