在 emacs 中上下移动行/区域

问题描述 投票:0回答:10

在 emacs 中向上或向下移动选定区域或行(如果没有选择)的最简单方法是什么?我正在寻找与 eclipse 中相同的功能(仅限于 M-up、M-down)。

emacs
10个回答
59
投票

更新: 从 Marmalade 或

MELPA
安装 move-text 软件包以获取以下代码。

这是我使用的,它适用于区域和单独的线路:

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

56
投票

可以使用绑定到 C-x C-t

transpose-lines
来移动线条。不过我不知道地区。

我发现 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)

43
投票

你应该尝试

drag-stuff

它的工作方式与 Eclipse Alt+Up/Down 对于单行以及选定区域行完全相同!

此外,它还允许您使用 Alt+Left/Right
移动单词 这正是您正在寻找的!它甚至可以从 ELPA 存储库获得!

其他解决方案对我来说从来没有用过。其中一些是错误的(在改变顺序的同时调换线条,wtf?),其中一些正在移动精确选定的区域,将线条的未选定部分留在其位置上。但是

drag-stuff
的工作方式与 Eclipse 中的完全一样!

还有更多!您可以尝试选择一个区域并使用Alt+Left/Right!这会将所选区域向左或向右调换一个字符。太棒了!

要全局启用它,只需运行以下命令:

(drag-stuff-global-mode)

14
投票

我编写了几个用于向上/向下移动行的交互函数:

;; 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 风格,但您可以使用任何您想要的。我可能也应该实现一些在区域上运行的函数。


6
投票

这是我的代码片段,用于移动当前行或活动区域跨越的行。它尊重光标位置和突出显示的区域。当该区域不在线条边界处开始/结束时,它不会断线。 (它的灵感来自 eclipse;我发现 eclipse 的方式比“转置线”更方便。)

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

4
投票

emacs wiki 中有一个条目专门用于此目的:

http://www.emacswiki.org/emacs/MoveLine

对于移动区域:

http://www.emacswiki.org/emacs/MoveRegion


1
投票

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

上的函数

适应地区也应该很容易。


1
投票

transpose-paragraph
功能可以帮助您。

您可能还想查看 Emacs 手册中的 transpose 部分。 本质上:

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

0
投票

为此,我使用 smart-shift 包(在 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))

0
投票

这是一个老问题,但今天(2024 年)我使用 move-dup 来解决这个问题。 :)

© www.soinside.com 2019 - 2024. All rights reserved.