mc-cycle-cursors.el (4209B)
1 ;;; mc-cycle-cursors.el 2 3 ;; Copyright (C) 2012 Magnar Sveen 4 5 ;; Author: Magnar Sveen <magnars@gmail.com> 6 ;; Keywords: editing cursors 7 8 ;; This program is free software; you can redistribute it and/or modify 9 ;; it under the terms of the GNU General Public License as published by 10 ;; the Free Software Foundation, either version 3 of the License, or 11 ;; (at your option) any later version. 12 13 ;; This program is distributed in the hope that it will be useful, 14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 ;; GNU General Public License for more details. 17 18 ;; You should have received a copy of the GNU General Public License 19 ;; along with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 ;;; Commentary: 22 23 ;; This scrolls the buffer to center each cursor in turn. 24 ;; Scroll down with C-v, scroll up with M-v 25 ;; This is nice when you have cursors that's outside of your view. 26 27 ;;; Code: 28 29 (require 'multiple-cursors-core) 30 31 (defun mc/next-fake-cursor-after-point () 32 (let ((pos (point)) 33 (next-pos (1+ (point-max))) 34 next) 35 (mc/for-each-fake-cursor 36 (let ((cursor-pos (overlay-get cursor 'point))) 37 (when (and (< pos cursor-pos) 38 (< cursor-pos next-pos)) 39 (setq next-pos cursor-pos) 40 (setq next cursor)))) 41 next)) 42 43 (defun mc/prev-fake-cursor-before-point () 44 (let ((pos (point)) 45 (prev-pos (1- (point-min))) 46 prev) 47 (mc/for-each-fake-cursor 48 (let ((cursor-pos (overlay-get cursor 'point))) 49 (when (and (> pos cursor-pos) 50 (> cursor-pos prev-pos)) 51 (setq prev-pos cursor-pos) 52 (setq prev cursor)))) 53 prev)) 54 55 (defcustom mc/cycle-looping-behaviour 'continue 56 "What to do if asked to cycle beyond the last cursor or before the first cursor." 57 :type '(radio (const :tag "Loop around to beginning/end of document." continue) 58 (const :tag "Warn and then loop around." warn) 59 (const :tag "Signal an error." error) 60 (const :tag "Don't loop." stop)) 61 :group 'multiple-cursors) 62 63 (defun mc/handle-loop-condition (error-message) 64 (cl-ecase mc/cycle-looping-behaviour 65 (error (error error-message)) 66 (warn (message error-message)) 67 (continue 'continue) 68 (stop 'stop))) 69 70 (defun mc/first-fake-cursor-after (point) 71 "Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)." 72 (let* ((cursors (mc/all-fake-cursors)) 73 (cursors-after-point (cl-remove-if (lambda (cursor) 74 (< (mc/cursor-beg cursor) point)) 75 cursors)) 76 (cursors-in-order (cl-sort cursors-after-point '< :key 'mc/cursor-beg))) 77 (car cursors-in-order))) 78 79 (defun mc/last-fake-cursor-before (point) 80 "Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)." 81 (let* ((cursors (mc/all-fake-cursors)) 82 (cursors-before-point (cl-remove-if (lambda (cursor) 83 (> (mc/cursor-end cursor) point)) 84 cursors)) 85 (cursors-in-order (cl-sort cursors-before-point '> :key 'mc/cursor-end))) 86 (car cursors-in-order))) 87 88 (cl-defun mc/cycle (next-cursor fallback-cursor loop-message) 89 (when (null next-cursor) 90 (when (eql 'stop (mc/handle-loop-condition loop-message)) 91 (return-from mc/cycle nil)) 92 (setf next-cursor fallback-cursor)) 93 (mc/create-fake-cursor-at-point) 94 (mc/pop-state-from-overlay next-cursor) 95 (recenter)) 96 97 (defun mc/cycle-forward () 98 (interactive) 99 (mc/cycle (mc/next-fake-cursor-after-point) 100 (mc/first-fake-cursor-after (point-min)) 101 "We're already at the last cursor.")) 102 103 (defun mc/cycle-backward () 104 (interactive) 105 (mc/cycle (mc/prev-fake-cursor-before-point) 106 (mc/last-fake-cursor-before (point-max)) 107 "We're already at the last cursor")) 108 109 (define-key mc/keymap (kbd "C-v") 'mc/cycle-forward) 110 (define-key mc/keymap (kbd "M-v") 'mc/cycle-backward) 111 112 (provide 'mc-cycle-cursors) 113 114 115 ;; Local Variables: 116 ;; coding: utf-8 117 ;; End: 118 119 ;;; mc-cycle-cursors.el ends here