branch: elpa/multiple-cursors
commit 19f842d60af81d44efb015026ebed486323b635f
Author: lexa <[email protected]>
Commit: lexa <[email protected]>
Undo after leaving mc mode will restore cursors as they was
---
features/multiple-cursors-core.feature | 8 +++++++
multiple-cursors-core.el | 40 ++++++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+)
diff --git a/features/multiple-cursors-core.feature
b/features/multiple-cursors-core.feature
index 0a6e8b9..3bd4103 100644
--- a/features/multiple-cursors-core.feature
+++ b/features/multiple-cursors-core.feature
@@ -65,6 +65,14 @@ Feature: Multiple cursors core
And I type "!"
Then I should see "This text! contains the word text! twice"
+ Scenario: Undo mode
+ Given I have cursors at "text" in "This text contains the word text twice"
+ When I press "C-g"
+ And I press "M-f"
+ And I press "C-_"
+ And I type "!"
+ Then I should see "This !text contains the word !text twice"
+
Scenario: Setting and popping mark
Given I have cursors at "text" in "This text contains the word text twice"
And I press "C-SPC"
diff --git a/multiple-cursors-core.el b/multiple-cursors-core.el
index d2b2c42..a0d10ef 100644
--- a/multiple-cursors-core.el
+++ b/multiple-cursors-core.el
@@ -52,6 +52,14 @@
(setq buffer-undo-list ;; otherwise add a function to activate this
cursor
(cons (cons 'apply (cons 'activate-cursor-for-undo (list id)))
buffer-undo-list))))))
+
+(defun mc/get-all-fake-cursors-state ()
+ "Return list of all fake cursor states
+like this: ((CURSOR-POS MARK-POSITION (list of cursor specific variables))
...)"
+ (mapcar (lambda (cursor)
+ (mc/get-state-from-overlay cursor))
+ (mc/all-fake-cursors)))
+
(defun mc/all-fake-cursors (&optional start end)
(remove-if-not 'mc/fake-cursor-p
(overlays-in (or start (point-min))
@@ -152,6 +160,23 @@ highlights the entire width of the window."
(dolist (var mc/cursor-specific-vars)
(when (boundp var) (set var (overlay-get o var)))))
+(defun mc/get-state-from-overlay (o)
+ "Return list describing state of cursor overlay"
+ (list
+ (marker-position (overlay-get o 'point))
+ (marker-position (overlay-get o 'mark))
+ (mapcar (lambda (var)
+ (when (boundp var) (cons var (overlay-get o var))))
+ mc/cursor-specific-vars)))
+
+(defun mc/create-overlay-from-state (point mark cursor-vars)
+ "Creates cursor overlay according to cursor-info"
+ (goto-char point)
+ (push-mark mark t)
+ (loop for (var . value) in cursor-vars
+ do (setq var value))
+ (mc/create-fake-cursor-at-point))
+
(defun mc/remove-fake-cursor (o)
"Delete overlay with state, including dependent overlays and markers."
(set-marker (overlay-get o 'point) nil)
@@ -459,6 +484,20 @@ They are temporarily disabled when multiple-cursors are
active.")
:group 'multiple-cursors)
(put 'mc/mode-line 'risky-local-variable t)
+(defun mc/restore-mode (real-cursor real-mark fake-cursors)
+ "Restore state of mc mode after undo"
+ (save-excursion
+ ;; remove all existing fake cursors
+ (when multiple-cursors-mode
+ (mc/remove-fake-cursors))
+ ;; and create set a new one
+ (mapc #'(lambda (cursor)
+ (apply 'mc/create-overlay-from-state cursor))
+ fake-cursors))
+ (goto-char real-cursor)
+ (push-mark real-mark t)
+ (multiple-cursors-mode t))
+
;;;###autoload
(define-minor-mode multiple-cursors-mode
"Mode while multiple cursors are active."
@@ -471,6 +510,7 @@ They are temporarily disabled when multiple-cursors are
active.")
(run-hooks 'multiple-cursors-mode-enabled-hook))
(remove-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t)
(remove-hook 'pre-command-hook 'mc/make-a-note-of-the-command-being-run t)
+ (push `(apply mc/restore-mode . ,(list (point) (mark)
(mc/get-all-fake-cursors-state))) buffer-undo-list)
(setq mc--this-command nil)
(mc--maybe-set-killed-rectangle)
(mc/remove-fake-cursors)