2010-03-11 46 views
74

在emacs中向上或向下移动所选区域或行(如果没有选择),最简单的方法是什么?我正在寻找与eclipse中相同的功能(以M-up,M-down为界)。在emacs中向上和向下移动行/区域

+1

我敢肯定,这个习惯用法是杀死你想要移动的东西,使用通常的导航功能(包括isearch等)来移动你想要的代码点,然后将yank 。记住,有一堆杀死的东西,所以你甚至不必立即找到位置;你可以收集其他比特以便稍后抽出。就个人而言,作为一个沉重的Emacs用户,我无法想象任何情况下,我宁愿手动移动一行或一行。它不会有用。 – jrockway 2010-03-12 02:27:36

+5

@jrockway:感谢您的评论。我认为每个人都有自己的做事方式。我在eclipse上工作很多,我非常习惯于移动线条/区域。 emacs非常具有可扩展性的好处之一是可以轻松添加此功能。 – fikovnik 2010-03-14 15:18:08

+2

同意。我经常想按照你所描述的来上下移动线条,不管我是否在支持它的编辑器中。或者,就此而言,我是否正在处理代码。 Word支持(按段落)Alt + Shift +向上和向下,并且我可以在我的编辑器中将其映射。 – harpo 2010-09-28 00:47:21

回答

35

一条线可以使用transpose-lines绑定到C-x C-t。不过不知道地区。

我找到了this elisp片段,它可以做你想做的事情,除非你需要改变绑定。

(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 
    (beginning-of-line) 
    (when (or (> arg 0) (not (bobp))) 
     (forward-line) 
     (when (or (< arg 0) (not (eobp))) 
      (transpose-lines arg)) 
     (forward-line -1))))) 

(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) 
+0

感谢您的摘录。这正是我所期待的! – fikovnik 2010-03-14 15:25:22

+0

非常好! – 2013-07-04 12:23:13

+0

这个解决方案和@sanityinc发布的几乎完全相同:如果我使用定义的快捷方式向上和/或向下移动区域,则立即使用快捷方式进行撤消(默认为C-_) ,该地区就消失了,消息“撤消在地区!”显示在回声区域中。另一个撤销命令产生消息“没有进一步的区域撤消信息”。但是,如果我移动光标,然后命令撤消,撤消重新开始工作。一个相对较小的刺激,但所有其他的Emacs命令可以立即撤消,而不诉诸于诡计。 – 2013-07-15 13:06:31

1

没有内置的。您可以使用转置线(C-x C-t),但不能反复使用。看看http://www.schuerig.de/michael/blog/index.php/2009/01/16/line-movement-for-emacs/上的功能。

它也应该很容易适应地区。

+0

+1,我在我的.emacs中有这样的东西,非常方便 – 2010-03-11 13:06:09

+1

顺便说一句,如果你决定使用链接的片段,你可能希望将let语句改为(let((col(current-column))(line-move-visual nil)),否则你会用包装线获得有趣的行为。 – 2010-03-11 14:47:48

1

transpose-paragraph功能可以帮助你。

您可能还想看看Emacs手册中的转置部分。 本质:

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). 
8

我已经写了几个互动功能动线向上/向下:

;; 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) 

的绑定键是IntelliJ IDEA的风格,但你可以使用任何你想要的。我也许应该实现一些在各个地区运作的功能。

43

更新:安装Marmalade的move-text包或MELPA获取以下代码。

这是我使用,这两个地区和各条线的工作原理:

(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) 
      (when (and (eval-when-compile 
         '(and (>= emacs-major-version 24) 
          (>= emacs-minor-version 3))) 
        (< arg 0)) 
      (forward-line -1))) 
     (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) 
+0

我已经将它添加到EmacsWiki中,它在这里:http://www.emacswiki.org/emacs/MoveText – ocodo 2010-10-04 22:48:25

+0

谢谢!我认为代码已经在那里(http://www.emacswiki.org/emacs/basic-edit-toolkit.el),但这个新的页面将会更容易让人找到。 – sanityinc 2010-10-05 08:59:57

+0

啊,很酷我以前没见过,看起来像basic-edit-toolkit可以使用清理。 – ocodo 2010-10-05 21:42:43

4

这里是我的代码片段来移动当前行或活动区域跨越的行。它尊重光标位置和突出显示的区域。当该区域不以线边界开始/结束时,它不会断线。 (它是由偏食的启发,我找到了日食的方式比“转线”更方便。)

;; move the line(s) spanned by the active region up/down (line transposing) 
;; {{{ 
(defun move-lines (n) 
    (let ((beg) (end) (keep)) 
    (if mark-active 
     (save-excursion 
      (setq keep t) 
      (setq beg (region-beginning) 
       end (region-end)) 
      (goto-char beg) 
      (setq beg (line-beginning-position)) 
      (goto-char end) 
      (setq end (line-beginning-position 2))) 
     (setq beg (line-beginning-position) 
      end (line-beginning-position 2))) 
    (let ((offset (if (and (mark t) 
          (and (>= (mark t) beg) 
           (< (mark t) end))) 
         (- (point) (mark t)))) 
      (rewind (- end (point)))) 
     (goto-char (if (< n 0) beg end)) 
     (forward-line n) 
     (insert (delete-and-extract-region beg end)) 
     (backward-char rewind) 
     (if offset (set-mark (- (point) offset)))) 
    (if keep 
     (setq mark-active t 
       deactivate-mark nil)))) 

(defun move-lines-up (n) 
    "move the line(s) spanned by the active region up by N lines." 
    (interactive "*p") 
    (move-lines (- (or n 1)))) 

(defun move-lines-down (n) 
    "move the line(s) spanned by the active region down by N lines." 
    (interactive "*p") 
    (move-lines (or n 1))) 
+1

对我来说,移动文本包被打破了。您的解决方案在我的系统上完美运行感谢那! – 2016-01-31 17:07:42

21

你应该尝试drag-stuff

它的工作原理完全一样日食Alt键 + 向上/单线条,以及符合所选区域的线!

此外,它可以让你与Alt键 + /
这正是你要寻找移动的话!它甚至可以从ELPA repos

其他解决方案从来没有为我工作。其中一些是越野车(在改变顺序的同时换位线,wtf?),其中一些正在移动恰好选定的区域,而未选定部分的线位于其位置上。但是drag-stuff和eclipse完全一样!

甚至更​​多!您可以尝试选择一个区域并使用Alt + Left/Right!这会将所选区域左移或右移一个字符。惊人!

要启用全局简单地运行这样的:

(drag-stuff-global-mode) 
+0

它确实需要左右移动可选,因为它覆盖了默认的emacs键盘映射。 – ocodo 2014-10-23 13:21:28

+0

@Slomojo也许!你为什么不建议在emacswiki上? :) – 2014-10-23 19:37:32

+0

干脆就像一个魅力工作 – blackwind 2015-03-08 03:19:18

0

我用的是智能换档组件(在Melpa)这一点。默认情况下,它重新绑定C-C <arrow>以移动一条线或区域。它按主模式特定的量水平移动(例如c-basic-offset或python-indent-offset)。也在地区工作。

;; binds C-C <arrows> 
(when (require 'smart-shift nil 'noerror) 
    (global-smart-shift-mode 1))