emacs에서 줄 / 영역을 위아래로 이동


85

emacs에서 선택한 영역이나 선 (선택 사항이없는 경우)을 위아래로 이동하는 가장 쉬운 방법은 무엇입니까? 이클립스에서와 동일한 기능을 찾고 있습니다 (M-up, M-down으로 제한됨).


1
이 관용구는 이동하려는 것을 죽이고 일반적인 탐색 기능 (isearch 등 포함)을 사용하여 코드를 원하는 지점을 이동 한 다음 잡아 당기는 것입니다. 킬 스택이 있으므로 즉시 위치를 찾을 필요조차 없습니다. 나중에 잡아 당길 다른 비트를 모을 수 있습니다. 개인적으로 무거운 Emacs 사용자로서 수동으로 한 줄을 위나 아래로 이동하려는 상황은 상상할 수 없습니다. 그것은 유용하지 않을 것입니다.
jrockway

7
@jrockway : 귀하의 의견에 감사드립니다. 나는 모든 사람이 자신 만의 방식을 가지고 있다고 생각합니다. 나는 이클립스로 많이 작업하고 선 / 영역을 이동하는 데 매우 익숙합니다. emacs를 매우 확장 할 수있는 장점 중 하나는이 기능을 쉽게 추가 할 수 있다는 것입니다.
fikovnik

3
동의했습니다. 나는 내가 그것을 지원하는 편집기에 있든 없든 당신이 설명하는대로 줄을 위아래로 움직이고 싶어요. 또는 그 문제에 대해 내가 코드 작업을하고 있든 아니든. Word는 Alt + Shift + 위쪽 및 아래쪽으로이 (단락 별)를 지원하며 가능할 때마다 편집기에서 매핑합니다.
harpo

6
@Drew와 jrockway : 나는 덜 만족하는 것이 이맥스 방식이 아니라고 생각합니다. 이동 라인은 kill / yankk보다 이동이 더 빠릅니다. 그리고 org-mode ofcourse는 그 이유 때문에 그것을 구현했습니다. 실제로 한 줄을 이동하고 싶은 경우가 많이 있습니다. 블록 범위 안 / 밖으로 잘못 배치 된 명령문을 이동하는 것은 하나, 명령문 순서 변경, 문서 순서 변경 (조직- 모드), .. 많은 사람들이 이클립스에서 그것을 사용합니다. 당신이 사용하지 않는 것, 당신은 종종 놓치지 않는다. 그러나 줄 이동의 유용성은 많은 프로그래머들에게 사실이다
Peter

2
이것은 재정렬하려는 커밋 목록이 포함 된 git-rebase 파일을 편집 할 때 유용합니다.
Ken Williams

답변:


47

에 바인딩 된 조바꿈 선을 사용하여 선을 이동할 수 있습니다 C-x C-t. 그러나 지역에 대해서는 Dunno.

바인딩을 변경해야하는 경우를 제외하고 원하는 작업을 수행하는 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)

스 니펫 주셔서 감사합니다. 이것이 바로 제가 찾던 것입니다!
fikovnik

이 솔루션과 @sanityinc가 게시 한 거의 동일한 솔루션에는 약간의 문제가 있습니다. 정의 된 바로 가기를 사용하여 영역을 위아래로 이동하면 즉시 실행 취소 바로 가기를 사용합니다 (기본적으로 C-_). 영역이 사라지고 "영역에서 실행 취소!"라는 메시지가 나타납니다. 에코 영역에가 표시됩니다. 다른 실행 취소 명령은 "지역에 대한 추가 실행 취소 정보가 없습니다"라는 메시지를 생성합니다. 그러나 커서를 이동 한 다음 실행 취소 명령을 실행하면 실행 취소 작업이 다시 시작됩니다. 비교적 사소한 자극이지만 다른 모든 Emacs 명령은 속임수에 의존하지 않고 즉시 취소 할 수 있습니다.
Teemu Leisti 2013

1
이것이 바로 올바른 방법입니다. Emacs의 기본 조옮김 행은 커서가 조옮김 후 다음 행으로 이동하여 단계별로 반복하기 어렵 기 때문에 올바른 기능이 아닙니다.
mythicalcoder

51

업데이트 :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)

1
저는

감사! 코드가 이미 거기에 있다고 생각 하지만 ( emacswiki.org/emacs/basic-edit-toolkit.el )이 새 페이지는 사람들이 찾기가 더 쉬울 것입니다.
sanityinc

Ahh, 내가 전에 보지 못했던 멋진 것은 basic-edit-toolkit이 정리를 사용할 수있는 것처럼 보입니다.
ocodo

1
@mcb 예, 모든 ELPA 패키지는 el-get을 통해 설치할 수 있습니다. (요즘 el-get 작성자도 package.el로 이동하고 있습니다.) 전체 줄을 선택하려면 현재 줄을 빠르게 선택하거나 전체 줄을 포함하도록 현재 영역을 확장하는 별도의 함수를 작성하는 것이 좋습니다. 그런 다음 이동 텍스트 함수 전에 해당 함수를 호출하십시오.
sanityinc 2014 년

1
@sanityinc 감사합니다. 처음 사용했을 때 미니 Emacs 'O'를 마 셨습니다. 좋은 물건!
JS.

31

시도해야합니다 drag-stuff!

이클립스 Alt+ Up/ Down단일 라인과 선택된 영역 라인에 대해 정확히 작동합니다 !

그 외에도 Alt+ Left/ 로 단어를 이동할 수 있습니다. Right
이것은 정확히 당신이 찾고있는 것입니다! ELPA repos 에서도 사용할 수 있습니다 !

다른 솔루션은 저에게 효과가 없었습니다. 그들 중 일부는 버그가 있었으며 (순서를 바꾸는 동안 줄 바꿈, wtf?) 일부는 정확히 선택된 영역을 이동하여 선의 선택되지 않은 부분을 위치에 남겨 둡니다. 그러나 drag-stuff일식에서와 똑같이 작동합니다!

그리고 더! 지역을 선택하고 Alt+ Left/ Right! 이렇게하면 선택한 영역이 한 문자 씩 왼쪽 또는 오른쪽으로 바뀝니다. 놀랄 만한!

전역 적으로 활성화하려면 다음을 실행하십시오.

(drag-stuff-global-mode)

기본 emacs 키맵을 재정의하기 때문에 왼쪽 및 오른쪽 이동 옵션이 ​​필요합니다.
ocodo

@Slomojo 아마도! emacswiki에서 제안하지 않으시겠습니까? :)
Aleks-Daniel Jakimenko-A.

1
이걸 사용했는데 지금은 스마트 시프트를 사용하고 있습니다. 나는 그것이 수평 이동을 위해 DWIM을 좋아합니다.
jpkotta 2015

1
(drag-stuff-define-keys)키 바인딩이 작동하기 전에 init 파일에 필요 합니다. 이것은이 github에서 설명합니다 : github.com/rejeep/drag-stuff.el
agent18

11

줄을 위 / 아래로 이동하기위한 몇 가지 대화 형 함수를 작성했습니다.

;; 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 스타일이지만 원하는 것을 사용할 수 있습니다. 지역에서도 작동하는 일부 기능을 구현해야합니다.


5

다음은 현재 줄 또는 활성 영역에 걸쳐있는 줄을 이동하는 스 니펫입니다. 커서 위치와 강조 표시된 영역을 고려합니다. 그리고 영역이 선 경계에서 시작 / 종료되지 않을 때 선을 끊지 않습니다. (일식에서 영감을 얻었습니다. 저는 이클립스 방식이 '전치 선'보다 더 편리하다는 것을 알았습니다.)

;; 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
나를 위해 이동 텍스트 패키지가 손상되었습니다. 귀하의 솔루션은 내 시스템에서 완벽하게 작동합니다. 감사합니다!
Rune Kaagaard


1

내장이 없습니다. 조옮김 선 (Cx Ct)을 사용할 수 있지만 반복적으로 사용할 수는 없습니다. http://www.schuerig.de/michael/blog/index.php/2009/01/16/line-movement-for-emacs/ 의 함수를 살펴보세요 .

지역에도 쉽게 적용 할 수 있어야합니다.


1
Btw, 연결된 스 니펫을 사용하기로 결정한 경우 let 문을 (let ((col (current-column)) (line-move-visual nil))로 변경하고 싶을 수 있습니다. 그렇지 않으면 줄 바꿈으로 재미있는 동작이 발생합니다. .
Leo Alekseyev

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

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))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.