Vim에서 전체 라인을 위아래로 이동


311

메모장 ++에서는 Ctrl+ Shift+ Up/ Down를 사용 하여 현재 줄을 위아래로 이동할 수 있습니다 . Vim에서도 이와 비슷한 명령이 있습니까? 나는 끝없는 가이드를 보았지만 아무것도 찾지 못했습니다.

없는 경우 해당 키 조합에 작업을 어떻게 바인딩 할 수 있습니까?

편집 : Mykola의 대답은 버퍼의 시작과 끝을 제외한 모든 줄에 적용됩니다. 첫 번째 줄을 위로 올리거나 맨 아래 줄을 아래로 내리면 줄이 삭제되고 맨 아래 줄을 위로 올리면 폰처럼 처음 두 칸씩 점프합니다! 누구나 개선을 제안 할 수 있습니까?


스크립팅 솔루션을 구현하는 것 외에는 선택의 여지가 없었습니다. 나는 그것이 당신의 요구에 깨끗하고 채택되기를 바랍니다.
— Mykola Golubyev

31
미래의 아이들을 위해 : vim.wikia.com/wiki/Moving_lines_up_or_down
— 총

왜 스크립트가 필요한지 잘 모르겠습니다. Wikia 기사 예제가 작동합니다. 3 가지 매핑 모드가있는 Wikia의 예제가 다소 까다로울 수 있기 때문에 단순화 된 버전을 게시했습니다. 블록 선택 매핑 만 사용하는 경우 단순히 선택 (Shift V)을 차단하고 사용하는 것을 기억할 수 있습니다 바로 가기 (아래 내 답변 참조)

주제에 대한 스크린 캐스트 : vimcasts.org/e/26
— glts

또한 vi SE
— cfi

답변:


81

.vimrc에 다음을 넣어 작업을 수행하십시오.

noremap <c-s-up> :call feedkeys( line('.')==1 ? '' : 'ddkP' )<CR>
noremap <c-s-down> ddp

줄이 사라지면 Vim 버그처럼 보입니다. 나는 그것을 피하기 위해 핵을 두었다. 아마도 더 정확한 해결책이있을 것입니다.

최신 정보

Vim 조합 만 사용하면 설명 할 수없는 어려움이 많이 있습니다. 이것들은 라인이 누락되고 여분의 라인 점프입니다.

.vimrc 또는 ~ / .vim / plugin / swap_lines.vim 안에 배치 할 수있는 스크립팅 솔루션은 다음과 같습니다.

function! s:swap_lines(n1, n2)
    let line1 = getline(a:n1)
    let line2 = getline(a:n2)
    call setline(a:n1, line2)
    call setline(a:n2, line1)
endfunction

function! s:swap_up()
    let n = line('.')
    if n == 1
        return
    endif

    call s:swap_lines(n, n - 1)
    exec n - 1
endfunction

function! s:swap_down()
    let n = line('.')
    if n == line('$')
        return
    endif

    call s:swap_lines(n, n + 1)
    exec n + 1
endfunction

noremap <silent> <c-s-up> :call <SID>swap_up()<CR>
noremap <silent> <c-s-down> :call <SID>swap_down()<CR>

1
설정과 충돌이있는 것처럼 보이는 <cj>와 <ck>로 변경해야했지만 환상적인 답변입니다! 정말 감사합니다
— user4812

1
감사합니다, git rebase --interactive. <cj>와 <ck>에 바인딩했습니다. cs-up / down이 작동하지 않았습니다.
— Lari Hotari

2
누군가가 다른 지름길을 원한다면 : c는 통제를위한 것이고, A는 대체를위한 것입니다, 나는 <A-up>일식에서 사용되는 것처럼 사용합니다.
— jan

1
사라지는 라인은 Vim 버그가 아닙니다! 오히려 ddkP문서의 마지막 줄 에서 수행되기 때문 입니다. 3 줄 파일로 직접 사용해보십시오. 이러한 문제를 피하려면 :mVim 위키에 제공된 훨씬 쉬운 매핑을 사용하십시오 .
— Sroo Stroobandt

1
나는에 마지막으로 라인을 변경 <A-up>하고 <A-down>하지만 시각적 실행에 정력에 그 열쇠를하려고 할 때 TMUX 선택 사라지고 커서가 이동 줄; 선택된 선을 움직이지 않고
— Konrad

574

한 줄을 위의 줄로 바꾸려면 일반적으로 다음을 수행하십시오.

ddkP

설명

  • dd는 행을 삭제하고 기본 레지스터에 추가합니다.
  • k는 한 줄 위로 이동합니다 (j는 줄 아래로 이동합니다)
  • P는 현재 줄 위에 붙여 넣습니다.

5
그리고 항상 사용 가능합니다. :-)
— Henno

71
그리고 ddp줄을 아래로 이동하려면 (줄을 삭제하고 현재 줄 아래에 붙여 넣기)
— bcoughlan

2
여러 줄을 이동하려면 4라고 말한 4 dd다음 2 줄로 이동 한 다음 :2붙여 넣기하려는 위치 로 이동하십시오 P.
— Guru

2
@Guru가 4dd대신 해야 4 dd합니까?
— 패트릭 맥도날드

3
그리고 dd<number>jp현재 줄 <number> +1 줄을 아래로 이동합니다. 그리고 dd<number>kp현재 줄 <number> 개를 위로 이동합니다.
— egelev

230

커서가 이동하려는 행에 있다고 가정합니다.

위아래 :m로 이동 : 이동

:m +1 -한 줄 아래로 이동

:m -2 -한 줄 위로 이동

(위 또는 아래로 이동하려는 행 수에 따라 +1을 임의의 숫자로 바꿀 수 있습니다. 즉, +2는 2 행 아래로 이동하고, -3은 2 행 위로 이동합니다)

특정 줄로 이동

:set number -번호 줄 표시 (이동하는 위치를 더 쉽게 볼 수 있음)

:m 3 -세 번째 줄 다음으로 줄을 이동하십시오 (3을 원하는 줄로 바꾸십시오)

여러 줄 이동 :

V(예 Shift- V) 상하 이동 준마는 VIM에서 여러 행을 선택합니다

히트를 선택하면 :위의 명령을 실행 m +1등


14
나를 위해 : m -2는 한 줄만 올라갑니다.
— Hermann Ingjaldsson

2
이 방법을 vimrc에 넣었지만 '.'를 사용하여 명령을 반복 할 수 없습니다. 왜 그런지 아는 사람이 있습니까?
— Hermann Ingjaldsson

아주 좋아요! 메모장 ++의 솔루션만큼 편안하지는 않지만 여전히 실제적이고 작동합니다.
— Arturas M

Hermann, 죄송합니다. 오타 / 실수입니다. 귀하는 옳습니다. : m -2 한 줄 위로 올립니다. 나는 그것을 바꿨다. 매우 늦게 답장을 드려 죄송합니다 (.vimrc 부분에 대해 잘 모르겠 음) Cheers
— Serg

2
OP를 사용하여 메모장 ++의 바인딩과 같은 바인딩에 명령을 사용하려면 명령을 사용하여 이동하십시오. .vimrc에 다음을 입력해야합니다.noremap <c-s-up> :m -2<CR> noremap <c-s-down> :m +1<CR>
— kap

74

줄을 위로 이동하십시오. ddkP

줄을 아래로 이동하십시오. ddp


1
vimrc에서 이것을 사용하면 '.'을 사용하여 명령을 반복 할 수 없습니다.
— Hermann Ingjaldsson 2016 년

@HermannIngjaldsson, .반복 을 사용하려면 명령을 함수로 래핑 할 수 있다고 가정합니다 .
— jacobsimeon

예, .. 더 많은 행을 이동해야하는 경우 dd 대신 V를 사용할 수 있습니다.
— sensorario

15

이것은 나를 위해 일했다 :

http://vim.wikia.com/wiki/Moving_lines_up_or_down_in_a_file

BTW, ALT + some_key를 사용하고 터미널 (urxvt 가이 작업을 수행하지 않음)을 거부하려면 .vimrc에 다음과 같이 입력해야합니다.

" For moving lines (^] is a special character; use <M-k> and <M-j> if it works)
nnoremap ^]k mz:m-2<CR>`z==
inoremap ^]j <Esc>:m+<CR>==gi
inoremap ^]k <Esc>:m-2<CR>==gi
vnoremap ^]j :m'>+<CR>gv=`<my`>mzgv`yo`z
nnoremap ^]j mz:m+<CR>`z==
vnoremap ^]k :m'<-2<CR>gv=`>my`<mzgv`yo`z

여기서 ^]는 ALT 키를 나타내는 단일 문자 입니다. 해당 문자를 입력하려면 C+v, EscVim 에서 사용하십시오 ( C+q, EscWindows).


1
Vim의 내장 명령을 사용하여 선을 이동하는 것이 좋습니다. 실행 취소 또는 오류가 발생했을 때 잘 작동합니다.
— Josh Lee

1
<kbd> Cv <kbd /> <kbd> Esc </ kbd> (linux)로 Esc를 입력하지 마십시오. 윈도우를 대체 <KBD> 이력서 <KBD />의 <KBD> Cq와 <KBD /> 특별한 삽입 / 명령 모드에서 키 입력 같은 방법이 있지만 전반적으로
— sehe

@sehe : 감사합니다. 당시에는 몰랐습니다. 답변을 업데이트했습니다.
— emil.p.stanchev

1
@RafaelRinaldi [niv]noremap는 일반 모드의 리맵 입니다. <CR>입니다 Carriage Return( Enter키).
— vp_arth

1
@vp_arth 없어요
— sehe

13

~ / .vimrc 파일에 다음을 추가하십시오 (n, m에 대한 매핑이 없는지 확인하십시오)

nmap n :m +1<CR>
nmap m :m -2<CR>

이제 n키를 누르면 줄이 아래 m로 이동하고 줄이 위로 이동합니다.


12

명령 모드에서 아래로 이동하려는 줄에 커서를 놓은 다음

ddp

설명 : dd는 일반 버퍼에 대한 현재 행을 삭제합니다. p는 커서 위치 이후 또는 전체 행의 경우 한 행 아래에 다시 넣습니다.

많은 문서에서 명령 p 및 P와 관련하여 약간의 혼동이 있습니다. 실제로 p는 AFTER 커서와 P AT 커서를 붙여 넣습니다.


8

이 코드를 .vimrc (또는 .gvimrc)에 추가하십시오.

nnoremap <A-j> :m+<CR>==
nnoremap <A-k> :m-2<CR>==
inoremap <A-j> <Esc>:m+<CR>==gi
inoremap <A-k> <Esc>:m-2<CR>==gi
vnoremap <A-j> :m'>+<CR>gv=gv
vnoremap <A-k> :m-2<CR>gv=gv

1
당으로 vim.wikia.com/wiki/... 포괄적 인 설명이 참조하십시오.
— Sroo Stroobandt

Mac에서 <A-something>이 ​​작동하지 않아 이유를 모르겠습니다. <Cj> <Ck>로 교체했으며 Ctrl 키를 사용하여 잘 작동합니다.
— Cédric NICOLAS



3

내 .vimrc 파일 끝에 다음을 넣습니다.

noremap H ddkkp
noremap N ddp

이제 'H'와 'N'은 각각 전류 라인을 위아래로 움직입니다.


H와 N은 실제로 유용한 명령입니다 (H는 커서를 화면의 상단과 시작으로 이동하고 N은 이전 검색 결과로 이동합니다). 다른 키를 사용하는 것이 좋습니다
— villapx

내가 참조. 나는 또한 그것들을 재구성했다. 화면 상단으로 이동하려면 a를 누른 다음 위로를 누릅니다. 항상 내 책에서 항상 의미합니다. 그리고 이전 결과를 검색하려면 f를 누른 다음 떠납니다. 그런 다음 F는 찾기를 나타냅니다. 그러나 그런 것을 가지고 있지 않은 사람들에게는 그렇습니다.
— Hermann Ingjaldsson 16:16에

1

다음은 Wikia 기사 예제를 사용하여 MacVim 용으로 단순화 된 버전입니다 ( 총 주석의 링크 참조 ).

" Move selection up/down (add =gv to reindent after move)
:vmap <D-S-Up> :m-2<CR>gv
:vmap <D-S-Down> :m'>+<CR>gv

현재 줄을 선택하려면 Shift-V 만 사용하고 선택적으로 더 많은 줄을 선택하려면 위 / 아래로 커서를 이동하기 때문에 블록 선택 변형 만 사용하고 있습니다.

위의 단축키에 따라 Cmd-Shift-Up / Down을 누르면 블록 선택이 위 / 아래로 이동합니다. "D"는 MacVim의 Command 키입니다. Windows의 경우 "C"(Control) 또는 "A"(Alt)를 시도하십시오 (예 : <CAf>는 Control Alt f 임).

Wikia 아티클에 "= gv"를 추가하면 주변 텍스트를 기준으로 이동 후 블록의 들여 쓰기를 조정하는 효과가 있습니다. 혼란 스럽기 때문에 제거하고 선택 항목을 빠르게 들여 쓰기위한 바로 가기를 추가했습니다.

" Indent selection left/right (Cmd Shift Left/Right is used for Tab switching)
:vmap <D-A-Left> <gv
:vmap <D-A-Right> >gv

<< 및 >>로도 동일한 작업을 수행 할 수 있지만 선택 항목이 손실되므로 위의 바로 가기를 사용하면 여러 번 들여 쓰기를 할 수 있으며 선택 항목이 유지되므로 블록을 계속 이동할 수 있습니다.

MacVim은 Cmd-Shift-Left / Right로 탭을 전환하도록 구성되어 있으므로 Cmd-Alt-Left / Right를 사용했습니다.

MacVim의 탭 전환은 다음과 같습니다 (위의 나머지 부분은 .gvimrc에 입력).

:macm Window.Select\ Previous\ Tab key=<D-S-Left>
:macm Window.Select\ Next\ Tab key=<D-S-Right>

1

vim 플러그인 unimpaired.vim [e and] e


2
이것은 과잉처럼 보이지만 실제로는 완전한 플러그인이 필요하다고 생각하지 않습니다. vimrc에서 2 줄은 OP가 원하는 것을 정확하게 수행합니다.
— Daniel Gratzer

1

:help move에서 command를 누르면 vim결과는 다음과 같습니다.

:[range]m[ove] {address} *:m* *:mo* *:move* *E134* Move the lines given by [range] to below the line given by {address}.

예 : 현재 줄을 한 줄 아래로 이동 => :m+1 .

예 : 숫자가 100 인 행을 숫자가 80 => 인 행 아래로 이동합니다 :100 m 80 .

예 : 숫자가 100 인 행을 숫자가 200 => 인 행 아래로 이동합니다 :100 m 200 .

예 : [100, 120] 내에 숫자가있는 행을 숫자 200 =>가있는 행 아래로 이동하십시오 :100,120 m 200 .


1

내 컴퓨터에서 작동하는 솔루션은 다음과 같습니다 . VIM 8.1을 실행하는 MacBook Pro

이 명령은 버퍼의 맨 위나 맨 아래 줄을 삭제하지 않습니다.

Alt-J 및 Alt-K 출력의 실제 기호를 사용하면 내 환경에서 키 코드가 올바르게 매핑되지 않는 해결 방법이 있습니다.

오래된 .vimrc에 이것을 던져서 당신에게 맞는지 확인하십시오.

" Maps Alt-J and Alt-K to macros for moving lines up and down
" Works for modes: Normal, Insert and Visual
nnoremap ∆ :m .+1<CR>==
nnoremap ˚ :m .-2<CR>==
inoremap ∆ <Esc>:m .+1<CR>==gi
inoremap ˚ <Esc>:m .-2<CR>==gi
vnoremap ∆ :m '>+1<CR>gv=gv
vnoremap ˚ :m '<-2<CR>gv=gv


0

한 줄을 이동하면 : m. + 1 또는 : m.-2가 수행합니다. 다음은 여러 줄을 이동하는 스크립트입니다. 비주얼 모드에서 Alt-up / Alt-down은 비주얼 선택을 포함하는 라인을 한 라인 씩 위 / 아래로 이동합니다. 삽입 모드 또는 일반 모드에서 카운트 접두사가 제공되지 않으면 Alt-up / Alt-down은 현재 행을 이동합니다. 카운트 접두사가 있으면 Alt-up / Alt-down은 현재 줄부터 시작하여 한 줄씩 많은 줄을 이동합니다.

function! MoveLines(offset) range
    let l:col = virtcol('.')
    let l:offset = str2nr(a:offset)
    exe 'silent! :' . a:firstline . ',' . a:lastline . 'm'
        \ . (l:offset > 0 ? a:lastline + l:offset : a:firstline + l:offset)
    exe 'normal ' . l:col . '|'
endf

imap <silent> <M-up> <C-O>:call MoveLines('-2')<CR>
imap <silent> <M-down> <C-O>:call MoveLines('+1')<CR>
nmap <silent> <M-up> :call MoveLines('-2')<CR>
nmap <silent> <M-down> :call MoveLines('+1')<CR>
vmap <silent> <M-up> :call MoveLines('-2')<CR>gv
vmap <silent> <M-down> :call MoveLines('+1')<CR>gv

0

특정 검색과 일치하는 여러 줄에서이 작업을 수행하려는 경우 :

  • 위로 : :g/Your query/ normal ddp또는:g/Your query/ m -1
  • 아래로 :g/Your query/ normal ddp또는:g/Your query/ m +1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.