branch: externals/cursor-undo
commit e82084c3d491ff7199e14cc8da69c250b9bda492
Author: Luke Lee <luke@gauss>
Commit: Luke Lee <luke@gauss>
Fix read-only buffer undo operations on end of undo list
(cundo-is-cursor-undo-entry, cundo-is-undo-boundary): New functions
for boundary conditions.
(cundo-track-screen-start, undo): fix for cleaner code and boundary.
---
cursor-undo.el | 48 +++++++++++++++++++++++++++++++++++-------------
1 file changed, 35 insertions(+), 13 deletions(-)
diff --git a/cursor-undo.el b/cursor-undo.el
index cd10f20c46..12c5443cc7 100644
--- a/cursor-undo.el
+++ b/cursor-undo.el
@@ -5,7 +5,7 @@
;; Author: Luke Lee <[email protected]>
;; Maintainer: Luke Lee <[email protected]>
;; Keywords: undo, cursor
-;; Version: 1.1.4
+;; Version: 1.1.5
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
@@ -138,7 +138,7 @@
(defun cundo-track-screen-start (prv-screen-start)
(let ((entry (list 'apply 'cundo-restore-win prv-screen-start)))
(if (eq buffer-undo-list 't)
- (setq buffer-undo-list entry)
+ (setq buffer-undo-list (list entry))
(push entry buffer-undo-list))))
(defun cundo-track-prev-point (prev-point)
@@ -288,23 +288,45 @@ relative screen position (screen-pos=NIL) nor `point'
position (no-move=t)."))
;; then safely set `buffer-read-only' back to NIL and continue your
;; editing.
;;
+
+(defun cundo-is-cursor-undo-entry (undolist)
+ (if (listp undolist)
+ (let ((uitem (if (null (car undolist))
+ (cadr undolist)
+ (car undolist))))
+ (or (numberp uitem) ;; point marker
+ ;; Cursor-undo created undo entry
+ (and (eq #'apply (nth 0 uitem))
+ (eq #'cundo-restore-win (nth 1 uitem)))))
+ (eq undolist 't)))
+
+(defun cundo-is-undo-boundary ()
+ (let ((undolist (if (eq last-command 'undo)
+ pending-undo-list
+ buffer-undo-list)))
+ (if (listp undolist)
+ (equal '(apply cdr nil) ;; undo boundary
+ (if (null (car undolist))
+ (cadr undolist)
+ (car undolist)))
+ (eq undolist 't))))
+
(define-advice undo (:around (orig-func &rest args)
undo-cursor-in-read-only-buffer)
(interactive "P") ;; Change the behavior from "*P" to "P"
(if (if (eq last-command 'undo)
;; last-command is undo, check pending undo list if the first command
- ;; is cursor movement or not
- (and (listp pending-undo-list)
- (numberp (car pending-undo-list)))
+ ;; is a cursor movement or not
+ (cundo-is-cursor-undo-entry pending-undo-list)
;; not a continuous undo, check first command is cursor movement or not
- (and (listp buffer-undo-list)
- (null (car buffer-undo-list))
- (numberp (cadr buffer-undo-list))))
- (apply orig-func args)
- (if buffer-read-only
- (if (listp pending-undo-list)
- (user-error "Buffer is read-only: cannot undo an editing command!")
- (apply orig-func args))
+ (cundo-is-cursor-undo-entry buffer-undo-list))
+ ;; if it's a cursor undo, go `undo' regardless of read-only settings
+ (let ((buffer-read-only nil)) ;; temp dynamically binding
+ (apply orig-func args))
+ ;; Not cursor undo
+ (if (and buffer-read-only
+ (not (cundo-is-undo-boundary)))
+ (user-error "Buffer is read-only: cannot undo an editing command")
(apply orig-func args))))
;;;