dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

multiple-cursors-core.el (33697B)


      1 ;;; multiple-cursors-core.el --- An experiment in multiple cursors for emacs.
      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 file contains the core functionality of multiple-cursors.
     24 ;; Please see multiple-cursors.el for more commentary.
     25 
     26 ;;; Code:
     27 
     28 (require 'cl-lib)
     29 (require 'rect)
     30 
     31 (defvar mc--read-char)
     32 
     33 (defface mc/cursor-face
     34   '((t (:inverse-video t)))
     35   "The face used for fake cursors"
     36   :group 'multiple-cursors)
     37 
     38 (defface mc/region-face
     39   '((t :inherit region))
     40   "The face used for fake regions"
     41   :group 'multiple-cursors)
     42 
     43 (defmacro mc/add-fake-cursor-to-undo-list (&rest forms)
     44   "Make sure point is in the right place when undoing"
     45   (let ((uc (make-symbol "undo-cleaner")))
     46     `(let ((,uc (cons 'apply (cons 'deactivate-cursor-after-undo (list id)))))
     47        (setq buffer-undo-list (cons ,uc buffer-undo-list))
     48        ,@forms
     49        (if (eq ,uc (car buffer-undo-list)) ;; if nothing has been added to the undo-list
     50            (setq buffer-undo-list (cdr buffer-undo-list)) ;; then pop the cleaner right off again
     51          (setq buffer-undo-list ;; otherwise add a function to activate this cursor
     52                (cons (cons 'apply (cons 'activate-cursor-for-undo (list id))) buffer-undo-list))))))
     53 
     54 (defun mc/all-fake-cursors (&optional start end)
     55   (cl-remove-if-not 'mc/fake-cursor-p
     56                     (overlays-in (or start (point-min))
     57                                  (or end   (point-max)))))
     58 
     59 (defmacro mc/for-each-fake-cursor (&rest forms)
     60   "Runs the body for each fake cursor, bound to the name cursor"
     61   `(mapc #'(lambda (cursor) ,@forms)
     62          (mc/all-fake-cursors)))
     63 
     64 (defmacro mc/save-excursion (&rest forms)
     65   "Saves and restores all the state that multiple-cursors cares about."
     66   (let ((cs (make-symbol "current-state")))
     67     `(let ((,cs (mc/store-current-state-in-overlay
     68                  (make-overlay (point) (point) nil nil t))))
     69        (overlay-put ,cs 'type 'original-cursor)
     70        (save-excursion ,@forms)
     71        (mc/pop-state-from-overlay ,cs))))
     72 
     73 (defun mc--compare-by-overlay-start (o1 o2)
     74   (< (overlay-start o1) (overlay-start o2)))
     75 
     76 (defmacro mc/for-each-cursor-ordered (&rest forms)
     77   "Runs the body for each cursor, fake and real, bound to the name cursor"
     78   (let ((rci (make-symbol "real-cursor-id")))
     79     `(let ((,rci (overlay-get (mc/create-fake-cursor-at-point) 'mc-id)))
     80        (mapc #'(lambda (cursor)
     81                  (when (mc/fake-cursor-p cursor)
     82                    ,@forms))
     83              (sort (overlays-in (point-min) (point-max)) 'mc--compare-by-overlay-start))
     84        (mc/pop-state-from-overlay (mc/cursor-with-id ,rci)))))
     85 
     86 (defmacro mc/save-window-scroll (&rest forms)
     87   "Saves and restores the window scroll position"
     88   (let ((p (make-symbol "p"))
     89         (s (make-symbol "start"))
     90         (h (make-symbol "hscroll")))
     91     `(let ((,p (set-marker (make-marker) (point)))
     92            (,s (set-marker (make-marker) (window-start)))
     93            (,h (window-hscroll)))
     94        ,@forms
     95        (goto-char ,p)
     96        (set-window-start nil ,s t)
     97        (set-window-hscroll nil ,h)
     98        (set-marker ,p nil)
     99        (set-marker ,s nil))))
    100 
    101 (defun mc/make-cursor-overlay-at-eol (pos)
    102   "Create overlay to look like cursor at end of line."
    103   (let ((overlay (make-overlay pos pos nil nil nil)))
    104     (overlay-put overlay 'after-string (propertize " " 'face 'mc/cursor-face))
    105     overlay))
    106 
    107 (defun mc/make-cursor-overlay-inline (pos)
    108   "Create overlay to look like cursor inside text."
    109   (let ((overlay (make-overlay pos (1+ pos) nil nil nil)))
    110     (overlay-put overlay 'face 'mc/cursor-face)
    111     overlay))
    112 
    113 (defun mc/make-cursor-overlay-at-point ()
    114   "Create overlay to look like cursor.
    115 Special case for end of line, because overlay over a newline
    116 highlights the entire width of the window."
    117   (if (eolp)
    118       (mc/make-cursor-overlay-at-eol (point))
    119     (mc/make-cursor-overlay-inline (point))))
    120 
    121 (defun mc/make-region-overlay-between-point-and-mark ()
    122   "Create overlay to look like active region."
    123   (let ((overlay (make-overlay (mark) (point) nil nil t)))
    124     (overlay-put overlay 'face 'mc/region-face)
    125     (overlay-put overlay 'type 'additional-region)
    126     overlay))
    127 
    128 (defvar mc/cursor-specific-vars '(transient-mark-mode
    129                                   kill-ring
    130                                   kill-ring-yank-pointer
    131                                   mark-ring
    132                                   mark-active
    133                                   yank-undo-function
    134                                   autopair-action
    135                                   autopair-wrap-action
    136                                   er/history)
    137   "A list of vars that need to be tracked on a per-cursor basis.")
    138 
    139 (defun mc/store-current-state-in-overlay (o)
    140   "Store relevant info about point and mark in the given overlay."
    141   (overlay-put o 'point (set-marker (make-marker) (point)))
    142   (overlay-put o 'mark (set-marker (make-marker) (mark)))
    143   (dolist (var mc/cursor-specific-vars)
    144     (when (boundp var) (overlay-put o var (symbol-value var))))
    145   o)
    146 
    147 (defun mc/restore-state-from-overlay (o)
    148   "Restore point and mark from stored info in the given overlay."
    149   (goto-char (overlay-get o 'point))
    150   (set-marker (mark-marker) (overlay-get o 'mark))
    151   (dolist (var mc/cursor-specific-vars)
    152     (when (boundp var) (set var (overlay-get o var)))))
    153 
    154 (defun mc/remove-fake-cursor (o)
    155   "Delete overlay with state, including dependent overlays and markers."
    156   (set-marker (overlay-get o 'point) nil)
    157   (set-marker (overlay-get o 'mark) nil)
    158   (mc/delete-region-overlay o)
    159   (delete-overlay o))
    160 
    161 (defun mc/pop-state-from-overlay (o)
    162   "Restore the state stored in given overlay and then remove the overlay."
    163   (mc/restore-state-from-overlay o)
    164   (mc/remove-fake-cursor o))
    165 
    166 (defun mc/delete-region-overlay (o)
    167   "Remove the dependent region overlay for a given cursor overlay."
    168   (ignore-errors
    169     (delete-overlay (overlay-get o 'region-overlay))))
    170 
    171 (defvar mc--current-cursor-id 0
    172   "Var to store increasing id of fake cursors, used to keep track of them for undo.")
    173 
    174 (defun mc/create-cursor-id ()
    175   "Returns a unique cursor id"
    176   (cl-incf mc--current-cursor-id))
    177 
    178 (defvar mc--max-cursors-original nil
    179   "This variable maintains the original maximum number of cursors.
    180 When `mc/create-fake-cursor-at-point' is called and
    181 `mc/max-cursors' is overridden, this value serves as a backup so
    182 that `mc/max-cursors' can take on a new value.  When
    183 `mc/remove-fake-cursors' is called, the values are reset.")
    184 
    185 (defcustom mc/max-cursors nil
    186   "Safety ceiling for the number of active cursors.
    187 If your emacs slows down or freezes when using too many cursors,
    188 customize this value appropriately.
    189 
    190 Cursors will be added until this value is reached, at which point
    191 you can either temporarily override the value or abort the
    192 operation entirely.
    193 
    194 If this value is nil, there is no ceiling."
    195   :type '(integer)
    196   :group 'multiple-cursors)
    197 
    198 (defun mc/create-fake-cursor-at-point (&optional id)
    199   "Add a fake cursor and possibly a fake active region overlay based on point and mark.
    200 Saves the current state in the overlay to be restored later."
    201   (unless mc--max-cursors-original
    202     (setq mc--max-cursors-original mc/max-cursors))
    203   (when mc/max-cursors
    204     (unless (< (mc/num-cursors) mc/max-cursors)
    205       (if (yes-or-no-p (format "%d active cursors. Continue? " (mc/num-cursors)))
    206           (setq mc/max-cursors (read-number "Enter a new, temporary maximum: "))
    207         (mc/remove-fake-cursors)
    208         (error "Aborted: too many cursors"))))
    209   (let ((overlay (mc/make-cursor-overlay-at-point)))
    210     (overlay-put overlay 'mc-id (or id (mc/create-cursor-id)))
    211     (overlay-put overlay 'type 'fake-cursor)
    212     (overlay-put overlay 'priority 100)
    213     (mc/store-current-state-in-overlay overlay)
    214     (when (use-region-p)
    215       (overlay-put overlay 'region-overlay
    216                    (mc/make-region-overlay-between-point-and-mark)))
    217     overlay))
    218 
    219 (defun mc/execute-command (cmd)
    220   "Run command, simulating the parts of the command loop that makes sense for fake cursors."
    221   (setq this-command cmd)
    222   (run-hooks 'pre-command-hook)
    223   (unless (eq this-command 'ignore)
    224     (call-interactively cmd))
    225   (run-hooks 'post-command-hook)
    226   (when deactivate-mark (deactivate-mark)))
    227 
    228 (defvar mc--executing-command-for-fake-cursor nil)
    229 
    230 (defun mc/execute-command-for-fake-cursor (cmd cursor)
    231   (let ((mc--executing-command-for-fake-cursor t)
    232         (id (overlay-get cursor 'mc-id))
    233         (annoying-arrows-mode nil)
    234         (smooth-scroll-margin 0))
    235     (mc/add-fake-cursor-to-undo-list
    236      (mc/pop-state-from-overlay cursor)
    237      (ignore-errors
    238        (mc/execute-command cmd)
    239        (mc/create-fake-cursor-at-point id)))))
    240 
    241 (defun mc/execute-command-for-all-fake-cursors (cmd)
    242   "Calls CMD interactively for each cursor.
    243 It works by moving point to the fake cursor, setting
    244 up the proper environment, and then removing the cursor.
    245 After executing the command, it sets up a new fake
    246 cursor with updated info."
    247   (mc/save-excursion
    248    (mc/save-window-scroll
    249     (mc/for-each-fake-cursor
    250      (save-excursion
    251        (mc/execute-command-for-fake-cursor cmd cursor)))))
    252   (mc--reset-read-prompts))
    253 
    254 (defun mc/execute-command-for-all-cursors (cmd)
    255   "Calls CMD interactively for the real cursor and all fakes."
    256   (call-interactively cmd)
    257   (mc/execute-command-for-all-fake-cursors cmd))
    258 
    259 ;; Intercept some reading commands so you won't have to
    260 ;; answer them for every single cursor
    261 
    262 (defvar mc--read-char nil)
    263 (defvar multiple-cursors-mode nil)
    264 (defadvice read-char (around mc-support activate)
    265   (if (not multiple-cursors-mode)
    266       ad-do-it
    267     (unless mc--read-char
    268       (setq mc--read-char ad-do-it))
    269     (setq ad-return-value mc--read-char)))
    270 
    271 (defvar mc--read-quoted-char nil)
    272 (defadvice read-quoted-char (around mc-support activate)
    273   (if (not multiple-cursors-mode)
    274       ad-do-it
    275     (unless mc--read-quoted-char
    276       (setq mc--read-quoted-char ad-do-it))
    277     (setq ad-return-value mc--read-quoted-char)))
    278 
    279 (defun mc--reset-read-prompts ()
    280   (setq mc--read-char nil)
    281   (setq mc--read-quoted-char nil))
    282 
    283 (mc--reset-read-prompts)
    284 
    285 (defun mc/fake-cursor-p (o)
    286   "Predicate to check if an overlay is a fake cursor"
    287   (eq (overlay-get o 'type) 'fake-cursor))
    288 
    289 (defun mc/cursor-with-id (id)
    290   "Find the first cursor with the given id, or nil"
    291   (cl-find-if #'(lambda (o) (and (mc/fake-cursor-p o)
    292                             (= id (overlay-get o 'mc-id))))
    293               (overlays-in (point-min) (point-max))))
    294 
    295 (defvar mc--stored-state-for-undo nil
    296   "Variable to keep the state of the real cursor while undoing a fake one")
    297 
    298 (defun activate-cursor-for-undo (id)
    299   "Called when undoing to temporarily activate the fake cursor which action is being undone."
    300   (let ((cursor (mc/cursor-with-id id)))
    301     (when cursor
    302       (setq mc--stored-state-for-undo (mc/store-current-state-in-overlay
    303                                        (make-overlay (point) (point) nil nil t)))
    304       (mc/pop-state-from-overlay cursor))))
    305 
    306 (defun deactivate-cursor-after-undo (id)
    307   "Called when undoing to reinstate the real cursor after undoing a fake one."
    308   (when mc--stored-state-for-undo
    309     (mc/create-fake-cursor-at-point id)
    310     (mc/pop-state-from-overlay mc--stored-state-for-undo)
    311     (setq mc--stored-state-for-undo nil)))
    312 
    313 (defun mc/prompt-for-inclusion-in-whitelist (original-command)
    314   "Asks the user, then adds the command either to the once-list or the all-list."
    315   (let ((all-p (y-or-n-p (format "Do %S for all cursors?" original-command))))
    316     (if all-p
    317         (add-to-list 'mc/cmds-to-run-for-all original-command)
    318       (add-to-list 'mc/cmds-to-run-once original-command))
    319     (mc/save-lists)
    320     all-p))
    321 
    322 (defun mc/num-cursors ()
    323   "The number of cursors (real and fake) in the buffer."
    324   (1+ (cl-count-if 'mc/fake-cursor-p
    325                    (overlays-in (point-min) (point-max)))))
    326 
    327 (defvar mc--this-command nil
    328   "Used to store the original command being run.")
    329 (make-variable-buffer-local 'mc--this-command)
    330 
    331 (defun mc/make-a-note-of-the-command-being-run ()
    332   "Used with pre-command-hook to store the original command being run.
    333 Since that cannot be reliably determined in the post-command-hook.
    334 
    335 Specifically, this-original-command isn't always right, because it could have
    336 been remapped. And certain modes (cua comes to mind) will change their
    337 remapping based on state. So a command that changes the state will afterwards
    338 not be recognized through the command-remapping lookup."
    339   (unless mc--executing-command-for-fake-cursor
    340     (let ((cmd (or (command-remapping this-original-command)
    341                    this-original-command)))
    342       (setq mc--this-command (and (not (eq cmd 'god-mode-self-insert))
    343                                   cmd)))))
    344 
    345 (defun mc/execute-this-command-for-all-cursors ()
    346   "Wrap around `mc/execute-this-command-for-all-cursors-1' to protect hook."
    347   (condition-case error
    348       (mc/execute-this-command-for-all-cursors-1)
    349     (error
    350      (message "[mc] problem in `mc/execute-this-command-for-all-cursors': %s"
    351               (error-message-string error)))))
    352 
    353 ;; execute-kbd-macro should never be run for fake cursors. The real cursor will
    354 ;; execute the keyboard macro, resulting in new commands in the command loop,
    355 ;; and the fake cursors can pick up on those instead.
    356 (defadvice execute-kbd-macro (around skip-fake-cursors activate)
    357   (unless mc--executing-command-for-fake-cursor
    358     ad-do-it))
    359 
    360 (defun mc/execute-this-command-for-all-cursors-1 ()
    361   "Used with post-command-hook to execute supported commands for all cursors.
    362 
    363 It uses two lists of commands to know what to do: the run-once
    364 list and the run-for-all list. If a command is in neither of these lists,
    365 it will prompt for the proper action and then save that preference.
    366 
    367 Some commands are so unsupported that they are even prevented for
    368 the original cursor, to inform about the lack of support."
    369   (unless mc--executing-command-for-fake-cursor
    370 
    371     (if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode
    372         (multiple-cursors-mode 0)
    373       (when this-original-command
    374         (let ((original-command (or mc--this-command
    375                                     (command-remapping this-original-command)
    376                                     this-original-command)))
    377 
    378           ;; skip keyboard macros, since they will generate actual commands that are
    379           ;; also run in the command loop - we'll handle those later instead.
    380           (when (functionp original-command)
    381 
    382             ;; if it's a lambda, we can't know if it's supported or not
    383             ;; - so go ahead and assume it's ok, because we're just optimistic like that
    384             (if (or (not (symbolp original-command))
    385                     ;; lambda registered by smartrep
    386                     (string-prefix-p "(" (symbol-name original-command)))
    387                 (mc/execute-command-for-all-fake-cursors original-command)
    388 
    389               ;; smartrep `intern's commands into own obarray to help
    390               ;; `describe-bindings'.  So, let's re-`intern' here to
    391               ;; make the command comparable by `eq'.
    392               (setq original-command (intern (symbol-name original-command)))
    393 
    394               ;; otherwise it's a symbol, and we can be more thorough
    395               (if (get original-command 'mc--unsupported)
    396                   (message "%S is not supported with multiple cursors%s"
    397                            original-command
    398                            (get original-command 'mc--unsupported))
    399                 (when (and original-command
    400                            (not (memq original-command mc--default-cmds-to-run-once))
    401                            (not (memq original-command mc/cmds-to-run-once))
    402                            (or (memq original-command mc--default-cmds-to-run-for-all)
    403                                (memq original-command mc/cmds-to-run-for-all)
    404                                (mc/prompt-for-inclusion-in-whitelist original-command)))
    405                   (mc/execute-command-for-all-fake-cursors original-command))))))))))
    406 
    407 (defun mc/remove-fake-cursors ()
    408   "Remove all fake cursors.
    409 Do not use to conclude editing with multiple cursors. For that
    410 you should disable multiple-cursors-mode."
    411   (mc/for-each-fake-cursor
    412    (mc/remove-fake-cursor cursor))
    413   (when mc--max-cursors-original
    414     (setq mc/max-cursors mc--max-cursors-original))
    415   (setq mc--max-cursors-original nil))
    416 
    417 (defun mc/keyboard-quit ()
    418   "Deactivate mark if there are any active, otherwise exit multiple-cursors-mode."
    419   (interactive)
    420   (if (not (use-region-p))
    421       (multiple-cursors-mode 0)
    422     (deactivate-mark)))
    423 
    424 (defvar mc/keymap nil
    425   "Keymap while multiple cursors are active.
    426 Main goal of the keymap is to rebind C-g and <return> to conclude
    427 multiple cursors editing.")
    428 (unless mc/keymap
    429   (setq mc/keymap (make-sparse-keymap))
    430   (define-key mc/keymap (kbd "C-g") 'mc/keyboard-quit)
    431   (define-key mc/keymap (kbd "<return>") 'multiple-cursors-mode)
    432   (when (fboundp 'phi-search)
    433     (define-key mc/keymap (kbd "C-s") 'phi-search))
    434   (when (fboundp 'phi-search-backward)
    435     (define-key mc/keymap (kbd "C-r") 'phi-search-backward)))
    436 
    437 (defun mc--all-equal (list)
    438   "Are all the items in LIST equal?"
    439   (let ((first (car list))
    440         (all-equal t))
    441     (while (and all-equal list)
    442       (setq all-equal (equal first (car list)))
    443       (setq list (cdr list)))
    444     all-equal))
    445 
    446 (defun mc--kill-ring-entries ()
    447   "Return the latest kill-ring entry for each cursor.
    448 The entries are returned in the order they are found in the buffer."
    449   (let (entries)
    450     (mc/for-each-cursor-ordered
    451      (setq entries (cons (car (overlay-get cursor 'kill-ring)) entries)))
    452     (reverse entries)))
    453 
    454 (defun mc--maybe-set-killed-rectangle ()
    455   "Add the latest kill-ring entry for each cursor to killed-rectangle.
    456 So you can paste it in later with `yank-rectangle'."
    457   (let ((entries (let (mc/max-cursors) (mc--kill-ring-entries))))
    458     (unless (mc--all-equal entries)
    459       (setq killed-rectangle entries))))
    460 
    461 (defvar mc/unsupported-minor-modes '(company-mode auto-complete-mode flyspell-mode jedi-mode)
    462   "List of minor-modes that does not play well with multiple-cursors.
    463 They are temporarily disabled when multiple-cursors are active.")
    464 
    465 (defvar mc/temporarily-disabled-minor-modes nil
    466   "The list of temporarily disabled minor-modes.")
    467 (make-variable-buffer-local 'mc/temporarily-disabled-minor-modes)
    468 
    469 (defun mc/temporarily-disable-minor-mode (mode)
    470   "If MODE is available and turned on, remember that and turn it off."
    471   (when (and (boundp mode) (eval mode))
    472     (add-to-list 'mc/temporarily-disabled-minor-modes mode)
    473     (funcall mode -1)))
    474 
    475 (defun mc/temporarily-disable-unsupported-minor-modes ()
    476   (mapc 'mc/temporarily-disable-minor-mode mc/unsupported-minor-modes))
    477 
    478 (defun mc/enable-minor-mode (mode)
    479   (funcall mode 1))
    480 
    481 (defun mc/enable-temporarily-disabled-minor-modes ()
    482   (mapc 'mc/enable-minor-mode mc/temporarily-disabled-minor-modes)
    483   (setq mc/temporarily-disabled-minor-modes nil))
    484 
    485 (defcustom mc/mode-line
    486   `(" mc:" (:eval (format ,(propertize "%d" 'face 'font-lock-warning-face)
    487                           (mc/num-cursors))))
    488   "What to display in the mode line while multiple-cursors-mode is active."
    489   :group 'multiple-cursors)
    490 (put 'mc/mode-line 'risky-local-variable t)
    491 
    492 ;;;###autoload
    493 (define-minor-mode multiple-cursors-mode
    494   "Mode while multiple cursors are active."
    495   nil mc/mode-line mc/keymap
    496   (if multiple-cursors-mode
    497       (progn
    498         (mc/temporarily-disable-unsupported-minor-modes)
    499         (add-hook 'pre-command-hook 'mc/make-a-note-of-the-command-being-run nil t)
    500         (add-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t t)
    501         (run-hooks 'multiple-cursors-mode-enabled-hook))
    502     (remove-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t)
    503     (remove-hook 'pre-command-hook 'mc/make-a-note-of-the-command-being-run t)
    504     (setq mc--this-command nil)
    505     (mc--maybe-set-killed-rectangle)
    506     (mc/remove-fake-cursors)
    507     (mc/enable-temporarily-disabled-minor-modes)
    508     (run-hooks 'multiple-cursors-mode-disabled-hook)))
    509 
    510 (add-hook 'after-revert-hook #'(lambda () (multiple-cursors-mode 0)))
    511 
    512 (defun mc/maybe-multiple-cursors-mode ()
    513   "Enable multiple-cursors-mode if there is more than one currently active cursor."
    514   (if (> (mc/num-cursors) 1)
    515       (multiple-cursors-mode 1)
    516     (multiple-cursors-mode 0)))
    517 
    518 (defmacro unsupported-cmd (cmd msg)
    519   "Adds command to list of unsupported commands and prevents it
    520 from being executed if in multiple-cursors-mode."
    521   `(progn
    522      (put (quote ,cmd) 'mc--unsupported ,msg)
    523      (defadvice ,cmd (around unsupported-advice activate)
    524        "command isn't supported with multiple cursors"
    525        (unless (and multiple-cursors-mode (called-interactively-p 'any))
    526          ad-do-it))))
    527 
    528 ;; Commands that does not work with multiple-cursors
    529 (unsupported-cmd isearch-forward ". Feel free to add a compatible version.")
    530 (unsupported-cmd isearch-backward ". Feel free to add a compatible version.")
    531 
    532 ;; Make sure pastes from other programs are added to all kill-rings when yanking
    533 (defadvice current-kill (before interprogram-paste-for-all-cursors activate)
    534   (let ((interprogram-paste (and (= n 0)
    535                                  interprogram-paste-function
    536                                  (funcall interprogram-paste-function))))
    537     (when interprogram-paste
    538       ;; Add interprogram-paste to normal kill ring, just
    539       ;; like current-kill usually does for itself.
    540       ;; We have to do the work for it tho, since the funcall only returns
    541       ;; something once. It is not a pure function.
    542       (let ((interprogram-cut-function nil))
    543         (if (listp interprogram-paste)
    544             (mapc 'kill-new (nreverse interprogram-paste))
    545           (kill-new interprogram-paste))
    546         ;; And then add interprogram-paste to the kill-rings
    547         ;; of all the other cursors too.
    548         (mc/for-each-fake-cursor
    549          (let ((kill-ring (overlay-get cursor 'kill-ring))
    550                (kill-ring-yank-pointer (overlay-get cursor 'kill-ring-yank-pointer)))
    551            (if (listp interprogram-paste)
    552                (mapc 'kill-new (nreverse interprogram-paste))
    553              (kill-new interprogram-paste))
    554            (overlay-put cursor 'kill-ring kill-ring)
    555            (overlay-put cursor 'kill-ring-yank-pointer kill-ring-yank-pointer)))))))
    556 
    557 (defvar mc/list-file (locate-user-emacs-file ".mc-lists.el")
    558   "The position of the file that keeps track of your preferences
    559 for running commands with multiple cursors.")
    560 
    561 (defun mc/dump-list (list-symbol)
    562   "Insert (setq 'LIST-SYMBOL LIST-VALUE) to current buffer."
    563   (cl-symbol-macrolet ((value (symbol-value list-symbol)))
    564     (insert "(setq " (symbol-name list-symbol) "\n"
    565             "      '(")
    566     (newline-and-indent)
    567     (set list-symbol
    568          (sort value (lambda (x y) (string-lessp (symbol-name x)
    569                                             (symbol-name y)))))
    570     (mapc #'(lambda (cmd) (insert (format "%S" cmd)) (newline-and-indent))
    571           value)
    572     (insert "))")
    573     (newline)))
    574 
    575 (defun mc/save-lists ()
    576   "Saves preferences for running commands with multiple cursors to `mc/list-file'"
    577   (with-temp-file mc/list-file
    578     (emacs-lisp-mode)
    579     (insert ";; This file is automatically generated by the multiple-cursors extension.")
    580     (newline)
    581     (insert ";; It keeps track of your preferences for running commands with multiple cursors.")
    582     (newline)
    583     (newline)
    584     (mc/dump-list 'mc/cmds-to-run-for-all)
    585     (newline)
    586     (mc/dump-list 'mc/cmds-to-run-once)))
    587 
    588 (defvar mc/cmds-to-run-once nil
    589   "Commands to run only once in multiple-cursors-mode.")
    590 
    591 (defvar mc--default-cmds-to-run-once nil
    592   "Default set of commands to run only once in multiple-cursors-mode.")
    593 
    594 (setq mc--default-cmds-to-run-once '(mc/edit-lines
    595                                      mc/edit-ends-of-lines
    596                                      mc/edit-beginnings-of-lines
    597                                      mc/mark-next-like-this
    598 				     mc/mark-next-like-this-word
    599 				     mc/mark-next-like-this-symbol
    600                                      mc/mark-next-word-like-this
    601                                      mc/mark-next-symbol-like-this
    602                                      mc/mark-previous-like-this
    603                                      mc/mark-previous-word-like-this
    604                                      mc/mark-previous-symbol-like-this
    605                                      mc/mark-all-like-this
    606                                      mc/mark-all-words-like-this
    607                                      mc/mark-all-symbols-like-this
    608                                      mc/mark-more-like-this-extended
    609                                      mc/mark-all-like-this-in-defun
    610                                      mc/mark-all-words-like-this-in-defun
    611                                      mc/mark-all-symbols-like-this-in-defun
    612                                      mc/mark-all-like-this-dwim
    613                                      mc/mark-all-dwim
    614                                      mc/mark-sgml-tag-pair
    615                                      mc/insert-numbers
    616 				     mc/insert-letters
    617                                      mc/sort-regions
    618                                      mc/reverse-regions
    619                                      mc/cycle-forward
    620                                      mc/cycle-backward
    621                                      mc/add-cursor-on-click
    622                                      mc/mark-pop
    623                                      mc/add-cursors-to-all-matches
    624                                      mc/mmlte--left
    625                                      mc/mmlte--right
    626                                      mc/mmlte--up
    627                                      mc/mmlte--down
    628                                      mc/unmark-next-like-this
    629                                      mc/unmark-previous-like-this
    630                                      mc/skip-to-next-like-this
    631                                      mc/skip-to-previous-like-this
    632                                      rrm/switch-to-multiple-cursors
    633                                      mc-hide-unmatched-lines-mode
    634                                      hum/keyboard-quit
    635                                      hum/unhide-invisible-overlays
    636                                      save-buffer
    637                                      ido-exit-minibuffer
    638                                      exit-minibuffer
    639                                      minibuffer-complete-and-exit
    640                                      execute-extended-command
    641                                      undo
    642                                      redo
    643                                      undo-tree-undo
    644                                      undo-tree-redo
    645                                      universal-argument
    646                                      universal-argument-more
    647                                      universal-argument-other-key
    648                                      negative-argument
    649                                      digit-argument
    650                                      top-level
    651                                      recenter-top-bottom
    652                                      describe-mode
    653                                      describe-key-1
    654                                      describe-function
    655                                      describe-bindings
    656                                      describe-prefix-bindings
    657                                      view-echo-area-messages
    658                                      other-window
    659                                      kill-buffer-and-window
    660                                      split-window-right
    661                                      split-window-below
    662                                      delete-other-windows
    663                                      toggle-window-split
    664                                      mwheel-scroll
    665                                      scroll-up-command
    666                                      scroll-down-command
    667                                      mouse-set-point
    668                                      mouse-drag-region
    669                                      quit-window
    670                                      toggle-read-only
    671                                      windmove-left
    672                                      windmove-right
    673                                      windmove-up
    674                                      windmove-down))
    675 
    676 (defvar mc--default-cmds-to-run-for-all nil
    677   "Default set of commands that should be mirrored by all cursors")
    678 
    679 (setq mc--default-cmds-to-run-for-all '(mc/keyboard-quit
    680                                         self-insert-command
    681                                         quoted-insert
    682                                         previous-line
    683                                         next-line
    684                                         newline
    685                                         newline-and-indent
    686                                         open-line
    687                                         delete-blank-lines
    688                                         transpose-chars
    689                                         transpose-lines
    690                                         transpose-paragraphs
    691                                         transpose-regions
    692                                         join-line
    693                                         right-char
    694                                         right-word
    695                                         forward-char
    696                                         forward-word
    697                                         left-char
    698                                         left-word
    699                                         backward-char
    700                                         backward-word
    701                                         forward-paragraph
    702                                         backward-paragraph
    703                                         upcase-word
    704                                         downcase-word
    705                                         capitalize-word
    706                                         forward-list
    707                                         backward-list
    708                                         hippie-expand
    709                                         hippie-expand-lines
    710                                         yank
    711                                         yank-pop
    712                                         append-next-kill
    713                                         kill-word
    714                                         kill-line
    715                                         kill-whole-line
    716                                         backward-kill-word
    717                                         backward-delete-char-untabify
    718                                         delete-char delete-forward-char
    719                                         delete-backward-char
    720                                         py-electric-backspace
    721                                         c-electric-backspace
    722                                         org-delete-backward-char
    723                                         cperl-electric-backspace
    724                                         python-indent-dedent-line-backspace
    725                                         paredit-backward-delete
    726                                         autopair-backspace
    727                                         just-one-space
    728                                         zap-to-char
    729                                         end-of-line
    730                                         set-mark-command
    731                                         exchange-point-and-mark
    732                                         cua-set-mark
    733                                         cua-replace-region
    734                                         cua-delete-region
    735                                         move-end-of-line
    736                                         beginning-of-line
    737                                         move-beginning-of-line
    738                                         kill-ring-save
    739                                         back-to-indentation
    740                                         subword-forward
    741                                         subword-backward
    742                                         subword-mark
    743                                         subword-kill
    744                                         subword-backward-kill
    745                                         subword-transpose
    746                                         subword-capitalize
    747                                         subword-upcase
    748                                         subword-downcase
    749                                         er/expand-region
    750                                         er/contract-region
    751                                         smart-forward
    752                                         smart-backward
    753                                         smart-up
    754                                         smart-down))
    755 
    756 (defvar mc/cmds-to-run-for-all nil
    757   "Commands to run for all cursors in multiple-cursors-mode")
    758 
    759 (load mc/list-file t) ;; load, but no errors if it does not exist yet please
    760 
    761 (provide 'multiple-cursors-core)
    762 
    763 ;; Local Variables:
    764 ;; coding: utf-8
    765 ;; End:
    766 
    767 ;;; multiple-cursors-core.el ends here