From c6fe19d5ddff128cc87fabcd0e7f82be6af19781 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Sat, 13 Jul 2013 16:34:40 +0100 Subject: [PATCH] Support for Magnar Sveen's awesome `multiple-cursors' package. Organization: Straylight/Edgeware From: Mark Wooding To use it: git clone https://github.com/magnars/multiple-cursors.el/ \ ~/lib/emacs/multiple-cursors/ --- dot/emacs | 7 ++ el/dot-emacs.el | 3 + el/mdw-multiple-cursors.el | 156 +++++++++++++++++++++++++++++++++++++ setup | 1 + 4 files changed, 167 insertions(+) create mode 100644 el/mdw-multiple-cursors.el diff --git a/dot/emacs b/dot/emacs index 83a8bd0..4705e7e 100644 --- a/dot/emacs +++ b/dot/emacs @@ -86,6 +86,13 @@ (trap (show-paren-mode t)) (or window-system (menu-bar-mode -1)) +;; Multiple cursors. + +(setq load-path (nconc load-path (list "~/lib/emacs/multiple-cursors/"))) +(global-set-key [?\C-c ?r] 'mdw-multiple-cursors-keymap) +(autoload 'mdw-multiple-cursors-keymap "mdw-multiple-cursors.el" + "A keymap for Magnar Sveen's awesome multiple-cursors." nil 'keymap) + ;; Temporary directory handling. (defun mdw-check-dir-exists (dir) diff --git a/el/dot-emacs.el b/el/dot-emacs.el index e8751ff..f21af7f 100644 --- a/el/dot-emacs.el +++ b/el/dot-emacs.el @@ -865,6 +865,9 @@ (mdw-define-face region (((type tty) (class color)) :background "blue") (((type tty) (class mono)) :inverse-video t) (t :background "grey30")) +(mdw-define-face mc/cursor-face + (((type tty) (class mono)) :inverse-video t) + (t :background "red")) (mdw-define-face minibuffer-prompt (t :weight bold)) (mdw-define-face mode-line diff --git a/el/mdw-multiple-cursors.el b/el/mdw-multiple-cursors.el new file mode 100644 index 0000000..8107d48 --- /dev/null +++ b/el/mdw-multiple-cursors.el @@ -0,0 +1,156 @@ +;;; -*-emacs-lisp-*- +;;; +;;; Key bindings for Magnar Sveen's `multiple-cursors' package +;;; +;;; (c) 2014 Mark Wooding +;;; + +;;;----- Licensing notice --------------------------------------------------- +;;; +;;; 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 2 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, write to the Free Software Foundation, +;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +;; Loading and setup: +;; +;; (global-set-key [...] 'mdw-multiple-values-keymap) +;; (autoload 'mdw-multiple-cursors-keymap "mdw-multiple-cursors.el" +;; "A keymap for Magnar Sveen's awesome multiple-cursors." nil 'keymap) + +;;;-------------------------------------------------------------------------- +;;; Some machinery for omitting key prefixes. + +(defvar mdw-omit-prefix-enable-repeat t + "*If true, allow invoking sequences of commands without repeating prefixes. +This is both a user twiddle (which you can turn on and off depending on +whether you like the feature) and a state variable used by the +implementation.") + +(defun mdw-omit-prefix-repeat (keys tag) + "Maybe invoke other commands with the same prefix. +The KEYS which invoked the current command, usually as collected via +`this-single-command-keys'. If the next keystroke refers to a command +whose name has a `mdw-omit-prefix-repeat' property with value TAG then run +that command and repeat. + +Call this at the end of your command function if you want to allow prefix +omission. Honours the `mdw-omit-prefix-enable-repeat' variable." + (when mdw-omit-prefix-enable-repeat + (let ((n (1- (length keys))) cmd done + (mdw-omit-prefix-enable-repeat nil)) + (while (not done) + (setq done t) + (aset keys n (read-event)) + (let* ((cmd (key-binding keys t)) + (cmdtag (get cmd 'mdw-omit-prefix-repeat))) + (clear-this-command-keys t) + (when (eq cmdtag tag) + (setq done nil) + (call-interactively cmd)))) + (when last-input-event + (setq unread-command-events (list last-input-event)))))) + +(defmacro mdw-omit-prefix-wrapper (name func args tag &rest things) + "Generate a prefix-omission wrapper function around a command. +The wrapper will be called NAME; it will invoke FUNC, passing it ARGS; +commands in the same keymap whose `mdw-omit-prefix-enable-repeat' +property has the value TAG can be invoked without repeating the +prefix. The THINGS are items (such as documentation or `interactive' +forms) to appear at the start of the wrapper function." + `(progn + (defun ,name ,args + ,@things + (let ((keys (this-single-command-keys))) + (,func ,@args) + (mdw-omit-prefix-repeat keys ',tag))) + (put ',name 'mdw-omit-prefix-repeat ',tag) + ',name)) + +;;;-------------------------------------------------------------------------- +;;; The multiple-cursors key bindings. + +(eval-when (load eval) + (require 'multiple-cursors)) + +(defvar mdw-multiple-cursors-keymap (make-sparse-keymap) + "Keymap for `multiple-cursors'.") +(fset 'mdw-multiple-cursors-keymap mdw-multiple-cursors-keymap) + +(defmacro mdw-make-multiple-cursors-repeat-wrappers (&rest specs) + "Set up wrappers around the `multiple-cursors' functions. +Each of the SPECS has the form + + (FUNC ARGS INTERACT BIND) + +where: + + * FUNC is the existing function which is to be wrapped; + + * ARGS are the arguments to be collected by the wrapper function, + and passed to FUNC; + + * INTERACT is an `interactive' string, or `nil' (if there are no + interactive arguments to be collected); and + + * BIND is the key binding to set in `mdw-multiple-cursors-keymap'." + + `(progn + ,@(apply #'append + (mapcar (lambda (spec) + (let* ((func (car spec)) + (args (cadr spec)) + (interact (car (cddr spec))) + (bind (cadr (cddr spec))) + (wrapper (intern + (concat "mdw-" + (symbol-name func))))) + `((mdw-omit-prefix-wrapper + ,wrapper ,func ,args + multiple-cursors + (interactive ,@(and interact + (list interact)))) + (define-key mdw-multiple-cursors-keymap + ,bind ',wrapper) + (pushnew ',wrapper mc/cmds-to-run-once)))) + specs)) + '(,@(mapcar #'car specs)))) + +;; Set up commands which want omit-prefix wrappers. +(mdw-make-multiple-cursors-repeat-wrappers + (mc/mark-next-like-this (arg) "p" "\C-s") + (mc/mark-previous-like-this (arg) "p" "\C-r") + (mc/mark-next-word-like-this (arg) "p" "\M-f") + (mc/mark-previous-word-like-this (arg) "p" "\M-b") + (mc/mark-next-symbol-like-this (arg) "p" "\C-\M-f") + (mc/mark-previous-symbol-like-this (arg) "p" "\C-\M-b") + (mc/skip-to-next-like-this () nil "\M-s") + (mc/skip-to-previous-like-this () nil "\M-r") + (mc/unmark-next-like-this () nil "\C-\M-s") + (mc/unmark-previous-like-this () nil "\C-\M-r") + (mc/cycle-forward () nil "\M-n") + (mc/cycle-backward () nil "\M-p") + (mc/mark-all-like-this-dwim (arg) "p" "a")) + +;; Set up other commands. +(let ((map mdw-multiple-cursors-keymap)) + (define-key map "/" 'mc/mark-sgml-tag-pair) + (define-key map "\M-a" 'mc/mark-all-dwim) + (define-key map "e" 'mc/edit-lines) + (define-key map "\C-e" 'mc/edit-ends-of-lines) + (define-key map "\C-a" 'mc/edit-beginnings-of-lines) + (define-key map "\C-@" 'set-rectangular-region-anchor) + (define-key map [?\C- ] 'set-rectangular-region-anchor)) + +;;;----- That's all, folks -------------------------------------------------- + +(provide 'mdw-multiple-cursors) diff --git a/setup b/setup index c15f062..5422976 100755 --- a/setup +++ b/setup @@ -297,6 +297,7 @@ emacspkg=" ew-hols mdw-gnus-patch git git-blame vc-git stgit + mdw-multiple-cursors quilt" for elib in $emacspkg; do $echon " $elib:$echoc" -- [mdw]