36 Commits

Author SHA1 Message Date
Magnar Sveen 47e03d54f4 Release 1.2.2 2013-08-11 20:51:37 +02:00
Magnar Sveen 39f17258b8 Add support for god-mode
@chrisdone
2013-08-11 20:51:09 +02:00
Magnar Sveen 66ceb0b0d4 Revert cursor specific pre- & post-command-hooks
- makes for problems with global post-command-hooks
 - doesn't really solve the problem they set out to do
2013-07-30 22:11:47 +02:00
Magnar Sveen 6cff0c2ebd Add pre- & post-command-hook to be cursor specific 2013-07-14 14:07:07 +02:00
Magnar Sveen 4c293c46fd Disable snapshot CI 2013-07-11 10:34:22 +02:00
Magnar Sveen 754de4e63b Backport set-temporary-overlay-map to emacs <24.3
Fixes #88
2013-07-11 09:14:06 +02:00
Magnar Sveen 1cb894d119 Add more mc-specific commands to the run-once list
#84
2013-06-08 10:31:49 +02:00
Magnar Sveen cc45842384 Improved mc/mark-more-like-this-extended
- support for terminal
 - more instructive message
 - keymap that can be rebound

Fixes #84
2013-06-07 23:18:19 +02:00
Magnar Sveen 94af07453d Add some readability enhancing step definitions 2013-06-07 08:03:05 +02:00
Magnar Sveen cb848b2a39 Add @smithzvk to contributors list
Closes #80
2013-05-27 05:52:38 +02:00
Magnar Sveen 474838666a Make mc/mark-pop only run once per invocation 2013-05-27 05:51:59 +02:00
Zach Kost-Smith 53db250b43 Added a mark-pop.feature file. 2013-05-26 16:08:21 -05:00
Zach Kost-Smith 75df47fc4a Added mention of mc/mark-pop to README.md 2013-05-26 16:07:27 -05:00
Zach Kost-Smith 4535033952 Added a new function mc/mark-pop that sets cursors by popping marks off the mark stack. 2013-05-26 14:34:58 -05:00
Magnar Sveen 69c99618f9 Use Carton for dev dependencies 2013-05-18 08:16:23 +02:00
Magnar Sveen 7a236d174e Add flyspell-mode to unsupported minor modes 2013-05-08 11:00:42 +02:00
Magnar Sveen 374244b66e Add support for C-s and C-r when phi-search is installed 2013-05-08 11:00:10 +02:00
Magnar Sveen 8b91e4788c Add py-electric-backspace to run-for-all list
- backspace = no in the prompt, causing people not to notice the prompt
2013-04-08 08:42:23 +02:00
Magnar Sveen bf0177205e Use phi-search for C-s in mc-mode when available. 2013-03-28 19:41:08 +01:00
Magnar Sveen 6e159238b2 Use uninterned symbols in macros to avoid surprising local vars 2013-03-21 10:17:50 +01:00
Magnar Sveen 9dac934bce Fix scrolling behavior in Emacs 24. 2013-03-21 10:09:41 +01:00
Magnar Sveen ccb42b5d70 Inline defun for better readability. 2013-03-15 20:21:34 +01:00
Magnar Sveen 8a53db8a39 Merge pull request #64 from tarsius/master
add .nosearch to directory with bundled libraries
2013-03-12 13:52:35 -07:00
Jonas Bernoulli 72ba43a08e add .nosearch to directory with bundled libraries
And move ert.el to that directory.
2013-03-12 21:40:43 +01:00
Magnar Sveen 16589a5af2 Update README.md 2013-03-10 07:58:04 +01:00
Magnar Sveen 980a8808dd Merge pull request #63 from tkf/select-thing-at-point
Automatically select word/symbol
2013-03-09 22:54:22 -08:00
Magnar Sveen ed18fa49c1 Merge pull request #62 from tkf/export-ECUKES_EMACS
Export $ECUKES_EMACS
2013-03-09 22:41:12 -08:00
Takafumi Arakaki 1cdd73037f Automatically select word/symbol 2013-03-10 06:53:53 +01:00
Takafumi Arakaki aa9a1ece7b Add failing scenarios for mark-all-symbols/words 2013-03-10 06:52:12 +01:00
Takafumi Arakaki 25dd14d350 Add more scenarios for mark-all-*-like-this 2013-03-10 06:49:25 +01:00
Takafumi Arakaki 373dcbe002 Add a scenario for mc/mark-all-symbols-like-this 2013-03-10 06:44:18 +01:00
Takafumi Arakaki d24ddc53ea Default ECUKES_EMACS to $EMACS
Otherwise, $EMACS set on .travis.yml is not used in test.
2013-03-10 06:17:30 +01:00
Takafumi Arakaki 5c60757080 export ECUKES_EMACS in run-travis-ci.sh 2013-03-10 06:12:07 +01:00
Magnar Sveen a6e0ccb22f mc/add-cursor-on-click should not run per cursor
Fixes #60
2013-02-26 21:38:26 +01:00
Magnar Sveen 0ee76bfad1 Add mc/add-cursor-on-click 2013-02-20 07:05:18 +01:00
Magnar Sveen e7a5fe61c4 Release 1.2.1 2013-02-11 07:32:09 +01:00
21 changed files with 599 additions and 3019 deletions
+1
View File
@@ -0,0 +1 @@
elpa
-6
View File
@@ -1,6 +0,0 @@
[submodule "util/ecukes"]
path = util/ecukes
url = git://github.com/rejeep/ecukes.git
[submodule "util/espuds"]
path = util/espuds
url = git://github.com/rejeep/espuds.git
+4 -3
View File
@@ -12,9 +12,10 @@ before_install:
sudo apt-get install -qq sudo apt-get install -qq
emacs24 emacs24-el emacs24-common-non-dfsg; emacs24 emacs24-el emacs24-common-non-dfsg;
fi fi
- curl -fsSkL https://raw.github.com/rejeep/carton/master/go | sh
- export PATH="/home/travis/.carton/bin:$PATH"
- carton
env: env:
- EMACS=emacs - EMACS=emacs24 TAGS=""
- EMACS=emacs24
- EMACS=emacs-snapshot
script: script:
./run-travis-ci.sh ./run-travis-ci.sh
+8
View File
@@ -0,0 +1,8 @@
(source "melpa" "http://melpa.milkbox.net/packages/")
(package-file "multiple-cursors.el")
(development
(depends-on "ecukes")
(depends-on "espuds")
(depends-on "wrap-region"))
+29 -4
View File
@@ -46,6 +46,16 @@ You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.co
- `mc/mark-previous-word-like-this`: Like `mc/mark-previous-like-this` but only for whole words. - `mc/mark-previous-word-like-this`: Like `mc/mark-previous-like-this` but only for whole words.
- `mc/mark-previous-symbol-like-this`: Like `mc/mark-previous-like-this` but only for whole symbols. - `mc/mark-previous-symbol-like-this`: Like `mc/mark-previous-like-this` but only for whole symbols.
- `mc/mark-more-like-this-extended`: Use arrow keys to quickly mark/skip next/previous occurances. - `mc/mark-more-like-this-extended`: Use arrow keys to quickly mark/skip next/previous occurances.
- `mc/add-cursor-on-click`: Bind to a mouse event to add cursors by clicking. See tips-section.
- `mc/pop-mark`: Set a cursor at the current point and move to the next (different) position on the mark stack. This allows for fine grained control over the placement of cursors.
### Juggle around with the current cursors
- `mc/unmark-next-like-this`: Remove the cursor furthest down in the buffer.
- `mc/unmark-previous-like-this`: Remove the cursor furthest up in the buffer.
- `mc/skip-to-next-like-this`: Remove the cursor furthest down, marking the next occurance down.
- `mc/skip-to-previous-like-this`: Remove the cursor furthest up, marking the next occurance up.
- `mc/mark-next-like-this-extended`: Temporarily bind the arrow keys to mark/unmark/skip cursors.
### Mark many occurrences ### Mark many occurrences
@@ -98,6 +108,18 @@ You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.co
BTW, I highly recommend adding `mc/mark-next-like-this` to a key binding that's BTW, I highly recommend adding `mc/mark-next-like-this` to a key binding that's
right next to the key for `er/expand-region`. right next to the key for `er/expand-region`.
### Binding mouse events
To override a mouse event, you will likely have to also unbind the
`down-mouse` part of the event. Like this:
(global-unset-key (kbd "M-<down-mouse-1>"))
(global-set-key (kbd "M-<mouse-1>") 'mc/add-cursor-on-click)
Or you can do like me and find an unused, but less convenient, binding:
(global-set-key (kbd "C-S-<mouse-1>") 'mc/add-cursor-on-click)
## Unknown commands ## Unknown commands
Multiple-cursors uses two lists of commands to know what to do: the run-once list Multiple-cursors uses two lists of commands to know what to do: the run-once list
@@ -130,21 +152,24 @@ You'll find the repo at:
https://github.com/magnars/multiple-cursors.el https://github.com/magnars/multiple-cursors.el
To fetch the test dependencies: To fetch the test dependencies, install
[carton](https://github.com/rejeep/carton) if you haven't already,
then:
$ cd /path/to/multiple-cursors $ cd /path/to/multiple-cursors
$ git submodule update --init $ carton
Run the tests with: Run the tests with:
$ ./util/ecukes/ecukes --graphical $ ./run-tests.sh
## Contributors ## Contributors
* [Takafumi Arakaki](https://github.com/tkf) made .mc-lists.el diff friendly * [Takafumi Arakaki](https://github.com/tkf) has contributed several small improvements
* [Marco Baringer](https://github.com/segv) contributed looping to mc/cycle and adding cursors without region for mark-more. * [Marco Baringer](https://github.com/segv) contributed looping to mc/cycle and adding cursors without region for mark-more.
* [Ivan Andrus](https://github.com/gvol) added showing number of cursors in mode-line * [Ivan Andrus](https://github.com/gvol) added showing number of cursors in mode-line
* [Fuco](https://github.com/Fuco1) added the first version of `mc/mark-all-like-this-dwim` * [Fuco](https://github.com/Fuco1) added the first version of `mc/mark-all-like-this-dwim`
* [Zach Kost-Smith](https://github.com/smithzvk) added `mc/mark-pop`
Thanks! Thanks!
+88
View File
@@ -0,0 +1,88 @@
Feature: Popping cursors off of the mark stack
Scenario: Single pop
Given I turn off transient-mark-mode
And I insert:
"""
hello
there
"""
And I go to the front of the word "hello"
And I set the mark
And I go to the front of the word "there"
And I press "M-x mc/mark-pop"
Then I should have 2 cursors
Scenario: Multiple pops
Given I turn off transient-mark-mode
And I insert:
"""
hello
there, my friend
"""
And I go to the front of the word "hello"
And I set the mark
And I go to the front of the word "my"
And I set the mark
And I go to the front of the word "friend"
And I press "M-x mc/mark-pop"
And I press "M-x mc/mark-pop"
Then I should have 3 cursors
Scenario: Discard identical mark and point
Given I turn off transient-mark-mode
And I insert:
"""
hello
there, my friend
"""
And I go to the front of the word "hello"
And I set the mark
And I go to the front of the word "my"
And I set the mark
And I go to the front of the word "friend"
And I set the mark
And I press "M-x mc/mark-pop"
And I press "M-x mc/mark-pop"
Then I should have 3 cursors
Scenario: Changing the text
Given I turn off transient-mark-mode
And I insert:
"""
hello
there, my friend
"""
And I go to the front of the word "hello"
And I set the mark
And I go to the front of the word "my"
And I set the mark
And I go to the front of the word "friend"
And I press "M-x mc/mark-pop"
And I press "M-x mc/mark-pop"
And I type "!"
Then I should see:
"""
!hello
there, !my !friend
"""
Scenario: With transient-mark-mode
And I insert:
"""
hello
there, my friend
"""
And I go to the front of the word "hello"
And I press "C-@ C-@"
And I go to the front of the word "my"
And I press "C-@ C-@"
And I go to the front of the word "friend"
And I press "M-x mc/mark-pop"
And I press "M-x mc/mark-pop"
And I type "!"
Then I should see:
"""
!hello
there, !my !friend
"""
+137
View File
@@ -0,0 +1,137 @@
Feature: Mark things
Scenario: Mark all symbols like this with select
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 select "ghi"
And I mark all symbols like this
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-ghi))
"""
Scenario: Mark all words like this with select
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 select "ghi"
And I mark all words like this
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-hmm))
"""
Scenario: Mark all symbols like this in defun with select
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 select "ghi"
And I mark all symbols like this in defun
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
Scenario: Mark all words like this in defun with select
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 select "ghi"
And I mark all words like this in defun
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
Scenario: Mark all symbols like this with no select
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 word "ghi"
And I mark all symbols like this
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-ghi))
"""
Scenario: Mark all words like this with no select
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 word "ghi"
And I mark all words like this
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-hmm))
"""
Scenario: Mark all symbols like this in defun with no select
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 word "ghi"
And I mark all symbols like this in defun
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
Scenario: Mark all words like this in defun with no select
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 word "ghi"
And I mark all words like this in defun
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
+2 -2
View File
@@ -115,7 +115,7 @@ Feature: Multiple cursors core
And I go to the front of the word "text" And I go to the front of the word "text"
And I press "C-SPC" And I press "C-SPC"
And I press "M-f" And I press "M-f"
And I press "C->" And I mark next like this
And I type "!" And I type "!"
Then I should see "This ! contains the word ! twice" Then I should see "This ! contains the word ! twice"
@@ -124,7 +124,7 @@ Feature: Multiple cursors core
And I insert "This text contains the word text twice" And I insert "This text contains the word text twice"
And I go to the front of the word "text" And I go to the front of the word "text"
And I press "C-M-SPC" And I press "C-M-SPC"
And I press "C->" And I mark next like this
And I press "C-g" And I press "C-g"
And I type "(" And I type "("
Then I should see "This (text contains the word (text twice" Then I should see "This (text contains the word (text twice"
@@ -1,7 +1,41 @@
(When "^I mark next like this$"
(lambda () (call-interactively 'mc/mark-next-like-this)))
(When "^I mark previous like this$"
(lambda () (call-interactively 'mc/mark-previous-like-this)))
(When "^I mark all like this$"
(lambda () (call-interactively 'mc/mark-all-like-this)))
(When "^I mark all like this dwim$"
(lambda () (call-interactively 'mc/mark-all-like-this-dwim)))
(When "^I mark all in region$"
(lambda () (call-interactively 'mc/mark-all-in-region)))
(When "^I insert numbers$"
(lambda () (call-interactively 'mc/insert-numbers)))
(When "^I reverse regions$"
(lambda () (call-interactively 'mc/reverse-regions)))
(When "^I sort regions$"
(lambda () (call-interactively 'mc/sort-regions)))
(When "^I edit lines$"
(lambda () (call-interactively 'mc/edit-lines)))
(When "^I set rectangular region anchor$"
(lambda () (call-interactively 'set-rectangular-region-anchor)))
(And "^delete-selection-mode is active$" (And "^delete-selection-mode is active$"
(lambda () (lambda ()
(delete-selection-mode 1))) (delete-selection-mode 1)))
(Given "^I turn off transient-mark-mode$"
(lambda ()
(transient-mark-mode -1)))
(Then "^I should have \\([0-9]+\\) cursors$" (Then "^I should have \\([0-9]+\\) cursors$"
(lambda (num) (lambda (num)
(let ((actual (mc/num-cursors))) (let ((actual (mc/num-cursors)))
@@ -95,3 +129,11 @@
(assert search nil "The text '%s' was not found in the current buffer." text)) (assert search nil "The text '%s' was not found in the current buffer." text))
(set-mark (point)) (set-mark (point))
(re-search-forward text))) (re-search-forward text)))
(When "^I mark all \\(.+\\)$"
(lambda (rest)
(let ((func (intern (mapconcat 'identity
(cons "mc/mark-all"
(split-string rest))
"-"))))
(call-interactively func))))
+145 -47
View File
@@ -191,17 +191,29 @@ With zero ARG, skip the last one and mark next."
(mc/maybe-multiple-cursors-mode)) (mc/maybe-multiple-cursors-mode))
;;;###autoload ;;;###autoload
(defun mc/unmark-next-like-this (arg) (defun mc/unmark-next-like-this ()
"Deselect next part of the buffer matching the currently active region." "Deselect next part of the buffer matching the currently active region."
(interactive) (interactive)
(mc/mark-next-like-this -1)) (mc/mark-next-like-this -1))
;;;###autoload ;;;###autoload
(defun mc/unmark-previous-like-this (arg) (defun mc/unmark-previous-like-this ()
"Deselect prev part of the buffer matching the currently active region." "Deselect prev part of the buffer matching the currently active region."
(interactive) (interactive)
(mc/mark-previous-like-this -1)) (mc/mark-previous-like-this -1))
;;;###autoload
(defun mc/skip-to-next-like-this ()
"Skip the current one and select the next part of the buffer matching the currently active region."
(interactive)
(mc/mark-next-like-this 0))
;;;###autoload
(defun mc/skip-to-previous-like-this ()
"Skip the current one and select the prev part of the buffer matching the currently active region."
(interactive)
(mc/mark-previous-like-this 0))
;;;###autoload ;;;###autoload
(defun mc/mark-all-like-this () (defun mc/mark-all-like-this ()
"Find and mark all the parts of the buffer matching the currently active region" "Find and mark all the parts of the buffer matching the currently active region"
@@ -225,15 +237,28 @@ With zero ARG, skip the last one and mark next."
(multiple-cursors-mode 1) (multiple-cursors-mode 1)
(multiple-cursors-mode 0))) (multiple-cursors-mode 0)))
(defun mc--select-thing-at-point (thing)
(let ((bound (bounds-of-thing-at-point thing)))
(when bound
(set-mark (car bound))
(goto-char (cdr bound))
bound)))
(defun mc--select-thing-at-point-or-bark (thing)
(unless (or (region-active-p) (mc--select-thing-at-point thing))
(error "Mark a region or set cursor on a %s." thing)))
;;;###autoload ;;;###autoload
(defun mc/mark-all-words-like-this () (defun mc/mark-all-words-like-this ()
(interactive) (interactive)
(mc--select-thing-at-point-or-bark 'word)
(let ((mc/enclose-search-term 'words)) (let ((mc/enclose-search-term 'words))
(mc/mark-all-like-this))) (mc/mark-all-like-this)))
;;;###autoload ;;;###autoload
(defun mc/mark-all-symbols-like-this () (defun mc/mark-all-symbols-like-this ()
(interactive) (interactive)
(mc--select-thing-at-point-or-bark 'symbol)
(let ((mc/enclose-search-term 'symbols)) (let ((mc/enclose-search-term 'symbols))
(mc/mark-all-like-this))) (mc/mark-all-like-this)))
@@ -256,52 +281,109 @@ With zero ARG, skip the last one and mark next."
(multiple-cursors-mode 1) (multiple-cursors-mode 1)
(multiple-cursors-mode 0))) (multiple-cursors-mode 0)))
(when (not (fboundp 'set-temporary-overlay-map))
;; Backport this function from newer emacs versions
(defun set-temporary-overlay-map (map &optional keep-pred)
"Set a new keymap that will only exist for a short period of time.
The new keymap to use must be given in the MAP variable. When to
remove the keymap depends on user input and KEEP-PRED:
- if KEEP-PRED is nil (the default), the keymap disappears as
soon as any key is pressed, whether or not the key is in MAP;
- if KEEP-PRED is t, the keymap disappears as soon as a key *not*
in MAP is pressed;
- otherwise, KEEP-PRED must be a 0-arguments predicate that will
decide if the keymap should be removed (if predicate returns
nil) or kept (otherwise). The predicate will be called after
each key sequence."
(let* ((clearfunsym (make-symbol "clear-temporary-overlay-map"))
(overlaysym (make-symbol "t"))
(alist (list (cons overlaysym map)))
(clearfun
`(lambda ()
(unless ,(cond ((null keep-pred) nil)
((eq t keep-pred)
`(eq this-command
(lookup-key ',map
(this-command-keys-vector))))
(t `(funcall ',keep-pred)))
(remove-hook 'pre-command-hook ',clearfunsym)
(setq emulation-mode-map-alists
(delq ',alist emulation-mode-map-alists))))))
(set overlaysym overlaysym)
(fset clearfunsym clearfun)
(add-hook 'pre-command-hook clearfunsym)
(push alist emulation-mode-map-alists))))
;;;###autoload ;;;###autoload
(defun mc/mark-more-like-this-extended () (defun mc/mark-more-like-this-extended ()
"Like mark-more-like-this, but then lets you adjust with arrows key. "Like mark-more-like-this, but then lets you adjust with arrows key.
The actual adjustment made depends on the final component of the The adjustments work like this:
key-binding used to invoke the command, with all modifiers removed:
<up> Mark previous like this <up> Mark previous like this and set direction to 'up
<down> Mark next like this <down> Mark next like this and set direction to 'down
<left> If last was previous, skip it
If last was next, remove it
<right> If last was next, skip it
If last was previous, remove it
Then, continue to read input events and further add or move marks If direction is 'up:
as long as the input event read (with all modifiers removed)
is one of the above." <left> Skip past the cursor furthest up
<right> Remove the cursor furthest up
If direction is 'down:
<left> Remove the cursor furthest down
<right> Skip past the cursor furthest down
The bindings for these commands can be changed. See `mc/mark-more-like-this-extended-keymap'."
(interactive) (interactive)
(let ((first t) (mc/mmlte--down)
(ev last-command-event) (set-temporary-overlay-map mc/mark-more-like-this-extended-keymap t))
(cmd 'mc/mark-next-like-this)
(arg 1) (defvar mc/mark-more-like-this-extended-direction nil
last echo-keystrokes) "When using mc/mark-more-like-this-extended are we working on the next or previous cursors?")
(while cmd
(let ((base (event-basic-type ev))) (make-variable-buffer-local 'mc/mark-more-like-this-extended)
(cond ((eq base 'left)
(if (eq last 'mc/mark-previous-like-this) (defun mc/mmlte--message ()
(setq cmd last arg 0) (if (eq mc/mark-more-like-this-extended-direction 'up)
(setq cmd 'mc/mark-next-like-this arg -1))) (message "<up> to mark previous, <left> to skip, <right> to remove, <down> to mark next")
((eq base 'up) (message "<down> to mark next, <right> to skip, <left> to remove, <up> to mark previous")))
(setq cmd 'mc/mark-previous-like-this arg 1))
((eq base 'right) (defun mc/mmlte--up ()
(if (eq last 'mc/mark-next-like-this) (interactive)
(setq cmd last arg 0) (mc/mark-previous-like-this 1)
(setq cmd 'mc/mark-previous-like-this arg -1))) (setq mc/mark-more-like-this-extended-direction 'up)
((eq base 'down) (mc/mmlte--message))
(setq cmd 'mc/mark-next-like-this arg 1))
(first (defun mc/mmlte--down ()
(setq cmd 'mc/mark-next-like-this arg 1)) (interactive)
(t (mc/mark-next-like-this 1)
(setq cmd nil)))) (setq mc/mark-more-like-this-extended-direction 'down)
(when cmd (mc/mmlte--message))
(ignore-errors
(funcall cmd arg)) (defun mc/mmlte--left ()
(setq first nil last cmd) (interactive)
(setq ev (read-event "Use arrow keys for more marks: ")))) (if (eq mc/mark-more-like-this-extended-direction 'down)
(push ev unread-command-events))) (mc/unmark-next-like-this)
(mc/skip-to-previous-like-this))
(mc/mmlte--message))
(defun mc/mmlte--right ()
(interactive)
(if (eq mc/mark-more-like-this-extended-direction 'up)
(mc/unmark-previous-like-this)
(mc/skip-to-next-like-this))
(mc/mmlte--message))
(defvar mc/mark-more-like-this-extended-keymap (make-sparse-keymap))
(define-key mc/mark-more-like-this-extended-keymap (kbd "<up>") 'mc/mmlte--up)
(define-key mc/mark-more-like-this-extended-keymap (kbd "<down>") 'mc/mmlte--down)
(define-key mc/mark-more-like-this-extended-keymap (kbd "<left>") 'mc/mmlte--left)
(define-key mc/mark-more-like-this-extended-keymap (kbd "<right>") 'mc/mmlte--right)
(defvar mc--restrict-mark-all-to-symbols nil) (defvar mc--restrict-mark-all-to-symbols nil)
@@ -314,7 +396,8 @@ 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)
(if (and (mc--no-region-and-in-sgmlish-mode) (if (and (not (use-region-p))
(derived-mode-p 'sgml-mode)
(mc--on-tag-name-p)) (mc--on-tag-name-p))
(mc/mark-sgml-tag-pair) (mc/mark-sgml-tag-pair)
(let ((before (mc/num-cursors))) (let ((before (mc/num-cursors)))
@@ -333,10 +416,6 @@ With prefix, it behaves the same as original `mc/mark-all-like-this'"
(when (<= (mc/num-cursors) before) (when (<= (mc/num-cursors) before)
(mc/mark-all-like-this)))))) (mc/mark-all-like-this))))))
(defun mc--no-region-and-in-sgmlish-mode ()
(and (not (use-region-p))
(derived-mode-p 'sgml-mode)))
(defun mc--in-defun () (defun mc--in-defun ()
(bounds-of-thing-at-point 'defun)) (bounds-of-thing-at-point 'defun))
@@ -355,6 +434,7 @@ With prefix, it behaves the same as original `mc/mark-all-like-this'"
(defun mc/mark-all-words-like-this-in-defun () (defun mc/mark-all-words-like-this-in-defun ()
"Mark all words like this in defun." "Mark all words like this in defun."
(interactive) (interactive)
(mc--select-thing-at-point-or-bark 'word)
(if (mc--in-defun) (if (mc--in-defun)
(save-restriction (save-restriction
(widen) (widen)
@@ -366,6 +446,7 @@ With prefix, it behaves the same as original `mc/mark-all-like-this'"
(defun mc/mark-all-symbols-like-this-in-defun () (defun mc/mark-all-symbols-like-this-in-defun ()
"Mark all symbols like this in defun." "Mark all symbols like this in defun."
(interactive) (interactive)
(mc--select-thing-at-point-or-bark 'symbol)
(if (mc--in-defun) (if (mc--in-defun)
(save-restriction (save-restriction
(widen) (widen)
@@ -398,6 +479,23 @@ With prefix, it behaves the same as original `mc/mark-all-like-this'"
(>= (point) beg) (>= (point) beg)
(<= (point) end)))) (<= (point) end))))
;;;###autoload
(defun mc/add-cursor-on-click (event)
"Add a cursor where you click."
(interactive "e")
(mouse-minibuffer-check event)
;; Use event-end in case called from mouse-drag-region.
;; If EVENT is a click, event-end and event-start give same value.
(let ((position (event-end event)))
(if (not (windowp (posn-window position)))
(error "Position not in text area of window"))
(select-window (posn-window position))
(if (numberp (posn-point position))
(save-excursion
(goto-char (posn-point position))
(mc/create-fake-cursor-at-point)))
(mc/maybe-multiple-cursors-mode)))
;;;###autoload ;;;###autoload
(defun mc/mark-sgml-tag-pair () (defun mc/mark-sgml-tag-pair ()
"Mark the tag we're in and its pair for renaming." "Mark the tag we're in and its pair for renaming."
+23
View File
@@ -0,0 +1,23 @@
;;; mc-mark-pop.el --- Pop cursors off of the mark stack
(require 'multiple-cursors-core)
;;;###autoload
(defun mc/mark-pop ()
"Add one cursor to each line of the active region.
Starts from mark and moves in straight down or up towards the
line point is on."
(interactive)
;; If the mark happens to be at the current point, just pop that one off.
(while (eql (mark) (point))
(pop-mark))
(mc/create-fake-cursor-at-point)
(exchange-point-and-mark)
(pop-mark)
(mc/maybe-multiple-cursors-mode))
;; A good key binding for this feature is perhaps "C-S-p" ('p' for pop).
(provide 'mc-mark-pop)
;;; mc-mark-pop.el ends here
+60 -44
View File
@@ -41,13 +41,14 @@
(defmacro mc/add-fake-cursor-to-undo-list (&rest forms) (defmacro mc/add-fake-cursor-to-undo-list (&rest forms)
"Make sure point is in the right place when undoing" "Make sure point is in the right place when undoing"
`(let ((undo-cleaner (cons 'apply (cons 'deactivate-cursor-after-undo (list id))))) (let ((uc (make-symbol "undo-cleaner")))
(setq buffer-undo-list (cons undo-cleaner buffer-undo-list)) `(let ((,uc (cons 'apply (cons 'deactivate-cursor-after-undo (list id)))))
(setq buffer-undo-list (cons ,uc buffer-undo-list))
,@forms ,@forms
(if (eq undo-cleaner (car buffer-undo-list)) ;; if nothing has been added to the undo-list (if (eq ,uc (car buffer-undo-list)) ;; if nothing has been added to the undo-list
(setq buffer-undo-list (cdr buffer-undo-list)) ;; then pop the cleaner right off again (setq buffer-undo-list (cdr buffer-undo-list)) ;; then pop the cleaner right off again
(setq buffer-undo-list ;; otherwise add a function to activate this cursor (setq buffer-undo-list ;; otherwise add a function to activate this cursor
(cons (cons 'apply (cons 'activate-cursor-for-undo (list id))) buffer-undo-list))))) (cons (cons 'apply (cons 'activate-cursor-for-undo (list id))) buffer-undo-list))))))
(defun mc/all-fake-cursors (&optional start end) (defun mc/all-fake-cursors (&optional start end)
(remove-if-not 'mc/fake-cursor-p (remove-if-not 'mc/fake-cursor-p
@@ -61,35 +62,40 @@
(defmacro mc/save-excursion (&rest forms) (defmacro mc/save-excursion (&rest forms)
"Saves and restores all the state that multiple-cursors cares about." "Saves and restores all the state that multiple-cursors cares about."
`(let ((current-state (mc/store-current-state-in-overlay (let ((cs (make-symbol "current-state")))
`(let ((,cs (mc/store-current-state-in-overlay
(make-overlay (point) (point) nil nil t)))) (make-overlay (point) (point) nil nil t))))
(overlay-put current-state 'type 'original-cursor) (overlay-put ,cs 'type 'original-cursor)
(save-excursion ,@forms) (save-excursion ,@forms)
(mc/pop-state-from-overlay current-state))) (mc/pop-state-from-overlay ,cs))))
(defun mc--compare-by-overlay-start (o1 o2) (defun mc--compare-by-overlay-start (o1 o2)
(< (overlay-start o1) (overlay-start o2))) (< (overlay-start o1) (overlay-start o2)))
(defmacro mc/for-each-cursor-ordered (&rest forms) (defmacro mc/for-each-cursor-ordered (&rest forms)
"Runs the body for each cursor, fake and real, bound to the name cursor" "Runs the body for each cursor, fake and real, bound to the name cursor"
`(let ((real-cursor-id (overlay-get (mc/create-fake-cursor-at-point) 'mc-id))) (let ((rci (make-symbol "real-cursor-id")))
`(let ((,rci (overlay-get (mc/create-fake-cursor-at-point) 'mc-id)))
(mapc #'(lambda (cursor) (mapc #'(lambda (cursor)
(when (mc/fake-cursor-p cursor) (when (mc/fake-cursor-p cursor)
,@forms)) ,@forms))
(sort (overlays-in (point-min) (point-max)) 'mc--compare-by-overlay-start)) (sort (overlays-in (point-min) (point-max)) 'mc--compare-by-overlay-start))
(mc/pop-state-from-overlay (mc/cursor-with-id real-cursor-id)))) (mc/pop-state-from-overlay (mc/cursor-with-id ,rci)))))
(defmacro mc/save-window-scroll (&rest forms) (defmacro mc/save-window-scroll (&rest forms)
"Saves and restores the window scroll position" "Saves and restores the window scroll position"
`(let ((p (set-marker (make-marker) (point))) (let ((p (make-symbol "p"))
(start (set-marker (make-marker) (window-start))) (s (make-symbol "start"))
(hscroll (window-hscroll))) (h (make-symbol "hscroll")))
`(let ((,p (set-marker (make-marker) (point)))
(,s (set-marker (make-marker) (window-start)))
(,h (window-hscroll)))
,@forms ,@forms
(goto-char p) (goto-char ,p)
(set-window-start nil start) (set-window-start nil ,s t)
(set-window-hscroll nil hscroll) (set-window-hscroll nil ,h)
(set-marker p nil) (set-marker ,p nil)
(set-marker start nil))) (set-marker ,s nil))))
(defun mc/make-cursor-overlay-at-eol (pos) (defun mc/make-cursor-overlay-at-eol (pos)
"Create overlay to look like cursor at end of line." "Create overlay to look like cursor at end of line."
@@ -118,22 +124,22 @@ highlights the entire width of the window."
(overlay-put overlay 'type 'additional-region) (overlay-put overlay 'type 'additional-region)
overlay)) overlay))
(defvar mc/cursor-specific-vars '(autopair-action (defvar mc/cursor-specific-vars '(transient-mark-mode
kill-ring
kill-ring-yank-pointer
mark-ring
mark-active
yank-undo-function
kill-ring-yank-pointer
autopair-action
autopair-wrap-action autopair-wrap-action
transient-mark-mode
er/history) er/history)
"A list of vars that need to be tracked on a per-cursor basis.") "A list of vars that need to be tracked on a per-cursor basis.")
(defun mc/store-current-state-in-overlay (o) (defun mc/store-current-state-in-overlay (o)
"Store relevant info about point and mark in the given overlay." "Store relevant info about point and mark in the given overlay."
(overlay-put o 'point (set-marker (make-marker) (point))) (overlay-put o 'point (set-marker (make-marker) (point)))
(overlay-put o 'kill-ring kill-ring)
(overlay-put o 'kill-ring-yank-pointer kill-ring-yank-pointer)
(overlay-put o 'mark (set-marker (make-marker) (mark))) (overlay-put o 'mark (set-marker (make-marker) (mark)))
(overlay-put o 'mark-ring mark-ring)
(overlay-put o 'mark-active mark-active)
(overlay-put o 'yank-undo-function yank-undo-function)
(overlay-put o 'kill-ring-yank-pointer kill-ring-yank-pointer)
(dolist (var mc/cursor-specific-vars) (dolist (var mc/cursor-specific-vars)
(when (boundp var) (overlay-put o var (symbol-value var)))) (when (boundp var) (overlay-put o var (symbol-value var))))
o) o)
@@ -141,13 +147,7 @@ highlights the entire width of the window."
(defun mc/restore-state-from-overlay (o) (defun mc/restore-state-from-overlay (o)
"Restore point and mark from stored info in the given overlay." "Restore point and mark from stored info in the given overlay."
(goto-char (overlay-get o 'point)) (goto-char (overlay-get o 'point))
(setq kill-ring (overlay-get o 'kill-ring))
(setq kill-ring-yank-pointer (overlay-get o 'kill-ring-yank-pointer))
(set-marker (mark-marker) (overlay-get o 'mark)) (set-marker (mark-marker) (overlay-get o 'mark))
(setq mark-ring (overlay-get o 'mark-ring))
(setq mark-active (overlay-get o 'mark-active))
(setq yank-undo-function (overlay-get o 'yank-undo-function))
(setq kill-ring-yank-pointer (overlay-get o 'kill-ring-yank-pointer))
(dolist (var mc/cursor-specific-vars) (dolist (var mc/cursor-specific-vars)
(when (boundp var) (set var (overlay-get o var))))) (when (boundp var) (set var (overlay-get o var)))))
@@ -306,8 +306,10 @@ been remapped. And certain modes (cua comes to mind) will change their
remapping based on state. So a command that changes the state will afterwards remapping based on state. So a command that changes the state will afterwards
not be recognized through the command-remapping lookup." not be recognized through the command-remapping lookup."
(unless mc--executing-command-for-fake-cursor (unless mc--executing-command-for-fake-cursor
(setq mc--this-command (or (command-remapping this-original-command) (let (cmd (or (command-remapping this-original-command)
this-original-command)))) this-original-command))
(setq mc--this-command (and (not (eq cmd 'god-mode-self-insert))
cmd)))))
(defun mc/execute-this-command-for-all-cursors () (defun mc/execute-this-command-for-all-cursors ()
"Wrap around `mc/execute-this-command-for-all-cursors-1' to protect hook." "Wrap around `mc/execute-this-command-for-all-cursors-1' to protect hook."
@@ -337,7 +339,6 @@ the original cursor, to inform about the lack of support."
(if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode (if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode
(multiple-cursors-mode 0) (multiple-cursors-mode 0)
(when this-original-command (when this-original-command
(let ((original-command (or mc--this-command (let ((original-command (or mc--this-command
(command-remapping this-original-command) (command-remapping this-original-command)
@@ -390,19 +391,22 @@ you should disable multiple-cursors-mode."
"Keymap while multiple cursors are active. "Keymap while multiple cursors are active.
Main goal of the keymap is to rebind C-g and <return> to conclude Main goal of the keymap is to rebind C-g and <return> to conclude
multiple cursors editing.") multiple cursors editing.")
(if mc/keymap (unless mc/keymap
nil
(setq mc/keymap (make-sparse-keymap)) (setq mc/keymap (make-sparse-keymap))
(define-key mc/keymap (kbd "C-g") 'mc/keyboard-quit) (define-key mc/keymap (kbd "C-g") 'mc/keyboard-quit)
(define-key mc/keymap (kbd "<return>") 'multiple-cursors-mode)) (define-key mc/keymap (kbd "<return>") 'multiple-cursors-mode)
(when (fboundp 'phi-search)
(define-key mc/keymap (kbd "C-s") 'phi-search))
(when (fboundp 'phi-search-backward)
(define-key mc/keymap (kbd "C-r") 'phi-search-backward)))
(defun mc--all-equal (entries) (defun mc--all-equal (list)
"Are all these entries equal?" "Are all the items in LIST equal?"
(let ((first (car entries)) (let ((first (car list))
(all-equal t)) (all-equal t))
(while (and all-equal entries) (while (and all-equal list)
(setq all-equal (equal first (car entries))) (setq all-equal (equal first (car list)))
(setq entries (cdr entries))) (setq list (cdr list)))
all-equal)) all-equal))
(defun mc--kill-ring-entries () (defun mc--kill-ring-entries ()
@@ -420,7 +424,7 @@ So you can paste it in later with `yank-rectangle'."
(unless (mc--all-equal entries) (unless (mc--all-equal entries)
(setq killed-rectangle entries)))) (setq killed-rectangle entries))))
(defvar mc/unsupported-minor-modes '(auto-complete-mode) (defvar mc/unsupported-minor-modes '(auto-complete-mode flyspell-mode)
"List of minor-modes that does not play well with multiple-cursors. "List of minor-modes that does not play well with multiple-cursors.
They are temporarily disabled when multiple-cursors are active.") They are temporarily disabled when multiple-cursors are active.")
@@ -575,6 +579,17 @@ for running commands with multiple cursors.")
mc/reverse-regions mc/reverse-regions
mc/cycle-forward mc/cycle-forward
mc/cycle-backward mc/cycle-backward
mc/add-cursor-on-click
mc/mark-pop
mc/add-cursors-to-all-matches
mc/mmlte--left
mc/mmlte--right
mc/mmlte--up
mc/mmlte--down
mc/unmark-next-like-this
mc/unmark-previous-like-this
mc/skip-to-next-like-this
mc/skip-to-previous-like-this
rrm/switch-to-multiple-cursors rrm/switch-to-multiple-cursors
save-buffer save-buffer
ido-exit-minibuffer ido-exit-minibuffer
@@ -660,6 +675,7 @@ for running commands with multiple cursors.")
backward-delete-char-untabify backward-delete-char-untabify
delete-char delete-forward-char delete-char delete-forward-char
delete-backward-char delete-backward-char
py-electric-backspace
c-electric-backspace c-electric-backspace
org-delete-backward-char org-delete-backward-char
paredit-backward-delete paredit-backward-delete
+17 -2
View File
@@ -1,8 +1,9 @@
;;; multiple-cursors.el --- An experiment in multiple cursors for emacs. ;;; multiple-cursors.el --- Multiple cursors for emacs.
;; Copyright (C) 2012 Magnar Sveen ;; Copyright (C) 2012-2013 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com> ;; Author: Magnar Sveen <magnars@gmail.com>
;; Version: 1.2.2
;; Keywords: editing cursors ;; Keywords: editing cursors
;; This program is free software; you can redistribute it and/or modify ;; This program is free software; you can redistribute it and/or modify
@@ -66,6 +67,7 @@
;; - `mc/mark-previous-word-like-this`: Like `mc/mark-previous-like-this` but only for whole words. ;; - `mc/mark-previous-word-like-this`: Like `mc/mark-previous-like-this` but only for whole words.
;; - `mc/mark-previous-symbol-like-this`: Like `mc/mark-previous-like-this` but only for whole symbols. ;; - `mc/mark-previous-symbol-like-this`: Like `mc/mark-previous-like-this` but only for whole symbols.
;; - `mc/mark-more-like-this-extended`: Use arrow keys to quickly mark/skip next/previous occurances. ;; - `mc/mark-more-like-this-extended`: Use arrow keys to quickly mark/skip next/previous occurances.
;; - `mc/add-cursor-on-click`: Bind to a mouse event to add cursors by clicking. See tips-section.
;; ### Mark many occurrences ;; ### Mark many occurrences
@@ -115,6 +117,18 @@
;; BTW, I highly recommend adding `mc/mark-next-like-this` to a key binding that's ;; BTW, I highly recommend adding `mc/mark-next-like-this` to a key binding that's
;; right next to the key for `er/expand-region`. ;; right next to the key for `er/expand-region`.
;; ### Binding mouse events
;; To override a mouse event, you will likely have to also unbind the
;; `down-mouse` part of the event. Like this:
;;
;; (global-unset-key (kbd "M-<down-mouse-1>"))
;; (global-set-key (kbd "M-<mouse-1>") 'mc/add-cursor-on-click)
;;
;; Or you can do like me and find an unused, but less convenient, binding:
;;
;; (global-set-key (kbd "C-S-<mouse-1>") 'mc/add-cursor-on-click)
;; ## Unknown commands ;; ## Unknown commands
;; Multiple-cursors uses two lists of commands to know what to do: the run-once list ;; Multiple-cursors uses two lists of commands to know what to do: the run-once list
@@ -168,6 +182,7 @@
(require 'mc-edit-lines) (require 'mc-edit-lines)
(require 'mc-cycle-cursors) (require 'mc-cycle-cursors)
(require 'mc-mark-more) (require 'mc-mark-more)
(require 'mc-mark-pop)
(require 'rectangular-region-mode) (require 'rectangular-region-mode)
(require 'mc-separate-operations) (require 'mc-separate-operations)
+4 -1
View File
@@ -67,6 +67,9 @@ an exceedingly quick way of adding multiple cursors to multiple lines."
(defun rrm/repaint () (defun rrm/repaint ()
"Start from the anchor and draw a rectangle between it and point." "Start from the anchor and draw a rectangle between it and point."
(if (not rectangular-region-mode)
(remove-hook 'post-command-hook 'rrm/repaint t)
;; else
(rrm/remove-rectangular-region-overlays) (rrm/remove-rectangular-region-overlays)
(let* ((annoying-arrows-mode nil) (let* ((annoying-arrows-mode nil)
(point-column (current-column)) (point-column (current-column))
@@ -87,7 +90,7 @@ an exceedingly quick way of adding multiple cursors to multiple lines."
(set-mark (point)) (set-mark (point))
(move-to-column point-column) (move-to-column point-column)
(when (= point-column (current-column)) (when (= point-column (current-column))
(mc/create-fake-cursor-at-point))))))) (mc/create-fake-cursor-at-point))))))))
(defun rrm/switch-to-multiple-cursors (&rest forms) (defun rrm/switch-to-multiple-cursors (&rest forms)
"Switch from rectangular-region-mode to multiple-cursors-mode." "Switch from rectangular-region-mode to multiple-cursors-mode."
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh -e
ECUKES=$(find elpa/ecukes-*/ecukes | tail -1)
carton exec "$ECUKES" "$@"
+3 -2
View File
@@ -2,11 +2,12 @@
cd "$(dirname "$0")" cd "$(dirname "$0")"
ECUKES_EMACS=${ECUKES_EMACS:-$(which emacs)} ECUKES_EMACS=${EMACS:-$(which emacs)}
export ECUKES_EMACS
echo "*** Emacs version ***" echo "*** Emacs version ***"
echo "ECUKES_EMACS = $ECUKES_EMACS" echo "ECUKES_EMACS = $ECUKES_EMACS"
"$ECUKES_EMACS" --version "$ECUKES_EMACS" --version
echo echo
exec ./util/ecukes/ecukes --graphical exec ./run-tests.sh $TAGS
Submodule util/ecukes deleted from b2c449cf01
-2544
View File
File diff suppressed because it is too large Load Diff
Submodule util/espuds deleted from 62ef75cb51
-329
View File
@@ -1,329 +0,0 @@
;;; wrap-region.el --- Wrap text with punctation or tag
;; Copyright (C) 2008-2012 Johan Andersson
;; Author: Johan Andersson <johan.rejeep@gmail.com>
;; Maintainer: Johan Andersson <johan.rejeep@gmail.com>
;; Version: 0.6.0
;; Keywords: speed, convenience
;; URL: http://github.com/rejeep/wrap-region
;; This file is NOT part of GNU Emacs.
;;; License:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; wrap-region is a minor mode that wraps a region with
;; punctuations. For tagged markup modes, such as HTML and XML, it
;; wraps with tags.
;;
;; To use wrap-region, make sure that this file is in Emacs load-path:
;; (add-to-list 'load-path "/path/to/directory/or/file")
;;
;; Then require wrap-region:
;; (require 'wrap-region)
;; To start wrap-region:
;; (wrap-region-mode t) or M-x wrap-region-mode
;;
;; If you only want wrap-region active in some mode, use hooks:
;; (add-hook 'ruby-mode-hook 'wrap-region-mode)
;;
;; Or if you want to activate it in all buffers, use the global mode:
;; (wrap-region-global-mode t)
;; To wrap a region, select that region and hit one of the punctuation
;; keys. In "tag-modes"" (see `wrap-region-tag-active-modes'), "<" is
;; replaced and wraps the region with a tag. To activate this behavior
;; in a mode that is not default:
;; (add-to-list 'wrap-region-tag-active-modes 'some-tag-mode)
;;
;; `wrap-region-table' contains the default punctuations
;; that wraps. You can add and remove new wrappers by using the
;; functions `wrap-region-add-wrapper' and
;; `wrap-region-remove-wrapper' respectively.
;; (wrap-region-add-wrapper "`" "'") ; hit ` then region -> `region'
;; (wrap-region-add-wrapper "/*" "*/" "/") ; hit / then region -> /*region*/
;; (wrap-region-add-wrapper "$" "$" nil 'latex-mode) ; hit $ then region -> $region$ in latex-mode
;; (wrap-region-remove-wrapper "(")
;; (wrap-region-remove-wrapper "$" 'latex-mode)
;;
;; Some modes may have conflicting key bindings with wrap-region. To
;; avoid conflicts, the list `wrap-region-except-modes' contains names
;; of modes where wrap-region should not be activated (note, only in
;; the global mode). You can add new modes like this:
;; (add-to-list 'wrap-region-except-modes 'conflicting-mode)
;;; Code:
(require 'edmacro)
(eval-when-compile
(require 'cl))
(defstruct wrap-region-wrapper key left right modes)
(defvar wrap-region-mode-map (make-sparse-keymap)
"Keymap for `wrap-region-mode'.")
(defvar wrap-region-table (make-hash-table :test 'equal)
"Table with wrapper pairs.")
(defvar wrap-region-tag-active-modes '(html-mode sgml-mode rhtml-mode nxml-mode nxhtml-mode)
"List of modes that uses tags.")
(defvar wrap-region-except-modes '(calc-mode dired-mode)
"A list of modes in which `wrap-region-mode' should not be activated.")
(defvar wrap-region-hook nil
"Called when `wrap-region-mode' is turned on.")
(defvar wrap-region-before-wrap-hook nil
"Called before wrapping.")
(defvar wrap-region-after-wrap-hook nil
"Called after wrapping.")
(defvar wrap-region-only-with-negative-prefix nil
"Only wrap if the trigger key is prefixed with a negative value.")
(defvar wrap-region-keep-mark nil
"Keep the wrapped region active.")
(defun wrap-region-trigger (arg key)
"Called when trigger key is pressed."
(let* ((wrapper (wrap-region-find key)))
(if (and wrapper
(region-active-p)
(if wrap-region-only-with-negative-prefix (< arg 0) t))
(if (wrap-region-insert-tag-p key)
(wrap-region-with-tag)
(wrap-region-with-punctuations
(wrap-region-wrapper-left wrapper)
(wrap-region-wrapper-right wrapper)))
(wrap-region-fallback key))))
(defun wrap-region-find (key)
"Find first wrapper with trigger KEY that should be active in MAJOR-MODE."
(let ((wrappers (gethash key wrap-region-table)))
(or
(find-if
(lambda (wrapper)
(member major-mode (wrap-region-wrapper-modes wrapper)))
wrappers)
(find-if
(lambda (wrapper)
(not (wrap-region-wrapper-modes wrapper)))
wrappers))))
(defun wrap-region-insert-tag-p (key)
"Check if tag should be inserted or not."
(and
(equal key "<")
(member major-mode wrap-region-tag-active-modes)))
(defun wrap-region-with-tag ()
"Wraps region with tag."
(let* ((tag (read-string "Enter Tag (with optional attributes): "))
(split (split-string tag " "))
(tag-name (car split))
(left (concat "<" tag ">"))
(right (concat "</" tag-name ">")))
(wrap-region-with left right)))
(defun wrap-region-with-punctuations (left right)
"Wraps region with LEFT and RIGHT punctuations."
(wrap-region-with left right))
(defun wrap-region-with (left right)
"Wraps region with LEFT and RIGHT."
(run-hooks 'wrap-region-before-wrap-hook)
(let ((beg (region-beginning))
(end (region-end))
(pos (point))
(deactivate-mark nil))
(save-excursion
(goto-char beg)
(insert left)
(goto-char (+ end (length left)))
(insert right))
(if wrap-region-keep-mark
(let* ((beg-p (eq beg pos))
(beg* (+ beg (length left)))
(end* (+ end (length left)))
(pos* (if beg-p beg* end*)))
(push-mark (if beg-p end* beg*) nil t)
(goto-char (if beg-p beg* end*)))
(deactivate-mark)))
(run-hooks 'wrap-region-after-wrap-hook))
(defun wrap-region-fallback (key)
"Execute function that KEY was bound to before `wrap-region-mode'."
(let ((wrap-region-mode nil))
(execute-kbd-macro
(edmacro-parse-keys key))))
(defun wrap-region-add-wrappers (wrappers)
"Add WRAPPERS by calling `wrap-region-add-wrapper' for each one."
(mapc
(lambda (wrapper)
(apply 'wrap-region-add-wrapper wrapper))
wrappers))
(defun wrap-region-add-wrapper (left right &optional key mode-or-modes)
"Add new LEFT and RIGHT wrapper.
Optional KEY is the trigger key and MODE-OR-MODES is a single
mode or multiple modes that the wrapper should trigger in."
(or key (setq key left))
(let ((wrappers (gethash key wrap-region-table))
(modes
(if mode-or-modes
(if (listp mode-or-modes)
mode-or-modes
(list mode-or-modes)))))
(if wrappers
(let ((wrapper-exactly-same
(find-if
(lambda (wrapper)
(and
(equal (wrap-region-wrapper-key wrapper) key)
(equal (wrap-region-wrapper-left wrapper) left)
(equal (wrap-region-wrapper-right wrapper) right)))
wrappers)))
(if wrapper-exactly-same
(when (wrap-region-wrapper-modes wrapper-exactly-same)
(if modes
(setf
(wrap-region-wrapper-modes wrapper-exactly-same)
(union modes (wrap-region-wrapper-modes wrapper-exactly-same)))
(let ((new-wrapper (make-wrap-region-wrapper :key key :left left :right right)))
(puthash key (cons new-wrapper wrappers) wrap-region-table))))
(let* ((new-wrapper (make-wrap-region-wrapper :key key :left left :right right :modes modes))
(wrapper-same-trigger
(find-if
(lambda (wrapper)
(equal (wrap-region-wrapper-key wrapper) key))
wrappers))
(wrapper-same-trigger-modes
(wrap-region-wrapper-modes wrapper-same-trigger)))
(when (and wrapper-same-trigger wrapper-same-trigger-modes)
(let ((new-modes (nset-difference (wrap-region-wrapper-modes wrapper-same-trigger) modes)))
(if new-modes
(setf (wrap-region-wrapper-modes wrapper-same-trigger) new-modes)
(setq wrappers (delete wrapper-same-trigger wrappers)))))
(puthash key (cons new-wrapper wrappers) wrap-region-table))))
(let ((new-wrapper (make-wrap-region-wrapper :key key :left left :right right :modes modes)))
(puthash key (list new-wrapper) wrap-region-table))))
(wrap-region-define-trigger key))
(defun wrap-region-remove-wrapper (key &optional mode-or-modes)
"Remove wrapper with trigger KEY or exclude from MODE-OR-MODES.
If MODE-OR-MODES is not present, all wrappers for KEY are removed."
(if mode-or-modes
(let ((wrappers (gethash key wrap-region-table))
(modes
(if mode-or-modes
(if (listp mode-or-modes)
mode-or-modes
(list mode-or-modes)))))
(mapc
(lambda (mode)
(let ((wrapper-including-mode
(find-if
(lambda (wrapper)
(member mode (wrap-region-wrapper-modes wrapper)))
wrappers)))
(when wrapper-including-mode
(let ((new-modes (delete mode (wrap-region-wrapper-modes wrapper-including-mode))))
(if new-modes
(setf (wrap-region-wrapper-modes wrapper-including-mode) new-modes)
(puthash key (delete wrapper-including-mode wrappers) wrap-region-table))))))
modes))
(wrap-region-destroy-wrapper key)))
(defun wrap-region-destroy-wrapper (key)
"Remove the wrapper bound to KEY, no questions asked."
(remhash key wrap-region-table)
(wrap-region-unset-key key))
(defun wrap-region-define-wrappers ()
"Defines defaults wrappers."
(mapc
(lambda (pair)
(apply 'wrap-region-add-wrapper pair))
'(("\"" "\"")
("'" "'")
("(" ")")
("{" "}")
("[" "]")
("<" ">"))))
(defun wrap-region-define-trigger (key)
"Defines KEY as wrapper."
(wrap-region-define-key
key
`(lambda (arg)
(interactive "p")
(wrap-region-trigger arg ,key))))
(defun wrap-region-unset-key (key)
"Remove KEY from `wrap-region-mode-map'."
(wrap-region-define-key key))
(defun wrap-region-define-key (key &optional fn)
"Binds KEY to FN in `wrap-region-mode-map'."
(define-key wrap-region-mode-map (read-kbd-macro key) fn))
;;;###autoload
(define-minor-mode wrap-region-mode
"Wrap region with stuff."
:init-value nil
:lighter " wr"
:keymap wrap-region-mode-map
(when wrap-region-mode
(wrap-region-define-wrappers)
(run-hooks 'wrap-region-hook)))
;;;###autoload
(defun turn-on-wrap-region-mode ()
"Turn on `wrap-region-mode'"
(interactive)
(unless (member major-mode wrap-region-except-modes)
(wrap-region-mode +1)))
;;;###autoload
(defun turn-off-wrap-region-mode ()
"Turn off `wrap-region-mode'."
(interactive)
(wrap-region-mode -1))
;;;###autoload
(define-globalized-minor-mode wrap-region-global-mode
wrap-region-mode
turn-on-wrap-region-mode)
(provide 'wrap-region)
;;; wrap-region.el ends here
+2 -2
View File
@@ -7,13 +7,13 @@ end
def run_all_tests def run_all_tests
system('clear') system('clear')
result = run "./util/ecukes/ecukes --graphical" result = run "./run-tests.sh"
puts result puts result
end end
def run_test(file) def run_test(file)
system('clear') system('clear')
result = run "./util/ecukes/ecukes --graphical #{file}" result = run "./run-tests.sh #{file} --verbose"
puts result puts result
end end