Làm thế nào để đình chỉ lịch sử VIM?


8

Khi chúng tôi chỉnh sửa một tệp, chúng tôi thường thực hiện nhiều lần UNDO liên tiếp, giả sử, 20 lần. Trong VIM, điều đó thường được thực hiện bằng cách nhấn u20 lần và điều đó làm cho VIM "tăng" trong ngăn xếp lịch sử 20 vị trí. Nếu sau đó bạn chắc chắn change, tất cả 20 lệnh lịch sử cuối cùng sẽ bị mất và được thay thế bằng change. Tôi muốn thực hiện changemà không mất 20 vị trí đó. Vì vậy, tôi đoán rằng tôi muốn nói với VIM ngừng ghi lại lịch sử trước khi tôi làm changevà tiếp tục lịch sử sau đó (không muốn changetrong lịch sử).

EDIT Cố gắng rõ ràng hơn: Tôi có một chức năng FFcập nhật các dòng cuối cùng của tệp khi bộ đệm được ghi. Vì vậy, nếu tôi thực hiện 20 undos + write, lần cuối cùng writesẽ mở một nhánh hoàn tác mới. Tôi đã thử thêm vào undojoinbên trong FF(cố gắng làm theo gợi ý của jlmg bên dưới), nhưng trình tự viết-hoàn tác ghi lại lỗi: hoàn tác không được phép sau khi hoàn tác . Thay vào đó tôi có thể thực hiện một số thao tác sed ....sau khi rời đi vim, nhưng vì tôi sử dụng điều này thông qua SSHtôi thích một giải pháp chỉ có vim (thực thi một lệnh sau khi dỡ bộ đệm không ghi vào tệp).

EDIT 2 Hãy thử làm điều này trong VIM: mở một tệp trống và làm:

i1<ESC>:wa2<ESC>:wa3<ESC>:wa4<ESC>uu:w

Nếu bây giờ bạn làm một <CTRL>R, VIM sẽ viết lại '3', <CTRL>Rbạn sẽ nhận được thêm 4. Điều này xảy ra NGAY nếu bạn làm :wsau mỗi lần <CTRL>R. Tuy nhiên, nếu mỗi lần bạn :wthực hiện một thao tác thông qua BufWritePre, <CTRL>Rsẽ không ghi 3lại. Và đây là những gì tôi muốn làm, đó là lý do tại sao tôi đã viết để 'đình chỉ gia đình', nhưng có lẽ những gì tôi đang hỏi là không thể, ngoài việc làm việc với đầy đủ undotree().


1
Câu hỏi này thuộc chủ đề cho trang web này, nhưng vì nó liên quan đến một tính năng tiềm năng khá bí truyền của VIM, bạn đã cân nhắc dùng thử vim.stackexchange.com chưa? Ý tôi là, tôi biết UNIX và tôi biết vi, nhưng với tôi vilệnh hoàn tác lại hoàn tác một lần, và sau đó khi bạn nhấn ulại, nó sẽ hoàn tác lại ("làm lại"). Đó là vi thật . Vì vậy, tôi và những người dùng khác của trang web này có thể không biết câu trả lời cho câu hỏi của bạn.
Celada

2
@Celada Tôi tin đó là vi.stackexchange.com hoặc Vi và Vim .
Satō Katsura

@SatoKatsura bạn hoàn toàn đúng!
Celada

1
@Celada: Tôi không biết vim.se, tôi đã thử nó. Dù sao, có vẻ như Sato biết cách giúp đỡ.
Luis A. Florit

Vấn đề bạn đưa ra "tất cả 20 lệnh lịch sử cuối cùng bị mất" đã được khắc phục với sự tồn tại của các nhánh hoàn tác, do đó, thật khó hiểu khi bạn muốn khắc phục vấn đề của mình bằng cách tránh việc tạo ra chúng. Bạn nói rằng bạn có thể nhận được kết quả mà bạn muốn sed, nhưng sed không thể hoàn tác, vậy làm thế nào để nó hoạt động? Nếu bạn có thể "tạm dừng lịch sử", bạn sẽ mong đợi hành vi nào của vim khi bạn hoàn tác sau đó? Hành vi duy nhất tôi có thể hình dung là nhóm các thay đổi đó (cùng với hoàn tác) trong một khối hoàn tác, do đó câu trả lời của tôi. Nhưng nếu đó không phải là nó, thì là gì?
JoL

Câu trả lời:


12

Bạn không cần phải tạm dừng lịch sử Vim. Dữ liệu thực tế tạo thành một cây và bạn có thể truy xuất nó với undotree()hàm. Tất nhiên, có một số plugin biến nó thành một thứ gì đó thân thiện hơn với người dùng, fi gundo , mundounotree . Nếu bạn cũng cho phép hoàn tác kiên trì (xem :h undo-persistence), bạn có thể dễ dàng điều hướng trong toàn bộ lịch sử thay đổi của tệp.


Thật thú vị, tôi không biết thứ hoàn tác thực sự là một cái cây. Trong trường hợp của tôi, tôi chỉ muốn quay lại một lần, tức là đến nhánh hoàn tác trước đó. Bạn có biết làm thế nào để làm điều đó? Có vẻ như undotree()sẽ giúp?
Luis A. Florit

Trên thực tế, trong trường hợp cụ thể này thúc đẩy câu hỏi của tôi, tôi muốn điều changeđó không xuất hiện ở tất cả, bất cứ nơi nào, cũng không history, trong undocây. Đó là lý do tại sao câu hỏi của tôi là "đình chỉ lịch sử".
Luis A. Florit

@ LuisA.Florit: Cách nhanh chóng và dễ dàng để thực hiện việc này là :earlierchấp nhận đơn vị thời gian và sẽ vượt qua các nhánh nếu cần thiết (ví dụ: :earlier 1hlàm cho bộ đệm trông giống như cách đây một giờ). Nếu bạn không thể sử dụng đơn vị thời gian (vì các thay đổi quá gần nhau?) Thì bạn sẽ phải sử dụng g-để đi bộ trên cây vài bước một lần.
Kevin

0

Nếu tôi hiểu bạn chính xác những gì bạn muốn là sau đó thực hiện hoàn tác thì nên hoàn tác điều đó changevà 20 lần hoàn tác.

Khi vim thực thi một chức năng hoặc lệnh, tất cả các hành động mà nó thực hiện được hoàn tác cùng nhau. Tôi không chắc chắn nếu những hành động đó có thể bao gồm hoàn tác. Có lẽ phần này của tài liệu có thể giúp:

3. Undo blocks                      *undo-blocks*

One undo command normally undoes a typed command, no matter how many changes
that command makes.  This sequence of undo-able changes forms an undo block.
Thus if the typed key(s) call a function, all the commands in the function are
undone together.

If you want to write a function or script that doesn't create a new undoable
change but joins in with the previous change use this command:

                        *:undoj* *:undojoin* *E790*
:undoj[oin]     Join further changes with the previous undo block.
            Warning: Use with care, it may prevent the user from
            properly undoing changes.  Don't use this after undo
            or redo.
            {not in Vi}

This is most useful when you need to prompt the user halfway through a change.
For example in a function that calls |getchar()|.  Do make sure that there was
a related change before this that you must join with.

This doesn't work by itself, because the next key press will start a new
change again.  But you can do something like this: >

    :undojoin | delete

After this an "u" command will undo the delete command and the previous
change.

To do the opposite, break a change into two undo blocks, in Insert mode use
CTRL-G u.  This is useful if you want an insert command to be undoable in
parts.  E.g., for each sentence.  |i_CTRL-G_u|
Setting the value of 'undolevels' also breaks undo.  Even when the new value
is equal to the old value.

Than ôi, tôi đã thử sử dụng :undo 2 | undojoin | normal ohi, nhưng tôi nhận được thông báo lỗi E790: undojoin is not allowed after undo.

Tuy nhiên, nếu các hành động được thực hiện trong một chức năng như thế này:

function F()
  undo 2
  normal ohi
endfunction

sau đó gọi nó với :call F()thực hiện undovà hành động khác trong một khối hoàn tác. Lưu ý rằng vì bạn đang sử dụng hoàn tác nên bạn đang tạo một nhánh hoàn tác mới. Sau khi xong, bạn có thể sử dụng lệnh chế độ bình thường g-, để hoàn tác F(); sử dụng usẽ giống như đã làm :undo 3lúc đầu.


Không chắc chắn nếu điều này hoạt động ... Điều tôi muốn là, sau khi bạn thực hiện một số undothứ, mọi thứ bạn làm trong chức năng của bạn F()sẽ không mở một nhánh hoàn tác mới. Trong trường hợp của tôi, F()được thực thi mỗi khi tôi viết tệp và nếu tôi làm undovà sau đó viết tệp, F()sẽ mở một nhánh hoàn tác mới. Tôi đã thử với undojoinlúc đầu F(), nhưng một chuỗi write-undo-write gây ra lỗi : undojoint not allowed after undo.
Luis A. Florit

Cập nhật câu hỏi của tôi cố gắng để rõ ràng hơn.
Luis A. Florit

@ LuisA.Florit Tôi đã viết trong câu trả lời :undojoinkhông hoạt động cho những gì bạn muốn, đề cập đến cùng một lỗi và tôi đã không đề xuất sử dụng :undojoinvào đầu F(). F()có nghĩa là làm những gì :undojoinkhông thể, đó là tham gia hoàn tác và các lệnh khác trong một khối hoàn tác.
JoL

@ LuisA.Florit Bạn nói rằng bạn muốn tránh tạo một nhánh hoàn tác, nhưng tôi không thể tìm thấy lý do tại sao bạn muốn điều đó. Tôi nghĩ rằng điểm của câu hỏi của bạn là có thể hoàn tác các lệnh và nhiều lần hoàn tác trong một lần. Nhìn lại nó, tôi tự hỏi liệu quan điểm của bạn là không làm mất đi những thay đổi mà bạn đã hoàn tác. Nếu đó là trường hợp sự tồn tại của cây hoàn tác chính xác là những gì bạn muốn. Bạn có thể điều hướng nó với g-g+.
JoL

Vâng, có vẻ như cây hoàn tác là những gì tôi cần.
Luis A. Florit
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.