Переместить линию / область вверх и вниз в emacs - PullRequest
78 голосов
/ 11 марта 2010

Какой самый простой способ переместить выбранную область или линию (если нет выделения) вверх или вниз в emacs?Я ищу ту же функциональность, что и в Eclipse (ограничена M-up, M-down).

Ответы [ 9 ]

48 голосов
/ 11 марта 2010

Обновление: Установите пакет move-text из Marmalade или 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)
41 голосов
/ 11 марта 2010

Строка может быть перемещена с помощью transpose-lines , привязанной к C-x C-t. Не знаю о регионах, хотя.

Я нашел этот фрагмент 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)
28 голосов
/ 15 октября 2013

Вы должны попробовать drag-stuff!

Работает точно так же, как затмение Alt + Вверх / Вниз для отдельных линий, а также для выбранных линий региона!

В дополнение к этому он позволяет перемещать слова с помощью Alt + Влево / Вправо
Это именно то, что вы ищете! И это даже доступно из репозиториев ELPA !

Другие решения никогда не работали для меня. Некоторые из них были глючными (транспонирование линий при изменении их порядка, wtf?), А некоторые из них перемещали точно выбранную область, оставляя невыбранные части линий на своих позициях. Но drag-stuff работает так же, как в затмении!

И даже больше! Вы можете попробовать выбрать регион и использовать Alt + Left / Right ! Это транспонирует выбранную область одним символом влево или вправо. Удивительно!

Чтобы включить его глобально, просто запустите:

(drag-stuff-global-mode)
8 голосов
/ 11 марта 2010

Я написал пару интерактивных функций для перемещения строк вверх / вниз:

;; 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, но вы можете использовать все, что захотите Вероятно, мне следует реализовать некоторые функции, которые работают и в регионах.

4 голосов
/ 20 сентября 2012

Вот мой фрагмент, чтобы переместить текущую строку или линии, охватываемые активной областью. Он учитывает положение курсора и выделенную область. И это не будет ломать линии, когда регион не начинается / не заканчивается на границе (ах) линии. (Он вдохновлен затмением; я нашел способ затмения более удобным, чем «транспонирование линий».)

;; 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 голосов
/ 18 марта 2011

В вики emacs есть запись только для этого:

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

Для движущихся регионов:

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

1 голос
/ 11 марта 2010

Функция transpose-paragraph может помочь вам.

Возможно, вы захотите взглянуть на раздел transpose в руководстве по 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).
1 голос
/ 11 марта 2010

Там нет встроенного. Вы можете использовать transpose-lines (C-x C-t), но вы не можете использовать его повторно Посмотрите на функции на http://www.schuerig.de/michael/blog/index.php/2009/01/16/line-movement-for-emacs/.

Должно быть легко адаптировать это и к регионам.

0 голосов
/ 10 декабря 2015

Для этого я использую пакет 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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...