110 Commits

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

Fixes #84
2013-06-07 23:18:19 +02:00
Magnar Sveen 94af07453d Add some readability enhancing step definitions 2013-06-07 08:03:05 +02:00
Magnar Sveen cb848b2a39 Add @smithzvk to contributors list
Closes #80
2013-05-27 05:52:38 +02:00
Magnar Sveen 474838666a Make mc/mark-pop only run once per invocation 2013-05-27 05:51:59 +02:00
Zach Kost-Smith 53db250b43 Added a mark-pop.feature file. 2013-05-26 16:08:21 -05:00
Zach Kost-Smith 75df47fc4a Added mention of mc/mark-pop to README.md 2013-05-26 16:07:27 -05:00
Zach Kost-Smith 4535033952 Added a new function mc/mark-pop that sets cursors by popping marks off the mark stack. 2013-05-26 14:34:58 -05:00
Magnar Sveen 69c99618f9 Use Carton for dev dependencies 2013-05-18 08:16:23 +02:00
Magnar Sveen 7a236d174e Add flyspell-mode to unsupported minor modes 2013-05-08 11:00:42 +02:00
Magnar Sveen 374244b66e Add support for C-s and C-r when phi-search is installed 2013-05-08 11:00:10 +02:00
Magnar Sveen 8b91e4788c Add py-electric-backspace to run-for-all list
- backspace = no in the prompt, causing people not to notice the prompt
2013-04-08 08:42:23 +02:00
Magnar Sveen bf0177205e Use phi-search for C-s in mc-mode when available. 2013-03-28 19:41:08 +01:00
Magnar Sveen 6e159238b2 Use uninterned symbols in macros to avoid surprising local vars 2013-03-21 10:17:50 +01:00
Magnar Sveen 9dac934bce Fix scrolling behavior in Emacs 24. 2013-03-21 10:09:41 +01:00
Magnar Sveen ccb42b5d70 Inline defun for better readability. 2013-03-15 20:21:34 +01:00
Magnar Sveen 8a53db8a39 Merge pull request #64 from tarsius/master
add .nosearch to directory with bundled libraries
2013-03-12 13:52:35 -07:00
Jonas Bernoulli 72ba43a08e add .nosearch to directory with bundled libraries
And move ert.el to that directory.
2013-03-12 21:40:43 +01:00
Magnar Sveen 16589a5af2 Update README.md 2013-03-10 07:58:04 +01:00
Magnar Sveen 980a8808dd Merge pull request #63 from tkf/select-thing-at-point
Automatically select word/symbol
2013-03-09 22:54:22 -08:00
Magnar Sveen ed18fa49c1 Merge pull request #62 from tkf/export-ECUKES_EMACS
Export $ECUKES_EMACS
2013-03-09 22:41:12 -08:00
Takafumi Arakaki 1cdd73037f Automatically select word/symbol 2013-03-10 06:53:53 +01:00
Takafumi Arakaki aa9a1ece7b Add failing scenarios for mark-all-symbols/words 2013-03-10 06:52:12 +01:00
Takafumi Arakaki 25dd14d350 Add more scenarios for mark-all-*-like-this 2013-03-10 06:49:25 +01:00
Takafumi Arakaki 373dcbe002 Add a scenario for mc/mark-all-symbols-like-this 2013-03-10 06:44:18 +01:00
Takafumi Arakaki d24ddc53ea Default ECUKES_EMACS to $EMACS
Otherwise, $EMACS set on .travis.yml is not used in test.
2013-03-10 06:17:30 +01:00
Takafumi Arakaki 5c60757080 export ECUKES_EMACS in run-travis-ci.sh 2013-03-10 06:12:07 +01:00
Magnar Sveen a6e0ccb22f mc/add-cursor-on-click should not run per cursor
Fixes #60
2013-02-26 21:38:26 +01:00
Magnar Sveen 0ee76bfad1 Add mc/add-cursor-on-click 2013-02-20 07:05:18 +01:00
Magnar Sveen e7a5fe61c4 Release 1.2.1 2013-02-11 07:32:09 +01:00
Magnar Sveen 641eb680ca Can use mc/reverse-regions w/o region or cursors
- will flip sexp at point with the one below it
2013-02-11 07:29:17 +01:00
Magnar Sveen 16add89d29 Bugfix for sort/reverse regions w/similar contents 2013-02-11 07:28:26 +01:00
Magnar Sveen cb7a145153 Release 1.2.0 2013-02-10 21:15:35 +01:00
Magnar Sveen 82a1fe3746 Add mc/sort-regions and mc/reverse-regions 2013-02-10 21:04:09 +01:00
Magnar Sveen 56839dfdca Update docs with mc/edit-*-lines 2013-02-07 05:36:22 +01:00
Magnar Sveen 3f3cdc6c92 Merge pull request #56 from paradoxxxzero/transient-mark-mode
Add transient-mark-mode to mc/cursor-specific-vars to fix other selections than C-SPC.
2013-02-01 02:57:19 -08:00
Florian Mounier 5190e0cdc6 Add test case for shift-select-mode 2013-02-01 11:52:21 +01:00
Florian Mounier a4f6ea179a Add transient-mark-mode to mc/cursor-specific-vars to fix other selections than C-SPC. Fixes #55 2013-01-30 16:34:48 +01:00
Magnar Sveen 9582c7220b Add mc/insert-numbers
- adds increasing numbers for each cursor, top to bottom
2013-01-23 12:05:18 +01:00
Magnar Sveen a6984a1141 Merge pull request #53 from oneself/master
Adding support for using mc/edit-lines without transient mark mode.
2013-01-23 00:31:28 -08:00
Eyal Erez 6a5969e14a Adding support for using mc/edit-lines without transient mark mode. 2013-01-22 15:30:01 -05:00
Magnar Sveen 9a376a6fa2 Add note about yank-rectangle
- thanks to @snosov1 for the text
2013-01-19 08:29:31 +01:00
Magnar Sveen bfb293f200 Merge pull request #48 from tkf/smartrep
Avoid strange behavior with smartrep
2012-12-12 13:12:51 -08:00
Takafumi Arakaki 3ce6e4a670 Avoid strange behavior with smartrep
smartrep `intern`s commands into own obarray to help
`describe-bindings`, but this is bad for multiple-cursors as it makes
impossible to compare command with `memq` (`eq`).  This patch
re-`intern's the command to make the command comparable by `eq'.
2012-12-12 20:55:51 +01:00
Magnar Sveen 424e0667a4 1.1.5 2012-12-02 08:29:52 +01:00
Magnar Sveen f1a5a39b48 Merge pull request #46 from tkf/fix-dump-list-take-2
Fix mc/dump-list (take 2): it looses old setting
2012-12-01 22:34:14 -08:00
Takafumi Arakaki 84ab4ee26a Fix mc/dump-list (take 2): it looses old setting
In the old code, heading part of `value` may lost due to in-place
modification by the `sort` function. ``(symbol-value list-symbol)``
must be re-evaluated before passing it to `mapc`.  To do that,
simply replacing `let` to `symbol-macrolet` works.

See also: #40
2012-12-01 22:01:02 +01:00
Magnar Sveen 07b88080b1 Merge pull request #43 from purcell/travis-script
Simplify travis script, and make it work when ECUKES_EMACS has spaces
2012-11-27 11:03:38 -08:00
Magnar Sveen e7605bbd7c Merge pull request #42 from purcell/cleanup
Fix byte-compilation warnings, and avoid unnecessary use of "eval"
2012-11-27 11:03:22 -08:00
Steve Purcell dc0aa99459 Simplify travis run script, and make it work when ECUKES_EMACS has a space in the path
Yes, on OS X, one might have:

ECUKES_EMACS='/Applications/Emacs 23.app/Contents/MacOS/Emacs'
2012-11-27 16:35:43 +00:00
Steve Purcell 6339657440 Fix byte-compilation warnings, and avoid unnecessary use of "eval"
multiple-cursors-core.el:28:1:Warning: cl package required at runtime

In mc/store-cursor-specific-var:
multiple-cursors-core.el:127:35:Warning: reference to free variable `o'

In mc/restore-cursor-specific-var:
multiple-cursors-core.el:130:44:Warning: reference to free variable `o'
2012-11-27 14:04:36 +00:00
Magnar Sveen 94164f706a Merge pull request #41 from purcell/patch-1
Prevent byte-compilation warnings 'cl functions
2012-11-26 03:28:46 -08:00
Steve Purcell 52300ff852 Prevent byte-compilation warnings 'cl functions
Prevents the following senseless warnings:

    In mc/first-fake-cursor-after:
    mc-cycle-cursors.el:76:70:Warning: function `remove-if' from cl package called
        at runtime
    mc-cycle-cursors.el:78:64:Warning: function `sort*' from cl package called at
        runtime

    In mc/last-fake-cursor-before:
    mc-cycle-cursors.el:85:71:Warning: function `remove-if' from cl package called
        at runtime
    mc-cycle-cursors.el:87:65:Warning: function `sort*' from cl package called at
        runtime
2012-11-26 11:21:27 +00:00
Magnar Sveen 129ea778cc 1.1.4 2012-11-25 09:23:14 +01:00
Magnar Sveen 0b9aae12ca Merge pull request #40 from tkf/fix-dump-list
Fix: mc/dump-list loosing old setting
2012-11-25 00:12:57 -08:00
Takafumi Arakaki fa753aa587 Fix: mc/dump-list loosing old setting 2012-11-24 23:27:46 +01:00
Magnar Sveen bc8af45bfe Use derived-mode-p to check for sgml-mode-ishness. 2012-11-21 13:22:27 +01:00
Magnar Sveen b218a13cf7 Run tests in Emacs 23, Emacs 24 and snapshot. 2012-11-19 20:12:09 +01:00
Magnar Sveen 0a081a7c5f Move mc/maybe-multiple-cursors-mode to core. 2012-11-18 21:10:09 +01:00
Magnar Sveen 839c6ef077 Update README with command overview and tips-n-tricks. 2012-11-18 16:36:45 +01:00
Magnar Sveen 7d79b983ea Autoload new functions. 2012-11-18 16:08:10 +01:00
Magnar Sveen 717c97e32b Added Fuco to list of contributors 2012-11-18 14:47:48 +01:00
Magnar Sveen c010afbbef Rename mc/mark-sgml-tags to mc/mark-sgml-tag-pair 2012-11-18 14:45:25 +01:00
Magnar Sveen f721308591 Tweak mc/mark-all-like-this-dwim and add tests 2012-11-18 14:43:39 +01:00
unknown 1074c88c99 Added mc/mark-all-like-this-dwim 2012-10-27 20:33:51 +02:00
Magnar Sveen a37e02b907 Add new mc-commands to default run-once list.
Fixes #36
2012-10-27 09:13:09 +02:00
Magnar Sveen fe211c018c Add word/symbol limiting mark-more functions:
- mc/mark-next-word-like-this
 - mc/mark-next-symbol-like-this
 - mc/mark-previous-word-like-this
 - mc/mark-previous-symbol-like-this
 - mc/mark-all-words-like-this
 - mc/mark-all-symbols-like-this

Fixes #24
2012-10-26 22:51:40 +02:00
Magnar Sveen 1afbb9317c Add mc/cycle-looping-behaviour to multiple-cursors custom group. 2012-10-26 22:15:12 +02:00
Magnar Sveen dce6c00fab Add mc/cursor-specific-vars to handle vars that need to be tracked per cursor.
- also add autopair-vars to this list.

Fixes #32
2012-10-25 10:57:58 +02:00
Magnar Sveen 5f7c92bb74 Add more backward-delete commands to run-for-all 2012-10-25 10:22:25 +02:00
Magnar Sveen 6b09b9c73f Add some more basic commands to the run-all and run-once lists. 2012-10-24 19:20:03 +02:00
Magnar Sveen b3ca408f52 Have to require 'cl for now, because of count-if. 2012-10-24 08:10:22 +02:00
Magnar Sveen 7382b462b2 Merge pull request #30 from gvol/master
Fixed mode-line not showing up
2012-10-20 15:27:38 -07:00
Ivan Andrus be4067da45 Fixed mode-line not showing up 2012-10-21 00:24:00 +02:00
Magnar Sveen 65d4f873fe Added Ivan Andrus to list of contributors 2012-10-21 00:54:04 +03:00
Magnar Sveen dce196ce9f Merge pull request #28 from gvol/master
Show number of cursors in mode-line
2012-10-20 14:49:04 -07:00
Ivan Andrus bb546b11d8 Display number of cursors in mode-line 2012-10-20 22:01:34 +02:00
Magnar Sveen 796fb640e1 Added segv to contributors list 2012-10-13 09:24:18 +03:00
Magnar Sveen c3b2d8483b Merge pull request #23 from segv/master
Improve mc/cycle and mc/mark-next/prev
2012-10-12 10:26:46 -07:00
Marco Baringer 2818d9e7ef Rename mc/(first|last)-cursor-(before|after)-point to mention that they operate on fake cursors 2012-10-12 17:07:55 +02:00
Marco Baringer 1ec78e195f Don't let mc/mark-lines create 'double' cursors.
Previously using mc/mark-lines in a fowards/backwards/forwards
combination would cause multiple cursors to be placed at the same
point of the same line. This is not useful behaviour.

Noted while implementing magnars suggestion: https://github.com/magnars/multiple-cursors.el/pull/23#commitcomment-1983183
2012-10-12 17:04:36 +02:00
Marco Baringer 038c9a7f03 Added stop as a possible value for mc/cycle-looping-behaviour.
Simply disables looping (no warning either).
2012-10-12 16:56:01 +02:00
Marco Baringer 19b1a83925 Refactor mc/first-cursor-after and mc/last-cursor-before to not use extreme.
Sometimes imperative code is more readable.
Suggested by magnars (https://github.com/magnars/multiple-cursors.el/pull/23#commitcomment-1983268)
2012-10-12 16:51:01 +02:00
Marco Baringer a8b632386d Remove superfluous lambda.
Caught by magnars (https://github.com/magnars/multiple-cursors.el/pull/23#commitcomment-1983191)
2012-10-12 16:27:39 +02:00
Marco Baringer e4adefc04e Fix issues with mc/cycle-(backward|forward) where the cycling was dependent on not having an active mark.
This patch also adds two utility functions mc/first-cursor-after and mc/last-cursor-before.
2012-10-10 13:39:28 +02:00
Marco Baringer 324d9354b5 Split macro mc/for-each-fake-cursor into a function returning all the cursor overlays and a macro to loop over this list. 2012-10-10 13:38:47 +02:00
Marco Baringer 80ebdbb35b Added test for mc/mark-(next|previous)-like-this when there is no active region. 2012-10-10 13:37:40 +02:00
Marco Baringer 9ac7675c78 Added tests for mc/cycle-forward and mc/cycle-backward with their new looping behaviour 2012-10-10 13:36:45 +02:00
Marco Baringer 3f20fc15a7 When no region is active mc/mark-next-like-this and mc/mark-previous-like-this should create a cursor one like up (or down).
Added the functions mc/mark-next-lines and mc/mark-previous-lines
which create cursors one line above and below point.

Refactored common mc/mark-previous-like-this and
mc/mark-next-like-this functionality into mc/mark-more-like-this.

Changed mc/mark-next-like-this and mc/mark-more-like-this to call
mc/mark-next-lines and mc/mark-previous-lines when there is no
active region (instead of erroring).
2012-10-10 11:15:22 +02:00
Marco Baringer 876937bfa3 Use (interactive "P") instead of the weird (but equivalent) (interactive (list prefix-arg)) 2012-10-10 10:04:22 +02:00
Marco Baringer fcbb7a4df9 Make mc/cycle-forward and mc/cycle-backward loop around by default.
Instead of erroring if there is no next (respectively previous) cursor
mc/cycle-forward (respectively mc/cycle-backward) will just loop back
to the first (respectively last) cursor.
2012-10-10 09:24:19 +02:00
Magnar Sveen a0f771f3e4 Include interactive commands for deselecting prev/next
Fixes #21
2012-10-04 07:47:31 +02:00
Magnar Sveen 879ddb0e97 Add Takafumi Arakaki to list of contributors 2012-10-03 20:12:56 +03:00
Magnar Sveen 6e9ea1ae52 Merge pull request #20 from tkf/diff-friendly-save-lists
Diff friendly .mc-lists.el
2012-10-03 10:10:41 -07:00
Magnar Sveen 8a12e97b7d Mention region-bindings-mode in README 2012-10-03 20:06:15 +03:00
Takafumi Arakaki f4d5aea860 Sort before saving list in mc/save-lists 2012-10-03 18:50:29 +02:00
Takafumi Arakaki 00f905549e Add mc/dump-list to make mc/save-lists diff-friendly 2012-10-03 18:47:31 +02:00
Magnar Sveen 7a6eb0df90 Never execute keyboard macros for fake cursors.
- The real cursor will execute the keyboard macro, resulting in new
   commands in the command loop, and the fake cursors can pick up on
   those instead.

Fixes #18
2012-10-02 12:19:00 +02:00
Magnar Sveen 6d4979db46 Bump to 1.1.3 2012-09-28 07:26:17 +02:00
Magnar Sveen f040a33e3c Add execute-extended-command to run-once list 2012-09-28 07:24:38 +02:00
Magnar Sveen 64ffd81491 Add quoted-insert to run-for-all list. 2012-09-27 19:44:48 +02:00
Magnar Sveen 97da9778fd Intercept some reading commands
- so you won't have to answer them for every single cursor

Fixes #15
2012-09-27 19:42:38 +02:00
Magnar Sveen ae0033fe3d Protect post-command-hook from errors to avoids undead cursors 2012-09-27 18:53:57 +02:00
Magnar Sveen 5fcc69cc54 Skip keyboard macros
- since they will generate actual commands that are also run in the
   command loop - we'll handle those later instead.
2012-09-27 18:53:05 +02:00
31 changed files with 1574 additions and 2878 deletions
+1
View File
@@ -0,0 +1 @@
elpa
-6
View File
@@ -1,6 +0,0 @@
[submodule "util/ecukes"]
path = util/ecukes
url = git://github.com/rejeep/ecukes.git
[submodule "util/espuds"]
path = util/espuds
url = git://github.com/rejeep/espuds.git
+11 -2
View File
@@ -1,12 +1,21 @@
language: emacs-lisp
before_install:
- if [ "$ECUKES_EMACS" = 'emacs-snapshot' ]; then
- if [ "$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
- if [ "$EMACS" = 'emacs24' ]; then
sudo add-apt-repository -y ppa:cassou/emacs &&
sudo apt-get update -qq &&
sudo apt-get install -qq
emacs24 emacs24-el emacs24-common-non-dfsg;
fi
- curl -fsSkL https://raw.github.com/rejeep/carton/master/go | sh
- export PATH="/home/travis/.carton/bin:$PATH"
- carton
env:
- ECUKES_EMACS=emacs
- EMACS=emacs24 TAGS=""
script:
./run-travis-ci.sh
+8
View File
@@ -0,0 +1,8 @@
(source "melpa" "http://melpa.milkbox.net/packages/")
(package-file "multiple-cursors.el")
(development
(depends-on "ecukes")
(depends-on "espuds")
(depends-on "wrap-region"))
+86 -27
View File
@@ -35,42 +35,90 @@ 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).
## More commands to play around with
## Command overview
I've set up my key-bindings like so:
### Mark one more occurrence
;; 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)
- `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-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 occurances.
- `mc/add-cursor-on-click`: Bind to a mouse event to add cursors by clicking. See tips-section.
- `mc/pop-mark`: Set a cursor at the current point and move to the next (different) position on the mark stack. This allows for fine grained control over the placement of cursors.
When you have an active region that spans multiple lines, the preceeding three
commands will add one cursor to each line.
### Juggle around with the current cursors
;; Rectangular region mode
(global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor)
- `mc/unmark-next-like-this`: Remove the cursor furthest down in the buffer.
- `mc/unmark-previous-like-this`: Remove the cursor furthest up in the buffer.
- `mc/skip-to-next-like-this`: Remove the cursor furthest down, marking the next occurance down.
- `mc/skip-to-previous-like-this`: Remove the cursor furthest up, marking the next occurance up.
- `mc/mark-next-like-this-extended`: Temporarily bind the arrow keys to mark/unmark/skip cursors.
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.
### Mark many occurrences
;; 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)
- `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-like-this-dwim`: Tries to be smart about marking everything you want. Can be pressed multiple times.
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.
### 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/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.
- 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.
- 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).
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`.
## Scrolling
### Binding mouse events
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`.
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
@@ -104,15 +152,26 @@ You'll find the repo at:
https://github.com/magnars/multiple-cursors.el
To fetch the test dependencies:
To fetch the test dependencies, install
[carton](https://github.com/rejeep/carton) if you haven't already,
then:
$ cd /path/to/multiple-cursors
$ git submodule update --init
$ carton
Run the tests with:
$ ./util/ecukes/ecukes --graphical
$ ./run-tests.sh
## 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
* [Fuco](https://github.com/Fuco1) added the first version of `mc/mark-all-like-this-dwim`
* [Zach Kost-Smith](https://github.com/smithzvk) added `mc/mark-pop`
Thanks!
## License
+13
View File
@@ -42,3 +42,16 @@ 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
+13
View File
@@ -0,0 +1,13 @@
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)"
+94
View File
@@ -0,0 +1,94 @@
Feature: Mark all do-what-I-mean (html)
Background:
Given I turn on html-mode
And I turn on delete-selection-mode
And I insert:
"""
<body>
<div class="abc"> def </div>
<div class="ghi"> jkl </div>
</body>
"""
Scenario: Marks tags in html-mode, from front
When I go to the front of the word "abc"
And I press "M-b"
And I press "M-b"
And I press "M-$"
And I type "h1"
Then I should see:
"""
<body>
<h1 class="abc"> def </h1>
<div class="ghi"> jkl </div>
</body>
"""
Scenario: Marks tags in html-mode, from back
When I go to the end of the word "jkl"
And I press "M-f"
And I press "M-$"
And I type "h1"
Then I should see:
"""
<body>
<div class="abc"> def </div>
<h1 class="ghi"> jkl </h1>
</body>
"""
Scenario: Marks tags in html-mode, from outside front
When I go to the front of the word "abc"
And I press "M-b"
And I press "M-b"
And I press "C-b"
And I press "M-$"
And I type "h1"
Then I should see:
"""
<body>
<h1 class="abc"> def </h1>
<div class="ghi"> jkl </div>
</body>
"""
Scenario: Marks tags in html-mode, from outside back
When I go to the end of the word "jkl"
And I press "M-f"
And I press "C-f"
And I press "M-$"
And I type "h1"
Then I should see:
"""
<body>
<div class="abc"> def </div>
<h1 class="ghi"> jkl </h1>
</body>
"""
Scenario: Marks words in html-mode
When I go to the front of the word "abc"
And I press "M-$"
And I type "def"
Then I should see:
"""
<body>
<div class="def"> def </div>
<div class="ghi"> jkl </div>
</body>
"""
Scenario: Marks words in html-mode
When I go to the front of the word "abc"
And I press "M-$"
And I type "def"
And I press "M-$"
And I type "hah"
Then I should see:
"""
<body>
<div class="hah"> hah </div>
<div class="ghi"> jkl </div>
</body>
"""
+38
View File
@@ -0,0 +1,38 @@
Feature: Mark all do-what-I-mean
Scenario: Mark symbols in defun
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I go to the end of the word "abc"
And I press "M-f"
And I press "M-$"
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
Scenario: Mark all symbols by pressing twice
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message ghi))
"""
When I go to the end of the word "abc"
And I press "M-f"
And I press "M-$"
And I press "M-$"
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message hmm))
"""
+48
View File
@@ -94,3 +94,51 @@ 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"
+88
View File
@@ -0,0 +1,88 @@
Feature: Popping cursors off of the mark stack
Scenario: Single pop
Given I turn off transient-mark-mode
And I insert:
"""
hello
there
"""
And I go to the front of the word "hello"
And I set the mark
And I go to the front of the word "there"
And I press "M-x mc/mark-pop"
Then I should have 2 cursors
Scenario: Multiple pops
Given I turn off transient-mark-mode
And I insert:
"""
hello
there, my friend
"""
And I go to the front of the word "hello"
And I set the mark
And I go to the front of the word "my"
And I set the mark
And I go to the front of the word "friend"
And I press "M-x mc/mark-pop"
And I press "M-x mc/mark-pop"
Then I should have 3 cursors
Scenario: Discard identical mark and point
Given I turn off transient-mark-mode
And I insert:
"""
hello
there, my friend
"""
And I go to the front of the word "hello"
And I set the mark
And I go to the front of the word "my"
And I set the mark
And I go to the front of the word "friend"
And I set the mark
And I press "M-x mc/mark-pop"
And I press "M-x mc/mark-pop"
Then I should have 3 cursors
Scenario: Changing the text
Given I turn off transient-mark-mode
And I insert:
"""
hello
there, my friend
"""
And I go to the front of the word "hello"
And I set the mark
And I go to the front of the word "my"
And I set the mark
And I go to the front of the word "friend"
And I press "M-x mc/mark-pop"
And I press "M-x mc/mark-pop"
And I type "!"
Then I should see:
"""
!hello
there, !my !friend
"""
Scenario: With transient-mark-mode
And I insert:
"""
hello
there, my friend
"""
And I go to the front of the word "hello"
And I press "C-@ C-@"
And I go to the front of the word "my"
And I press "C-@ C-@"
And I go to the front of the word "friend"
And I press "M-x mc/mark-pop"
And I press "M-x mc/mark-pop"
And I type "!"
Then I should see:
"""
!hello
there, !my !friend
"""
+137
View File
@@ -0,0 +1,137 @@
Feature: Mark things
Scenario: Mark all symbols like this with select
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I select "ghi"
And I mark all symbols like this
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-ghi))
"""
Scenario: Mark all words like this with select
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I select "ghi"
And I mark all words like this
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-hmm))
"""
Scenario: Mark all symbols like this in defun with select
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I select "ghi"
And I mark all symbols like this in defun
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
Scenario: Mark all words like this in defun with select
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I select "ghi"
And I mark all words like this in defun
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
Scenario: Mark all symbols like this with no select
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I go to word "ghi"
And I mark all symbols like this
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-ghi))
"""
Scenario: Mark all words like this with no select
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I go to word "ghi"
And I mark all words like this
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (hmm) (message some-other-hmm))
"""
Scenario: Mark all symbols like this in defun with no select
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I go to word "ghi"
And I mark all symbols like this in defun
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
Scenario: Mark all words like this in defun with no select
Given I turn on emacs-lisp-mode
And I turn on delete-selection-mode
And I insert:
"""
(defun abc (ghi) (message ghi))
(defun def (ghi) (message some-other-ghi))
"""
When I go to word "ghi"
And I mark all words like this in defun
And I type "hmm"
Then I should see:
"""
(defun abc (hmm) (message hmm))
(defun def (ghi) (message some-other-ghi))
"""
+32 -1
View File
@@ -115,10 +115,27 @@ Feature: Multiple cursors core
And I go to the front of the word "text"
And I press "C-SPC"
And I press "M-f"
And I press "C->"
And I mark next like this
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"
When I press "C-!"
When I press "C-!"
Then I should see "This __text contains the word __text twice"
Scenario: Interprogram paste
Given I have cursors at "text" in "This text contains the word text twice"
When I copy "external" in another program
@@ -141,3 +158,17 @@ Feature: Multiple cursors core
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 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"
+19
View File
@@ -0,0 +1,19 @@
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)"
@@ -1,7 +1,41 @@
(When "^I mark next like this$"
(lambda () (call-interactively 'mc/mark-next-like-this)))
(When "^I mark previous like this$"
(lambda () (call-interactively 'mc/mark-previous-like-this)))
(When "^I mark all like this$"
(lambda () (call-interactively 'mc/mark-all-like-this)))
(When "^I mark all like this dwim$"
(lambda () (call-interactively 'mc/mark-all-like-this-dwim)))
(When "^I mark all in region$"
(lambda () (call-interactively 'mc/mark-all-in-region)))
(When "^I insert numbers$"
(lambda () (call-interactively 'mc/insert-numbers)))
(When "^I reverse regions$"
(lambda () (call-interactively 'mc/reverse-regions)))
(When "^I sort regions$"
(lambda () (call-interactively 'mc/sort-regions)))
(When "^I edit lines$"
(lambda () (call-interactively 'mc/edit-lines)))
(When "^I set rectangular region anchor$"
(lambda () (call-interactively 'set-rectangular-region-anchor)))
(And "^delete-selection-mode is active$"
(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)))
@@ -68,6 +102,11 @@
(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 keyboard macro that insert \"_\"$"
(lambda ()
(fset 'mc-test-temp-kmacro "\C-q_")
(global-set-key (kbd "C-!") 'mc-test-temp-kmacro)))
(When "^I go to character \"\\(.+\\)\"$"
(lambda (char)
(goto-char (point-min))
@@ -90,3 +129,11 @@
(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))))
+7
View File
@@ -7,10 +7,12 @@
(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,7 +23,11 @@
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "M-!") 'mc/mark-all-like-this)
(global-set-key (kbd "M-$") 'mc/mark-all-like-this-dwim)
(global-set-key (kbd "M-#") 'mc/mark-all-in-region)
(global-set-key (kbd "H-0") 'mc/insert-numbers)
(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
@@ -31,6 +37,7 @@
(cua-mode 0)
(delete-selection-mode 0)
(subword-mode 0)
(wrap-region-mode 0)
(setq set-mark-default-inactive nil)
(deactivate-mark))
+56 -14
View File
@@ -30,7 +30,7 @@
(eval-when-compile (require 'cl))
(defun mc/next-cursor-after-point ()
(defun mc/next-fake-cursor-after-point ()
(let ((pos (point))
(next-pos (point-max))
next)
@@ -42,7 +42,7 @@
(setq next cursor))))
next))
(defun mc/prev-cursor-before-point ()
(defun mc/prev-fake-cursor-before-point ()
(let ((pos (point))
(prev-pos (point-min))
prev)
@@ -54,27 +54,69 @@
(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)
(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 (remove-if (lambda (cursor)
(< (mc/cursor-beg cursor) point))
cursors))
(cursors-in-order (sort* cursors-after-point '< :key 'mc/cursor-beg)))
(first 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 (remove-if (lambda (cursor)
(> (mc/cursor-end cursor) point))
cursors))
(cursors-in-order (sort* cursors-before-point '> :key 'mc/cursor-end)))
(first cursors-in-order)))
(defun* mc/cycle (next-cursor fallback-cursor loop-message)
(when (null next-cursor)
(when (eql 'stop (mc/handle-loop-condition loop-message))
(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)
(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)))
(mc/cycle (mc/next-fake-cursor-after-point)
(mc/first-fake-cursor-after (point-min))
"We're already at the last cursor."))
(defun mc/cycle-backward ()
(interactive)
(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)))
(mc/cycle (mc/prev-fake-cursor-before-point)
(mc/last-fake-cursor-before (point-max))
"We're already at the last cursor"))
(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
;; byte-compile-warnings: (not cl-functions)
;; End:
;;; mc-cycle-cursors.el ends here
+3 -5
View File
@@ -35,7 +35,7 @@
Starts from mark and moves in straight down or up towards the
line point is on."
(interactive)
(when (not (use-region-p))
(when (not (and mark-active (/= (point) (mark))))
(error "Mark a set of lines first."))
(mc/remove-fake-cursors)
(let* ((col (current-column))
@@ -57,16 +57,14 @@ line point is on."
"Add one cursor to the end of each line in the active region."
(interactive)
(mc/edit-lines)
(mc/execute-command-for-all-fake-cursors 'end-of-line)
(end-of-line))
(mc/execute-command-for-all-cursors '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-fake-cursors 'beginning-of-line)
(beginning-of-line))
(mc/execute-command-for-all-cursors 'beginning-of-line))
(provide 'mc-edit-lines)
+382 -85
View File
@@ -28,6 +28,7 @@
;;; Code:
(require 'multiple-cursors-core)
(require 'thingatpt)
(defun mc/cursor-end (cursor)
(if (overlay-get cursor 'mark-active)
@@ -79,34 +80,69 @@
(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 (ecase direction
(forwards (< (point) (mark)))
(backwards (not (< (point) (mark))))))
(furthest-cursor (ecase direction
(forwards (mc/furthest-cursor-after-point))
(backwards (mc/furthest-cursor-before-point))))
(start-char (ecase direction
(forwards (mc/furthest-region-end))
(backwards (mc/first-region-start))))
(search-function (ecase direction
(forwards 'search-forward-regexp)
(backwards 'search-backward-regexp)))
(match-point-getter (ecase direction
(forwards 'match-beginning)
(backwards 'match-end))))
(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))
(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
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p")
(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)))
(if (region-active-p)
(if (< arg 0)
(mc/remove-fake-cursor (mc/furthest-cursor-after-point))
(mc/mark-more-like-this (= arg 0) 'forwards))
(mc/mark-lines arg 'forwards))
(mc/maybe-multiple-cursors-mode))
;;;###autoload
(defun mc/mark-next-word-like-this (arg)
(interactive "p")
(let ((mc/enclose-search-term 'words))
(mc/mark-next-like-this arg)))
;;;###autoload
(defun mc/mark-next-symbol-like-this (arg)
(interactive "p")
(let ((mc/enclose-search-term 'symbols))
(mc/mark-next-like-this arg)))
;;;###autoload
(defun mc/mark-previous-like-this (arg)
@@ -114,28 +150,69 @@ With zero ARG, skip the last one and mark next."
With negative ARG, delete the last one instead.
With zero ARG, skip the last one and mark next."
(interactive "p")
(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)))
(if (region-active-p)
(if (< arg 0)
(mc/remove-fake-cursor (mc/furthest-cursor-before-point))
(mc/mark-more-like-this (= arg 0) 'backwards))
(mc/mark-lines arg 'backwards))
(mc/maybe-multiple-cursors-mode))
;;;###autoload
(defun mc/mark-previous-word-like-this (arg)
(interactive "p")
(let ((mc/enclose-search-term 'words))
(mc/mark-previous-like-this arg)))
;;;###autoload
(defun mc/mark-previous-symbol-like-this (arg)
(interactive "p")
(let ((mc/enclose-search-term 'symbols))
(mc/mark-previous-like-this arg)))
(defun mc/mark-lines (num-lines direction)
(dotimes (i num-lines)
(mc/create-fake-cursor-at-point)
(ecase direction
(forwards (loop do (next-line 1 nil)
while (mc/all-fake-cursors (point) (1+ (point)))))
(backwards (loop do (previous-line 1 nil)
while (mc/all-fake-cursors (point) (1+ (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))
;;;###autoload
(defun mc/mark-all-like-this ()
@@ -147,7 +224,7 @@ With zero ARG, skip the last one and mark next."
(let ((master (point))
(case-fold-search nil)
(point-first (< (point) (mark)))
(re (regexp-opt (mc/region-strings))))
(re (regexp-opt (mc/region-strings) mc/enclose-search-term)))
(mc/save-excursion
(goto-char 0)
(while (search-forward-regexp re nil t)
@@ -160,6 +237,31 @@ With zero ARG, skip the last one and mark next."
(multiple-cursors-mode 1)
(multiple-cursors-mode 0)))
(defun mc--select-thing-at-point (thing)
(let ((bound (bounds-of-thing-at-point thing)))
(when bound
(set-mark (car bound))
(goto-char (cdr bound))
bound)))
(defun mc--select-thing-at-point-or-bark (thing)
(unless (or (region-active-p) (mc--select-thing-at-point thing))
(error "Mark a region or set cursor on a %s." thing)))
;;;###autoload
(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)
"Find and mark all the parts in the region matching the given search"
@@ -179,52 +281,247 @@ With zero ARG, skip the last one and mark next."
(multiple-cursors-mode 1)
(multiple-cursors-mode 0)))
(when (not (fboundp 'set-temporary-overlay-map))
;; Backport this function from newer emacs versions
(defun set-temporary-overlay-map (map &optional keep-pred)
"Set a new keymap that will only exist for a short period of time.
The new keymap to use must be given in the MAP variable. When to
remove the keymap depends on user input and KEEP-PRED:
- if KEEP-PRED is nil (the default), the keymap disappears as
soon as any key is pressed, whether or not the key is in MAP;
- if KEEP-PRED is t, the keymap disappears as soon as a key *not*
in MAP is pressed;
- otherwise, KEEP-PRED must be a 0-arguments predicate that will
decide if the keymap should be removed (if predicate returns
nil) or kept (otherwise). The predicate will be called after
each key sequence."
(let* ((clearfunsym (make-symbol "clear-temporary-overlay-map"))
(overlaysym (make-symbol "t"))
(alist (list (cons overlaysym map)))
(clearfun
`(lambda ()
(unless ,(cond ((null keep-pred) nil)
((eq t keep-pred)
`(eq this-command
(lookup-key ',map
(this-command-keys-vector))))
(t `(funcall ',keep-pred)))
(remove-hook 'pre-command-hook ',clearfunsym)
(setq emulation-mode-map-alists
(delq ',alist emulation-mode-map-alists))))))
(set overlaysym overlaysym)
(fset clearfunsym clearfun)
(add-hook 'pre-command-hook clearfunsym)
(push alist emulation-mode-map-alists))))
;;;###autoload
(defun mc/mark-more-like-this-extended ()
"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:
The adjustments work like this:
<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
<up> Mark previous like this and set direction to 'up
<down> Mark next like this and set direction to 'down
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."
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'."
(interactive)
(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)))
(mc/mmlte--down)
(set-temporary-overlay-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/mark-more-like-this-extended-keymap (make-sparse-keymap))
(define-key mc/mark-more-like-this-extended-keymap (kbd "<up>") 'mc/mmlte--up)
(define-key mc/mark-more-like-this-extended-keymap (kbd "<down>") 'mc/mmlte--down)
(define-key mc/mark-more-like-this-extended-keymap (kbd "<left>") 'mc/mmlte--left)
(define-key mc/mark-more-like-this-extended-keymap (kbd "<right>") 'mc/mmlte--right)
(defvar mc--restrict-mark-all-to-symbols nil)
;;;###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))))))
(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 ">") (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/add-cursor-on-click (event)
"Add a cursor where you click."
(interactive "e")
(mouse-minibuffer-check event)
;; Use event-end in case called from mouse-drag-region.
;; If EVENT is a click, event-end and event-start give same value.
(let ((position (event-end event)))
(if (not (windowp (posn-window position)))
(error "Position not in text area of window"))
(select-window (posn-window position))
(if (numberp (posn-point position))
(save-excursion
(goto-char (posn-point position))
(mc/create-fake-cursor-at-point)))
(mc/maybe-multiple-cursors-mode)))
;;;###autoload
(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)))))
(provide 'mc-mark-more)
+23
View File
@@ -0,0 +1,23 @@
;;; mc-mark-pop.el --- Pop cursors off of the mark stack
(require 'multiple-cursors-core)
;;;###autoload
(defun mc/mark-pop ()
"Add one cursor to each line of the active region.
Starts from mark and moves in straight down or up towards the
line point is on."
(interactive)
;; If the mark happens to be at the current point, just pop that one off.
(while (eql (mark) (point))
(pop-mark))
(mc/create-fake-cursor-at-point)
(exchange-point-and-mark)
(pop-mark)
(mc/maybe-multiple-cursors-mode))
;; A good key binding for this feature is perhaps "C-S-p" ('p' for pop).
(provide 'mc-mark-pop)
;;; mc-mark-pop.el ends here
+90
View File
@@ -0,0 +1,90 @@
;;; mc-separate-operations.el - functions that work differently on each cursor
;; Copyright (C) 2012 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)
;;;###autoload
(defun mc/insert-numbers (arg)
"Insert increasing numbers for each cursor, starting at 0 or ARG."
(interactive "P")
(setq mc--insert-numbers-number (or arg 0))
(mc/for-each-cursor-ordered
(mc/execute-command-for-fake-cursor 'mc--insert-number-and-increase cursor)))
(defvar mc--insert-numbers-number 0)
(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--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)
(multiple-cursors-mode 0))
(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))
(provide 'mc-separate-operations)
;;; mc-separate-operations.el ends here
+236 -105
View File
@@ -25,7 +25,7 @@
;;; Code:
(eval-when-compile (require 'cl))
(require 'cl)
(require 'rect)
@@ -41,52 +41,61 @@
(defmacro mc/add-fake-cursor-to-undo-list (&rest forms)
"Make sure point is in the right place when undoing"
`(let ((undo-cleaner (cons 'apply (cons 'deactivate-cursor-after-undo (list id)))))
(setq buffer-undo-list (cons undo-cleaner buffer-undo-list))
,@forms
(if (eq undo-cleaner (car buffer-undo-list)) ;; if nothing has been added to the undo-list
(setq buffer-undo-list (cdr buffer-undo-list)) ;; then pop the cleaner right off again
(setq buffer-undo-list ;; otherwise add a function to activate this cursor
(cons (cons 'apply (cons 'activate-cursor-for-undo (list id))) buffer-undo-list)))))
(let ((uc (make-symbol "undo-cleaner")))
`(let ((,uc (cons 'apply (cons 'deactivate-cursor-after-undo (list id)))))
(setq buffer-undo-list (cons ,uc buffer-undo-list))
,@forms
(if (eq ,uc (car buffer-undo-list)) ;; if nothing has been added to the undo-list
(setq buffer-undo-list (cdr buffer-undo-list)) ;; then pop the cleaner right off again
(setq buffer-undo-list ;; otherwise add a function to activate this cursor
(cons (cons 'apply (cons 'activate-cursor-for-undo (list id))) buffer-undo-list))))))
(defun mc/all-fake-cursors (&optional start end)
(remove-if-not 'mc/fake-cursor-p
(overlays-in (or start (point-min))
(or end (point-max)))))
(defmacro mc/for-each-fake-cursor (&rest forms)
"Runs the body for each fake cursor, bound to the name cursor"
`(mapc #'(lambda (cursor)
(when (mc/fake-cursor-p cursor)
,@forms))
(overlays-in (point-min) (point-max))))
`(mapc #'(lambda (cursor) ,@forms)
(mc/all-fake-cursors)))
(defmacro mc/save-excursion (&rest forms)
"Saves and restores all the state that multiple-cursors cares about."
`(let ((current-state (mc/store-current-state-in-overlay
(make-overlay (point) (point) nil nil t))))
(overlay-put current-state 'type 'original-cursor)
(save-excursion ,@forms)
(mc/pop-state-from-overlay current-state)))
(let ((cs (make-symbol "current-state")))
`(let ((,cs (mc/store-current-state-in-overlay
(make-overlay (point) (point) nil nil t))))
(overlay-put ,cs 'type 'original-cursor)
(save-excursion ,@forms)
(mc/pop-state-from-overlay ,cs))))
(defun mc--compare-by-overlay-start (o1 o2)
(< (overlay-start o1) (overlay-start o2)))
(defmacro mc/for-each-cursor-ordered (&rest forms)
"Runs the body for each cursor, fake and real, bound to the name cursor"
`(let ((real-cursor (mc/create-fake-cursor-at-point)))
(mapc #'(lambda (cursor)
(when (mc/fake-cursor-p cursor)
,@forms))
(sort (overlays-in (point-min) (point-max)) 'mc--compare-by-overlay-start))
(mc/pop-state-from-overlay real-cursor)))
(let ((rci (make-symbol "real-cursor-id")))
`(let ((,rci (overlay-get (mc/create-fake-cursor-at-point) 'mc-id)))
(mapc #'(lambda (cursor)
(when (mc/fake-cursor-p cursor)
,@forms))
(sort (overlays-in (point-min) (point-max)) 'mc--compare-by-overlay-start))
(mc/pop-state-from-overlay (mc/cursor-with-id ,rci)))))
(defmacro mc/save-window-scroll (&rest forms)
"Saves and restores the window scroll position"
`(let ((p (set-marker (make-marker) (point)))
(start (set-marker (make-marker) (window-start)))
(hscroll (window-hscroll)))
,@forms
(goto-char p)
(set-window-start nil start)
(set-window-hscroll nil hscroll)
(set-marker p nil)
(set-marker start nil)))
(let ((p (make-symbol "p"))
(s (make-symbol "start"))
(h (make-symbol "hscroll")))
`(let ((,p (set-marker (make-marker) (point)))
(,s (set-marker (make-marker) (window-start)))
(,h (window-hscroll)))
,@forms
(goto-char ,p)
(set-window-start nil ,s t)
(set-window-hscroll nil ,h)
(set-marker ,p nil)
(set-marker ,s nil))))
(defun mc/make-cursor-overlay-at-eol (pos)
"Create overlay to look like cursor at end of line."
@@ -115,30 +124,32 @@ highlights the entire width of the window."
(overlay-put overlay 'type 'additional-region)
overlay))
(defvar mc/cursor-specific-vars '(transient-mark-mode
kill-ring
kill-ring-yank-pointer
mark-ring
mark-active
yank-undo-function
kill-ring-yank-pointer
autopair-action
autopair-wrap-action
er/history)
"A list of vars that need to be tracked on a per-cursor basis.")
(defun mc/store-current-state-in-overlay (o)
"Store relevant info about point and mark in the given overlay."
(overlay-put o 'point (set-marker (make-marker) (point)))
(overlay-put o 'kill-ring kill-ring)
(overlay-put o 'kill-ring-yank-pointer kill-ring-yank-pointer)
(overlay-put o 'mark (set-marker (make-marker) (mark)))
(overlay-put o 'mark-ring mark-ring)
(overlay-put o 'mark-active mark-active)
(overlay-put o 'yank-undo-function yank-undo-function)
(overlay-put o 'kill-ring-yank-pointer kill-ring-yank-pointer)
(when (boundp 'er/history) (overlay-put o 'er/history er/history))
(dolist (var mc/cursor-specific-vars)
(when (boundp var) (overlay-put o var (symbol-value var))))
o)
(defun mc/restore-state-from-overlay (o)
"Restore point and mark from stored info in the given overlay."
(goto-char (overlay-get o 'point))
(setq kill-ring (overlay-get o 'kill-ring))
(setq kill-ring-yank-pointer (overlay-get o 'kill-ring-yank-pointer))
(set-marker (mark-marker) (overlay-get o 'mark))
(setq mark-ring (overlay-get o 'mark-ring))
(setq mark-active (overlay-get o 'mark-active))
(setq yank-undo-function (overlay-get o 'yank-undo-function))
(setq kill-ring-yank-pointer (overlay-get o 'kill-ring-yank-pointer))
(when (boundp 'er/history) (setq er/history (overlay-get o 'er/history))))
(dolist (var mc/cursor-specific-vars)
(when (boundp var) (set var (overlay-get o var)))))
(defun mc/remove-fake-cursor (o)
"Delete overlay with state, including dependent overlays and markers."
@@ -183,10 +194,22 @@ Saves the current state in the overlay to be restored later."
(run-hooks 'pre-command-hook)
(unless (eq this-command 'ignore)
(call-interactively cmd))
(run-hooks 'post-command-hook)
(when deactivate-mark (deactivate-mark)))
(defvar mc--executing-command-for-fake-cursor nil)
(defun mc/execute-command-for-fake-cursor (cmd cursor)
(let ((mc--executing-command-for-fake-cursor t)
(id (overlay-get cursor 'mc-id))
(annoying-arrows-mode nil)
(smooth-scroll-margin 0))
(mc/add-fake-cursor-to-undo-list
(mc/pop-state-from-overlay cursor)
(ignore-errors
(mc/execute-command cmd)
(mc/create-fake-cursor-at-point id)))))
(defun mc/execute-command-for-all-fake-cursors (cmd)
"Calls CMD interactively for each cursor.
It works by moving point to the fake cursor, setting
@@ -197,15 +220,36 @@ cursor with updated info."
(mc/save-window-scroll
(mc/for-each-fake-cursor
(save-excursion
(let ((mc--executing-command-for-fake-cursor t)
(id (overlay-get cursor 'mc-id))
(annoying-arrows-mode nil)
(smooth-scroll-margin 0))
(mc/add-fake-cursor-to-undo-list
(mc/pop-state-from-overlay cursor)
(ignore-errors
(mc/execute-command cmd)
(mc/create-fake-cursor-at-point id)))))))))
(mc/execute-command-for-fake-cursor cmd cursor)))))
(mc--reset-read-prompts))
(defun mc/execute-command-for-all-cursors (cmd)
"Calls CMD interactively for the real cursor and all fakes."
(call-interactively cmd)
(mc/execute-command-for-all-fake-cursors cmd))
;; Intercept some reading commands so you won't have to
;; answer them for every single cursor
(defadvice read-char (around mc-support activate)
(if (not multiple-cursors-mode)
ad-do-it
(unless mc--read-char
(setq mc--read-char ad-do-it))
(setq ad-return-value mc--read-char)))
(defadvice read-quoted-char (around mc-support activate)
(if (not multiple-cursors-mode)
ad-do-it
(unless mc--read-quoted-char
(setq mc--read-quoted-char ad-do-it))
(setq ad-return-value mc--read-quoted-char)))
(defun mc--reset-read-prompts ()
(setq mc--read-char nil)
(setq mc--read-quoted-char nil))
(mc--reset-read-prompts)
(defun mc/fake-cursor-p (o)
"Predicate to check if an overlay is a fake cursor"
@@ -262,10 +306,27 @@ been remapped. And certain modes (cua comes to mind) will change their
remapping based on state. So a command that changes the state will afterwards
not be recognized through the command-remapping lookup."
(unless mc--executing-command-for-fake-cursor
(setq mc--this-command (or (command-remapping this-original-command)
this-original-command))))
(let (cmd (or (command-remapping this-original-command)
this-original-command))
(setq mc--this-command (and (not (eq cmd 'god-mode-self-insert))
cmd)))))
(defun mc/execute-this-command-for-all-cursors ()
"Wrap around `mc/execute-this-command-for-all-cursors-1' to protect hook."
(condition-case error
(mc/execute-this-command-for-all-cursors-1)
(error
(message "[mc] problem in `mc/execute-this-command-for-all-cursors': %s"
(error-message-string error)))))
;; execute-kbd-macro should never be run for fake cursors. The real cursor will
;; execute the keyboard macro, resulting in new commands in the command loop,
;; and the fake cursors can pick up on those instead.
(defadvice execute-kbd-macro (around skip-fake-cursors activate)
(unless mc--executing-command-for-fake-cursor
ad-do-it))
(defun mc/execute-this-command-for-all-cursors-1 ()
"Used with post-command-hook to execute supported commands for all cursors.
It uses two lists of commands to know what to do: the run-once
@@ -274,31 +335,43 @@ it will prompt for the proper action and then save that preference.
Some commands are so unsupported that they are even prevented for
the original cursor, to inform about the lack of support."
(if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode
(multiple-cursors-mode 0)
(unless mc--executing-command-for-fake-cursor
(when this-original-command
(let ((original-command (or mc--this-command
(command-remapping this-original-command)
this-original-command)))
(if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode
(multiple-cursors-mode 0)
(when this-original-command
(let ((original-command (or mc--this-command
(command-remapping this-original-command)
this-original-command)))
;; if it's a lambda, we can't know if it's supported or not
;; - so go ahead and assume it's ok, because we're just optimistic like that
(if (not (symbolp original-command))
(mc/execute-command-for-all-fake-cursors original-command)
;; skip keyboard macros, since they will generate actual commands that are
;; also run in the command loop - we'll handle those later instead.
(when (functionp original-command)
;; otherwise it's a symbol, and we can be more thorough
(if (get original-command 'mc--unsupported)
(message "%S is not supported with multiple cursors%s"
original-command
(get original-command 'mc--unsupported))
(when (and original-command
(not (memq original-command mc--default-cmds-to-run-once))
(not (memq original-command mc/cmds-to-run-once))
(or (memq original-command mc--default-cmds-to-run-for-all)
(memq original-command mc/cmds-to-run-for-all)
(mc/prompt-for-inclusion-in-whitelist original-command)))
(mc/execute-command-for-all-fake-cursors original-command))))))))
;; if it's a lambda, we can't know if it's supported or not
;; - so go ahead and assume it's ok, because we're just optimistic like that
(if (or (not (symbolp original-command))
;; lambda registered by smartrep
(string-prefix-p "(" (symbol-name original-command)))
(mc/execute-command-for-all-fake-cursors original-command)
;; smartrep `intern's commands into own obarray to help
;; `describe-bindings'. So, let's re-`intern' here to
;; make the command comparable by `eq'.
(setq original-command (intern (symbol-name original-command)))
;; otherwise it's a symbol, and we can be more thorough
(if (get original-command 'mc--unsupported)
(message "%S is not supported with multiple cursors%s"
original-command
(get original-command 'mc--unsupported))
(when (and original-command
(not (memq original-command mc--default-cmds-to-run-once))
(not (memq original-command mc/cmds-to-run-once))
(or (memq original-command mc--default-cmds-to-run-for-all)
(memq original-command mc/cmds-to-run-for-all)
(mc/prompt-for-inclusion-in-whitelist original-command)))
(mc/execute-command-for-all-fake-cursors original-command))))))))))
(defun mc/remove-fake-cursors ()
"Remove all fake cursors.
@@ -318,19 +391,22 @@ you should disable multiple-cursors-mode."
"Keymap while multiple cursors are active.
Main goal of the keymap is to rebind C-g and <return> to conclude
multiple cursors editing.")
(if mc/keymap
nil
(unless mc/keymap
(setq mc/keymap (make-sparse-keymap))
(define-key mc/keymap (kbd "C-g") 'mc/keyboard-quit)
(define-key mc/keymap (kbd "<return>") 'multiple-cursors-mode))
(define-key mc/keymap (kbd "<return>") 'multiple-cursors-mode)
(when (fboundp 'phi-search)
(define-key mc/keymap (kbd "C-s") 'phi-search))
(when (fboundp 'phi-search-backward)
(define-key mc/keymap (kbd "C-r") 'phi-search-backward)))
(defun mc--all-equal (entries)
"Are all these entries equal?"
(let ((first (car entries))
(defun mc--all-equal (list)
"Are all the items in LIST equal?"
(let ((first (car list))
(all-equal t))
(while (and all-equal entries)
(setq all-equal (equal first (car entries)))
(setq entries (cdr entries)))
(while (and all-equal list)
(setq all-equal (equal first (car list)))
(setq list (cdr list)))
all-equal))
(defun mc--kill-ring-entries ()
@@ -348,7 +424,7 @@ So you can paste it in later with `yank-rectangle'."
(unless (mc--all-equal entries)
(setq killed-rectangle entries))))
(defvar mc/unsupported-minor-modes '(auto-complete-mode)
(defvar mc/unsupported-minor-modes '(auto-complete-mode flyspell-mode)
"List of minor-modes that does not play well with multiple-cursors.
They are temporarily disabled when multiple-cursors are active.")
@@ -372,9 +448,16 @@ They are temporarily disabled when multiple-cursors are active.")
(mapc 'mc/enable-minor-mode mc/temporarily-disabled-minor-modes)
(setq mc/temporarily-disabled-minor-modes nil))
(defcustom mc/mode-line
`(" mc:" (:eval (format ,(propertize "%d" 'face 'font-lock-warning-face)
(mc/num-cursors))))
"What to display in the mode line while multiple-cursors-mode is active."
:group 'multiple-cursors)
(put 'mc/mode-line 'risky-local-variable t)
(define-minor-mode multiple-cursors-mode
"Mode while multiple cursors are active."
nil " mc" mc/keymap
nil mc/mode-line mc/keymap
(if multiple-cursors-mode
(progn
(mc/temporarily-disable-unsupported-minor-modes)
@@ -391,6 +474,12 @@ They are temporarily disabled when multiple-cursors are active.")
(add-hook 'after-revert-hook #'(lambda () (multiple-cursors-mode 0)))
(defun mc/maybe-multiple-cursors-mode ()
"Enable multiple-cursors-mode if there is more than one currently active cursor."
(if (> (mc/num-cursors) 1)
(multiple-cursors-mode 1)
(multiple-cursors-mode 0)))
(defmacro unsupported-cmd (cmd msg)
"Adds command to list of unsupported commands and prevents it
from being executed if in multiple-cursors-mode."
@@ -434,6 +523,20 @@ from being executed if in multiple-cursors-mode."
"The position of the file that keeps track of your preferences
for running commands with multiple cursors.")
(defun mc/dump-list (list-symbol)
"Insert (setq 'LIST-SYMBOL LIST-VALUE) to current buffer."
(symbol-macrolet ((value (symbol-value list-symbol)))
(insert "(setq " (symbol-name list-symbol) "\n"
" '(")
(newline-and-indent)
(set list-symbol
(sort value (lambda (x y) (string-lessp (symbol-name x)
(symbol-name y)))))
(mapc #'(lambda (cmd) (insert (format "%S" cmd)) (newline-and-indent))
value)
(insert "))")
(newline)))
(defun mc/save-lists ()
"Saves preferences for running commands with multiple cursors to `mc/list-file'"
(with-temp-file mc/list-file
@@ -443,21 +546,9 @@ for running commands with multiple cursors.")
(insert ";; It keeps track of your preferences for running commands with multiple cursors.")
(newline)
(newline)
(insert "(setq mc/cmds-to-run-for-all '(")
(mapc #'(lambda (cmd) (insert (format "%S" cmd)) (newline-and-indent)) mc/cmds-to-run-for-all)
(when mc/cmds-to-run-for-all
(forward-line -1)
(end-of-line))
(insert "))")
(mc/dump-list 'mc/cmds-to-run-for-all)
(newline)
(newline)
(insert "(setq mc/cmds-to-run-once '(")
(mapc #'(lambda (cmd) (insert (format "%S" cmd)) (newline-and-indent)) mc/cmds-to-run-once)
(when mc/cmds-to-run-once
(forward-line -1)
(end-of-line))
(insert "))")
(newline)))
(mc/dump-list 'mc/cmds-to-run-once)))
(defvar mc/cmds-to-run-once nil
"Commands to run only once in multiple-cursors-mode.")
@@ -469,16 +560,42 @@ for running commands with multiple cursors.")
mc/edit-ends-of-lines
mc/edit-beginnings-of-lines
mc/mark-next-like-this
mc/mark-next-word-like-this
mc/mark-next-symbol-like-this
mc/mark-previous-like-this
mc/mark-more-like-this-extended
mc/mark-previous-word-like-this
mc/mark-previous-symbol-like-this
mc/mark-all-like-this
mc/mark-all-words-like-this
mc/mark-all-symbols-like-this
mc/mark-more-like-this-extended
mc/mark-all-like-this-in-defun
mc/mark-all-words-like-this-in-defun
mc/mark-all-symbols-like-this-in-defun
mc/mark-all-like-this-dwim
mc/mark-sgml-tag-pair
mc/insert-numbers
mc/sort-regions
mc/reverse-regions
mc/cycle-forward
mc/cycle-backward
mc/add-cursor-on-click
mc/mark-pop
mc/add-cursors-to-all-matches
mc/mmlte--left
mc/mmlte--right
mc/mmlte--up
mc/mmlte--down
mc/unmark-next-like-this
mc/unmark-previous-like-this
mc/skip-to-next-like-this
mc/skip-to-previous-like-this
rrm/switch-to-multiple-cursors
save-buffer
ido-exit-minibuffer
exit-minibuffer
minibuffer-complete-and-exit
execute-extended-command
undo
redo
undo-tree-undo
@@ -495,6 +612,7 @@ for running commands with multiple cursors.")
describe-function
describe-bindings
describe-prefix-bindings
view-echo-area-messages
other-window
kill-buffer-and-window
split-window-right
@@ -502,6 +620,8 @@ for running commands with multiple cursors.")
delete-other-windows
toggle-window-split
mwheel-scroll
scroll-up-command
scroll-down-command
mouse-set-point
mouse-drag-region
quit-window
@@ -516,6 +636,7 @@ for running commands with multiple cursors.")
(setq mc--default-cmds-to-run-for-all '(mc/keyboard-quit
self-insert-command
quoted-insert
previous-line
next-line
newline
@@ -554,6 +675,11 @@ for running commands with multiple cursors.")
backward-delete-char-untabify
delete-char delete-forward-char
delete-backward-char
py-electric-backspace
c-electric-backspace
org-delete-backward-char
paredit-backward-delete
autopair-backspace
just-one-space
zap-to-char
end-of-line
@@ -589,4 +715,9 @@ for running commands with multiple cursors.")
(provide 'multiple-cursors-core)
;; Local Variables:
;; coding: utf-8
;; byte-compile-warnings: (not cl-functions)
;; End:
;;; multiple-cursors-core.el ends here
+1 -1
View File
@@ -1,2 +1,2 @@
(define-package "multiple-cursors" "1.1.2"
(define-package "multiple-cursors" "1.2.1"
"Multiple cursors for Emacs.")
+106 -50
View File
@@ -1,8 +1,9 @@
;;; multiple-cursors.el --- An experiment in multiple cursors for emacs.
;;; multiple-cursors.el --- Multiple cursors for emacs.
;; Copyright (C) 2012 Magnar Sveen
;; Copyright (C) 2012-2013 Magnar Sveen
;; Author: Magnar Sveen <magnars@gmail.com>
;; Version: 1.2.2
;; Keywords: editing cursors
;; This program is free software; you can redistribute it and/or modify
@@ -23,112 +24,167 @@
;; Multiple cursors for Emacs. This is some pretty crazy functionality, so yes,
;; there are kinks. Don't be afraid tho, I've been using it since 2011 with
;; 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-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 occurances.
;; - `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/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`.
;;
;; ## More commands to play around with
;; - Try pressing `mc/mark-next-like-this` with no region selected. It will just add a cursor
;; on the next line.
;;
;; 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.
;;
;; ;; 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.
;; - 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).
;;
;; 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:
(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)
+24 -21
View File
@@ -67,27 +67,30 @@ an exceedingly quick way of adding multiple cursors to multiple lines."
(defun rrm/repaint ()
"Start from the anchor and draw a rectangle between it and 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)))))))
(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 (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."
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh -e
ECUKES=$(find elpa/ecukes-*/ecukes | tail -1)
carton exec "$ECUKES" "$@"
+6 -13
View File
@@ -1,20 +1,13 @@
#!/bin/sh
#!/bin/sh -e
cd "$(dirname "$0")"
set_default () {
eval "
if [ -z \$$1 ]; then
$1=$2
fi
"
}
set_default ECUKES_EMACS "$(which emacs)"
ECUKES_EMACS=${EMACS:-$(which emacs)}
export ECUKES_EMACS
echo "*** Emacs version ***"
echo "ECUKES_EMACS =" $(which $ECUKES_EMACS)
$ECUKES_EMACS --version
echo "ECUKES_EMACS = $ECUKES_EMACS"
"$ECUKES_EMACS" --version
echo
exec ./util/ecukes/ecukes --graphical
exec ./run-tests.sh $TAGS
Submodule util/ecukes deleted from b2c449cf01
-2544
View File
File diff suppressed because it is too large Load Diff
Submodule util/espuds deleted from 62ef75cb51
+2 -2
View File
@@ -7,13 +7,13 @@ end
def run_all_tests
system('clear')
result = run "./util/ecukes/ecukes --graphical"
result = run "./run-tests.sh"
puts result
end
def run_test(file)
system('clear')
result = run "./util/ecukes/ecukes --graphical #{file}"
result = run "./run-tests.sh #{file} --verbose"
puts result
end