Pregunta Mover línea / región arriba y abajo en emacs


¿Cuál es la forma más fácil de mover la región o línea seleccionada (si no hay selección) hacia arriba o hacia abajo en emacs? Estoy buscando la misma funcionalidad que en eclipse (limitado a M-up, M-down).


74
2018-03-11 09:31


origen


Respuestas:


Una línea se puede mover usando líneas de transposición obligado a C-x C-t. Aunque no sé nada de las regiones.

encontré esta elisp snippet que hace lo que quieres, excepto que necesitas cambiar los enlaces.

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

36
2018-03-11 09:47



Actualizar: Instala el move-text paquete de Marmalade o MELPA para obtener el siguiente código

Esto es lo que uso, que funciona tanto en regiones como en líneas individuales:

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

44
2018-03-11 15:43



Deberías intentarlo drag-stuff !

Funciona exactamente igual que el eclipse Alt+Arriba/Abajo para líneas individuales, así como para líneas de región seleccionadas!

Además de eso, te permite mover palabras con Alt+Izquierda/Derecha
¡Esto es exactamente lo que estás buscando! E incluso está disponible desde el Repos de ELPA!

Otras soluciones nunca funcionaron para mí. Algunos de ellos tenían errores (transponiendo líneas mientras cambiaban su orden, wtf?) Y algunos de ellos se movían exactamente a la región seleccionada, dejando partes no seleccionadas de las líneas en sus posiciones. Pero drag-stuff funciona exactamente como en eclipse!

¡Y aún más! Puede intentar seleccionar una región y usar Alt+Izquierda/Derecha ! Esto transpondrá la región seleccionada por un carácter a la izquierda o a la derecha. ¡Asombroso!

Para habilitarlo globalmente, simplemente ejecuta esto:

(drag-stuff-global-mode)

24
2017-10-15 10:02



He escrito un par de funciones interactivas para mover líneas arriba / abajo:

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

Las combinaciones de teclas son estilo IntelliJ IDEA, pero puede usar cualquier cosa que desee. Probablemente debería implementar algunas funciones que operan en regiones también.


8
2018-03-11 14:35



Hay una entrada en la wiki de emacs solo para esto:

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

Para regiones en movimiento:

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


4
2018-03-18 11:17



Aquí está mi fragmento para mover la línea actual o las líneas abarcadas por la región activa. Respeta la posición del cursor y la región resaltada. Y no romperá las líneas cuando la región no comience / termine en los bordes de la línea. (Está inspirado en un eclipse; encontré que el eclipse es más conveniente que 'transpose-lines').

;; 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
2017-09-20 12:34



No hay incorporado. Puede usar líneas de transposición (C-x C-t) pero no puede usarlo repetidamente. Mira las funciones en http://www.schuerig.de/michael/blog/index.php/2009/01/16/line-movement-for-emacs/.

También debería ser fácil adaptar eso a las regiones.


1
2018-03-11 09:51



los transpose-paragraph función podría ayudarte.

También es posible que desee echar un vistazo a la transponer sección en el manual de Emacs. Esencialmente:

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
2018-03-11 10:03



Utilizo el paquete smart-shift (en Melpa) para esto. Por defecto revuelve C-C <arrow> para mover una línea o región Se mueve horizontalmente por una cantidad específica de modo principal (por ejemplo, c-basic-offset o python-indent-offset). Funciona en regiones también

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

0
2017-12-10 19:42