summaryrefslogtreecommitdiffstats
path: root/site-lisp/move-lines.el
diff options
context:
space:
mode:
authorRavi R Kiran <aine.marina@gmail.com>2013-12-02 06:39:42 (GMT)
committerRavikiran Rajagopal <aine.marina@gmail.com>2013-12-02 06:39:42 (GMT)
commitd2517ef2ae389e79a35d012c239b4c5ef63076ab (patch)
tree0e0fff309d5860b53576899c91b85cee3dc3fd47 /site-lisp/move-lines.el
parent1420cbed334187da4fc9b722ba8970703771d644 (diff)
downloaddotemacs-d2517ef2ae389e79a35d012c239b4c5ef63076ab.zip
dotemacs-d2517ef2ae389e79a35d012c239b4c5ef63076ab.tar.gz
dotemacs-d2517ef2ae389e79a35d012c239b4c5ef63076ab.tar.bz2
Add move-lines for moving regions and lines
Add wgrep for writable grep buffers
Diffstat (limited to 'site-lisp/move-lines.el')
-rw-r--r--site-lisp/move-lines.el128
1 files changed, 128 insertions, 0 deletions
diff --git a/site-lisp/move-lines.el b/site-lisp/move-lines.el
new file mode 100644
index 0000000..f96c598
--- /dev/null
+++ b/site-lisp/move-lines.el
@@ -0,0 +1,128 @@
+;;; move-lines.el --- move current line or lines surrounding region up or down
+
+;; Copyright (C) 2013 Emanuele Tomasi <targzeta@gmail.com>
+;;
+;; 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;
+
+;; There are two entry points: `move-lines-up' moves the text up and
+;; `move-lines-down' that moves the text down.
+;;
+;; Copy this file in a directory which is in the Emacs `load-path'. Then,
+;; execute the following code either directly or in your .emacs file:
+;;
+;; (require 'move-lines)
+;; (move-lines-binding)
+;;
+;; Now, you can move the line(s) up by M-p or M-<up> or down by M-n or M-<down>.
+
+;;; Code:
+
+(defun move-lines--internal (n)
+ (let* ((start (point)) ;; The position of beginning of line of the first line
+ (end start) ;; The position of eol+\n of the end line
+ col-init ;; The current column for the first line
+ (col-end (current-column)) ;; The current column for the end line
+ exchange_pm ;; If I had exchanged point and mark
+ delete-latest-newline) ;; If I had inserted a newline at the end
+
+ ;; STEP 1: Identifying the line(s) to cut.
+ ;; ---
+ ;; If region is actives, I ensure that point always is at the end of the
+ ;; region and mark at the beginning.
+ (when (region-active-p)
+ (when (< (point) (mark))
+ (setq exchange_pm t)
+ (exchange-point-and-mark))
+ (setq start (mark)
+ end (point)
+ col-end (current-column)))
+
+ (goto-char start) (setq col-init (current-column))
+ (beginning-of-line) (setq start (point))
+
+ (goto-char end) (end-of-line)
+ ;; If point == point-max, this buffers doesn't have the trailing newline.
+ ;; In this case I have to insert a newline otherwise the following
+ ;; `forward-char' (to keep the "\n") will fail.
+ (when (= (point) (point-max))
+ (setq delete-latest-newline t)
+ (insert-char ?\n) (forward-char -1))
+ (forward-char 1) (setq end (point))
+
+ ;; STEP 2: Moving the lines.
+ ;; ---
+ ;; The region I'm cutting span from the beginning of line of the current
+ ;; line (or current region) to the end of line + 1 (newline) of the current
+ ;; line (or current region).
+ (let ((line-text (delete-and-extract-region start end)))
+ (forward-line n)
+ ;; If the current-column != 0, I have moved the region at the bottom of a
+ ;; buffer doesn't have the trailing newline.
+ (when (not (= (current-column) 0))
+ (insert-char ?\n)
+ (setq delete-latest-newline t))
+ (setq start (+ (point) col-init)) ;; Now, start is the start of new region
+ (insert line-text))
+
+ ;; STEP 3: Restoring
+ ;; ---
+ ;; I'm at the end of new region (or line) and start has setted at the
+ ;; beginning of new region (if a region is active).
+ ;; Restoring the end column.
+ (forward-line -1)
+ (forward-char col-end)
+
+ (when delete-latest-newline
+ (save-excursion
+ (goto-char (point-max))
+ (delete-char -1)))
+
+ (when (region-active-p)
+ (setq deactivate-mark nil)
+ (set-mark start)
+ (if exchange_pm
+ (exchange-point-and-mark)))))
+
+;;;###autoload
+(defun move-lines-up (n)
+ "Moves the current line or, if region is actives, the lines surrounding
+region, up by N lines, or 1 line if N is nil."
+ (interactive "p")
+ (if (eq n nil)
+ (setq n 1))
+ (move-lines--internal (- n)))
+
+;;;###autoload
+(defun move-lines-down (n)
+ "Moves the current line or, if region is actives, the lines surrounding
+region, down by N lines, or 1 line if N is nil."
+ (interactive "p")
+ (if (eq n nil)
+ (setq n 1))
+ (move-lines--internal n))
+
+;;;###autoload
+(defun move-lines-binding ()
+ "Sets the default key binding for moving lines. M-p or M-<up> for moving up
+and M-n or M-<down> for moving down."
+ (global-set-key (kbd "M-p") 'move-lines-up)
+ (global-set-key (kbd "M-<up>") 'move-lines-up)
+ (global-set-key (kbd "M-n") 'move-lines-down)
+ (global-set-key (kbd "M-<down>") 'move-lines-down))
+
+(provide 'move-lines)
+
+;; move-lines.el ends here