Split multiline kill-ring entry over cursors when num lines match

This commit is contained in:
Magnar Sveen 2012-09-23 18:36:33 +02:00
parent 7a655b0c0b
commit 067063a346
2 changed files with 63 additions and 6 deletions

View File

@ -131,3 +131,26 @@ Feature: Multiple cursors core
contains contains
twice twice
""" """
Scenario: Split multiline kill-ring entry over cursors when num lines match
When I insert:
"""
a
b
c
"""
And I go to the front of the word "a"
And I press "C-SPC"
And I go to the end of the word "c"
And I press "M-w"
And I go to the end of the word "a"
And I press "H-SPC"
And I press "C-n"
And I press "C-n"
And I press "C-y"
Then I should see:
"""
aa
bb
cc
"""

View File

@ -62,11 +62,17 @@
(save-excursion ,@forms) (save-excursion ,@forms)
(mc/pop-state-from-overlay current-state))) (mc/pop-state-from-overlay current-state)))
(defmacro mc/for-each-cursor (&rest forms) (defun mc--compare-by-overlay-start (o1 o2)
(< (overlay-start o1) (overlay-start o2)))
(defmacro mc/for-each-cursor-ordered (&rest forms)
"Runs the body for each cursor, fake and real, bound to the name cursor" "Runs the body for each cursor, fake and real, bound to the name cursor"
`(let ((real-cursor (mc/create-fake-cursor-at-point))) `(let ((real-cursor (mc/create-fake-cursor-at-point)))
(mc/for-each-fake-cursor ,@forms) (mapc #'(lambda (cursor)
(mc/remove-fake-cursor real-cursor))) (when (mc/fake-cursor-p cursor)
,@forms))
(sort (overlays-in (point-min) (point-max)) 'mc--compare-by-overlay-start))
(mc/pop-state-from-overlay real-cursor)))
(defmacro mc/save-window-scroll (&rest forms) (defmacro mc/save-window-scroll (&rest forms)
"Saves and restores the window scroll position" "Saves and restores the window scroll position"
@ -177,6 +183,8 @@ Saves the current state in the overlay to be restored later."
(call-interactively cmd)) (call-interactively cmd))
(when deactivate-mark (deactivate-mark))) (when deactivate-mark (deactivate-mark)))
(defvar mc--executing-command-for-fake-cursor nil)
(defun mc/execute-command-for-all-fake-cursors (cmd) (defun mc/execute-command-for-all-fake-cursors (cmd)
"Calls CMD interactively for each cursor. "Calls CMD interactively for each cursor.
It works by moving point to the fake cursor, setting It works by moving point to the fake cursor, setting
@ -187,7 +195,8 @@ cursor with updated info."
(mc/save-window-scroll (mc/save-window-scroll
(mc/for-each-fake-cursor (mc/for-each-fake-cursor
(save-excursion (save-excursion
(let ((id (overlay-get cursor 'mc-id)) (let ((mc--executing-command-for-fake-cursor t)
(id (overlay-get cursor 'mc-id))
(annoying-arrows-mode nil)) (annoying-arrows-mode nil))
(mc/add-fake-cursor-to-undo-list (mc/add-fake-cursor-to-undo-list
(mc/pop-state-from-overlay cursor) (mc/pop-state-from-overlay cursor)
@ -301,13 +310,38 @@ multiple cursors editing.")
(setq entries (cdr entries))) (setq entries (cdr entries)))
all-equal)) all-equal))
(defun mc--maybe-consolidate-kill-rings () (defun mc--kill-ring-entries ()
(let (entries) (let (entries)
(mc/for-each-cursor (mc/for-each-cursor-ordered
(setq entries (cons (car (overlay-get cursor 'kill-ring)) entries))) (setq entries (cons (car (overlay-get cursor 'kill-ring)) entries)))
(reverse entries)))
(defun mc--maybe-consolidate-kill-rings ()
(let ((entries (mc--kill-ring-entries)))
(unless (mc--all-equal entries) (unless (mc--all-equal entries)
(kill-new (mapconcat 'identity entries "\n"))))) (kill-new (mapconcat 'identity entries "\n")))))
(defun mc--kill-new (entries)
(mc/for-each-cursor-ordered
(let ((kill-ring (overlay-get cursor 'kill-ring))
(kill-ring-yank-pointer (overlay-get cursor 'kill-ring-yank-pointer)))
(kill-new (car entries))
(setq entries (cdr entries))
(overlay-put cursor 'kill-ring kill-ring)
(overlay-put cursor 'kill-ring-yank-pointer kill-ring-yank-pointer))))
(defun mc--maybe-split-kill-ring ()
(let ((entries (mc--kill-ring-entries)))
(when (mc--all-equal entries)
(let ((lines (split-string (car entries) "\n")))
(when (= (mc/num-cursors) (length lines))
(mc--kill-new lines))))))
(defadvice yank (before maybe-split-kill-ring activate)
(when (and (or multiple-cursors-mode rectangular-region-mode)
(not mc--executing-command-for-fake-cursor))
(mc--maybe-split-kill-ring)))
(define-minor-mode multiple-cursors-mode (define-minor-mode multiple-cursors-mode
"Mode while multiple cursors are active." "Mode while multiple cursors are active."
nil " mc" mc/keymap nil " mc" mc/keymap