ย้ายทั้งบรรทัดขึ้นและลงในกลุ่ม


311

ใน Notepad ++ ฉันสามารถใช้Ctrl+ Shift+ Up/ Downเพื่อย้ายบรรทัดปัจจุบันขึ้นและลง มีคำสั่งที่คล้ายกันนี้ในกลุ่ม? ฉันดูคำแนะนำไม่รู้จบ แต่ไม่พบสิ่งใดเลย

หากไม่มีฉันจะผูกการกระทำกับชุดค่าผสมที่สำคัญได้อย่างไร

แก้ไข: คำตอบของ Mykola ใช้ได้กับทุกบรรทัดนอกเหนือจากที่จุดเริ่มต้นและจุดสิ้นสุดของบัฟเฟอร์ การย้ายบรรทัดแรกขึ้นหรือบรรทัดล่างลงลบบรรทัดและเมื่อย้ายบรรทัดล่างขึ้นมันจะกระโดดสองช่องว่างในตอนแรกเช่นจำนำ! ใครสามารถเสนอการปรับแต่งใด ๆ ได้บ้าง


ฉันไม่มีทางเลือกนอกจากต้องติดตั้งโซลูชันการเขียนสคริปต์ ฉันหวังว่ามันจะสะอาดและปรับให้เหมาะกับความต้องการของคุณ
Mykola Golubyev

31
สำหรับพวกท่านที่เป็นลูกหลานแห่งอนาคต: vim.wikia.com/wiki/Moving_lines_up_or_down
ปืน

ฉันไม่แน่ใจว่าทำไมคุณต้องมีสคริปต์ตัวอย่างบทความ Wikia ทำงาน ฉันโพสต์รุ่นที่เรียบง่ายด้านล่างเนื่องจากตัวอย่างของ Wikia ที่มี 3 โหมดการแมปที่แตกต่างกันอาจค่อนข้างน่ากลัว (และไม่จำเป็นจริงๆถ้าคุณใช้เฉพาะการแมปการเลือกบล็อกเท่านั้น ทางลัดเหล่านี้ (ดูคำตอบของฉันด้านล่าง)

Screencast ในหัวข้อ: 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 เหล่านี้คือสายที่ขาดหายไปและการกระโดดบรรทัดพิเศษ

ดังนั้นนี่คือโซลูชันการเขียนสคริปต์ที่สามารถวางไว้ภายใน. 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 - โต้ตอบ ต้องเชื่อมโยงกับ <cj> และ <ck> cs-up / down ไม่ทำงาน
Lari Hotari

2
หากใครบางคนต้องการทางลัดที่แตกต่าง: c สำหรับการควบคุม, A สำหรับ alt ฉันใช้<A-up>เหมือนกับใช้ใน eclipse
ม.ค.

1
บรรทัดที่หายไปไม่ใช่ข้อบกพร่องเป็นกลุ่ม! มันค่อนข้างเนื่องจากการดำเนินการddkPในบรรทัดสุดท้ายของเอกสาร ลองด้วยตัวคุณเองในไฟล์ 3 บรรทัด เพื่อหลีกเลี่ยงปัญหาดังกล่าวใช้ค่อนข้างมากขึ้นแมปที่กำหนดไว้ในวิกิพีเดียเป็นกลุ่ม:m
Serge 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?
Patrick McDonald

3
และเมื่อdd<number>jpต้องการย้ายบรรทัดปัจจุบัน <number> +1 ของบรรทัดลง และเมื่อdd<number>kpต้องการย้าย <number> บรรทัดปัจจุบันของบรรทัดขึ้น
egelev

230

สมมติว่าเคอร์เซอร์อยู่บนบรรทัดที่คุณต้องการย้าย

เลื่อนขึ้นและลง: :mเพื่อเลื่อน

:m +1 - เลื่อนลง 1 บรรทัด

:m -2 - เลื่อนขึ้น 1 บรรทัด

(โปรดทราบว่าคุณสามารถแทนที่ +1 ด้วยตัวเลขใด ๆ ขึ้นอยู่กับจำนวนบรรทัดที่คุณต้องการเลื่อนขึ้นหรือลงเช่น +2 จะเลื่อนลง 2 บรรทัด, 3 จะเลื่อนขึ้น 2 บรรทัด)

เพื่อย้ายไปยังบรรทัดที่เฉพาะเจาะจง

:set number - แสดงหมายเลขบรรทัด (ง่ายต่อการดูว่าคุณย้ายไปที่ใด)

:m 3 - ย้ายบรรทัดหลังบรรทัดที่ 3 (แทนที่ 3 เป็นบรรทัดใด ๆ ที่คุณต้องการ)

การย้ายหลายบรรทัด:

V(เช่นShift- V) และเลื่อนเคอร์เซอร์ขึ้นและลงเพื่อเลือกหลายบรรทัดใน VIM

เมื่อเลือกแล้วให้กด:และเรียกใช้คำสั่งด้านบนm +1ฯลฯ


14
สำหรับฉัน: m -2 เลื่อนขึ้นหนึ่งบรรทัดเท่านั้น
Hermann Ingjaldsson

2
ฉันใส่วิธีนี้ใน vimrc ของฉัน แต่แล้วฉันไม่สามารถทำซ้ำคำสั่งโดยใช้ '.' ไม่มีใครรู้ว่าทำไมนั่นคือ?
Hermann Ingjaldsson

ดีมาก! ไม่สบายเหมือนโซลูชันใน Notepad ++ แต่ยังใช้งานได้จริง
Arturas M

เฮอร์มันน์ขอโทษ / พิมพ์ผิดในส่วนของฉันคุณพูดถูก: m -2 จะเลื่อนขึ้นหนึ่งบรรทัด ฉันเปลี่ยนมัน ยังขอโทษสำหรับการตอบช้ามาก (ไม่แน่ใจเกี่ยวกับ. vimrc ส่วนหนึ่ง) Cheers
Serg

2
การย้ายโดยใช้คำสั่งทำงานได้ถ้าคุณต้องการใช้มันในการเชื่อมเช่นคำสั่งจาก Notepad ++ ตามที่ OP ถามคุณต้องป้อนคำสั่งต่อไปนี้ใน. vimrc:noremap <c-s-up> :m -2<CR> noremap <c-s-down> :m +1<CR>
kap

74

เลื่อนแถวขึ้น: ddkP

ย้ายบรรทัดลง: ddp


1
มีสิ่งนี้ใน vimrc ไม่อนุญาตให้ทำซ้ำคำสั่งโดยใช้ '.'
Hermann Ingjaldsson

@ HermannIngjaldsson ฉันคิดว่าคุณสามารถตัดคำสั่งในฟังก์ชั่นได้หากคุณต้องการที่จะใช้.ซ้ำ
jacobsimeon

Yess, .. และถ้าคุณต้องการย้ายบรรทัดมากขึ้นคุณสามารถใช้ V แทน dd
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, Escบน Windows)


1
เป็นสิ่งที่ดีโดยใช้คำสั่งในตัวของ Vim ในการเคลื่อนย้ายสาย มีแนวโน้มที่จะประพฤติตนเป็นอย่างดีเมื่อเผชิญกับการเลิกทำหรือข้อผิดพลาด
Josh Lee

1
ทำไมคุณไม่ป้อน Esc เป็น <kbd>Cv<kbd/> <kbd> Esc </kbd> (linux) Windows แทนที่ <kbd> Cv <kbd /> โดย <kbd> Cq <kbd /> ทั่วทั้งกระดาน แต่มีวิธีเดียวกับการป้อนคีย์พิเศษใด ๆ ในโหมดแทรก / คำสั่ง
sehe

@sehe: ขอบคุณฉันไม่รู้ในเวลานั้น ฉันได้อัพเดตคำตอบแล้ว
emil.p.stanchev

1
@RafaelRinaldi [niv]noremapเป็น remaps สำหรับโหมดปกติ | insert | visual <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/ ......ดูคำอธิบายที่ครอบคลุม
Serge 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 และขึ้นไป A เสมอหมายถึงทุกอย่างในหนังสือของฉัน และเพื่อค้นหาผลลัพธ์ก่อนหน้าฉันกด f แล้วไปทางซ้าย F ก็หมายถึงหา แต่สำหรับผู้ที่ไม่มีมันก็ใช่แล้ว .. มันใช้ได้จริง
Hermann Ingjaldsson

1

นี่เป็นเวอร์ชั่นที่เรียบง่ายสำหรับ MacVim โดยใช้ตัวอย่างบทความ Wikia (ลิงก์จากการแสดงความคิดเห็นของปืน )

" 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 สำหรับ Windows ลองใช้ "C" (ควบคุม) หรือ "A" (Alt) (เช่น <CAf> จะเป็นควบคุม 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

ใจสามารถทำเช่นเดียวกันกับ << และ >> แต่การเลือกจะหายไปดังนั้นทางลัดเหล่านี้อนุญาตให้เยื้องไปหลายครั้งและยังคงย้ายบล็อกไปรอบ ๆ เพราะยังคงการเลือกไว้

My 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

เป็นกลุ่มปลั๊กอิน unimpaired.vim [e และ] e


2
ดูเหมือนว่าเกินความจริงฉันไม่คิดว่าคุณจะต้องใช้ปลั๊กอินแบบเต็มสำหรับสิ่งนี้ 2 บรรทัดใน vimrc ทำตามที่ OP ต้องการ
Daniel Gratzer

1

เมื่อคุณกดคำสั่ง:help moveใน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

นี่เป็นวิธีแก้ปัญหาที่ทำงานบนเครื่องของฉัน : MacBook Pro ที่ใช้ VIM 8.1

คำสั่งเหล่านี้จะไม่ลบบรรทัดของคุณที่ด้านบนหรือด้านล่างของบัฟเฟอร์ของคุณ

การใช้สัญลักษณ์จริงที่เอาท์พุท 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.