branch: elpa/multiple-cursors
commit d7263f21f0817b878296f26e647dbcec27adb5a3
Author: Magnar Sveen <[email protected]>
Commit: Magnar Sveen <[email protected]>
A more rubust way of finding the command currently being invoked.
- which is necessary because cua-mode does some wacky stuff.
Fixes #8
---
features/multiple-cursors-core.feature | 10 ++++++
features/support/env.el | 1 +
multiple-cursors-core.el | 65 +++++++++++++++++++++++-----------
3 files changed, 56 insertions(+), 20 deletions(-)
diff --git a/features/multiple-cursors-core.feature
b/features/multiple-cursors-core.feature
index 64e3ae6..718e17f 100644
--- a/features/multiple-cursors-core.feature
+++ b/features/multiple-cursors-core.feature
@@ -109,6 +109,16 @@ Feature: Multiple cursors core
And I press "M-l"
Then I should see "This text_snippet contains the word text_snippet twice"
+ Scenario: cua-mode
+ Given I turn on cua-mode
+ And I insert "This text contains the word text twice"
+ And I go to the front of the word "text"
+ And I press "C-SPC"
+ And I press "M-f"
+ And I press "C->"
+ And I type "!"
+ Then I should see "This ! contains the word ! twice"
+
Scenario: Interprogram paste
Given I have cursors at "text" in "This text contains the word text twice"
When I copy "external" in another program
diff --git a/features/support/env.el b/features/support/env.el
index 652016a..a55d319 100644
--- a/features/support/env.el
+++ b/features/support/env.el
@@ -15,6 +15,7 @@
(defun mc/save-lists ()) ;; redefine to do nothing when running tests
(Before
+ (cua-mode 0)
(multiple-cursors-mode 0)
(rectangular-region-mode 0)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
diff --git a/multiple-cursors-core.el b/multiple-cursors-core.el
index 3adcaa6..12f3f48 100644
--- a/multiple-cursors-core.el
+++ b/multiple-cursors-core.el
@@ -249,6 +249,22 @@ cursor with updated info."
(1+ (count-if 'mc/fake-cursor-p
(overlays-in (point-min) (point-max)))))
+(defvar mc--this-command nil
+ "Used to store the original command being run.")
+(make-variable-buffer-local 'mc--this-command)
+
+(defun mc/make-a-note-of-the-command-being-run ()
+ "Used with pre-command-hook to store the original command being run.
+Since that cannot be reliably determined in the post-command-hook.
+
+Specifically, this-original-command isn't always right, because it could have
+been remapped. And certain modes (cua comes to mind) will change their
+remapping based on state. So a command that changes the state will afterwards
+not be recognized through the command-remapping lookup."
+ (unless mc--executing-command-for-fake-cursor
+ (setq mc--this-command (or (command-remapping this-original-command)
+ this-original-command))))
+
(defun mc/execute-this-command-for-all-cursors ()
"Used with post-command-hook to execute supported commands for all cursors.
@@ -260,26 +276,29 @@ Some commands are so unsupported that they are even
prevented for
the original cursor, to inform about the lack of support."
(if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode
(multiple-cursors-mode 0)
- (let ((original-command (or (command-remapping this-original-command)
- this-original-command)))
-
- ;; if it's a lambda, we can't know if it's supported or not
- ;; - so go ahead and assume it's ok, because we're just optimistic like
that
- (if (not (symbolp original-command))
- (mc/execute-command-for-all-fake-cursors original-command)
-
- ;; otherwise it's a symbol, and we can be more thorough
- (if (get original-command 'mc--unsupported)
- (message "%S is not supported with multiple cursors%s"
- original-command
- (get original-command 'mc--unsupported))
- (when (and original-command
- (not (memq original-command mc--default-cmds-to-run-once))
- (not (memq original-command mc/cmds-to-run-once))
- (or (memq original-command
mc--default-cmds-to-run-for-all)
- (memq original-command mc/cmds-to-run-for-all)
- (mc/prompt-for-inclusion-in-whitelist
original-command)))
- (mc/execute-command-for-all-fake-cursors original-command)))))))
+
+ (when this-original-command
+ (let ((original-command (or mc--this-command
+ (command-remapping this-original-command)
+ this-original-command)))
+
+ ;; if it's a lambda, we can't know if it's supported or not
+ ;; - so go ahead and assume it's ok, because we're just optimistic
like that
+ (if (not (symbolp original-command))
+ (mc/execute-command-for-all-fake-cursors original-command)
+
+ ;; otherwise it's a symbol, and we can be more thorough
+ (if (get original-command 'mc--unsupported)
+ (message "%S is not supported with multiple cursors%s"
+ original-command
+ (get original-command 'mc--unsupported))
+ (when (and original-command
+ (not (memq original-command
mc--default-cmds-to-run-once))
+ (not (memq original-command mc/cmds-to-run-once))
+ (or (memq original-command
mc--default-cmds-to-run-for-all)
+ (memq original-command mc/cmds-to-run-for-all)
+ (mc/prompt-for-inclusion-in-whitelist
original-command)))
+ (mc/execute-command-for-all-fake-cursors original-command))))))))
(defun mc/remove-fake-cursors ()
"Remove all fake cursors.
@@ -338,6 +357,7 @@ They are temporarily disabled when multiple-cursors are
active.")
(make-variable-buffer-local 'mc/temporarily-disabled-minor-modes)
(defun mc/temporarily-disable-minor-mode (mode)
+ "If MODE is available and turned on, remember that and turn it off."
(when (and (boundp mode) (eval mode))
(add-to-list 'mc/temporarily-disabled-minor-modes mode)
(funcall mode -1)))
@@ -358,9 +378,12 @@ They are temporarily disabled when multiple-cursors are
active.")
(if multiple-cursors-mode
(progn
(mc/temporarily-disable-unsupported-minor-modes)
+ (add-hook 'pre-command-hook 'mc/make-a-note-of-the-command-being-run
nil t)
(add-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors
t t)
(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)
+ (setq mc--this-command nil)
(mc--maybe-set-killed-rectangle)
(mc/remove-fake-cursors)
(mc/enable-temporarily-disabled-minor-modes)
@@ -536,6 +559,8 @@ for running commands with multiple cursors.")
end-of-line
set-mark-command
exchange-point-and-mark
+ cua-set-mark
+ cua-replace-region
move-end-of-line
beginning-of-line
move-beginning-of-line