1 Commits

Author SHA1 Message Date
Magnar Sveen 23791339eb Release 1.2.1 2013-02-11 07:29:36 +01:00
35 changed files with 3163 additions and 1697 deletions
-3
View File
@@ -1,3 +0,0 @@
elpa
*.elc
/.ecukes-failing-scenarios
+6
View File
@@ -0,0 +1,6 @@
[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
+3 -4
View File
@@ -12,10 +12,9 @@ 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/cask/cask/master/go | python
- export PATH="/home/travis/.cask/bin:$PATH"
- cask
env: env:
- EMACS=emacs24 TAGS="" - EMACS=emacs
- EMACS=emacs24
- EMACS=emacs-snapshot
script: script:
./run-travis-ci.sh ./run-travis-ci.sh
-9
View File
@@ -1,9 +0,0 @@
(source gnu)
(source melpa)
(package-file "multiple-cursors.el")
(development
(depends-on "ecukes")
(depends-on "espuds")
(depends-on "wrap-region"))
+10 -77
View File
@@ -4,18 +4,6 @@ Multiple cursors for Emacs. This is some pretty crazy functionality, so yes,
there are kinks. Don't be afraid tho, I've been using it since 2011 with there are kinks. Don't be afraid tho, I've been using it since 2011 with
great success and much merriment. great success and much merriment.
## Installation
I highly recommend installing multiple-cursors through `package.el`.
It's available on [MELPA](http://melpa.org/) and [MELPA Stable](http://stable.melpa.org):
M-x package-install multiple-cursors
The package depends on the `cl-lib` package, so if you do not use
`package.el` or have a recent Emacs, you would need to install that
too: see [GNU ELPA](http://elpa.gnu.org/packages/cl-lib.html).
## Basic usage ## Basic usage
Start out with: Start out with:
@@ -43,10 +31,6 @@ To get out of multiple-cursors-mode, press `<return>` or `C-g`. The latter will
first disable multiple regions before disabling multiple cursors. If you want to first disable multiple regions before disabling multiple cursors. If you want to
insert a newline in multiple-cursors-mode, use `C-j`. insert a newline in multiple-cursors-mode, use `C-j`.
## Important note
Multiple cursors does not do well when you invoke its commands with `M-x`. It needs to be bound to keys to work properly. Pull request to fix this is welcome.
## Video ## Video
You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.com/e13.html). You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.com/e13.html).
@@ -56,25 +40,12 @@ You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.co
### Mark one more occurrence ### Mark one more occurrence
- `mc/mark-next-like-this`: Adds a cursor and region at the next part of the buffer forwards that matches the current region. - `mc/mark-next-like-this`: Adds a cursor and region at the next part of the buffer forwards that matches the current region.
- `mc/mark-next-like-this-word`: Adds a cursor and region at the next part of the buffer forwards that matches the current region, if no region is selected it selects the word at the point.
- `mc/mark-next-like-this-symbol`: Adds a cursor and region at the next part of the buffer forwards that matches the current region, if no region is selected it selects the symbol at the point.
- `mc/mark-next-word-like-this`: Like `mc/mark-next-like-this` but only for whole words. - `mc/mark-next-word-like-this`: Like `mc/mark-next-like-this` but only for whole words.
- `mc/mark-next-symbol-like-this`: Like `mc/mark-next-like-this` but only for whole symbols. - `mc/mark-next-symbol-like-this`: Like `mc/mark-next-like-this` but only for whole symbols.
- `mc/mark-previous-like-this`: Adds a cursor and region at the next part of the buffer backwards that matches the current region. - `mc/mark-previous-like-this`: Adds a cursor and region at the next part of the buffer backwards that matches the current region.
- `mc/mark-previous-like-this-word`: Adds a cursor and region at the next part of the buffer backwards that matches the current region, if no region is selected it selects the word at the point.
- `mc/mark-previous-like-this-symbol`: Adds a cursor and region at the next part of the buffer backwards that matches the current region, if no region is selected it selects the symbol at the point.
- `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/mark-pop`: 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.
### Mark many occurrences ### Mark many occurrences
@@ -88,14 +59,13 @@ You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.co
- `mc/mark-all-like-this-in-defun`: Marks all parts of the current defun that matches the current region. - `mc/mark-all-like-this-in-defun`: Marks all parts of the current defun that matches the current region.
- `mc/mark-all-words-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole words. - `mc/mark-all-words-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole words.
- `mc/mark-all-symbols-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole symbols. - `mc/mark-all-symbols-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole symbols.
- `mc/mark-all-dwim`: Tries to be smart about marking everything you want. Can be pressed multiple times. - `mc/mark-all-like-this-dwim`: Tries to be smart about marking everything you want. Can be pressed multiple times.
### Special ### Special
- `set-rectangular-region-anchor`: Think of this one as `set-mark` except you're marking a rectangular region. - `set-rectangular-region-anchor`: Think of this one as `set-mark` except you're marking a rectangular region.
- `mc/mark-sgml-tag-pair`: Mark the current opening and closing tag. - `mc/mark-sgml-tag-pair`: Mark the current opening and closing tag.
- `mc/insert-numbers`: Insert increasing numbers for each cursor, top to bottom. - `mc/insert-numbers`: Insert increasing numbers for each cursor, top to bottom.
- `mc/insert-letters`: Insert increasing letters for each cursor, top to bottom.
- `mc/sort-regions`: Sort the marked regions alphabetically. - `mc/sort-regions`: Sort the marked regions alphabetically.
- `mc/reverse-regions`: Reverse the order of the marked regions. - `mc/reverse-regions`: Reverse the order of the marked regions.
@@ -105,20 +75,12 @@ You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.co
first disable multiple regions before disabling multiple cursors. If you want to first disable multiple regions before disabling multiple cursors. If you want to
insert a newline in multiple-cursors-mode, use `C-j`. insert a newline in multiple-cursors-mode, use `C-j`.
- `(define-key mc/keymap (kbd "<return>") nil)` will make `<return>` insert a
newline; multiple-cursors-mode can still be disabled with `C-g`.
- Sometimes you end up with cursors outside of your view. You can - Sometimes you end up with cursors outside of your view. You can
scroll the screen to center on each cursor with `C-v` and `M-v` or you can scroll the screen to center on each cursor with `C-v` and `M-v`.
press `C-'` to hide all lines without a cursor, press `C-'` again to unhide.
- Try pressing `mc/mark-next-like-this` with no region selected. It - Try pressing `mc/mark-next-like-this` with no region selected. It
will just add a cursor on the next line. will just add a cursor on the next line.
- Try pressing `mc/mark-next-like-this-word` or
`mc/mark-next-like-this-symbol` with no region selected. It will
mark the word or symbol and add a cursor at the next occurance
- Try pressing `mc/mark-all-like-this-dwim` on a tagname in html-mode. - Try pressing `mc/mark-all-like-this-dwim` on a tagname in html-mode.
- Notice that the number of cursors active can be seen in the modeline. - Notice that the number of cursors active can be seen in the modeline.
@@ -130,27 +92,12 @@ You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.co
- You can use `mc/reverse-regions` with nothing selected and just one cursor. - You can use `mc/reverse-regions` with nothing selected and just one cursor.
It will then flip the sexp at point and the one below it. It will then flip the sexp at point and the one below it.
- When you use `mc/edit-lines`, you can give it a positive or negative
prefix to change how it behaves on too short lines.
- If you would like to keep the global bindings clean, and get custom keybindings - If you would like to keep the global bindings clean, and get custom keybindings
when the region is active, you can try [region-bindings-mode](https://github.com/fgallina/region-bindings-mode). when the region is active, you can try [region-bindings-mode](https://github.com/fgallina/region-bindings-mode).
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
@@ -163,17 +110,11 @@ the location with:
(setq mc/list-file "/my/preferred/file") (setq mc/list-file "/my/preferred/file")
NB! Make sure to do so before requiring multiple-cursors.
It is possible to set multiple-cursors to "run-for-all" for every
command except for those that are listed in `mc/cmds-to-run-once`. To
enable this set `mc/always-run-for-all` to non-nil. Add commands to be
run once to `mc/cmds-to-run-once` in ".mc-lists.el".
## Known limitations ## Known limitations
* isearch-forward and isearch-backward aren't supported with multiple cursors. * isearch-forward and isearch-backward aren't supported with multiple cursors.
If you want this functionality, you can use [phi-search](https://github.com/zk-phi/phi-search). You should feel free to add a simplified version that can work with it.
* Commands run with `M-x` won't be repeated for all cursors. * Commands run with `M-x` won't be repeated for all cursors.
* All key bindings that refer to lambdas are always run for all cursors. If you * All key bindings that refer to lambdas are always run for all cursors. If you
need to limit it, you will have to give it a name. need to limit it, you will have to give it a name.
@@ -189,35 +130,27 @@ 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, install To fetch the test dependencies:
[cask](https://github.com/rejeep/cask.el) if you haven't already,
then:
$ cd /path/to/multiple-cursors $ cd /path/to/multiple-cursors
$ cask $ git submodule update --init
Run the tests with: Run the tests with:
$ ./run-tests.sh $ ./util/ecukes/ecukes --graphical
## Contributors ## Contributors
* [Takafumi Arakaki](https://github.com/tkf) has contributed several small improvements * [Takafumi Arakaki](https://github.com/tkf) made .mc-lists.el diff friendly
* [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, and different options for how to handle short lines in `mc/edit-lines`. * [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`
* [Maciej Katafiasz](https://github.com/mathrick) added `mc/mark-all-dwim`
* [Aleksey Fedotov](https://github.com/lexa) added `mc-hide-unmatched-lines-mode`
* [Jules Tamagnan](https://github.com/jtamagnan) added `mc/mark-next-like-this-word` and `mc/mark-next-like-this-symbol`
* [Ingo Lohmar](https://github.com/ilohmar) extended `mc/add-cursor-on-click` to toggle cursors.
* [Andrea Orru](https://github.com/AndreaOrru) added `mc/mark-previous-like-this-word`/`-symbol`
Thanks! Thanks!
## License ## License
Copyright (C) 2012-2016 Magnar Sveen Copyright (C) 2012 Magnar Sveen
Author: Magnar Sveen <magnars@gmail.com> Author: Magnar Sveen <magnars@gmail.com>
Keywords: editing cursors Keywords: editing cursors
-83
View File
@@ -55,86 +55,3 @@ Feature: Switching from a multiline region to multiple cursors
And I go to the front of the word "there" And I go to the front of the word "there"
And I press "C-S-c C-S-c" And I press "C-S-c C-S-c"
Then I should have 2 cursors Then I should have 2 cursors
Scenario: Edit default short lines
When I insert:
"""
hello
there
"""
And I go to the end of the word "hello"
And I set the mark
And I go to the end of the word "there"
And I press "C-S-c C-S-c"
And I press "you"
Then I should see:
"""
helloyou
you
thereyou
"""
Scenario: Pad short lines
When I insert:
"""
hello
there
"""
And I go to the end of the word "hello"
And I set the mark
And I go to the end of the word "there"
And I press "M-1 C-S-c C-S-c"
Then I should have 3 cursors
Scenario: Edit padding short lines
When I insert:
"""
hello
there
"""
And I go to the end of the word "hello"
And I set the mark
And I go to the end of the word "there"
And I press "M-1 C-S-c C-S-c"
And I press "you"
Then I should see:
"""
helloyou
you
thereyou
"""
Scenario: Skip short lines
When I insert:
"""
hello
there
"""
And I go to the end of the word "hello"
And I set the mark
And I go to the end of the word "there"
And I press "M-- M-1 C-S-c C-S-c"
Then I should have 2 cursors
Scenario: Edit skipping short lines
When I insert:
"""
hello
there
"""
And I go to the end of the word "hello"
And I set the mark
And I go to the end of the word "there"
And I press "M-- M-1 C-S-c C-S-c"
And I press "you"
Then I should see:
"""
helloyou
thereyou
"""
-73
View File
@@ -1,73 +0,0 @@
Feature: Hiding lines without cursor
Scenario: Hiding lines when three cursor active
Given I have cursors at "line" in :
"""
0
line
2
3
line
5
6
7
8
9
10
11
line
13
14
15
"""
And I press "C-'"
Then I should have 3 cursors
Then I should see exactly:
"""
0
line
2
3
line
5
6
10
11
line
13
14
"""
Scenario: Hiding lines when only two cursor active
When I insert:
"""
1
2
3
4
5
text
6
7
8
9
10
"""
And I go to the front of the word "text"
And I press "C->"
And I press "C-'"
Then I should have 2 cursors
Then I should see exactly:
"""
4
5
text
6
7
8
"""
-25
View File
@@ -1,25 +0,0 @@
Feature: Insert increasing letters
Scenario: Three cursors, a-b-c
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I press "H-3"
And I press "SPC"
Then I should see "This a text contains the word b text thrice (c text)"
Scenario: Three cursors, j-k-l
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I press "C-9 H-3"
And I press "SPC"
Then I should see "This j text contains the word k text thrice (l text)"
Scenario: Three cursors, z-aa-ab
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I press "C-u 2 5 H-3"
And I press "SPC"
Then I should see "This z text contains the word aa text thrice (ab text)"
Scenario: Three cursors, a-b-c
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I press "C-u H-3"
And I press "SPC"
Then I should see "This e text contains the word f text thrice (g text)"
-27
View File
@@ -11,30 +11,3 @@ Feature: Insert increasing numbers
When I press "C-9 H-0" When I press "C-9 H-0"
And I press "SPC" And I press "SPC"
Then I should see "This 9 text contains the word 10 text thrice (11 text)" Then I should see "This 9 text contains the word 10 text thrice (11 text)"
Scenario: Three cursors, 9-10-11
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I press "C-u H-0"
And I press "SPC"
Then I should see "This 4 text contains the word 5 text thrice (6 text)"
Scenario: Three cursors, 0-1-2, default
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I set mc/insert-numbers-default to 1
And I press "H-0"
And I press "SPC"
Then I should see "This 1 text contains the word 2 text thrice (3 text)"
Scenario: Three cursors, 9-10-11, default
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I set mc/insert-numbers-default to 1
And I press "C-9 H-0"
And I press "SPC"
Then I should see "This 9 text contains the word 10 text thrice (11 text)"
Scenario: Three cursors, 9-10-11, default
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I set mc/insert-numbers-default to 1
And I press "C-u H-0"
And I press "SPC"
Then I should see "This 4 text contains the word 5 text thrice (6 text)"
+9 -61
View File
@@ -1,16 +1,13 @@
Feature: Mark all do-what-I-mean Feature: Mark all do-what-I-mean
Background: Scenario: Mark symbols in defun
Given I turn on emacs-lisp-mode Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode And I turn on delete-selection-mode
And I insert: And I insert:
""" """
(defun abc (ghi) (message ghi)) (defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi)) (defun def (ghi) (message some-other-ghi))
""" """
Scenario: Mark symbols in defun
When I go to the end of the word "abc" When I go to the end of the word "abc"
And I press "M-f" And I press "M-f"
And I press "M-$" And I press "M-$"
@@ -20,17 +17,15 @@ Feature: Mark all do-what-I-mean
(defun abc (hmm) (message hmm)) (defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi)) (defun def (ghi) (message some-other-ghi))
""" """
When I press "C-g"
And I go to the front of the word "hmm"
And I press "C-$"
And I type "foo"
Then I should see:
"""
(defun abc (foo) (message foo))
(defun def (ghi) (message some-other-ghi))
"""
Scenario: Mark all symbols by pressing twice 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" When I go to the end of the word "abc"
And I press "M-f" And I press "M-f"
And I press "M-$" And I press "M-$"
@@ -39,52 +34,5 @@ Feature: Mark all do-what-I-mean
Then I should see: Then I should see:
""" """
(defun abc (hmm) (message hmm)) (defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-hmm)) (defun def (hmm) (message hmm))
"""
When I press "C-g"
And I press "M->"
And I insert:
"""
(defun def (hmm-hmm) (message hmm))
"""
And I go to the front of the word "hmm"
And I press "C-$"
And I press "C-$"
And I type "humm"
Then I should see:
"""
(defun abc (humm) (message humm))
(defun def (humm) (message some-other-humm))
(defun def (humm-humm) (message humm))
"""
Scenario: Mark dwim from selection
When I press "M-<"
And I press "S-M->"
And I press "C-$ ghi RET"
And I type "xyz"
Then I should see:
"""
(defun abc (xyz) (message xyz))
(defun def (xyz) (message some-other-xyz))
"""
When I press "C-g"
And I go to the front of the word "xyz"
And I press "C-M-SPC"
And I press "C-$"
And I type "foo"
Then I should see:
"""
(defun abc (foo) (message foo))
(defun def (xyz) (message some-other-xyz))
"""
When I press "C-g"
And I press "M-<"
And I press "S-M->"
And I press "C-u C-$"
And I type ";;"
Then I should see:
"""
;;(defun abc (foo) (message foo))
;;(defun def (xyz) (message some-other-xyz))
""" """
-16
View File
@@ -14,14 +14,6 @@ Feature: Marking multiple parts of the buffer
And I type "sentence" And I type "sentence"
Then I should see "This sentence has the word sentence in it" Then I should see "This sentence has the word sentence in it"
Scenario: Marking next like this, word
Given I turn on delete-selection-mode
When I insert "This text has the word text in it"
And I go to word "text"
And I press "C-S-c C->"
And I type "sentence"
Then I should see "This sentence has the word sentence in it"
Scenario: Skipping a mark Scenario: Skipping a mark
Given I turn on delete-selection-mode Given I turn on delete-selection-mode
When I insert "Here's text, text and text" When I insert "Here's text, text and text"
@@ -62,14 +54,6 @@ Feature: Marking multiple parts of the buffer
And I type "sentence" And I type "sentence"
Then I should see "This sentence has the word sentence in it" Then I should see "This sentence has the word sentence in it"
Scenario: Marking prev like this, word
Given I turn on delete-selection-mode
When I insert "This text has the word text in it"
And I go to last word "text"
And I press "C-S-c C-<"
And I type "sentence"
Then I should see "This sentence has the word sentence in it"
Scenario: Skipping a prev mark Scenario: Skipping a prev mark
Given I turn on delete-selection-mode Given I turn on delete-selection-mode
When I insert "Here's text, text and text" When I insert "Here's text, text and text"
-88
View File
@@ -1,88 +0,0 @@
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
@@ -1,137 +0,0 @@
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 -16
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 mark next like this And I press "C->"
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 mark next like this And I press "C->"
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"
@@ -166,23 +166,9 @@ Feature: Multiple cursors core
And I press "C-v" And I press "C-v"
Then the cursor should be at point "8" Then the cursor should be at point "8"
Scenario: Looping forwards around cursors including one at point-max
Given I have cursors at "_" in "1_34_67_"
And I press "C-f"
And I press "C-v"
And I press "C-v"
And I press "C-v"
Then the cursor should be at point "3"
Scenario: Looping backwards around cursors Scenario: Looping backwards around cursors
Given I have cursors at "_" in "1_34567_9" Given I have cursors at "_" in "1_34567_9"
And I press "M-v" And I press "M-v"
And I press "M-v" And I press "M-v"
Then the cursor should be at point "2" Then the cursor should be at point "2"
Scenario: Looping backwards around cursors including one at point-min
Given I have cursors at "_" in "_234_67_9"
And I press "M-v"
And I press "M-v"
And I press "M-v"
Then the cursor should be at point "1"
-37
View File
@@ -1,37 +0,0 @@
Feature: Repeat last interactive command for fake cursors (mc/repeat-command)
Scenario: Clone insert-char from M-x
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I start an action chain
When I press "M-x"
And I type "insert-char"
And I press "RET"
And I type "21"
And I press "RET"
And I press "C-:"
And I press "y"
And I execute the action chain
Then I should see "This !text contains the word !text thrice (!text)"
Scenario: Clone insert-char from M-:
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I start an action chain
When I press "M-:"
And I type "(insert-char (+ 40 2))"
And I press "RET"
And I press "C-:"
And I press "y"
And I execute the action chain
Then I should see "This *text contains the word *text thrice (*text)"
Scenario: Disable prompt
Given I have cursors at "text" in "This text/0000 contains the word text/1111 thrice (text/2222)"
When I set mc/always-repeat-command to t
When I start an action chain
And I press "M-x"
And I type "zap-to-char"
And I press "RET"
And I press "/"
And I press "C-:"
And I execute the action chain
Then I should see "This 0000 contains the word 1111 thrice (2222)"
@@ -1,79 +1,28 @@
(require 'cl) ;; For lexical-let
(When "^I mark next like this$"
(lambda () (call-interactively 'mc/mark-next-like-this)))
(When "^I mark next like this word$"
(lambda () (call-interactively 'mc/mark-next-like-this-word)))
(When "^I mark next like this symbol$"
(lambda () (call-interactively 'mc/mark-next-like-this-symbol)))
(When "^I mark previous like this$"
(lambda () (call-interactively 'mc/mark-previous-like-this)))
(When "^I mark previous like this word$"
(lambda () (call-interactively 'mc/mark-previous-like-this-word)))
(When "^I mark previous like this symbol$"
(lambda () (call-interactively 'mc/mark-previous-like-this-symbol)))
(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 insert letters$"
(lambda () (call-interactively 'mc/insert-letters)))
(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)))
(cl-assert (eq (string-to-number num) actual) nil (assert (eq (string-to-number num) actual) nil
"Expected to have %s cursors, but was %d." num actual)))) "Expected to have %s cursors, but was %d." num actual))))
(Then "^I should have one cursor$" (Then "^I should have one cursor$"
(lambda () (lambda ()
(cl-assert (not multiple-cursors-mode) nil (assert (not multiple-cursors-mode) nil
"Expected to have one cursor, but multiple-cursors-mode is still active.") "Expected to have one cursor, but multiple-cursors-mode is still active.")
(cl-assert (eq 1 (mc/num-cursors)) nil (assert (eq 1 (mc/num-cursors)) nil
"Expected to have one cursor, but there are still fake cursor overlays."))) "Expected to have one cursor, but there are still fake cursor overlays.")))
(Then "^rectangular-region-mode should be off$" (Then "^rectangular-region-mode should be off$"
(lambda () (lambda ()
(cl-assert (not rectangular-region-mode) nil (assert (not rectangular-region-mode) nil
"Expected rectangular-region-mode mode to be off, but wasn't."))) "Expected rectangular-region-mode mode to be off, but wasn't.")))
(Then "^rectangular-region-mode should be on$" (Then "^rectangular-region-mode should be on$"
(lambda () (lambda ()
(cl-assert rectangular-region-mode nil (assert rectangular-region-mode nil
"Expected rectangular-region-mode mode to be on, but wasn't."))) "Expected rectangular-region-mode mode to be on, but wasn't.")))
(When "^I press \"\\(.+\\)\"$" (When "^I press \"\\(.+\\)\"$"
@@ -96,17 +45,6 @@
(mc/mark-all-like-this) (mc/mark-all-like-this)
(mc/keyboard-quit))) (mc/keyboard-quit)))
(Given "^I have cursors at \"\\(.+\\)\" in \\(?: \"\\(.+\\)\"\\|:\\)$"
(lambda (needle haystack)
(insert haystack)
(goto-char (point-min))
(search-forward needle)
(set-mark (point))
(goto-char (match-beginning 0))
(mc/mark-all-like-this)
(mc/keyboard-quit)))
(When "^I copy \"\\(.+\\)\" in another program$" (When "^I copy \"\\(.+\\)\" in another program$"
(lambda (text) (lambda (text)
(lexical-let ((text text)) (lexical-let ((text text))
@@ -140,55 +78,20 @@
(goto-char (point-min)) (goto-char (point-min))
(let ((search (re-search-forward (format "%s" char) nil t)) (let ((search (re-search-forward (format "%s" char) nil t))
(message "Can not go to character '%s' since it does not exist in the current buffer: %s")) (message "Can not go to character '%s' since it does not exist in the current buffer: %s"))
(cl-assert search nil message char (espuds-buffer-contents))))) (assert search nil message char (espuds-buffer-contents)))))
(When "^I go to the \\(front\\|end\\) of the word \"\\(.+\\)\"$" (When "^I go to the \\(front\\|end\\) of the word \"\\(.+\\)\"$"
(lambda (pos word) (lambda (pos word)
(goto-char (point-min)) (goto-char (point-min))
(let ((search (re-search-forward (format "%s" word) nil t)) (let ((search (re-search-forward (format "%s" word) nil t))
(message "Can not go to character '%s' since it does not exist in the current buffer: %s")) (message "Can not go to character '%s' since it does not exist in the current buffer: %s"))
(cl-assert search nil message word (espuds-buffer-contents)) (assert search nil message word (espuds-buffer-contents))
(if (string-equal "front" pos) (backward-word))))) (if (string-equal "front" pos) (backward-word)))))
(When "^I go to last word \"\\(.+\\)\"$"
(lambda (text)
(goto-char (point-max))
(let ((search (re-search-backward text nil t)))
(cl-assert search nil "The text '%s' was not found in the current buffer." text))))
(When "^I select the last \"\\(.+\\)\"$" (When "^I select the last \"\\(.+\\)\"$"
(lambda (text) (lambda (text)
(goto-char (point-max)) (goto-char (point-max))
(let ((search (re-search-backward text nil t))) (let ((search (re-search-backward text nil t)))
(cl-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))))
(Then "^I should see exactly\\(?: \"\\(.+\\)\"\\|:\\)$"
"Asserts that the current buffer does not include some text with
respect of text hidden by overlays"
(lambda (expected)
(let ((p (point-min))
(visible-text "")
(message "Expected '%s' to be part of '%s', but was not found in current buffer.")
)
(while (not (= p (point-max)))
(if (not (invisible-p p))
(setq visible-text (concat visible-text (buffer-substring p (1+ p))))
)
(setq p (1+ p))
)
(cl-assert (s-equals? expected visible-text) nil message expected visible-text))))
;; Local Variables:
;; byte-compile-warnings: (not cl-functions)
;; End:
-6
View File
@@ -21,17 +21,11 @@
(multiple-cursors-mode 0) (multiple-cursors-mode 0)
(rectangular-region-mode 0) (rectangular-region-mode 0)
(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-S-c C->") 'mc/mark-next-like-this-word)
(global-set-key (kbd "C-S-c M->") 'mc/mark-next-like-this-symbol)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this) (global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-S-c C-<") 'mc/mark-previous-like-this-word)
(global-set-key (kbd "C-S-c M-<") 'mc/mark-previous-like-this-symbol)
(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-like-this-dwim)
(global-set-key (kbd "C-$") 'mc/mark-all-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 "H-0") 'mc/insert-numbers) (global-set-key (kbd "H-0") 'mc/insert-numbers)
(global-set-key (kbd "H-3") 'mc/insert-letters)
(global-set-key (kbd "H-1") 'mc/reverse-regions) (global-set-key (kbd "H-1") 'mc/reverse-regions)
(global-set-key (kbd "H-2") 'mc/sort-regions) (global-set-key (kbd "H-2") 'mc/sort-regions)
(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)
-27
View File
@@ -1,27 +0,0 @@
Feature: Align cursors with whitespaces
Scenario: Vertical aligning with `x'
Given I have cursors at "word" in :
"""
One word
Another word
"""
And I press "<<mc/vertical-align>> \170"
Then I should see:
"""
One xxxxword
Another word
"""
Scenario: Vertical aligning with space
Given I have cursors at "word" in :
"""
One word
Another word
"""
And I press "<<mc/vertical-align-with-space>>"
Then I should see:
"""
One word
Another word
"""
+14 -11
View File
@@ -1,6 +1,6 @@
;;; mc-cycle-cursors.el ;;; mc-cycle-cursors.el
;; Copyright (C) 2012-2016 Magnar Sveen ;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com> ;; Author: Magnar Sveen <magnars@gmail.com>
;; Keywords: editing cursors ;; Keywords: editing cursors
@@ -28,9 +28,11 @@
(require 'multiple-cursors-core) (require 'multiple-cursors-core)
(eval-when-compile (require 'cl))
(defun mc/next-fake-cursor-after-point () (defun mc/next-fake-cursor-after-point ()
(let ((pos (point)) (let ((pos (point))
(next-pos (1+ (point-max))) (next-pos (point-max))
next) next)
(mc/for-each-fake-cursor (mc/for-each-fake-cursor
(let ((cursor-pos (overlay-get cursor 'point))) (let ((cursor-pos (overlay-get cursor 'point)))
@@ -42,7 +44,7 @@
(defun mc/prev-fake-cursor-before-point () (defun mc/prev-fake-cursor-before-point ()
(let ((pos (point)) (let ((pos (point))
(prev-pos (1- (point-min))) (prev-pos (point-min))
prev) prev)
(mc/for-each-fake-cursor (mc/for-each-fake-cursor
(let ((cursor-pos (overlay-get cursor 'point))) (let ((cursor-pos (overlay-get cursor 'point)))
@@ -61,7 +63,7 @@
:group 'multiple-cursors) :group 'multiple-cursors)
(defun mc/handle-loop-condition (error-message) (defun mc/handle-loop-condition (error-message)
(cl-ecase mc/cycle-looping-behaviour (ecase mc/cycle-looping-behaviour
(error (error error-message)) (error (error error-message))
(warn (message error-message)) (warn (message error-message))
(continue 'continue) (continue 'continue)
@@ -70,22 +72,22 @@
(defun mc/first-fake-cursor-after (point) (defun mc/first-fake-cursor-after (point)
"Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)." "Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)."
(let* ((cursors (mc/all-fake-cursors)) (let* ((cursors (mc/all-fake-cursors))
(cursors-after-point (cl-remove-if (lambda (cursor) (cursors-after-point (remove-if (lambda (cursor)
(< (mc/cursor-beg cursor) point)) (< (mc/cursor-beg cursor) point))
cursors)) cursors))
(cursors-in-order (cl-sort cursors-after-point '< :key 'mc/cursor-beg))) (cursors-in-order (sort* cursors-after-point '< :key 'mc/cursor-beg)))
(car cursors-in-order))) (first cursors-in-order)))
(defun mc/last-fake-cursor-before (point) (defun mc/last-fake-cursor-before (point)
"Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)." "Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)."
(let* ((cursors (mc/all-fake-cursors)) (let* ((cursors (mc/all-fake-cursors))
(cursors-before-point (cl-remove-if (lambda (cursor) (cursors-before-point (remove-if (lambda (cursor)
(> (mc/cursor-end cursor) point)) (> (mc/cursor-end cursor) point))
cursors)) cursors))
(cursors-in-order (cl-sort cursors-before-point '> :key 'mc/cursor-end))) (cursors-in-order (sort* cursors-before-point '> :key 'mc/cursor-end)))
(car cursors-in-order))) (first cursors-in-order)))
(cl-defun mc/cycle (next-cursor fallback-cursor loop-message) (defun* mc/cycle (next-cursor fallback-cursor loop-message)
(when (null next-cursor) (when (null next-cursor)
(when (eql 'stop (mc/handle-loop-condition loop-message)) (when (eql 'stop (mc/handle-loop-condition loop-message))
(return-from mc/cycle nil)) (return-from mc/cycle nil))
@@ -114,6 +116,7 @@
;; Local Variables: ;; Local Variables:
;; coding: utf-8 ;; coding: utf-8
;; byte-compile-warnings: (not cl-functions)
;; End: ;; End:
;;; mc-cycle-cursors.el ends here ;;; mc-cycle-cursors.el ends here
+9 -48
View File
@@ -1,6 +1,6 @@
;;; mc-edit-lines.el ;;; mc-edit-lines.el
;; Copyright (C) 2012-2016 Magnar Sveen ;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com> ;; Author: Magnar Sveen <magnars@gmail.com>
;; Keywords: editing cursors ;; Keywords: editing cursors
@@ -29,65 +29,26 @@
(require 'multiple-cursors-core) (require 'multiple-cursors-core)
(defcustom mc/edit-lines-empty-lines nil
"What should be done by `mc/edit-lines' when a line is not long enough."
:type '(radio (const :tag "Pad the line with spaces." pad)
(const :tag "Ignore the line." ignore)
(const :tag "Signal an error." error)
(const :tag "Nothing. Cursor is at end of line." nil))
:group 'multiple-cursors)
;;;###autoload ;;;###autoload
(defun mc/edit-lines (&optional arg) (defun mc/edit-lines ()
"Add one cursor to each line of the active region. "Add one cursor to each line of the active region.
Starts from mark and moves in straight down or up towards the Starts from mark and moves in straight down or up towards the
line point is on. line point is on."
(interactive)
What is done with lines which are not long enough is governed by
`mc/edit-lines-empty-lines'. The prefix argument ARG can be used
to override this. If ARG is a symbol (when called from Lisp),
that symbol is used instead of `mc/edit-lines-empty-lines'.
Otherwise, if ARG negative, short lines will be ignored. Any
other non-nil value will cause short lines to be padded."
(interactive "P")
(when (not (and mark-active (/= (point) (mark)))) (when (not (and mark-active (/= (point) (mark))))
(error "Mark a set of lines first")) (error "Mark a set of lines first."))
(mc/remove-fake-cursors) (mc/remove-fake-cursors)
(let* ((col (current-column)) (let* ((col (current-column))
(point-line (line-number-at-pos)) (point-line (line-number-at-pos))
(mark-line (progn (exchange-point-and-mark) (line-number-at-pos))) (mark-line (progn (exchange-point-and-mark) (line-number-at-pos)))
(direction (if (< point-line mark-line) :up :down)) (direction (if (< point-line mark-line) :up :down)))
(style (cond
;; called from lisp
((and arg (symbolp arg))
arg)
;; negative argument
((< (prefix-numeric-value arg) 0)
'ignore)
(arg 'pad)
(t mc/edit-lines-empty-lines))))
(deactivate-mark) (deactivate-mark)
(when (and (eq direction :up) (bolp)) (when (and (eq direction :up) (bolp))
(previous-logical-line 1 nil) (forward-line -1)
(move-to-column col)) (move-to-column col))
;; Add the cursors
(while (not (eq (line-number-at-pos) point-line)) (while (not (eq (line-number-at-pos) point-line))
;; Pad the line (mc/create-fake-cursor-at-point)
(when (eq style 'pad) (if (eq direction :up) (forward-line -1) (forward-line 1))
(while (< (current-column) col)
(insert " ")))
;; Error
(when (and (eq style 'error)
(not (equal col (current-column))))
(error "Short line encountered in `mc/edit-lines'"))
;; create the cursor
(unless (and (eq style 'ignore)
(not (equal col (current-column))))
(mc/create-fake-cursor-at-point))
;; proceed to next
(if (eq direction :up)
(previous-logical-line 1 nil)
(next-logical-line 1 nil))
(move-to-column col)) (move-to-column col))
(multiple-cursors-mode))) (multiple-cursors-mode)))
-107
View File
@@ -1,107 +0,0 @@
;;; mc-hide-unmatched-lines.el
;; Copyright (C) 2014 Aleksey Fedotov
;; Author: Aleksey Fedotov <lexa@cfotr.com>
;; Keywords: editing cursors
;; 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 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This minor mode when enabled hides all lines where no cursors (and
;; also hum/lines-to-expand below and above) To make use of this mode
;; press "C-'" while multiple-cursor-mode is active. You can still
;; edit lines while you are in mc-hide-unmatched-lines mode. To leave
;; this mode press "<return>" or "C-g"
;;
;;; Code:
(require 'multiple-cursors-core)
(require 'mc-mark-more)
(defvar hum/hide-unmatched-lines-mode-map (make-sparse-keymap)
"Keymap for hide unmatched lines is mainly for rebinding C-g")
(define-key hum/hide-unmatched-lines-mode-map (kbd "C-g") 'hum/keyboard-quit)
(define-key hum/hide-unmatched-lines-mode-map (kbd "<return>") 'hum/keyboard-quit)
(defun hum/keyboard-quit ()
"Leave hide-unmatched-lines mode"
(interactive)
(mc-hide-unmatched-lines-mode 0))
;; used only in in multiple-cursors-mode-disabled-hook
(defun hum/disable-hum-mode ()
(mc-hide-unmatched-lines-mode 0))
;;;###autoload
(define-minor-mode mc-hide-unmatched-lines-mode
"Minor mode when enabled hides all lines where no cursors (and
also hum/lines-to-expand below and above) To make use of this
mode press \"C-'\" while multiple-cursor-mode is active. You can
still edit lines while you are in mc-hide-unmatched-lines
mode. To leave this mode press <return> or \"C-g\""
nil " hu"
hum/hide-unmatched-lines-mode-map
(if mc-hide-unmatched-lines-mode
;;just in case if mc mode will be disabled while hide-unmatched-lines is active
(progn
(hum/hide-unmatched-lines)
(add-hook 'multiple-cursors-mode-disabled-hook 'hum/disable-hum-mode t t))
(progn
(hum/unhide-unmatched-lines)
(remove-hook 'multiple-cursors-mode-disabled-hook 'hum/disable-hum-mode))))
(defconst hum/invisible-overlay-name 'hum/invisible-overlay-name)
(defcustom hum/lines-to-expand 2
"How many lines below and above cursor to show"
:type '(integer)
:group 'multiple-cursors)
(defcustom hum/placeholder "..."
"Placeholder which will be placed insted of hiden text"
:type '(string)
:group 'multiple-cursors)
(defun hum/add-invisible-overlay (begin end)
(let ((overlay (make-overlay begin
end
(current-buffer)
t
nil
)))
(overlay-put overlay hum/invisible-overlay-name t)
(overlay-put overlay 'invisible t)
(overlay-put overlay 'intangible t)
(overlay-put overlay 'evaporate t)
(overlay-put overlay 'after-string hum/placeholder)))
(defun hum/hide-unmatched-lines ()
(let ((begin (point-min)))
(mc/for-each-cursor-ordered
(save-excursion
(goto-char (mc/cursor-beg cursor))
(if (< begin (line-beginning-position (- hum/lines-to-expand)))
(hum/add-invisible-overlay begin (line-end-position (- hum/lines-to-expand))))
(setq begin (line-beginning-position (+ 2 hum/lines-to-expand)))))
(hum/add-invisible-overlay begin (point-max))))
(defun hum/unhide-unmatched-lines ()
(remove-overlays nil nil hum/invisible-overlay-name t))
(provide 'mc-hide-unmatched-lines-mode)
(define-key mc/keymap (kbd "C-'") 'mc-hide-unmatched-lines-mode)
+73 -352
View File
@@ -1,6 +1,6 @@
;;; mc-mark-more.el ;;; mc-mark-more.el
;; Copyright (C) 2012-2016 Magnar Sveen ;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com> ;; Author: Magnar Sveen <magnars@gmail.com>
;; Keywords: editing cursors ;; Keywords: editing cursors
@@ -55,7 +55,7 @@
beg)) beg))
(defun mc/furthest-cursor-before-point () (defun mc/furthest-cursor-before-point ()
(let ((beg (if mark-active (min (mark) (point)) (point))) (let ((beg (min (mark) (point)))
furthest) furthest)
(mc/for-each-fake-cursor (mc/for-each-fake-cursor
(when (< (mc/cursor-beg cursor) beg) (when (< (mc/cursor-beg cursor) beg)
@@ -64,7 +64,7 @@
furthest)) furthest))
(defun mc/furthest-cursor-after-point () (defun mc/furthest-cursor-after-point ()
(let ((end (if mark-active (max (mark) (point)) (point))) (let ((end (max (mark) (point)))
furthest) furthest)
(mc/for-each-fake-cursor (mc/for-each-fake-cursor
(when (> (mc/cursor-end cursor) end) (when (> (mc/cursor-end cursor) end)
@@ -72,18 +72,6 @@
(setq furthest cursor))) (setq furthest cursor)))
furthest)) furthest))
(defun mc/fake-cursor-at-point (&optional point)
"Return the fake cursor with its point right at POINT (defaults
to (point)), or nil."
(setq point (or point (point)))
(let ((cursors (mc/all-fake-cursors))
(c nil))
(catch 'found
(while (setq c (pop cursors))
(when (eq (marker-position (overlay-get c 'point))
point)
(throw 'found c))))))
(defun mc/region-strings () (defun mc/region-strings ()
(let ((strings (list (buffer-substring-no-properties (point) (mark))))) (let ((strings (list (buffer-substring-no-properties (point) (mark)))))
(mc/for-each-fake-cursor (mc/for-each-fake-cursor
@@ -104,23 +92,21 @@ Use like case-fold-search, don't recommend setting it globally.")
(defun mc/mark-more-like-this (skip-last direction) (defun mc/mark-more-like-this (skip-last direction)
(let ((case-fold-search nil) (let ((case-fold-search nil)
(re (regexp-opt (mc/region-strings) mc/enclose-search-term)) (re (regexp-opt (mc/region-strings) mc/enclose-search-term))
(point-out-of-order (cl-ecase direction (point-out-of-order (ecase direction
(forwards (< (point) (mark))) (forwards (< (point) (mark)))
(backwards (not (< (point) (mark)))))) (backwards (not (< (point) (mark))))))
(furthest-cursor (cl-ecase direction (furthest-cursor (ecase direction
(forwards (mc/furthest-cursor-after-point)) (forwards (mc/furthest-cursor-after-point))
(backwards (mc/furthest-cursor-before-point)))) (backwards (mc/furthest-cursor-before-point))))
(start-char (cl-ecase direction (start-char (ecase direction
(forwards (mc/furthest-region-end)) (forwards (mc/furthest-region-end))
(backwards (mc/first-region-start)))) (backwards (mc/first-region-start))))
(search-function (cl-ecase direction (search-function (ecase direction
(forwards 'search-forward-regexp) (forwards 'search-forward-regexp)
(backwards 'search-backward-regexp))) (backwards 'search-backward-regexp)))
(match-point-getter (cl-ecase direction (match-point-getter (ecase direction
(forwards 'match-beginning) (forwards 'match-beginning)
(backwards 'match-end)))) (backwards 'match-end))))
(if (and skip-last (not furthest-cursor))
(error "No cursors to be skipped")
(mc/save-excursion (mc/save-excursion
(goto-char start-char) (goto-char start-char)
(when skip-last (when skip-last
@@ -131,79 +117,29 @@ Use like case-fold-search, don't recommend setting it globally.")
(when point-out-of-order (when point-out-of-order
(exchange-point-and-mark)) (exchange-point-and-mark))
(mc/create-fake-cursor-at-point)) (mc/create-fake-cursor-at-point))
(user-error "no more matches found.")))))) (error "no more matches found.")))))
;;;###autoload ;;;###autoload
(defun mc/mark-next-like-this (arg) (defun mc/mark-next-like-this (arg)
"Find and mark the next part of the buffer matching the currently active region "Find and mark the next part of the buffer matching the currently active region
If no region is active add a cursor on the next line
With negative ARG, delete the last one instead. With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next." With zero ARG, skip the last one and mark next."
(interactive "p") (interactive "p")
(if (< arg 0)
(let ((cursor (mc/furthest-cursor-after-point)))
(if cursor
(mc/remove-fake-cursor cursor)
(error "No cursors to be unmarked")))
(if (region-active-p) (if (region-active-p)
(mc/mark-more-like-this (= arg 0) 'forwards)
(mc/mark-lines arg 'forwards)))
(mc/maybe-multiple-cursors-mode))
;;;###autoload
(defun mc/mark-next-like-this-word (arg)
"Find and mark the next part of the buffer matching the currently active region
If no region is active, mark the word at the point and find the next match
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p")
(if (< arg 0) (if (< arg 0)
(let ((cursor (mc/furthest-cursor-after-point))) (mc/remove-fake-cursor (mc/furthest-cursor-after-point))
(if cursor (mc/mark-more-like-this (= arg 0) 'forwards))
(mc/remove-fake-cursor cursor) (mc/mark-lines arg 'forwards))
(error "No cursors to be unmarked")))
(if (region-active-p)
(mc/mark-more-like-this (= arg 0) 'forwards)
(mc--select-thing-at-point 'word)
(mc/mark-more-like-this (= arg 0) 'forwards)))
(mc/maybe-multiple-cursors-mode)) (mc/maybe-multiple-cursors-mode))
(defun mc/mark-next-like-this-symbol (arg)
"Find and mark the next part of the buffer matching the currently active region
If no region is active, mark the symbol at the point and find the next match
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p")
(if (< arg 0)
(let ((cursor (mc/furthest-cursor-after-point)))
(if cursor
(mc/remove-fake-cursor cursor)
(error "No cursors to be unmarked")))
(if (region-active-p)
(mc/mark-more-like-this (= arg 0) 'forwards)
(mc--select-thing-at-point 'symbol)
(mc/mark-more-like-this (= arg 0) 'forwards)))
(mc/maybe-multiple-cursors-mode))
;;;###autoload ;;;###autoload
(defun mc/mark-next-word-like-this (arg) (defun mc/mark-next-word-like-this (arg)
"Find and mark the next word of the buffer matching the currently active region
The matching region must be a whole word to be a match
If no region is active, mark the symbol at the point and find the next match
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p") (interactive "p")
(let ((mc/enclose-search-term 'words)) (let ((mc/enclose-search-term 'words))
(mc/mark-next-like-this arg))) (mc/mark-next-like-this arg)))
;;;###autoload ;;;###autoload
(defun mc/mark-next-symbol-like-this (arg) (defun mc/mark-next-symbol-like-this (arg)
"Find and mark the next symbol of the buffer matching the currently active region
The matching region must be a whole symbol to be a match
If no region is active, mark the symbol at the point and find the next match
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p") (interactive "p")
(let ((mc/enclose-search-term 'symbols)) (let ((mc/enclose-search-term 'symbols))
(mc/mark-next-like-this arg))) (mc/mark-next-like-this arg)))
@@ -211,92 +147,36 @@ With zero ARG, skip the last one and mark next."
;;;###autoload ;;;###autoload
(defun mc/mark-previous-like-this (arg) (defun mc/mark-previous-like-this (arg)
"Find and mark the previous part of the buffer matching the currently active region "Find and mark the previous part of the buffer matching the currently active region
If no region is active add a cursor on the previous line
With negative ARG, delete the last one instead. With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next." With zero ARG, skip the last one and mark next."
(interactive "p") (interactive "p")
(if (< arg 0)
(let ((cursor (mc/furthest-cursor-before-point)))
(if cursor
(mc/remove-fake-cursor cursor)
(error "No cursors to be unmarked")))
(if (region-active-p) (if (region-active-p)
(mc/mark-more-like-this (= arg 0) 'backwards)
(mc/mark-lines arg 'backwards)))
(mc/maybe-multiple-cursors-mode))
;;;###autoload
(defun mc/mark-previous-like-this-word (arg)
"Find and mark the previous part of the buffer matching the currently active region
If no region is active, mark the word at the point and find the previous match
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark previous."
(interactive "p")
(if (< arg 0) (if (< arg 0)
(let ((cursor (mc/furthest-cursor-after-point))) (mc/remove-fake-cursor (mc/furthest-cursor-before-point))
(if cursor (mc/mark-more-like-this (= arg 0) 'backwards))
(mc/remove-fake-cursor cursor) (mc/mark-lines arg 'backwards))
(error "No cursors to be unmarked")))
(if (region-active-p)
(mc/mark-more-like-this (= arg 0) 'backwards)
(mc--select-thing-at-point 'word)
(mc/mark-more-like-this (= arg 0) 'backwards)))
(mc/maybe-multiple-cursors-mode)) (mc/maybe-multiple-cursors-mode))
(defun mc/mark-previous-like-this-symbol (arg)
"Find and mark the previous part of the buffer matching the currently active region
If no region is active, mark the symbol at the point and find the previous match
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark previous."
(interactive "p")
(if (< arg 0)
(let ((cursor (mc/furthest-cursor-after-point)))
(if cursor
(mc/remove-fake-cursor cursor)
(error "No cursors to be unmarked")))
(if (region-active-p)
(mc/mark-more-like-this (= arg 0) 'backwards)
(mc--select-thing-at-point 'symbol)
(mc/mark-more-like-this (= arg 0) 'backwards)))
(mc/maybe-multiple-cursors-mode))
;;;###autoload ;;;###autoload
(defun mc/mark-previous-word-like-this (arg) (defun mc/mark-previous-word-like-this (arg)
"Find and mark the previous part of the buffer matching the currently active region
The matching region must be a whole word to be a match
If no region is active add a cursor on the previous line
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p") (interactive "p")
(let ((mc/enclose-search-term 'words)) (let ((mc/enclose-search-term 'words))
(mc/mark-previous-like-this arg))) (mc/mark-previous-like-this arg)))
;;;###autoload ;;;###autoload
(defun mc/mark-previous-symbol-like-this (arg) (defun mc/mark-previous-symbol-like-this (arg)
"Find and mark the previous part of the buffer matching the currently active region
The matching region must be a whole symbol to be a match
If no region is active add a cursor on the previous line
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p") (interactive "p")
(let ((mc/enclose-search-term 'symbols)) (let ((mc/enclose-search-term 'symbols))
(mc/mark-previous-like-this arg))) (mc/mark-previous-like-this arg)))
(defun mc/mark-lines (num-lines direction) (defun mc/mark-lines (num-lines direction)
(dotimes (i (if (= num-lines 0) 1 num-lines)) (dotimes (i num-lines)
(mc/save-excursion (mc/create-fake-cursor-at-point)
(let ((furthest-cursor (cl-ecase direction (ecase direction
(forwards (mc/furthest-cursor-after-point)) (forwards (loop do (next-line 1 nil)
(backwards (mc/furthest-cursor-before-point))))) while (mc/all-fake-cursors (point) (1+ (point)))))
(when (overlayp furthest-cursor) (backwards (loop do (previous-line 1 nil)
(goto-char (overlay-get furthest-cursor 'point)) while (mc/all-fake-cursors (point) (1+ (point))))))))
(when (= num-lines 0)
(mc/remove-fake-cursor furthest-cursor))))
(cl-ecase direction
(forwards (next-logical-line 1 nil))
(backwards (previous-logical-line 1 nil)))
(mc/create-fake-cursor-at-point))))
;;;###autoload ;;;###autoload
(defun mc/mark-next-lines (arg) (defun mc/mark-next-lines (arg)
@@ -311,29 +191,17 @@ 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 () (defun mc/unmark-next-like-this (arg)
"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 () (defun mc/unmark-previous-like-this (arg)
"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"
@@ -357,183 +225,83 @@ 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)))
;;;###autoload ;;;###autoload
(defun mc/mark-all-in-region (beg end &optional search) (defun mc/mark-all-in-region (beg end)
"Find and mark all the parts in the region matching the given search" "Find and mark all the parts in the region matching the given search"
(interactive "r") (interactive "r")
(let ((search (or search (read-from-minibuffer "Mark all in region: "))) (let ((search (read-from-minibuffer "Mark all in region: "))
(case-fold-search nil)) (case-fold-search nil))
(if (string= search "")
(message "Mark aborted")
(progn
(mc/remove-fake-cursors) (mc/remove-fake-cursors)
(goto-char beg) (goto-char beg)
(while (search-forward search end t) (while (search-forward search end t)
(push-mark (match-beginning 0)) (push-mark (match-beginning 0))
(mc/create-fake-cursor-at-point)) (mc/create-fake-cursor-at-point))
(let ((first (car (last (mc/all-fake-cursors))))) (let ((first (mc/furthest-cursor-before-point)))
(if (not first) (if (not first)
(error "Search failed for %S" search) (error "Search failed for %S" search)
(mc/pop-state-from-overlay first))) (mc/pop-state-from-overlay first))))
(if (> (mc/num-cursors) 1) (if (> (mc/num-cursors) 1)
(multiple-cursors-mode 1) (multiple-cursors-mode 1)
(multiple-cursors-mode 0)))))) (multiple-cursors-mode 0)))
;;;###autoload
(defun mc/mark-all-in-region-regexp (beg end)
"Find and mark all the parts in the region matching the given regexp."
(interactive "r")
(let ((search (read-regexp "Mark regexp in region: "))
(case-fold-search nil))
(if (string= search "")
(message "Mark aborted")
(progn
(mc/remove-fake-cursors)
(goto-char beg)
(let ((lastmatch))
(while (and (< (point) end) ; can happen because of (forward-char)
(search-forward-regexp search end t))
(push-mark (match-beginning 0))
(mc/create-fake-cursor-at-point)
(setq lastmatch (point))
(when (= (point) (match-beginning 0))
(forward-char)))
(unless lastmatch
(error "Search failed for %S" search)))
(goto-char (match-end 0))
(if (< (mc/num-cursors) 3)
(multiple-cursors-mode 0)
(mc/pop-state-from-overlay (mc/furthest-cursor-before-point))
(multiple-cursors-mode 1))))))
(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 adjustments work like this: The actual adjustment made depends on the final component of the
key-binding used to invoke the command, with all modifiers removed:
<up> Mark previous like this and set direction to 'up <up> Mark previous like this
<down> Mark next like this and set direction to 'down <down> Mark next like this
<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
If direction is 'up: Then, continue to read input events and further add or move marks
as long as the input event read (with all modifiers removed)
<left> Skip past the cursor furthest up is one of the above."
<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)
(mc/mmlte--down) (let ((first t)
(set-temporary-overlay-map mc/mark-more-like-this-extended-keymap t)) (ev last-command-event)
(cmd 'mc/mark-next-like-this)
(defvar mc/mark-more-like-this-extended-direction nil (arg 1)
"When using mc/mark-more-like-this-extended are we working on the next or previous cursors?") last echo-keystrokes)
(while cmd
(make-variable-buffer-local 'mc/mark-more-like-this-extended) (let ((base (event-basic-type ev)))
(cond ((eq base 'left)
(defun mc/mmlte--message () (if (eq last 'mc/mark-previous-like-this)
(if (eq mc/mark-more-like-this-extended-direction 'up) (setq cmd last arg 0)
(message "<up> to mark previous, <left> to skip, <right> to remove, <down> to mark next") (setq cmd 'mc/mark-next-like-this arg -1)))
(message "<down> to mark next, <right> to skip, <left> to remove, <up> to mark previous"))) ((eq base 'up)
(setq cmd 'mc/mark-previous-like-this arg 1))
(defun mc/mmlte--up () ((eq base 'right)
(interactive) (if (eq last 'mc/mark-next-like-this)
(mc/mark-previous-like-this 1) (setq cmd last arg 0)
(setq mc/mark-more-like-this-extended-direction 'up) (setq cmd 'mc/mark-previous-like-this arg -1)))
(mc/mmlte--message)) ((eq base 'down)
(setq cmd 'mc/mark-next-like-this arg 1))
(defun mc/mmlte--down () (first
(interactive) (setq cmd 'mc/mark-next-like-this arg 1))
(mc/mark-next-like-this 1) (t
(setq mc/mark-more-like-this-extended-direction 'down) (setq cmd nil))))
(mc/mmlte--message)) (when cmd
(ignore-errors
(defun mc/mmlte--left () (funcall cmd arg))
(interactive) (setq first nil last cmd)
(if (eq mc/mark-more-like-this-extended-direction 'down) (setq ev (read-event "Use arrow keys for more marks: "))))
(mc/unmark-next-like-this) (push ev unread-command-events)))
(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)
@@ -546,8 +314,7 @@ 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 (not (use-region-p)) (if (and (mc--no-region-and-in-sgmlish-mode)
(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)))
@@ -566,27 +333,9 @@ 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))))))
;;;###autoload (defun mc--no-region-and-in-sgmlish-mode ()
(defun mc/mark-all-dwim (arg) (and (not (use-region-p))
"Tries even harder to guess what you want to mark all of. (derived-mode-p 'sgml-mode)))
If the region is active and spans multiple lines, it will behave
as if `mc/mark-all-in-region'. With the prefix ARG, it will call
`mc/edit-lines' instead.
If the region is inactive or on a single line, it will behave like
`mc/mark-all-like-this-dwim'."
(interactive "P")
(if (and (use-region-p)
(not (> (mc/num-cursors) 1))
(not (= (line-number-at-pos (region-beginning))
(line-number-at-pos (region-end)))))
(if arg
(call-interactively 'mc/edit-lines)
(call-interactively 'mc/mark-all-in-region))
(progn
(setq this-command 'mc/mark-all-like-this-dwim)
(mc/mark-all-like-this-dwim arg))))
(defun mc--in-defun () (defun mc--in-defun ()
(bounds-of-thing-at-point 'defun)) (bounds-of-thing-at-point 'defun))
@@ -606,7 +355,6 @@ If the region is inactive or on a single line, it will behave like
(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)
@@ -618,7 +366,6 @@ If the region is inactive or on a single line, it will behave like
(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)
@@ -651,32 +398,6 @@ If the region is inactive or on a single line, it will behave like
(>= (point) beg) (>= (point) beg)
(<= (point) end)))) (<= (point) end))))
;;;###autoload
(defun mc/toggle-cursor-on-click (event)
"Add a cursor where you click, or remove a fake cursor that is
already there."
(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))
(let ((pt (posn-point position)))
(if (numberp pt)
;; is there a fake cursor with the actual *point* right where we are?
(let ((existing (mc/fake-cursor-at-point pt)))
(if existing
(mc/remove-fake-cursor existing)
(save-excursion
(goto-char pt)
(mc/create-fake-cursor-at-point))))))
(mc/maybe-multiple-cursors-mode)))
;;;###autoload
(defalias 'mc/add-cursor-on-click 'mc/toggle-cursor-on-click)
;;;###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."
-22
View File
@@ -1,22 +0,0 @@
;;; mc-mark-pop.el --- Pop cursors off of the mark stack
(require 'multiple-cursors-core)
;;;###autoload
(defun mc/mark-pop ()
"Add a cursor at the current point, pop off mark ring and jump
to the popped mark."
(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
+5 -65
View File
@@ -1,6 +1,6 @@
;;; mc-separate-operations.el - functions that work differently on each cursor ;;; mc-separate-operations.el - functions that work differently on each cursor
;; Copyright (C) 2012-2016 Magnar Sveen ;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com> ;; Author: Magnar Sveen <magnars@gmail.com>
;; Keywords: editing cursors ;; Keywords: editing cursors
@@ -29,24 +29,16 @@
(require 'multiple-cursors-core) (require 'multiple-cursors-core)
(defcustom mc/insert-numbers-default 0
"The default number at which to start counting for
`mc/insert-numbers'"
:type 'integer
:group 'multiple-cursors)
(defvar mc--insert-numbers-number 0)
;;;###autoload ;;;###autoload
(defun mc/insert-numbers (arg) (defun mc/insert-numbers (arg)
"Insert increasing numbers for each cursor, starting at "Insert increasing numbers for each cursor, starting at 0 or ARG."
`mc/insert-numbers-default' or ARG."
(interactive "P") (interactive "P")
(setq mc--insert-numbers-number (or (and arg (prefix-numeric-value arg)) (setq mc--insert-numbers-number (or arg 0))
mc/insert-numbers-default))
(mc/for-each-cursor-ordered (mc/for-each-cursor-ordered
(mc/execute-command-for-fake-cursor 'mc--insert-number-and-increase cursor))) (mc/execute-command-for-fake-cursor 'mc--insert-number-and-increase cursor)))
(defvar mc--insert-numbers-number 0)
(defun mc--insert-number-and-increase () (defun mc--insert-number-and-increase ()
(interactive) (interactive)
(insert (number-to-string mc--insert-numbers-number)) (insert (number-to-string mc--insert-numbers-number))
@@ -61,32 +53,6 @@
(mc/cursor-end cursor)) strings)))) (mc/cursor-end cursor)) strings))))
(nreverse strings))) (nreverse strings)))
(defvar mc--insert-letters-number 0)
;;;###autoload
(defun mc/insert-letters (arg)
"Insert increasing letters for each cursor, starting at 0 or ARG.
Where letter[0]=a letter[2]=c letter[26]=aa"
(interactive "P")
(setq mc--insert-letters-number (or (and arg (prefix-numeric-value arg))
0))
(mc/for-each-cursor-ordered
(mc/execute-command-for-fake-cursor 'mc--insert-letter-and-increase cursor)))
(defun mc--number-to-letters (number)
(let ((letter
(char-to-string
(+ (mod number 26) ?a)))
(number2 (/ number 26)))
(if (> number2 0)
(concat (mc--number-to-letters (- number2 1)) letter)
letter)))
(defun mc--insert-letter-and-increase ()
(interactive)
(insert (mc--number-to-letters mc--insert-letters-number))
(setq mc--insert-letters-number (1+ mc--insert-letters-number)))
(defvar mc--strings-to-replace nil) (defvar mc--strings-to-replace nil)
(defun mc--replace-region-strings-1 () (defun mc--replace-region-strings-1 ()
@@ -120,31 +86,5 @@
(setq mc--strings-to-replace (sort (mc--ordered-region-strings) 'string<)) (setq mc--strings-to-replace (sort (mc--ordered-region-strings) 'string<))
(mc--replace-region-strings)) (mc--replace-region-strings))
;;;###autoload
(defun mc/vertical-align (character)
"Aligns all cursors vertically with a given CHARACTER to the one with the
highest colum number (the rightest).
Might not behave as intended if more than one cursors are on the same line."
(interactive "c")
(let ((rightest-column (current-column)))
(mc/execute-command-for-all-cursors
(lambda () "get the rightest cursor"
(interactive)
(setq rightest-column (max (current-column) rightest-column))
))
(mc/execute-command-for-all-cursors
(lambda ()
(interactive)
(let ((missing-spaces (- rightest-column (current-column))))
(save-excursion (insert (make-string missing-spaces character)))
(forward-char missing-spaces))))))
;;;###autoload
(defun mc/vertical-align-with-space ()
"Aligns all cursors with whitespace like `mc/vertical-align' does"
(interactive)
(mc/vertical-align 32))
(provide 'mc-separate-operations) (provide 'mc-separate-operations)
;;; mc-separate-operations.el ends here ;;; mc-separate-operations.el ends here
+64 -176
View File
@@ -1,6 +1,6 @@
;;; multiple-cursors-core.el --- An experiment in multiple cursors for emacs. ;;; multiple-cursors-core.el --- An experiment in multiple cursors for emacs.
;; Copyright (C) 2012-2016 Magnar Sveen ;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com> ;; Author: Magnar Sveen <magnars@gmail.com>
;; Keywords: editing cursors ;; Keywords: editing cursors
@@ -25,21 +25,15 @@
;;; Code: ;;; Code:
(require 'cl-lib) (require 'cl)
(require 'rect)
(defvar mc--read-char) (require 'rect)
(defface mc/cursor-face (defface mc/cursor-face
'((t (:inverse-video t))) '((t (:inverse-video t)))
"The face used for fake cursors" "The face used for fake cursors"
:group 'multiple-cursors) :group 'multiple-cursors)
(defface mc/cursor-bar-face
`((t (:height 1 :background ,(face-attribute 'cursor :background))))
"The face used for fake cursors if the cursor-type is bar"
:group 'multiple-cursors)
(defface mc/region-face (defface mc/region-face
'((t :inherit region)) '((t :inherit region))
"The face used for fake regions" "The face used for fake regions"
@@ -47,17 +41,16 @@
(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 ((uc (make-symbol "undo-cleaner"))) `(let ((undo-cleaner (cons 'apply (cons 'deactivate-cursor-after-undo (list id)))))
`(let ((,uc (cons 'apply (cons 'deactivate-cursor-after-undo (list id))))) (setq buffer-undo-list (cons undo-cleaner buffer-undo-list))
(setq buffer-undo-list (cons ,uc buffer-undo-list))
,@forms ,@forms
(if (eq ,uc (car buffer-undo-list)) ;; if nothing has been added to the undo-list (if (eq undo-cleaner (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)
(cl-remove-if-not 'mc/fake-cursor-p (remove-if-not 'mc/fake-cursor-p
(overlays-in (or start (point-min)) (overlays-in (or start (point-min))
(or end (point-max))))) (or end (point-max)))))
@@ -68,61 +61,46 @@
(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 ((cs (make-symbol "current-state"))) `(let ((current-state (mc/store-current-state-in-overlay
`(let ((,cs (mc/store-current-state-in-overlay
(make-overlay (point) (point) nil nil t)))) (make-overlay (point) (point) nil nil t))))
(overlay-put ,cs 'type 'original-cursor) (overlay-put current-state 'type 'original-cursor)
(save-excursion ,@forms) (save-excursion ,@forms)
(mc/pop-state-from-overlay ,cs)))) (mc/pop-state-from-overlay current-state)))
(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 ((rci (make-symbol "real-cursor-id"))) `(let ((real-cursor-id (overlay-get (mc/create-fake-cursor-at-point) 'mc-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 ,rci))))) (mc/pop-state-from-overlay (mc/cursor-with-id real-cursor-id))))
(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 (make-symbol "p")) `(let ((p (set-marker (make-marker) (point)))
(s (make-symbol "start")) (start (set-marker (make-marker) (window-start)))
(h (make-symbol "hscroll"))) (hscroll (window-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 ,s t) (set-window-start nil start)
(set-window-hscroll nil ,h) (set-window-hscroll nil hscroll)
(set-marker ,p nil) (set-marker p nil)
(set-marker ,s nil)))) (set-marker start nil)))
(defun mc/cursor-is-bar ()
"Return non-nil if the cursor is a bar."
(or (eq cursor-type 'bar)
(and (listp cursor-type)
(eq (car cursor-type) 'bar))))
(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."
(let ((overlay (make-overlay pos pos nil nil nil))) (let ((overlay (make-overlay pos pos nil nil nil)))
(if (mc/cursor-is-bar) (overlay-put overlay 'after-string (propertize " " 'face 'mc/cursor-face))
(overlay-put overlay 'before-string (propertize "|" 'face 'mc/cursor-bar-face))
(overlay-put overlay 'after-string (propertize " " 'face 'mc/cursor-face)))
overlay)) overlay))
(defun mc/make-cursor-overlay-inline (pos) (defun mc/make-cursor-overlay-inline (pos)
"Create overlay to look like cursor inside text." "Create overlay to look like cursor inside text."
(let ((overlay (make-overlay pos (1+ pos) nil nil nil))) (let ((overlay (make-overlay pos (1+ pos) nil nil nil)))
(if (mc/cursor-is-bar) (overlay-put overlay 'face 'mc/cursor-face)
(overlay-put overlay 'before-string (propertize "|" 'face 'mc/cursor-bar-face))
(overlay-put overlay 'face 'mc/cursor-face))
overlay)) overlay))
(defun mc/make-cursor-overlay-at-point () (defun mc/make-cursor-overlay-at-point ()
@@ -140,24 +118,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 '(transient-mark-mode (defvar mc/cursor-specific-vars '(autopair-action
kill-ring
kill-ring-yank-pointer
mark-ring
mark-active
yank-undo-function
autopair-action
autopair-wrap-action autopair-wrap-action
temporary-goal-column 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 'mark (set-marker (make-marker) (overlay-put o 'kill-ring kill-ring)
(let ((mark-even-if-inactive t)) (overlay-put o 'kill-ring-yank-pointer kill-ring-yank-pointer)
(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)
@@ -165,7 +141,13 @@ 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)))))
@@ -191,39 +173,11 @@ highlights the entire width of the window."
(defun mc/create-cursor-id () (defun mc/create-cursor-id ()
"Returns a unique cursor id" "Returns a unique cursor id"
(cl-incf mc--current-cursor-id)) (incf mc--current-cursor-id))
(defvar mc--max-cursors-original nil
"This variable maintains the original maximum number of cursors.
When `mc/create-fake-cursor-at-point' is called and
`mc/max-cursors' is overridden, this value serves as a backup so
that `mc/max-cursors' can take on a new value. When
`mc/remove-fake-cursors' is called, the values are reset.")
(defcustom mc/max-cursors nil
"Safety ceiling for the number of active cursors.
If your emacs slows down or freezes when using too many cursors,
customize this value appropriately.
Cursors will be added until this value is reached, at which point
you can either temporarily override the value or abort the
operation entirely.
If this value is nil, there is no ceiling."
:type '(integer)
:group 'multiple-cursors)
(defun mc/create-fake-cursor-at-point (&optional id) (defun mc/create-fake-cursor-at-point (&optional id)
"Add a fake cursor and possibly a fake active region overlay based on point and mark. "Add a fake cursor and possibly a fake active region overlay based on point and mark.
Saves the current state in the overlay to be restored later." Saves the current state in the overlay to be restored later."
(unless mc--max-cursors-original
(setq mc--max-cursors-original mc/max-cursors))
(when mc/max-cursors
(unless (< (mc/num-cursors) mc/max-cursors)
(if (yes-or-no-p (format "%d active cursors. Continue? " (mc/num-cursors)))
(setq mc/max-cursors (read-number "Enter a new, temporary maximum: "))
(mc/remove-fake-cursors)
(error "Aborted: too many cursors"))))
(let ((overlay (mc/make-cursor-overlay-at-point))) (let ((overlay (mc/make-cursor-overlay-at-point)))
(overlay-put overlay 'mc-id (or id (mc/create-cursor-id))) (overlay-put overlay 'mc-id (or id (mc/create-cursor-id)))
(overlay-put overlay 'type 'fake-cursor) (overlay-put overlay 'type 'fake-cursor)
@@ -277,8 +231,6 @@ cursor with updated info."
;; Intercept some reading commands so you won't have to ;; Intercept some reading commands so you won't have to
;; answer them for every single cursor ;; answer them for every single cursor
(defvar mc--read-char nil)
(defvar multiple-cursors-mode nil)
(defadvice read-char (around mc-support activate) (defadvice read-char (around mc-support activate)
(if (not multiple-cursors-mode) (if (not multiple-cursors-mode)
ad-do-it ad-do-it
@@ -286,7 +238,6 @@ cursor with updated info."
(setq mc--read-char ad-do-it)) (setq mc--read-char ad-do-it))
(setq ad-return-value mc--read-char))) (setq ad-return-value mc--read-char)))
(defvar mc--read-quoted-char nil)
(defadvice read-quoted-char (around mc-support activate) (defadvice read-quoted-char (around mc-support activate)
(if (not multiple-cursors-mode) (if (not multiple-cursors-mode)
ad-do-it ad-do-it
@@ -306,7 +257,7 @@ cursor with updated info."
(defun mc/cursor-with-id (id) (defun mc/cursor-with-id (id)
"Find the first cursor with the given id, or nil" "Find the first cursor with the given id, or nil"
(cl-find-if #'(lambda (o) (and (mc/fake-cursor-p o) (find-if #'(lambda (o) (and (mc/fake-cursor-p o)
(= id (overlay-get o 'mc-id)))) (= id (overlay-get o 'mc-id))))
(overlays-in (point-min) (point-max)))) (overlays-in (point-min) (point-max))))
@@ -328,16 +279,6 @@ cursor with updated info."
(mc/pop-state-from-overlay mc--stored-state-for-undo) (mc/pop-state-from-overlay mc--stored-state-for-undo)
(setq mc--stored-state-for-undo nil))) (setq mc--stored-state-for-undo nil)))
(defcustom mc/always-run-for-all nil
"Disables whitelisting and always executes commands for every fake cursor."
:type '(boolean)
:group 'multiple-cursors)
(defcustom mc/always-repeat-command nil
"Disables confirmation for `mc/repeat-command' command."
:type '(boolean)
:group 'multiple-cursors)
(defun mc/prompt-for-inclusion-in-whitelist (original-command) (defun mc/prompt-for-inclusion-in-whitelist (original-command)
"Asks the user, then adds the command either to the once-list or the all-list." "Asks the user, then adds the command either to the once-list or the all-list."
(let ((all-p (y-or-n-p (format "Do %S for all cursors?" original-command)))) (let ((all-p (y-or-n-p (format "Do %S for all cursors?" original-command))))
@@ -349,7 +290,7 @@ cursor with updated info."
(defun mc/num-cursors () (defun mc/num-cursors ()
"The number of cursors (real and fake) in the buffer." "The number of cursors (real and fake) in the buffer."
(1+ (cl-count-if 'mc/fake-cursor-p (1+ (count-if 'mc/fake-cursor-p
(overlays-in (point-min) (point-max))))) (overlays-in (point-min) (point-max)))))
(defvar mc--this-command nil (defvar mc--this-command nil
@@ -365,10 +306,8 @@ 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
(let ((cmd (or (command-remapping this-original-command) (setq mc--this-command (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."
@@ -398,6 +337,7 @@ 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)
@@ -427,8 +367,7 @@ the original cursor, to inform about the lack of support."
(when (and original-command (when (and original-command
(not (memq original-command mc--default-cmds-to-run-once)) (not (memq original-command mc--default-cmds-to-run-once))
(not (memq original-command mc/cmds-to-run-once)) (not (memq original-command mc/cmds-to-run-once))
(or mc/always-run-for-all (or (memq original-command mc--default-cmds-to-run-for-all)
(memq original-command mc--default-cmds-to-run-for-all)
(memq original-command mc/cmds-to-run-for-all) (memq original-command mc/cmds-to-run-for-all)
(mc/prompt-for-inclusion-in-whitelist original-command))) (mc/prompt-for-inclusion-in-whitelist original-command)))
(mc/execute-command-for-all-fake-cursors original-command)))))))))) (mc/execute-command-for-all-fake-cursors original-command))))))))))
@@ -438,10 +377,7 @@ the original cursor, to inform about the lack of support."
Do not use to conclude editing with multiple cursors. For that Do not use to conclude editing with multiple cursors. For that
you should disable multiple-cursors-mode." you should disable multiple-cursors-mode."
(mc/for-each-fake-cursor (mc/for-each-fake-cursor
(mc/remove-fake-cursor cursor)) (mc/remove-fake-cursor cursor)))
(when mc--max-cursors-original
(setq mc/max-cursors mc--max-cursors-original))
(setq mc--max-cursors-original nil))
(defun mc/keyboard-quit () (defun mc/keyboard-quit ()
"Deactivate mark if there are any active, otherwise exit multiple-cursors-mode." "Deactivate mark if there are any active, otherwise exit multiple-cursors-mode."
@@ -450,38 +386,23 @@ you should disable multiple-cursors-mode."
(multiple-cursors-mode 0) (multiple-cursors-mode 0)
(deactivate-mark))) (deactivate-mark)))
(defun mc/repeat-command ()
"Run last command from `command-history' for every fake cursor."
(interactive)
(when (or mc/always-repeat-command
(y-or-n-p (format "[mc] repeat complex command: %s? " (caar command-history))))
(mc/execute-command-for-all-fake-cursors
(lambda () (interactive)
(cl-letf (((symbol-function 'read-from-minibuffer)
(lambda (p &optional i k r h d m) (read i))))
(repeat-complex-command 0))))))
(defvar mc/keymap nil (defvar mc/keymap nil
"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.")
(unless mc/keymap (if 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))
(define-key mc/keymap (kbd "C-:") 'mc/repeat-command)
(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 (list) (defun mc--all-equal (entries)
"Are all the items in LIST equal?" "Are all these entries equal?"
(let ((first (car list)) (let ((first (car entries))
(all-equal t)) (all-equal t))
(while (and all-equal list) (while (and all-equal entries)
(setq all-equal (equal first (car list))) (setq all-equal (equal first (car entries)))
(setq list (cdr list))) (setq entries (cdr entries)))
all-equal)) all-equal))
(defun mc--kill-ring-entries () (defun mc--kill-ring-entries ()
@@ -495,11 +416,11 @@ The entries are returned in the order they are found in the buffer."
(defun mc--maybe-set-killed-rectangle () (defun mc--maybe-set-killed-rectangle ()
"Add the latest kill-ring entry for each cursor to killed-rectangle. "Add the latest kill-ring entry for each cursor to killed-rectangle.
So you can paste it in later with `yank-rectangle'." So you can paste it in later with `yank-rectangle'."
(let ((entries (let (mc/max-cursors) (mc--kill-ring-entries)))) (let ((entries (mc--kill-ring-entries)))
(unless (mc--all-equal entries) (unless (mc--all-equal entries)
(setq killed-rectangle entries)))) (setq killed-rectangle entries))))
(defvar mc/unsupported-minor-modes '(company-mode auto-complete-mode flyspell-mode jedi-mode) (defvar mc/unsupported-minor-modes '(auto-complete-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.")
@@ -530,7 +451,6 @@ They are temporarily disabled when multiple-cursors are active.")
:group 'multiple-cursors) :group 'multiple-cursors)
(put 'mc/mode-line 'risky-local-variable t) (put 'mc/mode-line 'risky-local-variable t)
;;;###autoload
(define-minor-mode multiple-cursors-mode (define-minor-mode multiple-cursors-mode
"Mode while multiple cursors are active." "Mode while multiple cursors are active."
nil mc/mode-line mc/keymap nil mc/mode-line mc/keymap
@@ -571,8 +491,7 @@ from being executed if in multiple-cursors-mode."
(unsupported-cmd isearch-backward ". Feel free to add a compatible version.") (unsupported-cmd isearch-backward ". Feel free to add a compatible version.")
;; Make sure pastes from other programs are added to all kill-rings when yanking ;; Make sure pastes from other programs are added to all kill-rings when yanking
(defadvice current-kill (before interprogram-paste-for-all-cursors (defadvice current-kill (before interprogram-paste-for-all-cursors activate)
(n &optional do-not-move) activate)
(let ((interprogram-paste (and (= n 0) (let ((interprogram-paste (and (= n 0)
interprogram-paste-function interprogram-paste-function
(funcall interprogram-paste-function)))) (funcall interprogram-paste-function))))
@@ -596,15 +515,13 @@ from being executed if in multiple-cursors-mode."
(overlay-put cursor 'kill-ring kill-ring) (overlay-put cursor 'kill-ring kill-ring)
(overlay-put cursor 'kill-ring-yank-pointer kill-ring-yank-pointer))))))) (overlay-put cursor 'kill-ring-yank-pointer kill-ring-yank-pointer)))))))
(defcustom mc/list-file (locate-user-emacs-file ".mc-lists.el") (defvar mc/list-file "~/.emacs.d/.mc-lists.el"
"The position of the file that keeps track of your preferences "The position of the file that keeps track of your preferences
for running commands with multiple cursors." for running commands with multiple cursors.")
:type 'file
:group 'multiple-cursors)
(defun mc/dump-list (list-symbol) (defun mc/dump-list (list-symbol)
"Insert (setq 'LIST-SYMBOL LIST-VALUE) to current buffer." "Insert (setq 'LIST-SYMBOL LIST-VALUE) to current buffer."
(cl-symbol-macrolet ((value (symbol-value list-symbol))) (symbol-macrolet ((value (symbol-value list-symbol)))
(insert "(setq " (symbol-name list-symbol) "\n" (insert "(setq " (symbol-name list-symbol) "\n"
" '(") " '(")
(newline-and-indent) (newline-and-indent)
@@ -639,13 +556,9 @@ for running commands with multiple cursors."
mc/edit-ends-of-lines mc/edit-ends-of-lines
mc/edit-beginnings-of-lines mc/edit-beginnings-of-lines
mc/mark-next-like-this mc/mark-next-like-this
mc/mark-next-like-this-word
mc/mark-next-like-this-symbol
mc/mark-next-word-like-this mc/mark-next-word-like-this
mc/mark-next-symbol-like-this mc/mark-next-symbol-like-this
mc/mark-previous-like-this mc/mark-previous-like-this
mc/mark-previous-like-this-word
mc/mark-previous-like-this-symbol
mc/mark-previous-word-like-this mc/mark-previous-word-like-this
mc/mark-previous-symbol-like-this mc/mark-previous-symbol-like-this
mc/mark-all-like-this mc/mark-all-like-this
@@ -656,37 +569,18 @@ for running commands with multiple cursors."
mc/mark-all-words-like-this-in-defun mc/mark-all-words-like-this-in-defun
mc/mark-all-symbols-like-this-in-defun mc/mark-all-symbols-like-this-in-defun
mc/mark-all-like-this-dwim mc/mark-all-like-this-dwim
mc/mark-all-dwim
mc/mark-sgml-tag-pair mc/mark-sgml-tag-pair
mc/insert-numbers mc/insert-numbers
mc/insert-letters
mc/sort-regions mc/sort-regions
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
mc-hide-unmatched-lines-mode
mc/repeat-command
hum/keyboard-quit
hum/unhide-invisible-overlays
save-buffer save-buffer
ido-exit-minibuffer ido-exit-minibuffer
ivy-done
exit-minibuffer exit-minibuffer
minibuffer-complete-and-exit minibuffer-complete-and-exit
execute-extended-command execute-extended-command
eval-expression
undo undo
redo redo
undo-tree-undo undo-tree-undo
@@ -720,8 +614,7 @@ for running commands with multiple cursors."
windmove-left windmove-left
windmove-right windmove-right
windmove-up windmove-up
windmove-down windmove-down))
repeat-complex-command))
(defvar mc--default-cmds-to-run-for-all nil (defvar mc--default-cmds-to-run-for-all nil
"Default set of commands that should be mirrored by all cursors") "Default set of commands that should be mirrored by all cursors")
@@ -767,11 +660,8 @@ 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
cperl-electric-backspace
python-indent-dedent-line-backspace
paredit-backward-delete paredit-backward-delete
autopair-backspace autopair-backspace
just-one-space just-one-space
@@ -781,7 +671,6 @@ for running commands with multiple cursors."
exchange-point-and-mark exchange-point-and-mark
cua-set-mark cua-set-mark
cua-replace-region cua-replace-region
cua-delete-region
move-end-of-line move-end-of-line
beginning-of-line beginning-of-line
move-beginning-of-line move-beginning-of-line
@@ -806,14 +695,13 @@ for running commands with multiple cursors."
(defvar mc/cmds-to-run-for-all nil (defvar mc/cmds-to-run-for-all nil
"Commands to run for all cursors in multiple-cursors-mode") "Commands to run for all cursors in multiple-cursors-mode")
;; load, but no errors if it does not exist yet please, and no message (load mc/list-file t) ;; load, but no errors if it does not exist yet please
;; while loading
(load mc/list-file 'noerror 'nomessage)
(provide 'multiple-cursors-core) (provide 'multiple-cursors-core)
;; Local Variables: ;; Local Variables:
;; coding: utf-8 ;; coding: utf-8
;; byte-compile-warnings: (not cl-functions)
;; End: ;; End:
;;; multiple-cursors-core.el ends here ;;; multiple-cursors-core.el ends here
+2 -3
View File
@@ -1,3 +1,2 @@
(define-package "multiple-cursors" "1.3.0" (define-package "multiple-cursors" "1.2.1"
"Multiple cursors for Emacs." "Multiple cursors for Emacs.")
'((cl-lib "0.5")))
+2 -29
View File
@@ -1,9 +1,8 @@
;;; multiple-cursors.el --- Multiple cursors for emacs. ;;; multiple-cursors.el --- An experiment in multiple cursors for emacs.
;; Copyright (C) 2012-2016 Magnar Sveen ;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com> ;; Author: Magnar Sveen <magnars@gmail.com>
;; Version: 1.4.0
;; 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
@@ -61,15 +60,12 @@
;; ### Mark one more occurrence ;; ### Mark one more occurrence
;; - `mc/mark-next-like-this`: Adds a cursor and region at the next part of the buffer forwards that matches the current region. ;; - `mc/mark-next-like-this`: Adds a cursor and region at the next part of the buffer forwards that matches the current region.
;; - `mc/mark-next-like-this-word`: Adds a cursor and region at the next part of the buffer forwards that matches the current region, if no region is selected it selects the word at the point.
;; - `mc/mark-next-like-this-symbol`: Adds a cursor and region at the next part of the buffer forwards that matches the current region, if no region is selected it selects the symbol at the point.
;; - `mc/mark-next-word-like-this`: Like `mc/mark-next-like-this` but only for whole words. ;; - `mc/mark-next-word-like-this`: Like `mc/mark-next-like-this` but only for whole words.
;; - `mc/mark-next-symbol-like-this`: Like `mc/mark-next-like-this` but only for whole symbols. ;; - `mc/mark-next-symbol-like-this`: Like `mc/mark-next-like-this` but only for whole symbols.
;; - `mc/mark-previous-like-this`: Adds a cursor and region at the next part of the buffer backwards that matches the current region. ;; - `mc/mark-previous-like-this`: Adds a cursor and region at the next part of the buffer backwards that matches the current region.
;; - `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
@@ -87,7 +83,6 @@
;; - `set-rectangular-region-anchor`: Think of this one as `set-mark` except you're marking a rectangular region. ;; - `set-rectangular-region-anchor`: Think of this one as `set-mark` except you're marking a rectangular region.
;; - `mc/mark-sgml-tag-pair`: Mark the current opening and closing tag. ;; - `mc/mark-sgml-tag-pair`: Mark the current opening and closing tag.
;; - `mc/insert-numbers`: Insert increasing numbers for each cursor, top to bottom. ;; - `mc/insert-numbers`: Insert increasing numbers for each cursor, top to bottom.
;; - `mc/insert-letters`: Insert increasing letters for each cursor, top to bottom.
;; - `mc/sort-regions`: Sort the marked regions alphabetically. ;; - `mc/sort-regions`: Sort the marked regions alphabetically.
;; - `mc/reverse-regions`: Reverse the order of the marked regions. ;; - `mc/reverse-regions`: Reverse the order of the marked regions.
@@ -103,10 +98,6 @@
;; - Try pressing `mc/mark-next-like-this` with no region selected. It will just add a cursor ;; - Try pressing `mc/mark-next-like-this` with no region selected. It will just add a cursor
;; on the next line. ;; on the next line.
;; ;;
;; - Try pressing `mc/mark-next-like-this-word` or
;; `mc/mark-next-like-this-symbol` with no region selected. It will
;; mark the symbol and add a cursor at the next occurance
;;
;; - Try pressing `mc/mark-all-like-this-dwim` on a tagname in html-mode. ;; - Try pressing `mc/mark-all-like-this-dwim` on a tagname in html-mode.
;; ;;
;; - Notice that the number of cursors active can be seen in the modeline. ;; - Notice that the number of cursors active can be seen in the modeline.
@@ -124,18 +115,6 @@
;; 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
@@ -186,17 +165,11 @@
;;; Code: ;;; Code:
(defgroup multiple-cursors nil
"Multiple cursors for emacs."
:group 'editing)
(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)
(require 'mc-hide-unmatched-lines-mode)
(provide 'multiple-cursors) (provide 'multiple-cursors)
+2 -8
View File
@@ -1,6 +1,6 @@
;;; rectangular-region-mode.el ;;; rectangular-region-mode.el
;; Copyright (C) 2012-2016 Magnar Sveen ;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com> ;; Author: Magnar Sveen <magnars@gmail.com>
;; Keywords: editing cursors ;; Keywords: editing cursors
@@ -38,8 +38,6 @@
(define-key rectangular-region-mode-map (kbd "C-g") 'rrm/keyboard-quit) (define-key rectangular-region-mode-map (kbd "C-g") 'rrm/keyboard-quit)
(define-key rectangular-region-mode-map (kbd "<return>") 'rrm/switch-to-multiple-cursors) (define-key rectangular-region-mode-map (kbd "<return>") 'rrm/switch-to-multiple-cursors)
(defvar rectangular-region-mode nil)
(defun rrm/keyboard-quit () (defun rrm/keyboard-quit ()
"Exit rectangular-region-mode." "Exit rectangular-region-mode."
(interactive) (interactive)
@@ -69,9 +67,6 @@ 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))
@@ -92,7 +87,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."
@@ -108,7 +103,6 @@ an exceedingly quick way of adding multiple cursors to multiple lines."
(when rectangular-region-mode (when rectangular-region-mode
(rrm/switch-to-multiple-cursors))) (rrm/switch-to-multiple-cursors)))
;;;###autoload
(define-minor-mode rectangular-region-mode (define-minor-mode rectangular-region-mode
"A mode for creating a rectangular region to edit" "A mode for creating a rectangular region to edit"
nil " rr" rectangular-region-mode-map nil " rr" rectangular-region-mode-map
-2
View File
@@ -1,2 +0,0 @@
#!/bin/sh -e
cask exec ecukes "$@" --no-win
+2 -3
View File
@@ -2,12 +2,11 @@
cd "$(dirname "$0")" cd "$(dirname "$0")"
ECUKES_EMACS=${EMACS:-$(which emacs)} ECUKES_EMACS=${ECUKES_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 ./run-tests.sh $TAGS exec ./util/ecukes/ecukes --graphical
Submodule
+1
Submodule util/ecukes added at b2c449cf01
+2544
View File
File diff suppressed because it is too large Load Diff
Submodule
+1
Submodule util/espuds added at 62ef75cb51
+329
View File
@@ -0,0 +1,329 @@
;;; 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 "./run-tests.sh" result = run "./util/ecukes/ecukes --graphical"
puts result puts result
end end
def run_test(file) def run_test(file)
system('clear') system('clear')
result = run "./run-tests.sh #{file} --verbose" result = run "./util/ecukes/ecukes --graphical #{file}"
puts result puts result
end end