Cách tạo tuyến tính hoàn tác cây - hoàn tác cây / hoàn tác / làm lại


10

Khi chạy lệnh undo-tree-undo/redoliên tiếp, mọi thứ sẽ được hoàn tác / làm lại dựa trên nhánh hoạt động hiện tại. Mặc dù người dùng nhận được thông báo điểm nhánh dọc đường, các nhánh trước đó bị bỏ qua trừ khi người dùng chọn thủ công một nhánh khác.

Tôi hiểu rằng tôi có thể mở trình hiển thị và chọn một nhánh khác, tuy nhiên, sẽ rất hữu ích khi chỉ cần giữ phím hoàn tác / làm lại và xem mọi thứ xảy ra theo thứ tự ngược lại chính xác. Lý tưởng nhất, điều này sẽ hoạt động bất kể visualizerbộ đệm có mở hay không - tức là, lập trình tính toán thứ tự từ đầu đến cuối và từ đầu đến cuối.

Q : Đây thực chất là một yêu cầu tính năng để mở rộng undo-treeđể cho phép hoàn tác / làm lại liên tiếp tuyến tính, bất kể bộ đệm của trình hiển thị có mở hay không. [Các chức năng mới và phím tắt thay thế cho tính năng mới này chắc chắn có thể chấp nhận được.]


undo-treetrông giống như nó là một phần của khái niệm mà bạn có thể chuyển đổi tự do giữa buffer-undo-treebuffer-undo-listbằng cách bật tắt undo-tree-mode. Theo tôi hiểu câu hỏi của bạn, việc xử lý ban đầu buffer-undo-listlàm những gì bạn muốn. Vì vậy, nó gợi ý để tạm thời tắt undo-tree-modecho mục đích của bạn. Đáng tiếc là việc chuyển đổi giữa buffer-undo-treebuffer-undo-listdường như là lỗi (ít nhất là đối với tôi). Vì vậy, có lẽ, cách để đi sẽ chỉ là một báo cáo lỗi cho người bảo trì undo-tree. Nhưng, có lẽ suy đoán của tôi về khái niệm ban đầu là sai.
Tobias

Tôi nghĩ rằng giải pháp tốt nhất cho vấn đề của bạn sẽ là sửa chữa undo-tree-modesao cho việc chuyển đổi giữa buffer-undo-treebuffer-undo-listhoạt động hoàn hảo. Bạn đã xem xét để đưa ra một báo cáo lỗi tại `toby-undo-tree @ dr-qubit.org` chưa?
Tobias

@Tobias - Tôi muốn xem và sử dụng trình hiển thị undo-treetrong khi sử dụng lineartính năng mới ; và, tôi muốn lineartính năng mới hoạt động mà không cần phải nhìn thấy bộ đệm visualizer. Nói chung, tôi triển khai các cải tiến / sửa đổi của riêng mình đối với Emacs, cả thư viện bên thứ ba tích hợp và tùy chọn của nó. Khi tôi gặp khó khăn hoặc tôi thấy một cái gì đó siêu phức tạp như undotính năng này, tôi yêu cầu giúp đỡ. Một yêu cầu tính năng cho người bảo trì không thể làm tổn thương, nhưng tôi muốn xử lý nó ở đây.
luật

@Tobias - Khi nhìn vào undo-tree.elmã ngày hôm nay, tôi thấy rằng có một tính năng dấu thời gian nút. Tôi không chắc mỗi nút có dấu thời gian hợp lệ hay không và liệu các nút đó có tồn tại đến phiên Emacs tiếp theo không (khi khôi phục lịch sử), nhưng âm thanh đó có thể là lối tắt để giải quyết yêu cầu tính năng mới này - tức là sắp xếp và chọn trước đó hoặc tiếp theo trong thời gian. Tôi chưa thấy bố cục của khu đất trông như thế nào tại một điểm nhánh, nhưng ... đó là những suy nghĩ sơ bộ của tôi. . . .
luật

Tôi nghĩ rằng chìa khóa để đi bộ tuyến tính qua cây hoàn tác là undo-list-rebuild-from-tree. Người ta nên - lettìm biến buffer-undo-listvà để undo-list-rebuild-from-treethực hiện công việc của nó. Sau đó, sao chép giá trị đó vào một biến cục bộ khác, giả sử my-undo-listvà để lại letdạng -form cho ràng buộc buffer-undo-list. Biến my-undo-listchỉ định đường dẫn tuyến tính thông qua undo-tree. Có một cái nhìn vào undo-list-rebuild-from-treebạn thấy rằng chức năng này cũng sử dụng dấu thời gian. Tôi trước đó đã xem xét sử dụng tem thời gian. Nhưng, tôi có ấn tượng rằng những điều đó thay đổi quá thường xuyên.
Tobias

Câu trả lời:


7

Sau đây là một triển khai nguyên mẫu của một xấp xỉ những gì bạn muốn. Nó khai thác thực tế là các nhánh mới trong cây hoàn tác được thêm vào ở phía bên trái của nút hiện tại.

Chuỗi khóa C-M-_được liên kết để undo-tree-walkđi qua phần trên bên phải của cây hoàn tác bắt đầu từ nút hiện tại.

Hành vi khác với những gì bạn muốn nếu nhánh hoạt động của một số cây con ở phía bên phải của nút hiện tại không phải là nhánh bên trái nhất trong cây con đó.

Bạn có thể có được trạng thái như vậy bằng các chuỗi không hoàn tác / làm lại.

Chỉ cần thử nó cho chính mình để xem liệu điều đó là đủ cho ứng dụng của bạn.

(defvar-local undo-tree-walk
  "Possible values:
nil: not in undo/redo-chain
undo: traversing undo tree upwards
redo: traversing undo tree downwards
")

(setq undo-tree-walk nil)

(defun undo-tree-walk ()
  "Walk the right-upper part of the undo-tree starting at the current node."
  (interactive)
  (when (eq buffer-undo-list t)
    (user-error "No undo information."))
  (unless undo-tree-mode
    (user-error "`undo-tree-walk' should only be used with `undo-tree-mode'."))
  (undo-list-transfer-to-tree)
  (set-transient-map undo-tree-walk-map t #'undo-tree-walk-off)
  (let ((num-branches (undo-tree-num-branches)))
    (cond
     ((= num-branches 0) ; arrived at leaf
      (setq undo-tree-walk 'undo))
     ((> num-branches 1) ; 
      (let ((branch (undo-tree-node-branch (undo-tree-current buffer-undo-tree))))
    (setf (undo-tree-node-branch (undo-tree-current buffer-undo-tree))
          (if (>= (1+ branch) (undo-tree-num-branches))
          (progn
            (setq undo-tree-walk 'undo)
            (1- (undo-tree-num-branches)))
        (setq undo-tree-walk 'redo)
        (1+ branch))))
      ;; no state change for (= num-branches 1)
      )
     ))
  (case undo-tree-walk
   (undo
    (undo-tree-undo-1))
   (redo
    (undo-tree-redo-1))
   (t
    (setq undo-tree-walk 'undo)
    (undo-tree-undo-1)))
  (let ((curbuf (current-buffer)))
    (undo-tree-visualize)
    (switch-to-buffer-other-window curbuf)))

(defun undo-tree-walk-off ()
  "Switch `undo-tree-walk' off."
  (setq undo-tree-walk nil))

(defvar undo-tree-walk-map
  (make-sparse-keymap)
  "Keymap active while `undo-tree-walk'.")

(define-key undo-tree-walk-map (kbd "C-M-_") #'undo-tree-walk)

(global-set-key (kbd "C-M-_") #'undo-tree-walk)

Lưu ý, tôi đã thêm vào undo-tree-visualizecuối undo-tree-walkđể hiển thị các hậu quả của việc đi trên cây hoàn tác với undo-tree-walk. Hãy thoải mái sửa đổi mã theo ý thích của bạn.

Cũng lưu ý rằng tôi phải chọn một giải pháp gần đúng đơn giản nhất cho vấn đề của bạn vì giới hạn thời gian.


Tôi đã thêm phần sau vào phần đầu undo-tree-walkđể vượt qua một số lỗi ban đầu, có lẽ vì tôi không có chế độ này hoạt động trên toàn cầu. (when (eq buffer-undo-list t) (user-error "No undo information.")) (undo-list-transfer-to-tree) Điều đó đã làm im lặng những lỗi ban đầu của tôi trong một bộ đệm mới trong khi thử câu trả lời này. Quan sát tiếp theo của tôi là undo-tree-walkđến điểm nhánh và sau đó chuyển sang nhánh bên phải, nhưng chỉ đi xuống nhánh một notch / nốt trước khi đi ngược nhánh lên thân cây. Thiết lập ưa thích của tôi tạo ra một notch / nốt cho mỗi lần nhấn phím.
luật

Hoàn toàn không có vội vàng về một giải pháp. Xin vui lòng dành tất cả thời gian mà bạn cần - ngoài thời gian tiền thưởng là hoàn toàn chấp nhận được. Khi được triển khai, tôi chắc chắn rằng tôi sẽ sử dụng tính năng này hàng ngày trong tương lai gần và đánh giá bởi các upvote cho đến nay, những người khác cũng muốn sử dụng tính năng này.
luật

@lawlist Đáng tiếc, thời gian của tôi bị hạn chế. Nếu có thể tôi sẽ viết câu trả lời này chứ không phải là một nhận xét hơn là một câu trả lời. Hy vọng, một người khác nghĩ ra thứ gì đó tốt hơn trước khi thời kỳ tiền thưởng kết thúc.
Tobias

@lawlist Tôi đã thêm undo-list-transfer-to-treenhư bạn đề xuất. Trước đó tôi kiểm tra xem undo-tree-modecó hoạt động hay không undo-list-transfer-to-treecó thể gây tử vong.
Tobias

Được trao tặng tiền thưởng gần đây cho câu trả lời trong chủ đề liên quan: emacs.stackexchange.com/a/32415/2287emacs.stackexchange.com/a/32416/2287 vì chúng là thành phần chính để thực hiện tính năng mới. Tóm lại, mỗi nút sẽ có một danh sách các dấu thời gian - mỗi nút sẽ trở thành hiện tại sau khi hoàn tác / làm lại thành công và cả khi nhập lần đầu. Tôi đã nảy ra một ý tưởng để hình dung bằng cách hiển thị các dấu thời gian theo chiều dọc bên dưới mỗi nút và kéo dài các nhánh tương ứng - sẽ mất một thời gian để lập trình ra.
luật

3

Đặc biệt cảm ơn @Tobias vì đã viết lên một chức năng để xác định dấu thời gian tiếp theo / trước đó trong lịch sử hoàn tác / làm lại: /emacs//a/32415/2287 ; và, cũng để viết lên một loạt các chức năng để sao chép cây hoàn tác: /emacs//a/32230/2287 .

Như một số độc giả có thể đã biết, dĩa chỉ được MELPA chấp nhận trong những trường hợp khắc nghiệt. Tạo một tiện ích bổ sung có thể có thể thực hiện được, nhưng dường như không thực tế với số lượng thay đổi đã được thực hiện bởi @lawlist - bao gồm, nhưng không giới hạn, thêm các yếu tố vào các vectơ cấu trúc dữ liệu cơ bản và thay đổi tên của một số các hàm / biến không tuân thủ undo-tree-...quy ước đặt tên tiền tố, v.v ... @lawlist đã liên hệ với tác giả ban đầu (Dr. Cubitt) để cung cấp tính năng mới này, cũng như các sửa lỗi và cải tiến khác nhau.

Nếu bất cứ ai quan tâm, xin vui lòng cung cấp cho tính năng mới này một cơn lốc. Bài bình luận chứa một mẫu đệ trình báo cáo lỗi mẫu bắt đầu từ emacs -qtrong trường hợp bất cứ ai có vấn đề.

Mã nguồn:   https://github.com/lawlist/undo_tree

Bình luận:

;;; This unofficial modification by @lawlist to the `undo-tree.el` library authored
;;; by Toby Cubitt adds semi-linear undo/redo support and a corresponding visualizer
;;; view accessible with `C-u C-x u` or by using the 3-way toggle with the letter `t`
;;; in the visualization buffer.  This entire library is meant to be a replacement
;;; of the stock version of `undo-tree.el`, which would need to be completely removed
;;; from the `load-path'.  In the visualization buffer, the letters `u` / `r`
;;; or `z` / `Z` are used for semi-linear undo/redo.  In the working buffer,
;;; `super-u` / `super-r` or `super-z`/`super-Z` are used for semi-linear undo/redo.
;;; Semi-linear undo/redo also work in the classic views of the visualization buffer.
;;; All previous keyboard shortcuts remain unchanged.  The mouse can be used to
;;; select semi-linear nodes or branch-point timestamps in the visualization buffer.
;;;
;;; The term `semi-linear` was chosen because the time-line is generally structured
;;; as follows:  When undoing, the movement is in an upward direction from the
;;; leaf to the branch-point and then the previous branch begins undoing from the
;;; leaf.  When redoing, the movement is in a downward direction from the branch-
;;; point to the leaf and then the next branch begins redoing from the branch-point.
;;; It is not a situation where we walk-up and back-down the same branch, or walk-
;;; down and back-up the same branch again.  If that missing feature is useful,
;;; then perhaps it could be implemented someday....
;;;
;;; In a nutshell, the classic version of undo-tree undo/redo limits a user to
;;; the active branch (skipping over inactive branches), unless the user calls
;;; `undo-tree-switch-branch' or `undo-tree-visualize-switch-branch-right' or
;;; `undo-tree-visualize-switch-branch-left' to select an alternative branch.  This
;;; generally means a user must pop-open the visualizer buffer to see what is going
;;; on to make a proper decision.  The new semi-linear feature is essentially
;;; "mindless" where the user can just hold down the forward/reverse button and
;;; go through every node of the tree in chronological order -- i.e., all branches
;;; and nodes are visited in the process (nothing is skipped over).
;;;
;;; The labels in the visualization buffer remain the same:  `o`, `x`, `s`, register.
;;; The branches are labeled consecutively as they are drawn with lowercase letters.
;;; The branch-points are labeled consecutively as they are drawn with uppercase
;;; letters.  The branches coming off of each branch-point are labeled with the nth
;;; numeric position of the branch -- e.g., far left is always nth 0.  The nodes of
;;; each branch are numbered consecutively commencing just after the branch-point.
;;;
;;; The features that are available in `undo-tree.el` version 0.6.6 remain the same;
;;; however, some of the functions have been consolidated and the names have changed.
;;;
;;; `undo-tree-history-save' and `undo-tree-history-restore' support input/output
;;; to/from a string or a file.  The history string/file contains three components:
;;; `buffer-file-name' (if it exists; else `nil`); SHA1 string; the `undo-tree-list'.
;;; Histories created with the unmodified stock version of `undo-tree.el` contained 2
;;; components and those previous versions are no longer supported.  Saving/exporting
;;; excludes all text-properties, yasnippet entries, and multiple-cursors entries.
;;; `read' chokes when encountering #<marker in no buffer> or #<overlay in no buffer>,
;;; that can make their way into the `undo-tree-list' when killing the visualizer
;;; buffer by brute force or when using the yasnippet library.  Those two known
;;; situations have been dealt with programmatically.  However, there are surely
;;; other libraries that use markers and/or overlays that could make their way into
;;; the tree and new ways of dealing with those entries will be required.  If you
;;; encounter an error message when performing `undo-tree-history-save', please
;;; inspect the `*Messages*` buffer for clues such as the above examples.  Inasmuch
;;; as there is now a sanity check at the tail end of `undo-tree-history-save', any
;;; problems should materialize before a user actually tries to restore the history.
;;;
;;; The persistent undo storage has been expanded by adding certain features borrowed
;;; from the built-in `image-dired.el' library:
;;;
;;; `undo-tree-history-autosave':  When non-nil, `undo-tree-mode' will save undo
;;;                                history to a file when a buffer is saved; and,
;;;                                the save/restore functions attached to the
;;;                                following hooks will become active:
;;;                                -  `write-file-functions'
;;;                                -  `find-file-hook'
;;;                                To exclude certain files, users may wish to let-
;;;                                bind this variable to `nil` if it has a global
;;;                                non-nil value.  See also the next variable below.
;;;
;;; `undo-tree-history-file-exclusions':  A list of absolute file names that will be
;;;                                       excluded from the auto save/restore process.
;;;
;;; `undo-tree-history-alist':  Used when `undo-tree-history-storage' is 'classic.
;;;                             See the doc-string for customization tips/tricks.
;;;
;;; `undo-tree-history-directory':  Directory where history files are stored when
;;;                                `undo-tree-history-storage' is 'central.
;;;
;;; `undo-tree-history-storage':  How to store undo-tree history files.
;;;                               'classic:  See `undo-tree-history-alist'.
;;;                               'home (md5):  A folder in the HOME directory.
;;;                               'central (md5):  See `undo-tree-history-directory'.
;;;                               'local:  Create sub-directory in working directory.
;;;
;;; For those users who wish to use Emacs to view the saved/exported history, be
;;; aware that the undo history is one long string, and Emacs has trouble viewing a
;;; buffer with very long lines.  `(setq-default bidi-display-reordering nil)` will
;;; help permit Emacs to view buffers with very long lines without bogging down.
;;;
;;; The primary interactive functions for undo/redo in the working buffer are:
;;;
;;;   M-x undo-tree-classic-undo
;;;   M-x undo-tree-classic-redo
;;;   M-x undo-tree-linear-undo
;;;   M-x undo-tree-linear-redo
;;;
;;; The primary interactive functions for undo/redo in the visualization buffer are:
;;;
;;;   M-x undo-tree-visualize-classic-undo
;;;   M-x undo-tree-visualize-classic-redo
;;;   M-x undo-tree-visualize-linear-undo
;;;   M-x undo-tree-visualize-linear-redo
;;;
;;; If the built-in undo amalgamation business is not to your liking, it can be
;;; disabled to permit undo boundaries after every command:
;;;
;;;   ;;; /programming//a/41560712/2112489
;;;   (advice-add 'undo-auto--last-boundary-amalgamating-number :override #'ignore)
;;;
;;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27214
;;; /emacs//q/33248/2287
;;; GARBAGE COLLECTION:  @lawlist has encountered a few situations where garbage
;;; collection truncates the `undo-tree-canary' in the `buffer-undo-list', which
;;; causes `undo-tree-transfer-list' to replace the existing `undo-tree-list'
;;; with the new tree fragment obtained from the `buffer-undo-list'.  In this
;;; circumstance, the user loses the entire undo-tree saved history!  The internal
;;; function responsible is `truncate_undo_list' in `undo.c`.  @lawlist has added a
;;; programmatic warning when loss of the existing `undo-tree-list' is about to
;;; occur; however, that does not fix the problem.  The relevant section from
;;; `truncate_undo_list' in `undo.c` is as follows:
;;;          /* When we get to a boundary, decide whether to truncate
;;;      either before or after it.  The lower threshold, undo_limit,
;;;      tells us to truncate after it.  If its size pushes past
;;;      the higher threshold undo_strong_limit, we truncate before it.  */
;;;          if (NILP (elt))
;;;     {
;;;       if (size_so_far > undo_strong_limit)
;;;         break;
;;;       last_boundary = prev;
;;;       if (size_so_far > undo_limit)
;;;         break;
;;;     }
;;; @lawlist opines that setting the `undo-limit' to the same value as
;;; `undo-strong-limit' will cause `truncate_undo_list' to preserve the
;;; `undo-tree-canary' in the `buffer-undo-list' by truncating before the boundary.
;;; This workaround is not ideal because a more recent undo would be truncated in
;;; lieu of an older undo.  One idea would be to convince the Emacs team to modify
;;; `truncate_undo_list' to preserve certain user-defined elements; e.g., a symbol
;;; of `undo-tree-canary'.
;;;
;;; The built-in function named `primitive-undo' defined in `simple.el` was used
;;; in the original version of `undo-tree.el`.  @lawlist created a modified
;;; function named `undo-tree--primitive-undo' that serves the same purpose, but
;;; permits setting a window-point in the working buffer while a user is in a
;;; different window such as the visualization buffer.  The revised version also
;;; merely reports a problem with a message instead of throwing an error when it
;;; encounters an `undo-tree-canary' in the wrong location.  This bug was noticed
;;; by @lawlist when performing undo/redo in region, and a Google search revealed
;;; that others too have experienced the same problem.  The bug is fairly easy to
;;; reproduce, but @lawlist has not yet invested the time to look for the cause
;;; and try to come up with a solution.  For anyone who wishes to work on fixing
;;; this and view other mentions of the same problem on the internet, Google:
;;;   "Unrecognized entry in undo list undo-tree-canary"
;;;
;;; The semi-linear visualization buffer view looks like this:
;;;
;;;        o-00001-a-0
;;;        20.34.55.46
;;;             |
;;;        o-br/pt-A-0
;;;        20.47.57.25
;;;        20.34.55.47
;;;         ____|_______________________________
;;;        /                                    \
;;;  o-00001-b-0                            o-00001-c-1
;;;  20.47.57.26                            20.34.55.48
;;;       |                                      |
;;;  o-00002-b-0                            o-00002-c-1
;;;  20.47.57.27                            20.34.55.49
;;;       |                                      |
;;;  o-00003-b-0                            o-00003-c-1
;;;  20.47.57.28                            20.34.55.50
;;;                                              |
;;;                                         o-00004-c-1
;;;                                         20.34.55.51
;;;                                              |
;;;                                         o-br/pt-B-1
;;;                                         21.25.32.05
;;;                                         20.35.06.89
;;;                                         20.35.02.23
;;;                                         20.34.58.43
;;;                                         20.34.55.57
;;;         _____________________________________|________________________
;;;        /            /                        |                        \
;;;  o-00001-d-0  o-00001-e-1               o-br/pt-C-2               o-00001-f-3
;;;  21.25.32.06  20.35.06.90               23.03.45.34               20.34.58.44
;;;                    |                    00.27.40.07                    |
;;;               o-00002-e-1               20.35.02.24               o-00002-f-3
;;;               20.35.06.91         ___________|___________         20.34.58.45
;;;                    |             /           |           \             |
;;;               o-00003-e-1  o-00001-g-0  o-00001-h-1  o-00001-i-2  o-00003-f-3
;;;               20.35.06.92  23.03.45.35  00.27.40.08  20.35.02.25  20.34.58.46
;;;                    |            |            |            |            |
;;;               o-00004-e-1  x-00002-g-0  o-00002-h-1  o-00002-i-2  o-00004-f-3
;;;               20.35.06.93  23:03:45:36  00.27.44.51  20.35.02.26  20.34.58.47
;;;                    |                                      |            |
;;;               o-00005-e-1                            o-00003-i-2  o-00005-f-3
;;;               20.35.06.94                            20.35.02.27  20.34.58.48
;;;                    |                                      |            |
;;;               o-00006-e-1                            o-00004-i-2  o-00006-f-3
;;;               20.35.06.95                            20.35.02.28  20.34.58.49
;;;                    |                                      |            |
;;;               o-00007-e-1                            o-00005-i-2  o-00007-f-3
;;;               20.35.06.96                            20.35.02.29  20.34.58.50
;;;                    |                                      |            |
;;;               o-00008-e-1                            o-00006-i-2  o-00008-f-3
;;;               20.35.06.97                            20.35.02.30  20.34.58.51
;;;
;;; To check for updates, please visit the source-code of the link listed at the
;;; top and also review the "Change Log" at the bottom.
;;;
;;; Bug reports and feature requests may be submitted via email to the address at
;;; the top.  Essentially, if it breaks in half, I can guarantee that you will
;;; have 2 pieces that may not necessarily be the same size.  :)  That being said,
;;; I will certainly make efforts to fix any problem that may arise relating to
;;; the semi-linear undo/redo feature.  A step 1-2-3 recipe starting from emacs -q
;;; would be very helpful so that @lawlist can observe the same behavior described
;;; in the bug report.  Here is an example to get you started:
;;;
;;; 1.  In an internet browser, visit: https://www.lawlist.com/lisp/undo-tree.el
;;;
;;;     Select/highlight all and copy everything to the clipboard.
;;;
;;; 2.  Launch Emacs without any user settings whatsoever:  emacs -q
;;;
;;;     If possible, please use the latest stable public release of Emacs.
;;;     @lawlist is using the GUI version of Emacs 25.2.1 on OSX.
;;;
;;; 3.  Switch to the `*scratch*` buffer.
;;;
;;; 4.  Paste the entire contents of the clpipboard into the `*scratch*` buffer.
;;;
;;; 5.  M-x eval-buffer RET
;;;
;;; 6.  M-x eval-expression RET (setq undo-tree-history-autosave t) RET
;;;
;;; 7.  M-x undo-tree-mode RET
;;;
;;;     The mode-line indicates `UT`, meaning that `undo-tree-mode' is active.
;;;
;;; 8.  M-x save-buffer RET
;;;
;;;     @lawlist chose to save the file to his desktop with the name `foo`, and
;;;     also chose to overwrite the file if it already existed; i.e., `y`.
;;;
;;;     Look at the lower left-hand side of the mode-line and notice that it
;;;     indicates an unmodified state; i.e., U:--- foo ....
;;;
;;; 9.  M-x undo-tree-classic-undo RET
;;;
;;;     Look at the lower left-hand side of the mode-line and notice that it
;;;     indicates we have returned to a modified state; i.e., U:**- foo ....
;;;
;;; 10. M-x undo-tree-classic-undo RET
;;;
;;;     The `undo-tree' library that we had previously pasted to the `*scratch*`
;;;     buffer should now be completely undone; i.e., removed.
;;;
;;; 11. M-x undo-tree-classic-undo RET
;;;
;;;     The buffer should be completely empty at this point; i.e., the initial
;;;     `*scratch*` message has been removed.
;;;
;;; 12. M-x undo-tree-classic-undo RET
;;;
;;;     The following `user-error' appears:
;;;
;;;       "user-error:  undo-tree--undo-or-redo:  No further undo information."
;;;
;;;     This is exactly the behavior that @lawlist expected would happen, so
;;;     everything up to this point appears to be working correctly.
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.