Personal emacs config
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.

655 lines
22 KiB

  1. ;;; mc-mark-more.el
  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 functions to mark more parts of the buffer.
  17. ;; See ./features/mark-more.feature for examples.
  18. ;; Please see multiple-cursors.el for more commentary.
  19. ;;; Code:
  20. (require 'multiple-cursors-core)
  21. (require 'thingatpt)
  22. (defun mc/cursor-end (cursor)
  23. (if (overlay-get cursor 'mark-active)
  24. (max (overlay-get cursor 'point)
  25. (overlay-get cursor 'mark))
  26. (overlay-get cursor 'point)))
  27. (defun mc/cursor-beg (cursor)
  28. (if (overlay-get cursor 'mark-active)
  29. (min (overlay-get cursor 'point)
  30. (overlay-get cursor 'mark))
  31. (overlay-get cursor 'point)))
  32. (defun mc/furthest-region-end ()
  33. (let ((end (max (mark) (point))))
  34. (mc/for-each-fake-cursor
  35. (setq end (max end (mc/cursor-end cursor))))
  36. end))
  37. (defun mc/first-region-start ()
  38. (let ((beg (min (mark) (point))))
  39. (mc/for-each-fake-cursor
  40. (setq beg (min beg (mc/cursor-beg cursor))))
  41. beg))
  42. (defun mc/furthest-cursor-before-point ()
  43. (let ((beg (if mark-active (min (mark) (point)) (point)))
  44. furthest)
  45. (mc/for-each-fake-cursor
  46. (when (< (mc/cursor-beg cursor) beg)
  47. (setq beg (mc/cursor-beg cursor))
  48. (setq furthest cursor)))
  49. furthest))
  50. (defun mc/furthest-cursor-after-point ()
  51. (let ((end (if mark-active (max (mark) (point)) (point)))
  52. furthest)
  53. (mc/for-each-fake-cursor
  54. (when (> (mc/cursor-end cursor) end)
  55. (setq end (mc/cursor-end cursor))
  56. (setq furthest cursor)))
  57. furthest))
  58. (defun mc/fake-cursor-at-point (&optional point)
  59. "Return the fake cursor with its point right at POINT (defaults
  60. to (point)), or nil."
  61. (setq point (or point (point)))
  62. (let ((cursors (mc/all-fake-cursors))
  63. (c nil))
  64. (catch 'found
  65. (while (setq c (pop cursors))
  66. (when (eq (marker-position (overlay-get c 'point))
  67. point)
  68. (throw 'found c))))))
  69. (defun mc/region-strings ()
  70. (let ((strings (list (buffer-substring-no-properties (point) (mark)))))
  71. (mc/for-each-fake-cursor
  72. (add-to-list 'strings (buffer-substring-no-properties
  73. (mc/cursor-beg cursor)
  74. (mc/cursor-end cursor))))
  75. strings))
  76. (defvar mc/enclose-search-term nil
  77. "How should mc/mark-more-* search for more matches?
  78. Match everything: nil
  79. Match only whole words: 'words
  80. Match only whole symbols: 'symbols
  81. Use like case-fold-search, don't recommend setting it globally.")
  82. (defun mc/mark-more-like-this (skip-last direction)
  83. (let ((case-fold-search nil)
  84. (re (regexp-opt (mc/region-strings) mc/enclose-search-term))
  85. (point-out-of-order (cl-ecase direction
  86. (forwards (< (point) (mark)))
  87. (backwards (not (< (point) (mark))))))
  88. (furthest-cursor (cl-ecase direction
  89. (forwards (mc/furthest-cursor-after-point))
  90. (backwards (mc/furthest-cursor-before-point))))
  91. (start-char (cl-ecase direction
  92. (forwards (mc/furthest-region-end))
  93. (backwards (mc/first-region-start))))
  94. (search-function (cl-ecase direction
  95. (forwards 'search-forward-regexp)
  96. (backwards 'search-backward-regexp)))
  97. (match-point-getter (cl-ecase direction
  98. (forwards 'match-beginning)
  99. (backwards 'match-end))))
  100. (if (and skip-last (not furthest-cursor))
  101. (error "No cursors to be skipped")
  102. (mc/save-excursion
  103. (goto-char start-char)
  104. (when skip-last
  105. (mc/remove-fake-cursor furthest-cursor))
  106. (if (funcall search-function re nil t)
  107. (progn
  108. (push-mark (funcall match-point-getter 0))
  109. (when point-out-of-order
  110. (exchange-point-and-mark))
  111. (mc/create-fake-cursor-at-point))
  112. (error "no more matches found."))))))
  113. ;;;###autoload
  114. (defun mc/mark-next-like-this (arg)
  115. "Find and mark the next part of the buffer matching the currently active region
  116. If no region is active add a cursor on the next line
  117. With negative ARG, delete the last one instead.
  118. With zero ARG, skip the last one and mark next."
  119. (interactive "p")
  120. (if (< arg 0)
  121. (let ((cursor (mc/furthest-cursor-after-point)))
  122. (if cursor
  123. (mc/remove-fake-cursor cursor)
  124. (error "No cursors to be unmarked")))
  125. (if (region-active-p)
  126. (mc/mark-more-like-this (= arg 0) 'forwards)
  127. (mc/mark-lines arg 'forwards)))
  128. (mc/maybe-multiple-cursors-mode))
  129. ;;;###autoload
  130. (defun mc/mark-next-like-this-word (arg)
  131. "Find and mark the next part of the buffer matching the currently active region
  132. If no region is active, mark the word at the point and find the next match
  133. With negative ARG, delete the last one instead.
  134. With zero ARG, skip the last one and mark next."
  135. (interactive "p")
  136. (if (< arg 0)
  137. (let ((cursor (mc/furthest-cursor-after-point)))
  138. (if cursor
  139. (mc/remove-fake-cursor cursor)
  140. (error "No cursors to be unmarked")))
  141. (if (region-active-p)
  142. (mc/mark-more-like-this (= arg 0) 'forwards)
  143. (mc--select-thing-at-point 'word)
  144. (mc/mark-more-like-this (= arg 0) 'forwards)))
  145. (mc/maybe-multiple-cursors-mode))
  146. (defun mc/mark-next-like-this-symbol (arg)
  147. "Find and mark the next part of the buffer matching the currently active region
  148. If no region is active, mark the symbol at the point and find the next match
  149. With negative ARG, delete the last one instead.
  150. With zero ARG, skip the last one and mark next."
  151. (interactive "p")
  152. (if (< arg 0)
  153. (let ((cursor (mc/furthest-cursor-after-point)))
  154. (if cursor
  155. (mc/remove-fake-cursor cursor)
  156. (error "No cursors to be unmarked")))
  157. (if (region-active-p)
  158. (mc/mark-more-like-this (= arg 0) 'forwards)
  159. (mc--select-thing-at-point 'symbol)
  160. (mc/mark-more-like-this (= arg 0) 'forwards)))
  161. (mc/maybe-multiple-cursors-mode))
  162. ;;;###autoload
  163. (defun mc/mark-next-word-like-this (arg)
  164. (interactive "p")
  165. (let ((mc/enclose-search-term 'words))
  166. (mc/mark-next-like-this arg)))
  167. ;;;###autoload
  168. (defun mc/mark-next-symbol-like-this (arg)
  169. (interactive "p")
  170. (let ((mc/enclose-search-term 'symbols))
  171. (mc/mark-next-like-this arg)))
  172. ;;;###autoload
  173. (defun mc/mark-previous-like-this (arg)
  174. "Find and mark the previous part of the buffer matching the currently active region
  175. With negative ARG, delete the last one instead.
  176. With zero ARG, skip the last one and mark next."
  177. (interactive "p")
  178. (if (< arg 0)
  179. (let ((cursor (mc/furthest-cursor-before-point)))
  180. (if cursor
  181. (mc/remove-fake-cursor cursor)
  182. (error "No cursors to be unmarked")))
  183. (if (region-active-p)
  184. (mc/mark-more-like-this (= arg 0) 'backwards)
  185. (mc/mark-lines arg 'backwards)))
  186. (mc/maybe-multiple-cursors-mode))
  187. ;;;###autoload
  188. (defun mc/mark-previous-word-like-this (arg)
  189. (interactive "p")
  190. (let ((mc/enclose-search-term 'words))
  191. (mc/mark-previous-like-this arg)))
  192. ;;;###autoload
  193. (defun mc/mark-previous-symbol-like-this (arg)
  194. (interactive "p")
  195. (let ((mc/enclose-search-term 'symbols))
  196. (mc/mark-previous-like-this arg)))
  197. (defun mc/mark-lines (num-lines direction)
  198. (dotimes (i (if (= num-lines 0) 1 num-lines))
  199. (mc/save-excursion
  200. (let ((furthest-cursor (cl-ecase direction
  201. (forwards (mc/furthest-cursor-after-point))
  202. (backwards (mc/furthest-cursor-before-point)))))
  203. (when (overlayp furthest-cursor)
  204. (goto-char (overlay-get furthest-cursor 'point))
  205. (when (= num-lines 0)
  206. (mc/remove-fake-cursor furthest-cursor))))
  207. (cl-ecase direction
  208. (forwards (next-logical-line 1 nil))
  209. (backwards (previous-logical-line 1 nil)))
  210. (mc/create-fake-cursor-at-point))))
  211. ;;;###autoload
  212. (defun mc/mark-next-lines (arg)
  213. (interactive "p")
  214. (mc/mark-lines arg 'forwards)
  215. (mc/maybe-multiple-cursors-mode))
  216. ;;;###autoload
  217. (defun mc/mark-previous-lines (arg)
  218. (interactive "p")
  219. (mc/mark-lines arg 'backwards)
  220. (mc/maybe-multiple-cursors-mode))
  221. ;;;###autoload
  222. (defun mc/unmark-next-like-this ()
  223. "Deselect next part of the buffer matching the currently active region."
  224. (interactive)
  225. (mc/mark-next-like-this -1))
  226. ;;;###autoload
  227. (defun mc/unmark-previous-like-this ()
  228. "Deselect prev part of the buffer matching the currently active region."
  229. (interactive)
  230. (mc/mark-previous-like-this -1))
  231. ;;;###autoload
  232. (defun mc/skip-to-next-like-this ()
  233. "Skip the current one and select the next part of the buffer matching the currently active region."
  234. (interactive)
  235. (mc/mark-next-like-this 0))
  236. ;;;###autoload
  237. (defun mc/skip-to-previous-like-this ()
  238. "Skip the current one and select the prev part of the buffer matching the currently active region."
  239. (interactive)
  240. (mc/mark-previous-like-this 0))
  241. ;;;###autoload
  242. (defun mc/mark-all-like-this ()
  243. "Find and mark all the parts of the buffer matching the currently active region"
  244. (interactive)
  245. (unless (region-active-p)
  246. (error "Mark a region to match first."))
  247. (mc/remove-fake-cursors)
  248. (let ((master (point))
  249. (case-fold-search nil)
  250. (point-first (< (point) (mark)))
  251. (re (regexp-opt (mc/region-strings) mc/enclose-search-term)))
  252. (mc/save-excursion
  253. (goto-char 0)
  254. (while (search-forward-regexp re nil t)
  255. (push-mark (match-beginning 0))
  256. (when point-first (exchange-point-and-mark))
  257. (unless (= master (point))
  258. (mc/create-fake-cursor-at-point))
  259. (when point-first (exchange-point-and-mark)))))
  260. (if (> (mc/num-cursors) 1)
  261. (multiple-cursors-mode 1)
  262. (multiple-cursors-mode 0)))
  263. (defun mc--select-thing-at-point (thing)
  264. (let ((bound (bounds-of-thing-at-point thing)))
  265. (when bound
  266. (set-mark (car bound))
  267. (goto-char (cdr bound))
  268. bound)))
  269. (defun mc--select-thing-at-point-or-bark (thing)
  270. (unless (or (region-active-p) (mc--select-thing-at-point thing))
  271. (error "Mark a region or set cursor on a %s." thing)))
  272. ;;;###autoload
  273. (defun mc/mark-all-words-like-this ()
  274. (interactive)
  275. (mc--select-thing-at-point-or-bark 'word)
  276. (let ((mc/enclose-search-term 'words))
  277. (mc/mark-all-like-this)))
  278. ;;;###autoload
  279. (defun mc/mark-all-symbols-like-this ()
  280. (interactive)
  281. (mc--select-thing-at-point-or-bark 'symbol)
  282. (let ((mc/enclose-search-term 'symbols))
  283. (mc/mark-all-like-this)))
  284. ;;;###autoload
  285. (defun mc/mark-all-in-region (beg end &optional search)
  286. "Find and mark all the parts in the region matching the given search"
  287. (interactive "r")
  288. (let ((search (or search (read-from-minibuffer "Mark all in region: ")))
  289. (case-fold-search nil))
  290. (if (string= search "")
  291. (message "Mark aborted")
  292. (progn
  293. (mc/remove-fake-cursors)
  294. (goto-char beg)
  295. (while (search-forward search end t)
  296. (push-mark (match-beginning 0))
  297. (mc/create-fake-cursor-at-point))
  298. (let ((first (mc/furthest-cursor-before-point)))
  299. (if (not first)
  300. (error "Search failed for %S" search)
  301. (mc/pop-state-from-overlay first)))
  302. (if (> (mc/num-cursors) 1)
  303. (multiple-cursors-mode 1)
  304. (multiple-cursors-mode 0))))))
  305. ;;;###autoload
  306. (defun mc/mark-all-in-region-regexp (beg end)
  307. "Find and mark all the parts in the region matching the given regexp."
  308. (interactive "r")
  309. (let ((search (read-regexp "Mark regexp in region: "))
  310. (case-fold-search nil))
  311. (if (string= search "")
  312. (message "Mark aborted")
  313. (progn
  314. (mc/remove-fake-cursors)
  315. (goto-char beg)
  316. (let ((lastmatch))
  317. (while (and (< (point) end) ; can happen because of (forward-char)
  318. (search-forward-regexp search end t))
  319. (push-mark (match-beginning 0))
  320. (mc/create-fake-cursor-at-point)
  321. (setq lastmatch (point))
  322. (when (= (point) (match-beginning 0))
  323. (forward-char)))
  324. (when lastmatch (goto-char lastmatch)))
  325. (when (> (mc/num-cursors) 0)
  326. (goto-char (match-end 0)))
  327. (let ((first (mc/furthest-cursor-before-point)))
  328. (if (not first)
  329. (error "Search failed for %S" search)
  330. (mc/pop-state-from-overlay first)))
  331. (if (> (mc/num-cursors) 1)
  332. (multiple-cursors-mode 1)
  333. (multiple-cursors-mode 0))))))
  334. (when (not (fboundp 'set-temporary-overlay-map))
  335. ;; Backport this function from newer emacs versions
  336. (defun set-temporary-overlay-map (map &optional keep-pred)
  337. "Set a new keymap that will only exist for a short period of time.
  338. The new keymap to use must be given in the MAP variable. When to
  339. remove the keymap depends on user input and KEEP-PRED:
  340. - if KEEP-PRED is nil (the default), the keymap disappears as
  341. soon as any key is pressed, whether or not the key is in MAP;
  342. - if KEEP-PRED is t, the keymap disappears as soon as a key *not*
  343. in MAP is pressed;
  344. - otherwise, KEEP-PRED must be a 0-arguments predicate that will
  345. decide if the keymap should be removed (if predicate returns
  346. nil) or kept (otherwise). The predicate will be called after
  347. each key sequence."
  348. (let* ((clearfunsym (make-symbol "clear-temporary-overlay-map"))
  349. (overlaysym (make-symbol "t"))
  350. (alist (list (cons overlaysym map)))
  351. (clearfun
  352. `(lambda ()
  353. (unless ,(cond ((null keep-pred) nil)
  354. ((eq t keep-pred)
  355. `(eq this-command
  356. (lookup-key ',map
  357. (this-command-keys-vector))))
  358. (t `(funcall ',keep-pred)))
  359. (remove-hook 'pre-command-hook ',clearfunsym)
  360. (setq emulation-mode-map-alists
  361. (delq ',alist emulation-mode-map-alists))))))
  362. (set overlaysym overlaysym)
  363. (fset clearfunsym clearfun)
  364. (add-hook 'pre-command-hook clearfunsym)
  365. (push alist emulation-mode-map-alists))))
  366. ;;;###autoload
  367. (defun mc/mark-more-like-this-extended ()
  368. "Like mark-more-like-this, but then lets you adjust with arrows key.
  369. The adjustments work like this:
  370. <up> Mark previous like this and set direction to 'up
  371. <down> Mark next like this and set direction to 'down
  372. If direction is 'up:
  373. <left> Skip past the cursor furthest up
  374. <right> Remove the cursor furthest up
  375. If direction is 'down:
  376. <left> Remove the cursor furthest down
  377. <right> Skip past the cursor furthest down
  378. The bindings for these commands can be changed. See `mc/mark-more-like-this-extended-keymap'."
  379. (interactive)
  380. (mc/mmlte--down)
  381. (set-temporary-overlay-map mc/mark-more-like-this-extended-keymap t))
  382. (defvar mc/mark-more-like-this-extended-direction nil
  383. "When using mc/mark-more-like-this-extended are we working on the next or previous cursors?")
  384. (make-variable-buffer-local 'mc/mark-more-like-this-extended)
  385. (defun mc/mmlte--message ()
  386. (if (eq mc/mark-more-like-this-extended-direction 'up)
  387. (message "<up> to mark previous, <left> to skip, <right> to remove, <down> to mark next")
  388. (message "<down> to mark next, <right> to skip, <left> to remove, <up> to mark previous")))
  389. (defun mc/mmlte--up ()
  390. (interactive)
  391. (mc/mark-previous-like-this 1)
  392. (setq mc/mark-more-like-this-extended-direction 'up)
  393. (mc/mmlte--message))
  394. (defun mc/mmlte--down ()
  395. (interactive)
  396. (mc/mark-next-like-this 1)
  397. (setq mc/mark-more-like-this-extended-direction 'down)
  398. (mc/mmlte--message))
  399. (defun mc/mmlte--left ()
  400. (interactive)
  401. (if (eq mc/mark-more-like-this-extended-direction 'down)
  402. (mc/unmark-next-like-this)
  403. (mc/skip-to-previous-like-this))
  404. (mc/mmlte--message))
  405. (defun mc/mmlte--right ()
  406. (interactive)
  407. (if (eq mc/mark-more-like-this-extended-direction 'up)
  408. (mc/unmark-previous-like-this)
  409. (mc/skip-to-next-like-this))
  410. (mc/mmlte--message))
  411. (defvar mc/mark-more-like-this-extended-keymap (make-sparse-keymap))
  412. (define-key mc/mark-more-like-this-extended-keymap (kbd "<up>") 'mc/mmlte--up)
  413. (define-key mc/mark-more-like-this-extended-keymap (kbd "<down>") 'mc/mmlte--down)
  414. (define-key mc/mark-more-like-this-extended-keymap (kbd "<left>") 'mc/mmlte--left)
  415. (define-key mc/mark-more-like-this-extended-keymap (kbd "<right>") 'mc/mmlte--right)
  416. (defvar mc--restrict-mark-all-to-symbols nil)
  417. ;;;###autoload
  418. (defun mc/mark-all-like-this-dwim (arg)
  419. "Tries to guess what you want to mark all of.
  420. Can be pressed multiple times to increase selection.
  421. With prefix, it behaves the same as original `mc/mark-all-like-this'"
  422. (interactive "P")
  423. (if arg
  424. (mc/mark-all-like-this)
  425. (if (and (not (use-region-p))
  426. (derived-mode-p 'sgml-mode)
  427. (mc--on-tag-name-p))
  428. (mc/mark-sgml-tag-pair)
  429. (let ((before (mc/num-cursors)))
  430. (unless (eq last-command 'mc/mark-all-like-this-dwim)
  431. (setq mc--restrict-mark-all-to-symbols nil))
  432. (unless (use-region-p)
  433. (mc--mark-symbol-at-point)
  434. (setq mc--restrict-mark-all-to-symbols t))
  435. (if mc--restrict-mark-all-to-symbols
  436. (mc/mark-all-symbols-like-this-in-defun)
  437. (mc/mark-all-like-this-in-defun))
  438. (when (<= (mc/num-cursors) before)
  439. (if mc--restrict-mark-all-to-symbols
  440. (mc/mark-all-symbols-like-this)
  441. (mc/mark-all-like-this)))
  442. (when (<= (mc/num-cursors) before)
  443. (mc/mark-all-like-this))))))
  444. ;;;###autoload
  445. (defun mc/mark-all-dwim (arg)
  446. "Tries even harder to guess what you want to mark all of.
  447. If the region is active and spans multiple lines, it will behave
  448. as if `mc/mark-all-in-region'. With the prefix ARG, it will call
  449. `mc/edit-lines' instead.
  450. If the region is inactive or on a single line, it will behave like
  451. `mc/mark-all-like-this-dwim'."
  452. (interactive "P")
  453. (if (and (use-region-p)
  454. (not (> (mc/num-cursors) 1))
  455. (not (= (line-number-at-pos (region-beginning))
  456. (line-number-at-pos (region-end)))))
  457. (if arg
  458. (call-interactively 'mc/edit-lines)
  459. (call-interactively 'mc/mark-all-in-region))
  460. (progn
  461. (setq this-command 'mc/mark-all-like-this-dwim)
  462. (mc/mark-all-like-this-dwim arg))))
  463. (defun mc--in-defun ()
  464. (bounds-of-thing-at-point 'defun))
  465. ;;;###autoload
  466. (defun mc/mark-all-like-this-in-defun ()
  467. "Mark all like this in defun."
  468. (interactive)
  469. (if (mc--in-defun)
  470. (save-restriction
  471. (widen)
  472. (narrow-to-defun)
  473. (mc/mark-all-like-this))
  474. (mc/mark-all-like-this)))
  475. ;;;###autoload
  476. (defun mc/mark-all-words-like-this-in-defun ()
  477. "Mark all words like this in defun."
  478. (interactive)
  479. (mc--select-thing-at-point-or-bark 'word)
  480. (if (mc--in-defun)
  481. (save-restriction
  482. (widen)
  483. (narrow-to-defun)
  484. (mc/mark-all-words-like-this))
  485. (mc/mark-all-words-like-this)))
  486. ;;;###autoload
  487. (defun mc/mark-all-symbols-like-this-in-defun ()
  488. "Mark all symbols like this in defun."
  489. (interactive)
  490. (mc--select-thing-at-point-or-bark 'symbol)
  491. (if (mc--in-defun)
  492. (save-restriction
  493. (widen)
  494. (narrow-to-defun)
  495. (mc/mark-all-symbols-like-this))
  496. (mc/mark-all-symbols-like-this)))
  497. (defun mc--mark-symbol-at-point ()
  498. "Select the symbol under cursor"
  499. (interactive)
  500. (when (not (use-region-p))
  501. (let ((b (bounds-of-thing-at-point 'symbol)))
  502. (goto-char (car b))
  503. (set-mark (cdr b)))))
  504. (defun mc--get-nice-sgml-context ()
  505. (car
  506. (last
  507. (progn
  508. (when (looking-at "<") (forward-char 1))
  509. (when (looking-back ">") (forward-char -1))
  510. (sgml-get-context)))))
  511. (defun mc--on-tag-name-p ()
  512. (let* ((context (save-excursion (mc--get-nice-sgml-context)))
  513. (tag-name-len (length (aref context 4)))
  514. (beg (aref context 2))
  515. (end (+ beg tag-name-len (if (eq 'open (aref context 1)) 1 3))))
  516. (and context
  517. (>= (point) beg)
  518. (<= (point) end))))
  519. ;;;###autoload
  520. (defun mc/toggle-cursor-on-click (event)
  521. "Add a cursor where you click, or remove a fake cursor that is
  522. already there."
  523. (interactive "e")
  524. (mouse-minibuffer-check event)
  525. ;; Use event-end in case called from mouse-drag-region.
  526. ;; If EVENT is a click, event-end and event-start give same value.
  527. (let ((position (event-end event)))
  528. (if (not (windowp (posn-window position)))
  529. (error "Position not in text area of window"))
  530. (select-window (posn-window position))
  531. (let ((pt (posn-point position)))
  532. (if (numberp pt)
  533. ;; is there a fake cursor with the actual *point* right where we are?
  534. (let ((existing (mc/fake-cursor-at-point pt)))
  535. (if existing
  536. (mc/remove-fake-cursor existing)
  537. (save-excursion
  538. (goto-char pt)
  539. (mc/create-fake-cursor-at-point))))))
  540. (mc/maybe-multiple-cursors-mode)))
  541. ;;;###autoload
  542. (defalias 'mc/add-cursor-on-click 'mc/toggle-cursor-on-click)
  543. ;;;###autoload
  544. (defun mc/mark-sgml-tag-pair ()
  545. "Mark the tag we're in and its pair for renaming."
  546. (interactive)
  547. (when (not (mc--inside-tag-p))
  548. (error "Place point inside tag to rename."))
  549. (let ((context (mc--get-nice-sgml-context)))
  550. (if (looking-at "</")
  551. (setq context (car (last (sgml-get-context)))))
  552. (goto-char (aref context 2))
  553. (let* ((tag-name (aref context 4))
  554. (num-chars (length tag-name))
  555. (master-start (1+ (point)))
  556. (mirror-end (save-excursion
  557. (sgml-skip-tag-forward 1)
  558. (1- (point)))))
  559. (goto-char (- mirror-end num-chars))
  560. (set-mark mirror-end)
  561. (mc/create-fake-cursor-at-point)
  562. (goto-char master-start)
  563. (set-mark (+ (point) num-chars))))
  564. (mc/maybe-multiple-cursors-mode))
  565. (defun mc--inside-tag-p ()
  566. (save-excursion
  567. (not (null (sgml-get-context)))))
  568. (provide 'mc-mark-more)
  569. ;;; mc-mark-more.el ends here