Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
179 lines (146 sloc) 6.31 KB
;;; iedit-rect.el --- visible rectangle editing support based on Iedit.
;; Copyright (C) 2010, 2011, 2012 Victor Ren
;; Time-stamp: <2013-02-09 00:55:45 Victor Ren>
;; Author: Victor Ren <>
;; Keywords: occurrence region simultaneous rectangle refactoring
;; Version: 0.97
;; X-URL:
;; Compatibility: GNU Emacs: 22.x, 23.x, 24.x
;; This file is not part of GNU Emacs, but it is distributed under
;; the same terms as GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <>.
;;; Commentary:
;; This package also provides rectangle support with *visible rectangle*
;; highlighting, which is similar with cua-mode rectangle support. But it is
;; lighter weight and uses iedit mechanisms.
;; The code was developed and fully tested on Gnu Emacs 24.0.93, partially
;; tested on Gnu Emacs 22. If you have any compatible problem, please let me
;; know.
;;; todo:
;; - Add restrict function back
;;; Code:
(eval-when-compile (require 'cl))
(require 'rect) ;; kill-rectangle
(require 'iedit-lib)
(defvar iedit-rectangle-mode nil) ;; Name of the minor mode
(make-variable-buffer-local 'iedit-rectangle-mode)
(or (assq 'iedit-rectangle-mode minor-mode-alist)
(nconc minor-mode-alist
(list '(iedit-rectangle-mode iedit-rectangle-mode))))
;;; Default key bindings:
(define-key global-map [C-return] 'iedit-rectangle-mode)
(defvar iedit-rectangle nil
"This buffer local variable which is the rectangle geometry if
current mode is iedit-rect. Otherwise it is nil.
\(car iedit-rectangle) is the top-left corner and
\(cadr iedit-rectangle) is the bottom-right corner" )
(make-variable-buffer-local 'iedit-rectangle)
;;; Define Iedit rect mode map
(defvar iedit-rect-keymap
(let ((map (make-sparse-keymap)))
(set-keymap-parent map iedit-occurrence-keymap-default)
(define-key map (kbd "M-K") 'iedit-kill-rectangle)
"Keymap used within overlays in Iedit-rect mode.")
(or (assq 'iedit-rectangle-mode minor-mode-map-alist)
(setq minor-mode-map-alist
(cons (cons 'iedit-rectangle-mode iedit-lib-keymap) minor-mode-map-alist)))
;; Avoid to restore Iedit-rect mode when restoring desktop
(add-to-list 'desktop-minor-mode-handlers
'(iedit-rectangle-mode . nil))
(defun iedit-rectangle-mode (&optional beg end)
"Toggle Iedit-rect mode.
When Iedit-rect mode is on, a rectangle is started with visible
rectangle highlighting. Rectangle editing support is based on
Iedit mechanism.
(interactive (when (iedit-region-active)
(list (region-beginning)
;; enforce skip modification once, errors may happen to cause this to be
;; unset.
(setq iedit-skip-modification-once t)
(if iedit-rectangle-mode
(if (and beg end)
(progn (setq mark-active nil)
(run-hooks 'deactivate-mark-hook)
(iedit-rectangle-start beg end))
(error "no region available."))))
(defun iedit-rectangle-start (beg end)
"Start Iedit mode for the region as a rectangle."
(setq beg (copy-marker beg))
(setq end (copy-marker end t))
(setq iedit-occurrences-overlays nil)
(setq iedit-initial-string-local nil)
(setq iedit-occurrence-keymap iedit-rect-keymap)
(let ((beg-col (progn (goto-char beg) (current-column)))
(end-col (progn (goto-char end) (current-column))))
(when (< end-col beg-col)
(rotatef beg-col end-col))
(goto-char beg)
(push (iedit-make-occurrence-overlay
(move-to-column beg-col t)
(move-to-column end-col t)
(and (< (point) end) (forward-line 1))))))
(setq iedit-rectangle (list beg end))
(setq iedit-rectangle-mode
(concat " Iedit-rect:"
(number-to-string (length iedit-occurrences-overlays)))
(add-hook 'kbd-macro-termination-hook 'iedit-rectangle-done nil t)
(add-hook 'change-major-mode-hook 'iedit-rectangle-done nil t)
(add-hook 'iedit-aborting-hook 'iedit-rectangle-done nil t))
(defun iedit-rectangle-done ()
"Exit Iedit mode.
Save the current occurrence string locally and globally. Save
the initial string globally."
(when iedit-buffering
(setq iedit-rectangle-mode nil)
(remove-hook 'kbd-macro-termination-hook 'iedit-rectangle-done t)
(remove-hook 'change-major-mode-hook 'iedit-rectangle-done t)
(remove-hook 'iedit-aborting-hook 'iedit-rectangle-done t))
(defun iedit-kill-rectangle(&optional fill)
"Kill the rectangle.
The behavior is the same as `kill-rectangle' in rect mode."
(interactive "*P")
(or (and iedit-rectangle (iedit-same-column))
(error "Not a rectangle"))
(let ((inhibit-modification-hooks t))
(kill-rectangle (marker-position (car iedit-rectangle))
(marker-position (cadr iedit-rectangle)) fill)))
(provide 'iedit-rect)
;;; iedit-rect.el ends here
;; LocalWords: iedit el MERCHANTABILITY kbd isearch todo ert Lindberg Tassilo
;; LocalWords: eval rect defgroup defcustom boolean defvar assq alist nconc
;; LocalWords: substring cadr keymap defconst purecopy bkm defun princ prev
;; LocalWords: iso lefttab backtab upcase downcase concat setq autoload arg
;; LocalWords: refactoring propertize cond goto nreverse progn rotatef eq elp
;; LocalWords: dolist pos unmatch args ov sReplace iedit's cdr quote'ed