From f721308591d170e922fa5338f6f0e96053bda11d Mon Sep 17 00:00:00 2001 From: Magnar Sveen Date: Sun, 18 Nov 2012 14:43:39 +0100 Subject: [PATCH] Tweak mc/mark-all-like-this-dwim and add tests --- features/mark-all-dwim-html.feature | 94 ++++++++++++++++ features/mark-all-dwim.feature | 38 +++++++ features/support/env.el | 1 + mc-mark-more.el | 142 ++++++++++++++++++------- multiple-cursors-core.el | 5 + run-tests.watchr => watch-tests.watchr | 0 6 files changed, 241 insertions(+), 39 deletions(-) create mode 100644 features/mark-all-dwim-html.feature create mode 100644 features/mark-all-dwim.feature rename run-tests.watchr => watch-tests.watchr (100%) diff --git a/features/mark-all-dwim-html.feature b/features/mark-all-dwim-html.feature new file mode 100644 index 0000000..51866a8 --- /dev/null +++ b/features/mark-all-dwim-html.feature @@ -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: + """ + +
def
+
jkl
+ + """ + + 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: + """ + +

def

+
jkl
+ + """ + + 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: + """ + +
def
+

jkl

+ + """ + + 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: + """ + +

def

+
jkl
+ + """ + + 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: + """ + +
def
+

jkl

+ + """ + + 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: + """ + +
def
+
jkl
+ + """ + + 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: + """ + +
hah
+
jkl
+ + """ diff --git a/features/mark-all-dwim.feature b/features/mark-all-dwim.feature new file mode 100644 index 0000000..9eca714 --- /dev/null +++ b/features/mark-all-dwim.feature @@ -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)) + """ diff --git a/features/support/env.el b/features/support/env.el index 33fa6e7..53edb3b 100644 --- a/features/support/env.el +++ b/features/support/env.el @@ -23,6 +23,7 @@ (global-set-key (kbd "C->") 'mc/mark-next-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-dwim) (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 "H-SPC") 'set-rectangular-region-anchor) diff --git a/mc-mark-more.el b/mc-mark-more.el index 7a0f519..5270950 100644 --- a/mc-mark-more.el +++ b/mc-mark-more.el @@ -28,6 +28,7 @@ ;;; Code: (require 'multiple-cursors-core) +(require 'thingatpt) (defun mc/cursor-end (cursor) (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: ")))) (push ev unread-command-events))) -(defun mc/mark-all-like-this-dwim (arg) - "Uses some sane defaults to guess what the user want to do: +(defvar mc--restrict-mark-all-to-symbols nil) -- If inside a defun, find and mark all the parts of current defun matchign -the currently active region. If no region is active, activate the word -under cursor. -- If in SGML/HTML mode and inside a tag, select the tag and its pair +(defun mc/mark-all-like-this-dwim (arg) + "Tries to guess what you want to mark all of. +Can be pressed multiple times to increase selection. With prefix, it behaves the same as original `mc/mark-all-like-this'" (interactive "P") (if arg (mc/mark-all-like-this) - (let ((mode (with-current-buffer (current-buffer) major-mode))) - (cond ((and (member mode '(sgml-mode html-mode)) - (mc/mark-tags)) t) - ((bounds-of-thing-at-point 'defun) - (mc/select-under-cursor) - (save-restriction - (widen) - (narrow-to-defun) - (mc/mark-all-like-this))) - (t (mc/select-under-cursor) (mc/mark-all-like-this)))))) + (if (and (mc--no-region-and-in-sgmlish-mode) + (mc--on-tag-name-p)) + (mc/mark-sgml-tags) + (let ((before (mc/num-cursors))) + (unless (eq last-command 'mc/mark-all-like-this-dwim) + (setq mc--restrict-mark-all-to-symbols nil)) + (unless (use-region-p) + (mc--mark-symbol-at-point) + (setq mc--restrict-mark-all-to-symbols t)) + (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 () - "Select the word under cursor" +(defun mc--no-region-and-in-sgmlish-mode () + (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) (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)) (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." (interactive) - (let ((context (car (last (save-excursion (sgml-get-context)))))) - (when (and context - (> (point) (aref context 2)) - (< (point) (aref context 3))) - (let* ((tag-position (aref context 1)) - (tag-length (length (aref context 4))) - (main-start (- (aref context 3) 1 tag-length)) - (mirror-start (save-excursion - (if (eq tag-position 'open) - (sgml-skip-tag-forward 1) - (sgml-skip-tag-backward 1) - (forward-sexp)) - (- (point) 1 tag-length)))) - (goto-char main-start) - (set-mark (+ main-start tag-length)) - (mc/save-excursion (goto-char mirror-start) - (push-mark (+ mirror-start tag-length)) - (mc/create-fake-cursor-at-point)) - (mc/maybe-multiple-cursors-mode))))) + (when (not (mc--inside-tag-p)) + (error "Place point inside tag to rename.")) + (let ((context (mc--get-nice-sgml-context))) + (if (looking-at "