rectangular-region-mode.el (4700B)
1 ;;; rectangular-region-mode.el 2 3 ;; Copyright (C) 2012 Magnar Sveen 4 5 ;; Author: Magnar Sveen <magnars@gmail.com> 6 ;; Keywords: editing cursors 7 8 ;; This program is free software; you can redistribute it and/or modify 9 ;; it under the terms of the GNU General Public License as published by 10 ;; the Free Software Foundation, either version 3 of the License, or 11 ;; (at your option) any later version. 12 13 ;; This program is distributed in the hope that it will be useful, 14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 ;; GNU General Public License for more details. 17 18 ;; You should have received a copy of the GNU General Public License 19 ;; along with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 ;;; Commentary: 22 23 ;; (global-set-key (kbd "H-SPC") 'set-rectangular-region-anchor) 24 25 ;; Think of this one as `set-mark` except you're marking a rectangular region. It is 26 ;; an exceedingly quick way of adding multiple cursors to multiple lines. 27 28 ;;; Code: 29 30 (require 'multiple-cursors-core) 31 32 (defvar rrm/anchor (make-marker) 33 "The position in the buffer that anchors the rectangular region.") 34 35 (defvar rectangular-region-mode-map (make-sparse-keymap) 36 "Keymap for rectangular region is mainly for rebinding C-g") 37 38 (define-key rectangular-region-mode-map (kbd "C-g") 'rrm/keyboard-quit) 39 (define-key rectangular-region-mode-map (kbd "<return>") 'rrm/switch-to-multiple-cursors) 40 41 (defvar rectangular-region-mode nil) 42 43 (defun rrm/keyboard-quit () 44 "Exit rectangular-region-mode." 45 (interactive) 46 (rectangular-region-mode 0) 47 (rrm/remove-rectangular-region-overlays) 48 (deactivate-mark)) 49 50 ;; Bind this to a key (for instance H-SPC) to start rectangular-region-mode 51 ;;;###autoload 52 (defun set-rectangular-region-anchor () 53 "Anchors the rectangular region at point. 54 55 Think of this one as `set-mark' except you're marking a rectangular region. It is 56 an exceedingly quick way of adding multiple cursors to multiple lines." 57 (interactive) 58 (set-marker rrm/anchor (point)) 59 (push-mark (point)) 60 (rectangular-region-mode 1)) 61 62 (defun rrm/remove-rectangular-region-overlays () 63 "Remove all rectangular-region overlays." 64 (mc/remove-fake-cursors) 65 (mapc #'(lambda (o) 66 (when (eq (overlay-get o 'type) 'additional-region) 67 (delete-overlay o))) 68 (overlays-in (point-min) (point-max)))) 69 70 (defun rrm/repaint () 71 "Start from the anchor and draw a rectangle between it and point." 72 (if (not rectangular-region-mode) 73 (remove-hook 'post-command-hook 'rrm/repaint t) 74 ;; else 75 (rrm/remove-rectangular-region-overlays) 76 (let* ((annoying-arrows-mode nil) 77 (point-column (current-column)) 78 (point-line (line-number-at-pos)) 79 (anchor-column (save-excursion (goto-char rrm/anchor) (current-column))) 80 (anchor-line (save-excursion (goto-char rrm/anchor) (line-number-at-pos))) 81 (left-column (if (< point-column anchor-column) point-column anchor-column)) 82 (right-column (if (> point-column anchor-column) point-column anchor-column)) 83 (navigation-step (if (< point-line anchor-line) 1 -1))) 84 (move-to-column anchor-column) 85 (set-mark (point)) 86 (move-to-column point-column) 87 (mc/save-excursion 88 (while (not (= anchor-line (line-number-at-pos))) 89 (forward-line navigation-step) 90 (move-to-column anchor-column) 91 (when (= anchor-column (current-column)) 92 (set-mark (point)) 93 (move-to-column point-column) 94 (when (= point-column (current-column)) 95 (mc/create-fake-cursor-at-point)))))))) 96 97 (defun rrm/switch-to-multiple-cursors (&rest forms) 98 "Switch from rectangular-region-mode to multiple-cursors-mode." 99 (interactive) 100 (rectangular-region-mode 0) 101 (multiple-cursors-mode 1)) 102 103 (defadvice er/expand-region (before switch-from-rrm-to-mc activate) 104 (when rectangular-region-mode 105 (rrm/switch-to-multiple-cursors))) 106 107 (defadvice kill-ring-save (before switch-from-rrm-to-mc activate) 108 (when rectangular-region-mode 109 (rrm/switch-to-multiple-cursors))) 110 111 ;;;###autoload 112 (define-minor-mode rectangular-region-mode 113 "A mode for creating a rectangular region to edit" 114 nil " rr" rectangular-region-mode-map 115 (if rectangular-region-mode 116 (progn 117 (add-hook 'after-change-functions 'rrm/switch-to-multiple-cursors t t) 118 (add-hook 'post-command-hook 'rrm/repaint t t)) 119 (remove-hook 'after-change-functions 'rrm/switch-to-multiple-cursors t) 120 (remove-hook 'post-command-hook 'rrm/repaint t) 121 (set-marker rrm/anchor nil))) 122 123 (provide 'rectangular-region-mode) 124 125 ;;; rectangular-region-mode.el ends here