tags:

views:

304

answers:

5

Hi,

do you know what is the easiest way to move selected region or line (if there is no selection) up or down in emacs? I'm looking for the same functionality as is in eclipse (bounded to M-up, M-down).

Thanks

+5  A: 

A line can be moved using transpose-lines bound to C-x C-t. Dunno about regions though.

I found this elisp snippet that does what you want, except you need to change the bindings.

Martin Wickman
Thanks for the snippet. This is exactly what I was looking for!
fikovnik
+1  A: 

There's no built-in. You can use transpose-lines (C-x C-t) but you cannot use it repeatedly. Look at the functions on http://www.schuerig.de/michael/blog/index.php/2009/01/16/line-movement-for-emacs/.

It should be easy to adapt that to regions, too.

Florian Thiel
+1, I have something like this in my .emacs, it's very handy
Leo Alekseyev
Btw, if you do decide to use the linked snippet, you might want to change the let statement to (let ((col (current-column)) (line-move-visual nil)), otherwise you get funny behavior with wrapped lines.
Leo Alekseyev
A: 

The transpose-paragraph function could help you.

You might also want to have a look to the transpose section in the Emacs manual. Essentially:

C-t
Transpose two characters (transpose-chars).
M-t
Transpose two words (transpose-words).
C-M-t
Transpose two balanced expressions (transpose-sexps).
C-x C-t
Transpose two lines (transpose-lines).
Roberto Aloi
A: 

I have written a couple of interactive functions for moving lines up/down:

;; move line up
(defun move-line-up ()
  (interactive)
  (transpose-lines 1)
  (previous-line 2))

(global-set-key [(control shift up)] 'move-line-up)

;; move line down
(defun move-line-down ()
  (interactive)
  (next-line 1)
  (transpose-lines 1)
  (previous-line 1))

(global-set-key [(control shift down)] 'move-line-down)

The keybindings are IntelliJ IDEA style, but you can use anything you want. I should probably implement some functions that operate on regions as well.

Bozhidar Batsov
+4  A: 

Here's what I use, which works on both regions and individual lines:

(defun move-text-internal (arg)
  (cond
   ((and mark-active transient-mark-mode)
    (if (> (point) (mark))
        (exchange-point-and-mark))
    (let ((column (current-column))
          (text (delete-and-extract-region (point) (mark))))
      (forward-line arg)
      (move-to-column column t)
      (set-mark (point))
      (insert text)
      (exchange-point-and-mark)
      (setq deactivate-mark nil)))
   (t
    (let ((column (current-column)))
      (beginning-of-line)
      (when (or (> arg 0) (not (bobp)))
        (forward-line)
        (when (or (< arg 0) (not (eobp)))
          (transpose-lines arg))
        (forward-line -1))
      (move-to-column column t)))))

(defun move-text-down (arg)
  "Move region (transient-mark-mode active) or current line
  arg lines down."
  (interactive "*p")
  (move-text-internal arg))

(defun move-text-up (arg)
  "Move region (transient-mark-mode active) or current line
  arg lines up."
  (interactive "*p")
  (move-text-internal (- arg)))


(global-set-key [M-S-up] 'move-text-up)
(global-set-key [M-S-down] 'move-text-down)
sanityinc
this guy picked the wrong answer, in my opinion. I despised your bindings, and changed them to M-up arrow and M-down arrow, but this works BETTER then the emacs wiki version http://www.emacswiki.org/emacs/MoveLineRegion . post your solution there sanityinc. thanks.
pjammer
@sanityinc - Ive added this to EmacsWiki for you, it's here: http://www.emacswiki.org/emacs/MoveText
slomojo
Thanks! I think that code was already on there (http://www.emacswiki.org/emacs/basic-edit-toolkit.el) but this new page will be easier for people to find.
sanityinc
Ahh, cool I've not seen that before, looks like basic-edit-toolkit could use a cleanup.
slomojo