Tweak mc/mark-all-like-this-dwim and add tests

This commit is contained in:
Magnar Sveen 2012-11-18 14:43:39 +01:00
parent 1074c88c99
commit f721308591
6 changed files with 241 additions and 39 deletions

View File

@ -0,0 +1,94 @@
Feature: Mark all do-what-I-mean (html)
Background:
Given I turn on html-mode
And I turn on delete-selection-mode
And I insert:
"""
<body>
<div class="abc"> def </div>
<div class="ghi"> jkl </div>
</body>
"""
Scenario: Marks tags in html-mode, from front
When I go to the front of the word "abc"
And I press "M-b"
And I press "M-b"
And I press "M-$"
And I type "h1"
Then I should see:
"""
<body>
<h1 class="abc"> def </h1>
<div class="ghi"> jkl </div>
</body>
"""
Scenario: Marks tags in html-mode, from back
When I go to the end of the word "jkl"
And I press "M-f"
And I press "M-$"
And I type "h1"
Then I should see:
"""
<body>
<div class="abc"> def </div>
<h1 class="ghi"> jkl </h1>
</body>
"""
Scenario: Marks tags in html-mode, from outside front
When I go to the front of the word "abc"
And I press "M-b"
And I press "M-b"
And I press "C-b"
And I press "M-$"
And I type "h1"
Then I should see:
"""
<body>
<h1 class="abc"> def </h1>
<div class="ghi"> jkl </div>
</body>
"""
Scenario: Marks tags in html-mode, from outside back
When I go to the end of the word "jkl"
And I press "M-f"
And I press "C-f"
And I press "M-$"
And I type "h1"
Then I should see:
"""
<body>
<div class="abc"> def </div>
<h1 class="ghi"> jkl </h1>
</body>
"""
Scenario: Marks words in html-mode
When I go to the front of the word "abc"
And I press "M-$"
And I type "def"
Then I should see:
"""
<body>
<div class="def"> def </div>
<div class="ghi"> jkl </div>
</body>
"""
Scenario: Marks words in html-mode
When I go to the front of the word "abc"
And I press "M-$"
And I type "def"
And I press "M-$"
And I type "hah"
Then I should see:
"""
<body>
<div class="hah"> hah </div>
<div class="ghi"> jkl </div>
</body>
"""

View File

@ -0,0 +1,38 @@
Feature: Mark all do-what-I-mean
Scenario: Mark symbols in defun
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I go to the end of the word "abc"
And I press "M-f"
And I press "M-$"
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
Scenario: Mark all symbols by pressing twice
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message ghi))
"""
When I go to the end of the word "abc"
And I press "M-f"
And I press "M-$"
And I press "M-$"
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message hmm))
"""

View File

@ -23,6 +23,7 @@
(global-set-key (kbd "C->") 'mc/mark-next-like-this) (global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this) (global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "M-!") 'mc/mark-all-like-this) (global-set-key (kbd "M-!") 'mc/mark-all-like-this)
(global-set-key (kbd "M-$") 'mc/mark-all-like-this-dwim)
(global-set-key (kbd "M-#") 'mc/mark-all-in-region) (global-set-key (kbd "M-#") 'mc/mark-all-in-region)
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines) (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor) (global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor)

View File

@ -28,6 +28,7 @@
;;; Code: ;;; Code:
(require 'multiple-cursors-core) (require 'multiple-cursors-core)
(require 'thingatpt)
(defun mc/cursor-end (cursor) (defun mc/cursor-end (cursor)
(if (overlay-get cursor 'mark-active) (if (overlay-get cursor 'mark-active)
@ -308,59 +309,122 @@ is one of the above."
(setq ev (read-event "Use arrow keys for more marks: ")))) (setq ev (read-event "Use arrow keys for more marks: "))))
(push ev unread-command-events))) (push ev unread-command-events)))
(defun mc/mark-all-like-this-dwim (arg) (defvar mc--restrict-mark-all-to-symbols nil)
"Uses some sane defaults to guess what the user want to do:
- If inside a defun, find and mark all the parts of current defun matchign (defun mc/mark-all-like-this-dwim (arg)
the currently active region. If no region is active, activate the word "Tries to guess what you want to mark all of.
under cursor. Can be pressed multiple times to increase selection.
- If in SGML/HTML mode and inside a tag, select the tag and its pair
With prefix, it behaves the same as original `mc/mark-all-like-this'" With prefix, it behaves the same as original `mc/mark-all-like-this'"
(interactive "P") (interactive "P")
(if arg (if arg
(mc/mark-all-like-this) (mc/mark-all-like-this)
(let ((mode (with-current-buffer (current-buffer) major-mode))) (if (and (mc--no-region-and-in-sgmlish-mode)
(cond ((and (member mode '(sgml-mode html-mode)) (mc--on-tag-name-p))
(mc/mark-tags)) t) (mc/mark-sgml-tags)
((bounds-of-thing-at-point 'defun) (let ((before (mc/num-cursors)))
(mc/select-under-cursor) (unless (eq last-command 'mc/mark-all-like-this-dwim)
(save-restriction (setq mc--restrict-mark-all-to-symbols nil))
(widen) (unless (use-region-p)
(narrow-to-defun) (mc--mark-symbol-at-point)
(mc/mark-all-like-this))) (setq mc--restrict-mark-all-to-symbols t))
(t (mc/select-under-cursor) (mc/mark-all-like-this)))))) (if mc--restrict-mark-all-to-symbols
(mc/mark-all-symbols-like-this-in-defun)
(mc/mark-all-like-this-in-defun))
(when (<= (mc/num-cursors) before)
(if mc--restrict-mark-all-to-symbols
(mc/mark-all-symbols-like-this)
(mc/mark-all-like-this)))
(when (<= (mc/num-cursors) before)
(mc/mark-all-like-this))))))
(defun mc/select-under-cursor () (defun mc--no-region-and-in-sgmlish-mode ()
"Select the word under cursor" (and (not (use-region-p))
(memq major-mode '(sgml-mode html-mode))))
(defun mc--in-defun ()
(bounds-of-thing-at-point 'defun))
(defun mc/mark-all-like-this-in-defun ()
"Mark all like this in defun."
(interactive)
(if (mc--in-defun)
(save-restriction
(widen)
(narrow-to-defun)
(mc/mark-all-like-this))
(mc/mark-all-like-this)))
(defun mc/mark-all-words-like-this-in-defun ()
"Mark all words like this in defun."
(interactive)
(if (mc--in-defun)
(save-restriction
(widen)
(narrow-to-defun)
(mc/mark-all-words-like-this))
(mc/mark-all-words-like-this)))
(defun mc/mark-all-symbols-like-this-in-defun ()
"Mark all symbols like this in defun."
(interactive)
(if (mc--in-defun)
(save-restriction
(widen)
(narrow-to-defun)
(mc/mark-all-symbols-like-this))
(mc/mark-all-symbols-like-this)))
(defun mc--mark-symbol-at-point ()
"Select the symbol under cursor"
(interactive) (interactive)
(when (not (use-region-p)) (when (not (use-region-p))
(let ((b (bounds-of-thing-at-point 'word))) (let ((b (bounds-of-thing-at-point 'symbol)))
(goto-char (car b)) (goto-char (car b))
(set-mark (cdr b))))) (set-mark (cdr b)))))
(defun mc/mark-tags () (defun mc--get-nice-sgml-context ()
(car
(last
(progn
(when (looking-at "<") (forward-char 1))
(when (looking-back ">") (forward-char -1))
(sgml-get-context)))))
(defun mc--on-tag-name-p ()
(let* ((context (save-excursion (mc--get-nice-sgml-context)))
(tag-name-len (length (aref context 4)))
(beg (aref context 2))
(end (+ beg tag-name-len (if (eq 'open (aref context 1)) 1 3))))
(and context
(>= (point) beg)
(<= (point) end))))
(defun mc/mark-sgml-tags ()
"Mark the tag we're in and its pair for renaming." "Mark the tag we're in and its pair for renaming."
(interactive) (interactive)
(let ((context (car (last (save-excursion (sgml-get-context)))))) (when (not (mc--inside-tag-p))
(when (and context (error "Place point inside tag to rename."))
(> (point) (aref context 2)) (let ((context (mc--get-nice-sgml-context)))
(< (point) (aref context 3))) (if (looking-at "</")
(let* ((tag-position (aref context 1)) (setq context (car (last (sgml-get-context)))))
(tag-length (length (aref context 4))) (goto-char (aref context 2))
(main-start (- (aref context 3) 1 tag-length)) (let* ((tag-name (aref context 4))
(mirror-start (save-excursion (num-chars (length tag-name))
(if (eq tag-position 'open) (master-start (1+ (point)))
(sgml-skip-tag-forward 1) (mirror-end (save-excursion
(sgml-skip-tag-backward 1) (sgml-skip-tag-forward 1)
(forward-sexp)) (1- (point)))))
(- (point) 1 tag-length)))) (goto-char (- mirror-end num-chars))
(goto-char main-start) (set-mark mirror-end)
(set-mark (+ main-start tag-length)) (mc/create-fake-cursor-at-point)
(mc/save-excursion (goto-char mirror-start) (goto-char master-start)
(push-mark (+ mirror-start tag-length)) (set-mark (+ (point) num-chars))))
(mc/create-fake-cursor-at-point)) (mc/maybe-multiple-cursors-mode))
(mc/maybe-multiple-cursors-mode)))))
(defun mc--inside-tag-p ()
(save-excursion
(not (null (sgml-get-context)))))
(provide 'mc-mark-more) (provide 'mc-mark-more)

View File

@ -545,6 +545,11 @@ for running commands with multiple cursors.")
mc/mark-all-words-like-this mc/mark-all-words-like-this
mc/mark-all-symbols-like-this mc/mark-all-symbols-like-this
mc/mark-more-like-this-extended mc/mark-more-like-this-extended
mc/mark-all-like-this-in-defun
mc/mark-all-words-like-this-in-defun
mc/mark-all-symbols-like-this-in-defun
mc/mark-all-like-this-dwim
mc/mark-sgml-tags
mc/cycle-forward mc/cycle-forward
mc/cycle-backward mc/cycle-backward
rrm/switch-to-multiple-cursors rrm/switch-to-multiple-cursors