A more rubust way of finding the command currently being invoked.

- which is necessary because cua-mode does some wacky stuff.

Fixes #8
This commit is contained in:
Magnar Sveen 2012-09-27 00:29:25 +02:00
parent 80bc6f6d56
commit d7263f21f0
3 changed files with 54 additions and 18 deletions

View File

@ -109,6 +109,16 @@ Feature: Multiple cursors core
And I press "M-l" And I press "M-l"
Then I should see "This text_snippet contains the word text_snippet twice" 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 Scenario: Interprogram paste
Given I have cursors at "text" in "This text contains the word text twice" Given I have cursors at "text" in "This text contains the word text twice"
When I copy "external" in another program When I copy "external" in another program

View File

@ -15,6 +15,7 @@
(defun mc/save-lists ()) ;; redefine to do nothing when running tests (defun mc/save-lists ()) ;; redefine to do nothing when running tests
(Before (Before
(cua-mode 0)
(multiple-cursors-mode 0) (multiple-cursors-mode 0)
(rectangular-region-mode 0) (rectangular-region-mode 0)
(global-set-key (kbd "C->") 'mc/mark-next-like-this) (global-set-key (kbd "C->") 'mc/mark-next-like-this)

View File

@ -249,6 +249,22 @@ cursor with updated info."
(1+ (count-if 'mc/fake-cursor-p (1+ (count-if 'mc/fake-cursor-p
(overlays-in (point-min) (point-max))))) (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 () (defun mc/execute-this-command-for-all-cursors ()
"Used with post-command-hook to execute supported commands 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." the original cursor, to inform about the lack of support."
(if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode (if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode
(multiple-cursors-mode 0) (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 (when this-original-command
;; - so go ahead and assume it's ok, because we're just optimistic like that (let ((original-command (or mc--this-command
(if (not (symbolp original-command)) (command-remapping this-original-command)
(mc/execute-command-for-all-fake-cursors original-command) this-original-command)))
;; otherwise it's a symbol, and we can be more thorough ;; if it's a lambda, we can't know if it's supported or not
(if (get original-command 'mc--unsupported) ;; - so go ahead and assume it's ok, because we're just optimistic like that
(message "%S is not supported with multiple cursors%s" (if (not (symbolp original-command))
original-command (mc/execute-command-for-all-fake-cursors original-command)
(get original-command 'mc--unsupported))
(when (and original-command ;; otherwise it's a symbol, and we can be more thorough
(not (memq original-command mc--default-cmds-to-run-once)) (if (get original-command 'mc--unsupported)
(not (memq original-command mc/cmds-to-run-once)) (message "%S is not supported with multiple cursors%s"
(or (memq original-command mc--default-cmds-to-run-for-all) original-command
(memq original-command mc/cmds-to-run-for-all) (get original-command 'mc--unsupported))
(mc/prompt-for-inclusion-in-whitelist original-command))) (when (and original-command
(mc/execute-command-for-all-fake-cursors 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 () (defun mc/remove-fake-cursors ()
"Remove all 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) (make-variable-buffer-local 'mc/temporarily-disabled-minor-modes)
(defun mc/temporarily-disable-minor-mode (mode) (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)) (when (and (boundp mode) (eval mode))
(add-to-list 'mc/temporarily-disabled-minor-modes mode) (add-to-list 'mc/temporarily-disabled-minor-modes mode)
(funcall mode -1))) (funcall mode -1)))
@ -358,9 +378,12 @@ They are temporarily disabled when multiple-cursors are active.")
(if multiple-cursors-mode (if multiple-cursors-mode
(progn (progn
(mc/temporarily-disable-unsupported-minor-modes) (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) (add-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t t)
(run-hooks 'multiple-cursors-mode-enabled-hook)) (run-hooks 'multiple-cursors-mode-enabled-hook))
(remove-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t) (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--maybe-set-killed-rectangle)
(mc/remove-fake-cursors) (mc/remove-fake-cursors)
(mc/enable-temporarily-disabled-minor-modes) (mc/enable-temporarily-disabled-minor-modes)
@ -536,6 +559,8 @@ for running commands with multiple cursors.")
end-of-line end-of-line
set-mark-command set-mark-command
exchange-point-and-mark exchange-point-and-mark
cua-set-mark
cua-replace-region
move-end-of-line move-end-of-line
beginning-of-line beginning-of-line
move-beginning-of-line move-beginning-of-line