Compare commits

..

No commits in common. "master" and "1.1.3" have entirely different histories.

37 changed files with 3185 additions and 2978 deletions

View File

@ -1,36 +0,0 @@
name: CI
on:
pull_request:
push:
paths-ignore:
- '**.md'
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
emacs_version:
- 25.1
- 25.2
- 25.3
- 26.1
- 26.2
- 26.3
- 27.2
- 28.1
- snapshot
steps:
- uses: purcell/setup-emacs@master
with:
version: ${{ matrix.emacs_version }}
- name: Install Cask
run: git clone https://github.com/cask/cask ~/.cask
- name: Add Cask to PATH
run: echo "$HOME/.cask/bin" >> $GITHUB_PATH
- uses: actions/checkout@v3
- name: Install dependencies with Cask
run: cask
- name: Run tests
run: script -e -c /bin/bash -c 'TERM=xterm ./run-tests.sh'

3
.gitignore vendored
View File

@ -1,3 +0,0 @@
elpa
*.elc
/.ecukes-failing-scenarios

6
.gitmodules vendored Normal file
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

12
.travis.yml Normal file
View File

@ -0,0 +1,12 @@
language: emacs-lisp
before_install:
- if [ "$ECUKES_EMACS" = 'emacs-snapshot' ]; then
sudo add-apt-repository -y ppa:cassou/emacs &&
sudo apt-get update -qq &&
sudo apt-get install -qq
emacs-snapshot-el emacs-snapshot-gtk emacs-snapshot;
fi
env:
- ECUKES_EMACS=emacs
script:
./run-travis-ci.sh

9
Cask
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"))

198
README.md
View File

@ -1,45 +1,9 @@
[![Build Status](https://github.com/magnars/multiple-cursors.el/workflows/CI/badge.svg)](https://github.com/magnars/multiple-cursors.el/actions)
[![MELPA](https://melpa.org/packages/multiple-cursors-badge.svg)](https://melpa.org/#/multiple-cursors)
[![MELPA Stable](https://stable.melpa.org/packages/multiple-cursors-badge.svg)](https://stable.melpa.org/#/multiple-cursors)
[![NonGNU ELPA](https://elpa.nongnu.org/nongnu/multiple-cursors.svg)](https://elpa.nongnu.org/nongnu/multiple-cursors.html)
# multiple-cursors.el
# multiple-cursors.el [![Build Status](https://secure.travis-ci.org/magnars/multiple-cursors.el.png)](http://travis-ci.org/magnars/multiple-cursors.el)
Multiple cursors for Emacs. This is some pretty crazy functionality, so yes,
there are kinks. Don't be afraid though, 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.
## Maintenance warning
I use this package every day, and have been doing so for years. It just works.
At least, it works for all my use cases. And if it breaks somehow, I fix it.
However, it has become painfully clear to me that I don't have time to fix
problems I don't have. It's been years since I could keep pace with the issues
and pull requests. Whenever I try, I keep getting feedback that my fix isn't
good enough by some standard I don't particularly care about.
So, I have closed the issue tracker and the pull requests. I hope you can
happily use this package, just like I do. If it doesn't work for you, then I'm
sorry. Thankfully Emacs is infinitely malleable, you can probably fix it
yourself.
TLDR: *I am still maintaining this package*, but I am no longer crowdsourcing a list of issues.
## Installation
I highly recommend installing multiple-cursors through `package.el`.
It's available on [MELPA](http://melpa.org/), [MELPA Stable](http://stable.melpa.org) and
[NonGNU ELPA](https://elpa.nongnu.org/nongnu/multiple-cursors.html) (enabled by default
from Emacs 28 onwards):
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
Start out with:
@ -71,119 +35,42 @@ insert a newline in multiple-cursors-mode, use `C-j`.
You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.com/e13.html).
## Command overview
## More commands to play around with
### Mark one more occurrence
I've set up my key-bindings like so:
| Command | Description |
|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `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-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-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-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 occurrences. |
| `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. |
;; From active region to multiple cursors:
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C-S-c C-e") 'mc/edit-ends-of-lines)
(global-set-key (kbd "C-S-c C-a") 'mc/edit-beginnings-of-lines)
### Juggle around with the current cursors
When you have an active region that spans multiple lines, the preceeding three
commands will add one cursor to each line.
| Command | Description |
|---------------------------------|--------------------------------------------------------------------|
| `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 occurrence down. |
| `mc/skip-to-previous-like-this` | Remove the cursor furthest up, marking the next occurrence up. |
;; Rectangular region mode
(global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor)
### Mark many occurrences
Think of this one as `set-mark` except you're marking a rectangular region. It is
an exceedingly quick way of adding multiple cursors to multiple lines.
| Command | Description |
|------------------------------------------|-------------------------------------------------------------------------------------|
| `mc/edit-lines` | Adds one cursor to each line in the current region. |
| `mc/edit-beginnings-of-lines` | Adds a cursor at the start of each line in the current region. |
| `mc/edit-ends-of-lines` | Adds a cursor at the end of each line in the current region. |
| `mc/mark-all-like-this` | Marks all parts of the buffer that matches the current region. |
| `mc/mark-all-words-like-this` | Like `mc/mark-all-like-this` but only for whole words. |
| `mc/mark-all-symbols-like-this` | Like `mc/mark-all-like-this` but only for whole symbols. |
| `mc/mark-all-in-region` | Prompts for a string to match in the region, adding cursors to all of them. |
| `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-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. |
;; Mark more like this
(global-set-key (kbd "M-æ") 'mc/mark-all-like-this)
(global-set-key (kbd "C-å") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-æ") 'mc/mark-next-like-this)
(global-set-key (kbd "C-Æ") 'mc/mark-more-like-this-extended)
(global-set-key (kbd "M-å") 'mc/mark-all-in-region)
### Special
| Command | Description |
|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `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/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/reverse-regions` | Reverse the order of the marked regions. |
| `mc/vertical-align` | Aligns all cursors vertically with a given CHARACTER to the one with the highest column number (the rightest). (Might not behave as intended if more than one cursors are on the same line.) |
| `mc/vertical-align-with-space` | Aligns all cursors with whitespace like `mc/vertical-align` does. |
## Tips and tricks
- 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
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
scroll the screen to center on each cursor with `C-v` and `M-v` or you can
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
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 occurrence
- 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.
- If you get out of multiple-cursors-mode and yank - it will yank only
from the kill-ring of main cursor. To yank from the kill-rings of
every cursor use yank-rectangle, normally found at C-x r y.
- 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.
- 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
when the region is active, you can try [region-bindings-mode](https://github.com/fgallina/region-bindings-mode).
- There is a special hook that is run when the mode is diabled
(which is equivalent to the number of cursors going back to 1):
`multiple-cursors-mode-disabled-hook`
Okay, yes, I have a crazy norwegian keyboard. Regardless, these will look at
whatever you've got selected at the moment, and mark more places like that in
the buffer.
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`.
### Binding mouse events
## Scrolling
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)
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`.
## Unknown commands
@ -197,17 +84,12 @@ the location with:
(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
* 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.
* 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.
* Redo might screw with your cursors. Undo works very well.
@ -222,35 +104,19 @@ You'll find the repo at:
https://github.com/magnars/multiple-cursors.el
To fetch the test dependencies, install
[cask](https://github.com/rejeep/cask.el) if you haven't already,
then:
To fetch the test dependencies:
$ cd /path/to/multiple-cursors
$ cask
$ git submodule update --init
Run the tests with:
$ ./run-tests.sh
$ ./util/ecukes/ecukes --graphical
## Contributors
* [Takafumi Arakaki](https://github.com/tkf) has contributed several small improvements
* [Marco Baringer](https://github.com/segv) contributed looping to `mc/cycle` and adding cursors without region for mark-more.
* [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`.
* [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!
## License
Copyright (C) 2012-2016 Magnar Sveen
Copyright (C) 2012 Magnar Sveen
Author: Magnar Sveen <magnars@gmail.com>
Keywords: editing cursors

View File

@ -42,99 +42,3 @@ Feature: Switching from a multiline region to multiple cursors
And I go to the front of the word "long"
And I press "C-S-c C-S-c"
Then I should have 2 cursors
Scenario: Edit without using transient mark mode
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 "C-S-c C-S-c"
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
"""

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

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)"

View File

@ -1,40 +0,0 @@
Feature: Insert increasing numbers
Scenario: Three cursors, 0-1-2
Given I have cursors at "text" in "This text contains the word text thrice (text)"
When I press "H-0"
And I press "SPC"
Then I should see "This 0 text contains the word 1 text thrice (2 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-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
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)"

View File

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

View File

@ -1,90 +0,0 @@
Feature: Mark all do-what-I-mean
Background:
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))
"""
Scenario: Mark symbols in defun
When I go to the end of the word "abc"
And I press "M-f"
And I press "M-$"
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
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
When I go to the end of the word "abc"
And I press "M-f"
And I press "M-$"
And I press "M-$"
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-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))
"""

View File

@ -14,14 +14,6 @@ Feature: Marking multiple parts of the buffer
And I type "sentence"
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
Given I turn on delete-selection-mode
When I insert "Here's text, text and text"
@ -62,14 +54,6 @@ Feature: Marking multiple parts of the buffer
And I type "sentence"
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
Given I turn on delete-selection-mode
When I insert "Here's text, text and text"
@ -110,51 +94,3 @@ Feature: Marking multiple parts of the buffer
And I type "more"
Then I should have 2 cursors
And I should see "Here's more, more and text"
Scenario: Marking without an active region
When I insert:
"""
aaa
bbb
ccc
"""
And I go to the front of the word "bbb"
And I press "C->"
And I type "_"
Then I should have 2 cursors
And I should see:
"""
aaa
_bbb
_ccc
"""
Scenario: Increasing number of cursors without an active region
When I insert:
"""
aaa
bbb
ccc
"""
And I go to the front of the word "bbb"
And I press "C->"
And I press "C-<"
And i press "C-f"
And I type "_"
Then I should have 3 cursors
And I should see:
"""
a_aa
b_bb
c_cc
"""
Scenario: Multiple cursor with shift selection
When I insert "This text contains the word text twice"
And I go to the front of the word "text"
And I press "M-S-f"
And I press "C->"
And I press "C-f"
And I press "<deletechar>"
Then I should see "This text ontains the word text wice"

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

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))
"""

View File

@ -50,13 +50,6 @@ Feature: Multiple cursors core
And I press "C-!"
Then I should see "This aatext contains the word aatext twice"
Scenario: Unknown command with multiple read: yes, do for all
Given I have bound C-! to a new command that inserts two read-chars
And I have cursors at "text" in "This text contains the word text twice"
When I press "C-! b c y"
And I press "C-! d e"
Then I should see "This bcdetext contains the word bcdetext twice"
Scenario: Unknown command: no, don't do for all
Given I have bound C-! to another new command that inserts "a"
And I have cursors at "text" in "This text contains the word text twice"
@ -64,28 +57,6 @@ Scenario: Unknown command with multiple read: yes, do for all
And I press "C-!"
Then I should see "This aatext contains the word text twice"
Scenario: Multiple supported M-x command (forward-word in this case)
Given I have cursors at "text" in "This text contains the word text twice"
And I type "("
And I press "M-x forward-word"
And I press "M-x forward-word"
And I type ")"
Then I should see "This (text contains) the word (text twice)"
Scenario: Unknown M-x command: yes, do for all
Given I have cursors at "text" in "This text contains the word text twice"
And I press "C-SPC"
And I press "M-f"
And I press "M-x upcase-dwim RET y"
Then I should see "This TEXT contains the word TEXT twice"
Scenario: Unknown M-x command: no, don't do for all
Given I have cursors at "text" in "This text contains the word text twice"
And I press "C-SPC"
And I press "M-f"
And I press "M-x upcase-dwim RET n"
Then I should see "This TEXT contains the word text twice"
Scenario: Undo
Given I have cursors at "text" in "This text contains the word text twice"
When I press "M-f"
@ -144,20 +115,10 @@ Scenario: Unknown command with multiple read: yes, do for all
And I go to the front of the word "text"
And I press "C-SPC"
And I press "M-f"
And I mark next like this
And I press "C->"
And I type "!"
Then I should see "This ! contains the word ! twice"
Scenario: wrap-region (function turns to keyboard macros)
Given I turn on wrap-region-mode
And I insert "This text contains the word text twice"
And I go to the front of the word "text"
And I press "C-M-SPC"
And I mark next like this
And I press "C-g"
And I type "("
Then I should see "This (text contains the word (text twice"
Scenario: Bound keyboard macros
Given I have bound C-! to a keyboard macro that insert "_"
And I have cursors at "text" in "This text contains the word text twice"
@ -187,31 +148,3 @@ Scenario: Unknown command with multiple read: yes, do for all
contains
twice
"""
Scenario: Looping forwards around cursors
Given I have cursors at "_" in "1_34567_9"
And I press "C-v"
And I press "C-v"
And I press "C-v"
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
Given I have cursors at "_" in "1_34567_9"
And I press "M-v"
And I press "M-v"
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"

View File

@ -1,39 +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 type "n"
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 set mc/always-run-for-all 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)"

View File

@ -1,19 +0,0 @@
Feature: Sorting and reversing cursor regions
Scenario: Reversing regions
Given I have cursors at "text" in "This text contains the word text thrice (text here)"
When I press "M-f"
And I press "C-f"
And I press "C-SPC"
And I press "M-f"
And I press "H-1"
Then I should see "This text here the word text thrice (text contains)"
Scenario: Sorting regions
Given I have cursors at "text" in "This text contains the word text thrice (text here)"
When I press "M-f"
And I press "C-f"
And I press "C-SPC"
And I press "M-f"
And I press "H-2"
Then I should see "This text contains the word text here (text thrice)"

View File

@ -1,80 +1,29 @@
(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$"
(lambda ()
(delete-selection-mode 1)))
(Given "^I turn off transient-mark-mode$"
(lambda ()
(transient-mark-mode -1)))
(Then "^I should have \\([0-9]+\\) cursors$"
(lambda (num)
(let ((actual (mc/num-cursors)))
(cl-assert (eq (string-to-number num) actual) nil
"Expected to have %s cursors, but was %d." num actual))))
(assert (eq (string-to-number num) actual) nil
"Expected to have %s cursors, but was %d." num actual))))
(Then "^I should have one cursor$"
(lambda ()
(cl-assert (not multiple-cursors-mode) nil
"Expected to have one cursor, but multiple-cursors-mode is still active.")
(cl-assert (eq 1 (mc/num-cursors)) nil
"Expected to have one cursor, but there are still fake cursor overlays.")))
(assert (not multiple-cursors-mode) nil
"Expected to have one cursor, but multiple-cursors-mode is still active.")
(assert (eq 1 (mc/num-cursors)) nil
"Expected to have one cursor, but there are still fake cursor overlays.")))
(Then "^rectangular-region-mode should be off$"
(lambda ()
(cl-assert (not rectangular-region-mode) nil
"Expected rectangular-region-mode mode to be off, but wasn't.")))
(lambda ()
(assert (not rectangular-region-mode) nil
"Expected rectangular-region-mode mode to be off, but wasn't.")))
(Then "^rectangular-region-mode should be on$"
(lambda ()
(cl-assert rectangular-region-mode nil
"Expected rectangular-region-mode mode to be on, but wasn't.")))
(lambda ()
(assert rectangular-region-mode nil
"Expected rectangular-region-mode mode to be on, but wasn't.")))
(When "^I press \"\\(.+\\)\"$"
(lambda (keybinding)
@ -96,17 +45,6 @@
(mc/mark-all-like-this)
(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$"
(lambda (text)
(lexical-let ((text text))
@ -130,11 +68,6 @@
(defun mc-test-temp-command-2 () (interactive) (insert ins))
(global-set-key (kbd "C-!") 'mc-test-temp-command-2))))
(Given "^I have bound C-! to a new command that inserts two read-chars$"
(lambda ()
(defun mc-test-temp-command-3 () (interactive) (insert (read-char "first: ")) (insert (read-char "second: ")))
(global-set-key (kbd "C-!") 'mc-test-temp-command-3)))
(Given "^I have bound C-! to a keyboard macro that insert \"_\"$"
(lambda ()
(fset 'mc-test-temp-kmacro "\C-q_")
@ -145,55 +78,20 @@
(goto-char (point-min))
(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"))
(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 \"\\(.+\\)\"$"
(lambda (pos word)
(goto-char (point-min))
(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"))
(cl-assert search nil message word (espuds-buffer-contents))
(assert search nil message word (espuds-buffer-contents))
(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 \"\\(.+\\)\"$"
(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))
(assert search nil "The text '%s' was not found in the current buffer." text))
(set-mark (point))
(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:

View File

@ -7,12 +7,10 @@
(add-to-list 'load-path multiple-cursors-root-path)
(add-to-list 'load-path multiple-cursors-util-path)
(add-to-list 'load-path (expand-file-name "espuds" multiple-cursors-util-path))
(add-to-list 'load-path (expand-file-name "vendor" multiple-cursors-util-path))
(require 'multiple-cursors)
(require 'espuds)
(require 'ert)
(require 'wrap-region)
(defun mc/save-lists ()) ;; redefine to do nothing when running tests
@ -21,19 +19,9 @@
(multiple-cursors-mode 0)
(rectangular-region-mode 0)
(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-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-dwim)
(global-set-key (kbd "C-$") 'mc/mark-all-dwim)
(global-set-key (kbd "M-#") 'mc/mark-all-in-region)
(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-2") 'mc/sort-regions)
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor)
(switch-to-buffer
@ -43,10 +31,7 @@
(cua-mode 0)
(delete-selection-mode 0)
(subword-mode 0)
(wrap-region-mode 0)
(setq set-mark-default-inactive nil)
(deactivate-mark)
(setq mc/cmds-to-run-for-all nil)
(setq mc/cmds-to-run-once nil))
(deactivate-mark))
(After)

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

View File

@ -1,6 +1,6 @@
;;; mc-cycle-cursors.el -*- lexical-binding: t; -*-
;;; mc-cycle-cursors.el
;; Copyright (C) 2012-2016 Magnar Sveen
;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com>
;; Keywords: editing cursors
@ -28,9 +28,11 @@
(require 'multiple-cursors-core)
(defun mc/next-fake-cursor-after-point ()
(eval-when-compile (require 'cl))
(defun mc/next-cursor-after-point ()
(let ((pos (point))
(next-pos (1+ (point-max)))
(next-pos (point-max))
next)
(mc/for-each-fake-cursor
(let ((cursor-pos (overlay-get cursor 'point)))
@ -40,9 +42,9 @@
(setq next cursor))))
next))
(defun mc/prev-fake-cursor-before-point ()
(defun mc/prev-cursor-before-point ()
(let ((pos (point))
(prev-pos (1- (point-min)))
(prev-pos (point-min))
prev)
(mc/for-each-fake-cursor
(let ((cursor-pos (overlay-get cursor 'point)))
@ -52,72 +54,27 @@
(setq prev cursor))))
prev))
(defcustom mc/cycle-looping-behaviour 'continue
"What to do if asked to cycle beyond the last cursor or before the first cursor."
:type '(radio (const :tag "Loop around to beginning/end of document." continue)
(const :tag "Warn and then loop around." warn)
(const :tag "Signal an error." error)
(const :tag "Don't loop." stop))
:group 'multiple-cursors)
(defun mc/handle-loop-condition (error-message)
(cl-ecase mc/cycle-looping-behaviour
(error (error error-message))
(warn (message error-message))
(continue 'continue)
(stop 'stop)))
(defun mc/first-fake-cursor-after (point)
"Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)."
(let* ((cursors (mc/all-fake-cursors))
(cursors-after-point (cl-remove-if (lambda (cursor)
(< (mc/cursor-beg cursor) point))
cursors))
(cursors-in-order (cl-sort cursors-after-point '< :key 'mc/cursor-beg)))
(car cursors-in-order)))
(defun mc/last-fake-cursor-before (point)
"Very similar to mc/furthest-cursor-before-point, but ignores (mark) and (point)."
(let* ((cursors (mc/all-fake-cursors))
(cursors-before-point (cl-remove-if (lambda (cursor)
(> (mc/cursor-end cursor) point))
cursors))
(cursors-in-order (cl-sort cursors-before-point '> :key 'mc/cursor-end)))
(car cursors-in-order)))
(cl-defun mc/cycle (next-cursor fallback-cursor loop-message)
(when (null next-cursor)
(when (eql 'stop (mc/handle-loop-condition loop-message))
(cond
((fboundp 'cl-return-from)
(cl-return-from mc/cycle nil))
((fboundp 'return-from)
(cl-return-from mc/cycle nil))))
(setf next-cursor fallback-cursor))
(mc/create-fake-cursor-at-point)
(mc/pop-state-from-overlay next-cursor)
(recenter))
(defun mc/cycle-forward ()
(interactive)
(mc/cycle (mc/next-fake-cursor-after-point)
(mc/first-fake-cursor-after (point-min))
"We're already at the last cursor."))
(let ((next-cursor (mc/next-cursor-after-point)))
(unless next-cursor
(error "We're already at the last cursor"))
(mc/create-fake-cursor-at-point)
(mc/pop-state-from-overlay next-cursor)
(recenter)))
(defun mc/cycle-backward ()
(interactive)
(mc/cycle (mc/prev-fake-cursor-before-point)
(mc/last-fake-cursor-before (point-max))
"We're already at the last cursor"))
(let ((prev-cursor (mc/prev-cursor-before-point)))
(unless prev-cursor
(error "We're already at the first cursor"))
(mc/create-fake-cursor-at-point)
(mc/pop-state-from-overlay prev-cursor)
(recenter)))
(define-key mc/keymap (kbd "C-v") 'mc/cycle-forward)
(define-key mc/keymap (kbd "M-v") 'mc/cycle-backward)
(provide 'mc-cycle-cursors)
;; Local Variables:
;; coding: utf-8
;; End:
;;; mc-cycle-cursors.el ends here

View File

@ -1,6 +1,6 @@
;;; mc-edit-lines.el -*- lexical-binding: t; -*-
;;; mc-edit-lines.el
;; Copyright (C) 2012-2016 Magnar Sveen
;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com>
;; Keywords: editing cursors
@ -29,65 +29,26 @@
(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
(defun mc/edit-lines (&optional arg)
(defun mc/edit-lines ()
"Add one cursor to each line of the active region.
Starts from mark and moves in straight down or up towards the
line point is on.
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")
(unless mark-active
(error "Mark a set of lines first"))
line point is on."
(interactive)
(when (not (use-region-p))
(error "Mark a set of lines first."))
(mc/remove-fake-cursors)
(let* ((col (current-column))
(point-line (mc/line-number-at-pos))
(mark-line (progn (exchange-point-and-mark) (mc/line-number-at-pos)))
(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))))
(point-line (line-number-at-pos))
(mark-line (progn (exchange-point-and-mark) (line-number-at-pos)))
(direction (if (< point-line mark-line) :up :down)))
(deactivate-mark)
(when (and (eq direction :up) (bolp))
(previous-logical-line 1 nil)
(forward-line -1)
(move-to-column col))
;; Add the cursors
(while (not (eq (mc/line-number-at-pos) point-line))
;; Pad the line
(when (eq style 'pad)
(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))
(while (not (eq (line-number-at-pos) point-line))
(mc/create-fake-cursor-at-point)
(if (eq direction :up) (forward-line -1) (forward-line 1))
(move-to-column col))
(multiple-cursors-mode)))
@ -96,14 +57,16 @@ other non-nil value will cause short lines to be padded."
"Add one cursor to the end of each line in the active region."
(interactive)
(mc/edit-lines)
(mc/execute-command-for-all-cursors 'end-of-line))
(mc/execute-command-for-all-fake-cursors 'end-of-line)
(end-of-line))
;;;###autoload
(defun mc/edit-beginnings-of-lines ()
"Add one cursor to the beginning of each line in the active region."
(interactive)
(mc/edit-lines)
(mc/execute-command-for-all-cursors 'beginning-of-line))
(mc/execute-command-for-all-fake-cursors 'beginning-of-line)
(beginning-of-line))
(provide 'mc-edit-lines)

View File

@ -1,109 +0,0 @@
;;; mc-hide-unmatched-lines-mode.el -*- lexical-binding: t; -*-
;; 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\""
:init-value nil
:lighter " hu"
:keymap 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 instead of hidden 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))
(define-key mc/keymap (kbd "C-'") 'mc-hide-unmatched-lines-mode)
(provide 'mc-hide-unmatched-lines-mode)

View File

@ -1,6 +1,6 @@
;;; mc-mark-more.el -*- lexical-binding: t; -*-
;;; mc-mark-more.el
;; Copyright (C) 2012-2016 Magnar Sveen
;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com>
;; Keywords: editing cursors
@ -28,8 +28,6 @@
;;; Code:
(require 'multiple-cursors-core)
(require 'thingatpt)
(require 'sgml-mode)
(defun mc/cursor-end (cursor)
(if (overlay-get cursor 'mark-active)
@ -56,7 +54,7 @@
beg))
(defun mc/furthest-cursor-before-point ()
(let ((beg (if mark-active (min (mark) (point)) (point)))
(let ((beg (min (mark) (point)))
furthest)
(mc/for-each-fake-cursor
(when (< (mc/cursor-beg cursor) beg)
@ -65,7 +63,7 @@
furthest))
(defun mc/furthest-cursor-after-point ()
(let ((end (if mark-active (max (mark) (point)) (point)))
(let ((end (max (mark) (point)))
furthest)
(mc/for-each-fake-cursor
(when (> (mc/cursor-end cursor) end)
@ -73,18 +71,6 @@
(setq furthest cursor)))
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 ()
(let ((strings (list (buffer-substring-no-properties (point) (mark)))))
(mc/for-each-fake-cursor
@ -93,273 +79,63 @@ to (point)), or nil."
(mc/cursor-end cursor))))
strings))
(defvar mc/enclose-search-term nil
"How should mc/mark-more-* search for more matches?
Match everything: nil
Match only whole words: \\='words
Match only whole symbols: \\='symbols
Use like case-fold-search, don't recommend setting it globally.")
(defun mc/mark-more-like-this (skip-last direction)
(let ((case-fold-search nil)
(re (regexp-opt (mc/region-strings) mc/enclose-search-term))
(point-out-of-order (cl-ecase direction
(forwards (< (point) (mark)))
(backwards (not (< (point) (mark))))))
(furthest-cursor (cl-ecase direction
(forwards (mc/furthest-cursor-after-point))
(backwards (mc/furthest-cursor-before-point))))
(start-char (cl-ecase direction
(forwards (mc/furthest-region-end))
(backwards (mc/first-region-start))))
(search-function (cl-ecase direction
(forwards 'search-forward-regexp)
(backwards 'search-backward-regexp)))
(match-point-getter (cl-ecase direction
(forwards 'match-beginning)
(backwards 'match-end))))
(if (and skip-last (not furthest-cursor))
(error "No cursors to be skipped")
(mc/save-excursion
(goto-char start-char)
(when skip-last
(mc/remove-fake-cursor furthest-cursor))
(if (funcall search-function re nil t)
(progn
(push-mark (funcall match-point-getter 0))
(when point-out-of-order
(exchange-point-and-mark))
(mc/create-fake-cursor-at-point))
(user-error "no more matches found."))))))
;;;###autoload
(defun mc/mark-next-like-this (arg)
"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 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/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)
(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 'word)
(mc/mark-more-like-this (= arg 0) 'forwards)))
(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
(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 add a cursor on the next line
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p")
(let ((mc/enclose-search-term 'words))
(mc/mark-next-like-this arg)))
;;;###autoload
(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 add a cursor on the next line
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p")
(let ((mc/enclose-search-term 'symbols))
(mc/mark-next-like-this arg)))
(unless (region-active-p)
(error "Mark a region to match first."))
(when (< arg 0)
(mc/remove-fake-cursor (mc/furthest-cursor-after-point)))
(when (>= arg 0)
(let ((case-fold-search nil)
(point-first (< (point) (mark)))
(re (regexp-opt (mc/region-strings)))
(furthest-cursor (mc/furthest-cursor-after-point)))
(mc/save-excursion
(goto-char (mc/furthest-region-end))
(when (= arg 0)
(mc/remove-fake-cursor furthest-cursor))
(if (search-forward-regexp re nil t)
(progn
(push-mark (match-beginning 0))
(when point-first (exchange-point-and-mark))
(mc/create-fake-cursor-at-point))
(error "no more found forward")))))
(if (> (mc/num-cursors) 1)
(multiple-cursors-mode 1)
(multiple-cursors-mode 0)))
;;;###autoload
(defun mc/mark-previous-like-this (arg)
"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.
"Find and mark the previous part of the buffer matching the currently active region
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-before-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/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)
(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 'word)
(mc/mark-more-like-this (= arg 0) 'backwards)))
(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
(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")
(let ((mc/enclose-search-term 'words))
(mc/mark-previous-like-this arg)))
;;;###autoload
(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")
(let ((mc/enclose-search-term 'symbols))
(mc/mark-previous-like-this arg)))
(defun mc/mark-lines (num-lines direction)
(dotimes (i (if (= num-lines 0) 1 num-lines))
(mc/save-excursion
(let ((furthest-cursor (cl-ecase direction
(forwards (mc/furthest-cursor-after-point))
(backwards (mc/furthest-cursor-before-point)))))
(when (overlayp furthest-cursor)
(goto-char (overlay-get furthest-cursor '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
(defun mc/mark-next-lines (arg)
(interactive "p")
(mc/mark-lines arg 'forwards)
(mc/maybe-multiple-cursors-mode))
;;;###autoload
(defun mc/mark-previous-lines (arg)
(interactive "p")
(mc/mark-lines arg 'backwards)
(mc/maybe-multiple-cursors-mode))
;;;###autoload
(defun mc/unmark-next-like-this ()
"Deselect next part of the buffer matching the currently active region."
(interactive)
(mc/mark-next-like-this -1))
;;;###autoload
(defun mc/unmark-previous-like-this ()
"Deselect prev part of the buffer matching the currently active region."
(interactive)
(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))
(unless (region-active-p)
(error "Mark a region to match first."))
(when (< arg 0)
(mc/remove-fake-cursor (mc/furthest-cursor-before-point)))
(when (>= arg 0)
(let ((case-fold-search nil)
(point-first (< (point) (mark)))
(re (regexp-opt (mc/region-strings)))
(furthest-cursor (mc/furthest-cursor-before-point)))
(mc/save-excursion
(goto-char (mc/first-region-start))
(when (= arg 0)
(mc/remove-fake-cursor furthest-cursor))
(if (search-backward-regexp re nil t)
(progn
(push-mark (match-end 0))
(unless point-first (exchange-point-and-mark))
(mc/create-fake-cursor-at-point))
(error "no more found backward")))))
(if (> (mc/num-cursors) 1)
(multiple-cursors-mode 1)
(multiple-cursors-mode 0)))
;;;###autoload
(defun mc/mark-all-like-this ()
@ -371,7 +147,7 @@ matching the currently active region."
(let ((master (point))
(case-fold-search nil)
(point-first (< (point) (mark)))
(re (regexp-opt (mc/region-strings) mc/enclose-search-term)))
(re (regexp-opt (mc/region-strings))))
(mc/save-excursion
(goto-char 0)
(while (search-forward-regexp re nil t)
@ -382,358 +158,73 @@ matching the currently active region."
(when point-first (exchange-point-and-mark)))))
(if (> (mc/num-cursors) 1)
(multiple-cursors-mode 1)
(mc/disable-multiple-cursors-mode)))
(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)))
(multiple-cursors-mode 0)))
;;;###autoload
(defun mc/mark-all-words-like-this ()
(interactive)
(mc--select-thing-at-point-or-bark 'word)
(let ((mc/enclose-search-term 'words))
(mc/mark-all-like-this)))
;;;###autoload
(defun mc/mark-all-symbols-like-this ()
(interactive)
(mc--select-thing-at-point-or-bark 'symbol)
(let ((mc/enclose-search-term 'symbols))
(mc/mark-all-like-this)))
;;;###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"
(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))
(if (string= search "")
(message "Mark aborted")
(progn
(mc/remove-fake-cursors)
(goto-char beg)
(let ((lastmatch))
(while (search-forward search end t)
(push-mark (match-beginning 0))
(mc/create-fake-cursor-at-point)
(setq lastmatch t))
(unless lastmatch
(error "Search failed for %S" search)))
(goto-char (match-end 0))
(if (< (mc/num-cursors) 3)
(mc/disable-multiple-cursors-mode)
(mc/pop-state-from-overlay (mc/furthest-cursor-before-point))
(multiple-cursors-mode 1))))))
;;;###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)
(mc/disable-multiple-cursors-mode)
(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))))
(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)
(mc/remove-fake-cursors)
(goto-char beg)
(while (search-forward search end t)
(push-mark (match-beginning 0))
(mc/create-fake-cursor-at-point))
(let ((first (mc/furthest-cursor-before-point)))
(if (not first)
(error "Search failed for %S" search)
(mc/pop-state-from-overlay first))))
(if (> (mc/num-cursors) 1)
(multiple-cursors-mode 1)
(multiple-cursors-mode 0)))
;;;###autoload
(defun mc/mark-more-like-this-extended ()
"Like mark-more-like-this, but then lets you adjust with arrow keys.
The adjustments work like this:
"Like mark-more-like-this, but then lets you adjust with arrows key.
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
<down> Mark next like this and set direction to \\='down
<up> Mark previous like this
<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:
<left> Skip past the cursor furthest up
<right> Remove the cursor furthest up
If direction is \\='down:
<left> Remove the cursor furthest down
<right> Skip past the cursor furthest down
The bindings for these commands can be changed.
See `mc/mark-more-like-this-extended-keymap'."
Then, continue to read input events and further add or move marks
as long as the input event read (with all modifiers removed)
is one of the above."
(interactive)
(mc/mmlte--down)
(set-transient-map mc/mark-more-like-this-extended-keymap t))
(defvar mc/mark-more-like-this-extended-direction nil
"When using mc/mark-more-like-this-extended
are we working on the next or previous cursors?")
(make-variable-buffer-local 'mc/mark-more-like-this-extended)
(defun mc/mmlte--message ()
(if (eq mc/mark-more-like-this-extended-direction 'up)
(message "<up> to mark previous, <left> to skip, <right> to remove, <down> to mark next")
(message "<down> to mark next, <right> to skip, <left> to remove, <up> to mark previous")))
(defun mc/mmlte--up ()
(interactive)
(mc/mark-previous-like-this 1)
(setq mc/mark-more-like-this-extended-direction 'up)
(mc/mmlte--message))
(defun mc/mmlte--down ()
(interactive)
(mc/mark-next-like-this 1)
(setq mc/mark-more-like-this-extended-direction 'down)
(mc/mmlte--message))
(defun mc/mmlte--left ()
(interactive)
(if (eq mc/mark-more-like-this-extended-direction 'down)
(mc/unmark-next-like-this)
(mc/skip-to-previous-like-this))
(mc/mmlte--message))
(defun mc/mmlte--right ()
(interactive)
(if (eq mc/mark-more-like-this-extended-direction 'up)
(mc/unmark-previous-like-this)
(mc/skip-to-next-like-this))
(mc/mmlte--message))
(defvar mc--restrict-mark-all-to-symbols nil)
;;;###autoload
(defun mc/mark-all-like-this-dwim (arg)
"Tries to guess what you want to mark all of.
Can be pressed multiple times to increase selection.
With prefix, it behaves the same as original `mc/mark-all-like-this'"
(interactive "P")
(if arg
(mc/mark-all-like-this)
(if (and (not (use-region-p))
(derived-mode-p 'sgml-mode)
(mc--on-tag-name-p))
(mc/mark-sgml-tag-pair)
(let ((before (mc/num-cursors)))
(unless (eq last-command 'mc/mark-all-like-this-dwim)
(setq mc--restrict-mark-all-to-symbols nil))
(unless (use-region-p)
(mc--mark-symbol-at-point)
(setq mc--restrict-mark-all-to-symbols t))
(if mc--restrict-mark-all-to-symbols
(mc/mark-all-symbols-like-this-in-defun)
(mc/mark-all-like-this-in-defun))
(when (<= (mc/num-cursors) before)
(if mc--restrict-mark-all-to-symbols
(mc/mark-all-symbols-like-this)
(mc/mark-all-like-this)))
(when (<= (mc/num-cursors) before)
(mc/mark-all-like-this))))))
;;;###autoload
(defun mc/mark-all-dwim (arg)
"Tries even harder to guess what you want to mark all of.
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 (= (mc/line-number-at-pos (region-beginning))
(mc/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 ()
(bounds-of-thing-at-point 'defun))
;;;###autoload
(defun mc/mark-all-like-this-in-defun ()
"Mark all like this in defun."
(interactive)
(if (mc--in-defun)
(save-restriction
(widen)
(narrow-to-defun)
(mc/mark-all-like-this))
(mc/mark-all-like-this)))
;;;###autoload
(defun mc/mark-all-words-like-this-in-defun ()
"Mark all words like this in defun."
(interactive)
(mc--select-thing-at-point-or-bark 'word)
(if (mc--in-defun)
(save-restriction
(widen)
(narrow-to-defun)
(mc/mark-all-words-like-this))
(mc/mark-all-words-like-this)))
;;;###autoload
(defun mc/mark-all-symbols-like-this-in-defun ()
"Mark all symbols like this in defun."
(interactive)
(mc--select-thing-at-point-or-bark 'symbol)
(if (mc--in-defun)
(save-restriction
(widen)
(narrow-to-defun)
(mc/mark-all-symbols-like-this))
(mc/mark-all-symbols-like-this)))
(defun mc--mark-symbol-at-point ()
"Select the symbol under cursor"
(interactive)
(when (not (use-region-p))
(let ((b (bounds-of-thing-at-point 'symbol)))
(goto-char (car b))
(set-mark (cdr b)))))
(defun mc--get-nice-sgml-context ()
(car
(last
(progn
(when (looking-at "<") (forward-char 1))
(when (looking-back ">" 1) (forward-char -1))
(sgml-get-context)))))
(defun mc--on-tag-name-p ()
(let* ((context (save-excursion (mc--get-nice-sgml-context)))
(tag-name-len (length (aref context 4)))
(beg (aref context 2))
(end (+ beg tag-name-len (if (eq 'open (aref context 1)) 1 3))))
(and context
(>= (point) beg)
(<= (point) end))))
;;;###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
(defun mc/mark-sgml-tag-pair ()
"Mark the tag we're in and its pair for renaming."
(interactive)
(when (not (mc--inside-tag-p))
(error "Place point inside tag to rename."))
(let ((context (mc--get-nice-sgml-context)))
(if (looking-at "</")
(setq context (car (last (sgml-get-context)))))
(goto-char (aref context 2))
(let* ((tag-name (aref context 4))
(num-chars (length tag-name))
(master-start (1+ (point)))
(mirror-end (save-excursion
(sgml-skip-tag-forward 1)
(1- (point)))))
(goto-char (- mirror-end num-chars))
(set-mark mirror-end)
(mc/create-fake-cursor-at-point)
(goto-char master-start)
(set-mark (+ (point) num-chars))))
(mc/maybe-multiple-cursors-mode))
(defun mc--inside-tag-p ()
(save-excursion
(not (null (sgml-get-context)))))
(let ((first t)
(ev last-command-event)
(cmd 'mc/mark-next-like-this)
(arg 1)
last echo-keystrokes)
(while cmd
(let ((base (event-basic-type ev)))
(cond ((eq base 'left)
(if (eq last 'mc/mark-previous-like-this)
(setq cmd last arg 0)
(setq cmd 'mc/mark-next-like-this arg -1)))
((eq base 'up)
(setq cmd 'mc/mark-previous-like-this arg 1))
((eq base 'right)
(if (eq last 'mc/mark-next-like-this)
(setq cmd last arg 0)
(setq cmd 'mc/mark-previous-like-this arg -1)))
((eq base 'down)
(setq cmd 'mc/mark-next-like-this arg 1))
(first
(setq cmd 'mc/mark-next-like-this arg 1))
(t
(setq cmd nil))))
(when cmd
(ignore-errors
(funcall cmd arg))
(setq first nil last cmd)
(setq ev (read-event "Use arrow keys for more marks: "))))
(push ev unread-command-events)))
(provide 'mc-mark-more)

View File

@ -1,22 +0,0 @@
;;; mc-mark-pop.el --- Pop cursors off of the mark stack -*- lexical-binding: t; -*-
(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

View File

@ -1,151 +0,0 @@
;;; mc-separate-operations.el - functions that work differently on each cursor -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2016 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.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 file contains functions that work differently on each cursor,
;; instead of treating all of them the same.
;; Please see multiple-cursors.el for more commentary.
;;; Code:
(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
(defun mc/insert-numbers (arg)
"Insert increasing numbers for each cursor, starting at
`mc/insert-numbers-default' or ARG."
(interactive "P")
(setq mc--insert-numbers-number (or (and arg (prefix-numeric-value arg))
mc/insert-numbers-default))
(mc/for-each-cursor-ordered
(mc/execute-command-for-fake-cursor 'mc--insert-number-and-increase cursor)))
(defun mc--insert-number-and-increase ()
(interactive)
(insert (number-to-string mc--insert-numbers-number))
(setq mc--insert-numbers-number (1+ mc--insert-numbers-number)))
(defun mc--ordered-region-strings ()
(let (strings)
(save-excursion
(mc/for-each-cursor-ordered
(setq strings (cons (buffer-substring-no-properties
(mc/cursor-beg cursor)
(mc/cursor-end cursor)) 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)
(defun mc--replace-region-strings-1 ()
(interactive)
(delete-region (region-beginning) (region-end))
(save-excursion (insert (car mc--strings-to-replace)))
(setq mc--strings-to-replace (cdr mc--strings-to-replace)))
(defun mc--replace-region-strings ()
(mc/for-each-cursor-ordered
(mc/execute-command-for-fake-cursor 'mc--replace-region-strings-1 cursor)))
;;;###autoload
(defun mc/reverse-regions ()
(interactive)
(if (not multiple-cursors-mode)
(progn
(mc/mark-next-lines 1)
(mc/reverse-regions)
(mc/disable-multiple-cursors-mode)
)
(unless (use-region-p)
(mc/execute-command-for-all-cursors 'mark-sexp))
(setq mc--strings-to-replace (nreverse (mc--ordered-region-strings)))
(mc--replace-region-strings)))
;;;###autoload
(defun mc/sort-regions ()
(interactive)
(unless (use-region-p)
(mc/execute-command-for-all-cursors 'mark-sexp))
(setq mc--strings-to-replace (sort (mc--ordered-region-strings) 'string<))
(mc--replace-region-strings))
;;;###autoload
(defun mc/vertical-align (character)
"Aligns all cursors vertically with a given CHARACTER to the one with the
highest column 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)
;;; mc-separate-operations.el ends here

File diff suppressed because it is too large Load Diff

2
multiple-cursors-pkg.el Normal file
View File

@ -0,0 +1,2 @@
(define-package "multiple-cursors" "1.1.3"
"Multiple cursors for Emacs.")

View File

@ -1,12 +1,9 @@
;;; multiple-cursors.el --- Multiple cursors for emacs. -*- lexical-binding: t; -*-
;;; 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>
;; Package-Version: 1.5.0
;; Package-Requires: ((cl-lib "0.5"))
;; Keywords: editing cursors
;; Homepage: https://github.com/magnars/multiple-cursors.el
;; 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
@ -24,178 +21,114 @@
;;; Commentary:
;; Multiple cursors for Emacs. This is some pretty crazy functionality, so yes,
;; there are kinks. Don't be afraid though, 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.
;;
;; ## Basic usage
;;
;; Start out with:
;;
;; (require 'multiple-cursors)
;; Then you have to set up your keybindings - multiple-cursors doesn't presume to
;; know how you'd like them laid out. Here are some examples:
;;
;; When you have an active region that spans multiple lines, the following will
;; add a cursor to each line:
;;
;; (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
;;
;; When you want to add multiple cursors not based on continuous lines, but based on
;; keywords in the buffer, use:
;;
;; (global-set-key (kbd "C->") 'mc/mark-next-like-this)
;; (global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
;; (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
;;
;; First mark the word, then add more cursors.
;;
;; 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
;; insert a newline in multiple-cursors-mode, use `C-j`.
;; ## Video
;; You can [watch an intro to multiple-cursors at Emacs Rocks](http://emacsrocks.com/e13.html).
;; ## Command overview
;; ### 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-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-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-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-more-like-this-extended`: Use arrow keys to quickly mark/skip next/previous occurrences.
;; - `mc/add-cursor-on-click`: Bind to a mouse event to add cursors by clicking. See tips-section.
;; ### Mark many occurrences
;; - `mc/mark-all-like-this`: Marks all parts of the buffer that matches the current region.
;; - `mc/mark-all-words-like-this`: Like `mc/mark-all-like-this` but only for whole words.
;; - `mc/mark-all-symbols-like-this`: Like `mc/mark-all-like-this` but only for whole symbols.
;; - `mc/mark-all-in-region`: Prompts for a string to match in the region, adding cursors to all of them.
;; - `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-symbols-like-this-in-defun`: Like `mc/mark-all-like-this-in-defun` but only for whole symbols.
;; - `mc/mark-all-like-this-dwim`: Tries to be smart about marking everything you want. Can be pressed multiple times.
;; ### Special
;; - `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/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/reverse-regions`: Reverse the order of the marked regions.
;; ## Tips and tricks
;; - 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
;; insert a newline in multiple-cursors-mode, use `C-j`.
;;
;; - 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`.
;;
;; - Try pressing `mc/mark-next-like-this` with no region selected. It will just add a cursor
;; on the next line.
;; ## More commands to play around with
;;
;; - 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 occurrence
;; I've set up my key-bindings like so:
;;
;; - Try pressing `mc/mark-all-like-this-dwim` on a tagname in html-mode.
;; ;; From active region to multiple cursors:
;; (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
;; (global-set-key (kbd "C-S-c C-e") 'mc/edit-ends-of-lines)
;; (global-set-key (kbd "C-S-c C-a") 'mc/edit-beginnings-of-lines)
;;
;; - Notice that the number of cursors active can be seen in the modeline.
;; When you have an active region that spans multiple lines, the preceeding three
;; commands will add one cursor to each line.
;;
;; - If you get out of multiple-cursors-mode and yank - it will yank only
;; from the kill-ring of main cursor. To yank from the kill-rings of
;; every cursor use yank-rectangle, normally found at C-x r y.
;; ;; Rectangular region mode
;; (global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor)
;;
;; - 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.
;; Think of this one as `set-mark` except you're marking a rectangular region. It is
;; an exceedingly quick way of adding multiple cursors to multiple lines.
;;
;; - 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).
;; ;; Mark more like this
;; (global-set-key (kbd "M-æ") 'mc/mark-all-like-this)
;; (global-set-key (kbd "C-å") 'mc/mark-previous-like-this)
;; (global-set-key (kbd "C-æ") 'mc/mark-next-like-this)
;; (global-set-key (kbd "C-Æ") 'mc/mark-more-like-this-extended)
;; (global-set-key (kbd "M-å") 'mc/mark-all-in-region)
;;
;; Okay, yes, I have a crazy norwegian keyboard. Regardless, these will look at
;; whatever you've got selected at the moment, and mark more places like that in
;; the buffer.
;;
;; 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`.
;; ### 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
;;
;; Multiple-cursors uses two lists of commands to know what to do: the run-once list
;; and the run-for-all list. It comes with a set of defaults, but it would be beyond silly
;; to try and include all the known Emacs commands.
;;
;; So that's why multiple-cursors occasionally asks what to do about a command. It will
;; then remember your choice by saving it in `~/.emacs.d/.mc-lists.el`. You can change
;; the location with:
;;
;; (setq mc/list-file "/my/preferred/file")
;;
;;
;; ## Known limitations
;;
;; * isearch-forward and isearch-backward aren't supported with multiple cursors.
;; 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.
;; * 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.
;; * Redo might screw with your cursors. Undo works very well.
;;
;;
;; ## Contribute
;;
;; Yes, please do. There's a suite of tests, so remember to add tests for your
;; specific feature, or I might break it later.
;;
;; You'll find the repo at:
;;
;; https://github.com/magnars/multiple-cursors.el
;;
;; To fetch the test dependencies:
;;
;; $ cd /path/to/multiple-cursors
;; $ git submodule update --init
;;
;; Run the tests with:
;;
;; $ ./util/ecukes/ecukes --graphical
;; ## Contributors
;; * [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.
;; * [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`
;; Thanks!
;;
;;; Code:
(defgroup multiple-cursors nil
"Multiple cursors for emacs."
:group 'editing)
(require 'mc-edit-lines)
(require 'mc-cycle-cursors)
(require 'mc-mark-more)
(require 'mc-mark-pop)
(require 'rectangular-region-mode)
(require 'mc-separate-operations)
(provide 'multiple-cursors)

View File

@ -1,6 +1,6 @@
;;; rectangular-region-mode.el -*- lexical-binding: t; -*-
;;; rectangular-region-mode.el
;; Copyright (C) 2012-2016 Magnar Sveen
;; Copyright (C) 2012 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com>
;; 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 "<return>") 'rrm/switch-to-multiple-cursors)
(defvar rectangular-region-mode nil)
(defun rrm/keyboard-quit ()
"Exit rectangular-region-mode."
(interactive)
@ -52,9 +50,8 @@
(defun set-rectangular-region-anchor ()
"Anchors the rectangular region at point.
Think of this one as `set-mark' except you're marking a
rectangular region. It is an exceedingly quick way of adding
multiple cursors to multiple lines."
Think of this one as `set-mark' except you're marking a rectangular region. It is
an exceedingly quick way of adding multiple cursors to multiple lines."
(interactive)
(set-marker rrm/anchor (point))
(push-mark (point))
@ -70,30 +67,27 @@ multiple cursors to multiple lines."
(defun rrm/repaint ()
"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)
(let* ((annoying-arrows-mode nil)
(point-column (current-column))
(point-line (mc/line-number-at-pos))
(anchor-column (save-excursion (goto-char rrm/anchor) (current-column)))
(anchor-line (save-excursion (goto-char rrm/anchor) (mc/line-number-at-pos)))
(left-column (if (< point-column anchor-column) point-column anchor-column))
(right-column (if (> point-column anchor-column) point-column anchor-column))
(navigation-step (if (< point-line anchor-line) 1 -1)))
(move-to-column anchor-column)
(set-mark (point))
(move-to-column point-column)
(mc/save-excursion
(while (not (= anchor-line (mc/line-number-at-pos)))
(forward-line navigation-step)
(move-to-column anchor-column)
(when (= anchor-column (current-column))
(set-mark (point))
(move-to-column point-column)
(when (= point-column (current-column))
(mc/create-fake-cursor-at-point))))))))
(rrm/remove-rectangular-region-overlays)
(let* ((annoying-arrows-mode nil)
(point-column (current-column))
(point-line (line-number-at-pos))
(anchor-column (save-excursion (goto-char rrm/anchor) (current-column)))
(anchor-line (save-excursion (goto-char rrm/anchor) (line-number-at-pos)))
(left-column (if (< point-column anchor-column) point-column anchor-column))
(right-column (if (> point-column anchor-column) point-column anchor-column))
(navigation-step (if (< point-line anchor-line) 1 -1)))
(move-to-column anchor-column)
(set-mark (point))
(move-to-column point-column)
(mc/save-excursion
(while (not (= anchor-line (line-number-at-pos)))
(forward-line navigation-step)
(move-to-column anchor-column)
(when (= anchor-column (current-column))
(set-mark (point))
(move-to-column point-column)
(when (= point-column (current-column))
(mc/create-fake-cursor-at-point)))))))
(defun rrm/switch-to-multiple-cursors (&rest forms)
"Switch from rectangular-region-mode to multiple-cursors-mode."
@ -109,12 +103,9 @@ multiple cursors to multiple lines."
(when rectangular-region-mode
(rrm/switch-to-multiple-cursors)))
;;;###autoload
(define-minor-mode rectangular-region-mode
"A mode for creating a rectangular region to edit"
:init-value nil
:lighter " rr"
:keymap rectangular-region-mode-map
nil " rr" rectangular-region-mode-map
(if rectangular-region-mode
(progn
(add-hook 'after-change-functions 'rrm/switch-to-multiple-cursors t t)

View File

@ -1,2 +0,0 @@
#!/bin/sh -e
cask exec ecukes "$@" --no-win

View File

@ -7,13 +7,13 @@ end
def run_all_tests
system('clear')
result = run "./run-tests.sh"
result = run "./util/ecukes/ecukes --graphical"
puts result
end
def run_test(file)
system('clear')
result = run "./run-tests.sh #{file} --verbose"
result = run "./util/ecukes/ecukes --graphical #{file}"
puts result
end

20
run-travis-ci.sh Executable file
View File

@ -0,0 +1,20 @@
#!/bin/sh
cd "$(dirname "$0")"
set_default () {
eval "
if [ -z \$$1 ]; then
$1=$2
fi
"
}
set_default ECUKES_EMACS "$(which emacs)"
echo "*** Emacs version ***"
echo "ECUKES_EMACS =" $(which $ECUKES_EMACS)
$ECUKES_EMACS --version
echo
exec ./util/ecukes/ecukes --graphical

1
util/ecukes Submodule

@ -0,0 +1 @@
Subproject commit b2c449cf01163df3aa41f401b9aeac4887b3177c

2544
util/ert.el Normal file

File diff suppressed because it is too large Load Diff

1
util/espuds Submodule

@ -0,0 +1 @@
Subproject commit 62ef75cb51eef76c547d33a81cb2b6b6e384aefc