Simple image host.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

multiple-cursors-core.el 31KB

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