From 13668a9e1c9963b5d74a2601c24fcba689feb391 Mon Sep 17 00:00:00 2001 From: Magnar Sveen Date: Tue, 24 Jan 2012 10:04:11 +0100 Subject: [PATCH] initial commit --- README.org | 3 ++ multiple-cursors.el | 94 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 README.org create mode 100644 multiple-cursors.el diff --git a/README.org b/README.org new file mode 100644 index 0000000..c169def --- /dev/null +++ b/README.org @@ -0,0 +1,3 @@ +* multiple-cursors.el + +An experiment in multiple cursors for emacs. Still very much in beta. diff --git a/multiple-cursors.el b/multiple-cursors.el new file mode 100644 index 0000000..e6aded8 --- /dev/null +++ b/multiple-cursors.el @@ -0,0 +1,94 @@ +(defface mc/cursor-face + '((t (:inverse-video t))) + "The face used for additional cursors" + :group 'multiple-cursors) + +(defun mc/make-cursor-overlay-at-eol (pos) + (let ((overlay (make-overlay pos pos nil nil t))) + (overlay-put overlay 'after-string (propertize " " 'face 'mc/cursor-face)) + overlay)) + +(defun mc/make-cursor-overlay-inline (pos) + (let ((overlay (make-overlay pos (1+ pos) nil nil t))) + (overlay-put overlay 'face 'mc/cursor-face) + overlay)) + +(defun mc/make-cursor-overlay-at-point () + (if (eolp) + (mc/make-cursor-overlay-at-eol (point)) + (mc/make-cursor-overlay-inline (point)))) + +(defun mc/add-cursor-at-point () + (let ((overlay (mc/make-cursor-overlay-at-point))) + (overlay-put overlay 'type 'additional-cursor) + (overlay-put overlay 'priority 100))) + +(setq mc--cmds '(self-insert-command + previous-line + next-line + newline + right-char + right-word + left-char + left-word + yank + kill-word + kill-region-or-backward-word + backward-kill-word + backward-delete-char-untabify + delete-char + delete-backward-char + move-end-of-line-or-next-line + move-start-of-line-or-prev-line)) + +(defun mc/execute-this-command-for-all-cursors () + (if (not (memq this-original-command mc--cmds)) + (message "Skipping %S" this-original-command) + (save-excursion + (mapc #'(lambda (o) + (when (eq (overlay-get o 'type) 'additional-cursor) + (goto-char (overlay-start o)) + (delete-overlay o) + (ignore-errors + (call-interactively this-original-command) + (mc/add-cursor-at-point)))) + (overlays-in (point-min) (point-max)))))) + +(defun mc/remove-additional-cursors () + (mapc #'(lambda (o) + (when (eq (overlay-get o 'type) 'additional-cursor) + (delete-overlay o))) + (overlays-in (point-min) (point-max)))) + +(defvar mc/keymap nil + "Keymap while multiple cursors are active.") +(if mc/keymap + nil + (setq mc/keymap (make-sparse-keymap)) + (define-key mc/keymap (kbd "C-g") 'multiple-cursors-mode)) + +(define-minor-mode multiple-cursors-mode + "Mode while multiple cursors are active." + nil " mc" mc/keymap + (cond ((not multiple-cursors-mode) + (remove-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t) + (mc/remove-additional-cursors)) + (t (add-hook 'post-command-hook 'mc/execute-this-command-for-all-cursors t t)))) + +(defun mc/edit-ends-of-lines () + (interactive) + (mc/remove-additional-cursors) + (let* ((point-line (line-number-at-pos)) + (mark-line (save-excursion (exchange-point-and-mark) (line-number-at-pos))) + (num-cursors (abs (- point-line mark-line))) + (navigation-func (if (< point-line mark-line) 'previous-line 'next-line))) + (exchange-point-and-mark) + (while (not (eq (line-number-at-pos) point-line)) + (end-of-line) + (mc/add-cursor-at-point) + (funcall navigation-func)) + (end-of-line) + (deactivate-mark) + (multiple-cursors-mode))) + +(provide 'multiple-cursors)