Pindahkan seluruh baris ke atas dan ke bawah di Vim


311

Di Notepad ++, saya bisa menggunakan Ctrl+ Shift+ Up/ Downuntuk memindahkan garis saat ini ke atas dan ke bawah. Apakah ada perintah yang mirip dengan ini di Vim? Saya telah melihat melalui panduan yang tak ada habisnya, tetapi tidak menemukan apa pun.

Jika tidak ada, bagaimana saya bisa mengikat tindakan ke kombinasi tombol itu?

Sunting: Jawaban Mykola bekerja untuk semua baris, selain yang ada di awal dan akhir buffer. Memindahkan garis pertama ke atas atau garis bawah ke bawah menghapus garis, dan ketika memindahkan garis bawah ke atas itu melompat dua spasi pada awalnya, seperti pion! Adakah yang bisa menawarkan perbaikan?


Saya tidak punya pilihan selain menerapkan solusi scripting. Saya harap ini bersih dan dapat diadaptasi untuk kebutuhan Anda.
Mykola Golubyev

31
Untuk anak-anak Anda di masa depan: vim.wikia.com/wiki/Moving_lines_up_or_down
senjata

Saya tidak yakin mengapa Anda memerlukan skrip, contoh artikel Wikia berfungsi. Saya telah memposting di bawah ini versi yang disederhanakan, karena contoh Wikia dengan 3 mode pemetaan berbeda bisa agak menakutkan (dan tidak terlalu diperlukan. Jika Anda hanya menggunakan pemetaan pemilihan blok, maka Anda dapat dengan mudah mengingat untuk memblokir pemilihan (Shift V) dan menggunakan pintasan ini (lihat jawaban saya di bawah ini).

Screencast pada topik: vimcasts.org/e/26
glts

Juga pada vi SE
cfi

Jawaban:


81

Masukkan berikut ini ke .vimrc Anda untuk melakukan pekerjaan

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

Menghilangnya garis itu tampak seperti bug Vim. Saya menaruh retasan untuk menghindarinya. Mungkin ada beberapa solusi yang lebih akurat.

Memperbarui

Ada banyak kesulitan yang tidak dapat dijelaskan dengan hanya menggunakan kombinasi Vim. Ini adalah garis yang hilang dan garis melompat ekstra.

Jadi di sini adalah solusi scripting yang dapat ditempatkan di dalam .vimrc atau ~ / .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
Harus berubah menjadi <cj> dan <ck> karena tampaknya ada bentrokan dengan pengaturan saya, tetapi jawaban yang fantastis! Terima kasih banyak
user4812

1
Terima kasih, bagus untuk git rebase --interaktif. Harus mengikat ke <cj> dan <ck>. cs-up / down tidak berfungsi.
Lari Hotari

2
Jika seseorang menginginkan jalan pintas yang berbeda: c adalah untuk kontrol, A adalah untuk alt, saya menggunakan <A-up>seperti yang digunakan dalam gerhana.
Januari

1
Garis yang menghilang bukanlah bug Vim! Ini lebih disebabkan oleh kinerja ddkPpada baris terakhir dokumen. Cobalah sendiri pada file 3-baris. Untuk menghindari masalah seperti itu, gunakan :mpemetaan yang lebih mudah seperti yang diberikan pada Vim wiki .
Serge Stroobandt

1
Saya mengubah baris terakhir menjadi <A-up>dan <A-down>tetapi ketika saya mencoba kunci-kunci itu dalam vim dalam menjalankan visual dalam tmux pilihan menghilang dan kursor bergerak sejajar; tanpa memindahkan garis yang dipilih.
Konrad

574

Jika saya ingin menukar satu baris dengan baris di atas, saya biasanya melakukan hal berikut

ddkP

Penjelasan

  • dd akan menghapus baris dan menambahkannya ke register default.
  • k akan bergerak ke atas garis (j akan pindah ke bawah garis)
  • P akan menempel di atas garis saat ini

5
Dan selalu tersedia juga. :-)
Henno

71
Dan ddpuntuk memindahkan garis ke bawah (hapus garis dan tempel di bawah garis saat ini)
bcoughlan

2
Untuk memindahkan banyak baris, ucapkan 4, 4 ddlalu pindah ke, ucapkan 2 baris, lalu :2tempat yang ingin Anda tempel dan P.
Guru

2
@Uru seharusnya itu 4ddbukan 4 dd?
Patrick McDonald

3
Dan dd<number>jpuntuk memindahkan garis saat ini <nomor> +1 garis ke bawah. Dan dd<number>kpuntuk memindahkan baris <number> saat ini ke atas.
egelev

230

Dengan asumsi kursor berada pada garis yang ingin Anda pindahkan.

Bergerak ke atas dan ke bawah: :muntuk bergerak

:m +1 - bergerak ke bawah 1 baris

:m -2 - naik 1 baris

(Catatan Anda dapat mengganti +1 dengan angka apa saja tergantung pada berapa banyak garis yang ingin Anda pindahkan ke atas atau ke bawah, yaitu +2 akan memindahkannya ke bawah 2 baris, -3 akan memindahkannya ke atas 2 baris)

Untuk pindah ke jalur tertentu

:set number - menampilkan garis angka (lebih mudah untuk melihat ke mana Anda memindahkannya)

:m 3 - pindahkan garis setelah garis ke-3 (ganti 3 ke garis yang Anda inginkan)

Memindahkan banyak baris:

V(ie Shift- V) dan gerakkan courser ke atas dan ke bawah untuk memilih beberapa baris dalam VIM

sekali dipilih tekan :dan jalankan perintah di atas, m +1dll


14
bagi saya: m -2 hanya naik satu baris.
Fzs2

2
saya meletakkan metode ini di vimrc saya tetapi kemudian saya tidak bisa mengulangi perintah menggunakan '.' apakah ada yang tahu mengapa itu terjadi?
Fzs2

Sangat bagus! Tidak senyaman solusi di Notepad ++, tapi tetap - nyata dan berfungsi.
Arturas M

Hermann, Maaf, salah ketik / kesalahan saya, Anda benar,: m -2 akan naik satu baris. Saya mengubahnya. Juga maaf atas jawaban yang sangat terlambat (tidak yakin tentang bagian .vimrc) Cheers
Serg

2
Memindahkan menggunakan perintah berfungsi, jika Anda ingin menggunakannya dalam binding seperti yang dari Notepad ++ seperti yang diminta OP, Anda harus memasukkan yang berikut ini ke .vimrc:noremap <c-s-up> :m -2<CR> noremap <c-s-down> :m +1<CR>
kap

74

Pindahkan garis ke atas: ddkP

Pindahkan garis ke bawah: ddp


1
memiliki ini di vimrc melarang mengulangi perintah menggunakan '.'
Fzs2

@HermannIngjaldsson, saya kira Anda bisa membungkus perintah dalam suatu fungsi jika Anda ingin dapat menggunakan .untuk mengulang.
jacobsimeon

Yess, .. dan jika Anda perlu memindahkan lebih banyak baris, Anda dapat menggunakan V daripada dd.
sensorario

15

Ini bekerja untuk saya:

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

BTW, jika Anda ingin menggunakan ALT + some_key dan terminal Anda (urxvt melakukan ini) menolak untuk mematuhi, Anda harus memasukkan sesuatu seperti ini di .vimrc Anda:

" 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

di mana ^] adalah karakter tunggal yang mewakili kunci ALT. Untuk memasukkan karakter itu, gunakan C+v, Escdalam Vim ( C+q, Escpada Windows).


1
Ini bagus, menggunakan perintah bawaan Vim untuk memindahkan garis. Ini lebih cenderung berperilaku baik saat menghadapi kegagalan atau kesalahan.
Josh Lee

1
Mengapa Anda tidak memasukkan Esc sebagai <kbd>Cv<kbd/> <kbd> Esc </kbd> (linux). Windows menggantikan <kbd> Cv <kbd /> dengan <kbd> Cq <kbd /> di seluruh papan tetapi memiliki cara yang sama untuk memasukkan kunci khusus apa pun dalam mode sisipkan / perintah
lihat

@sehe: Terima kasih, saya tidak tahu itu saat itu. Saya sudah memperbarui jawabannya.
emil.p.stanchev

1
@RafaelRinaldi, [niv]noremapadalah pemetaan untuk mode | insert | visual yang normal. <CR>adalah Carriage Return( Enterkunci).
vp_arth

1
@vp_arth Tidak ada
sehe

13

tambahkan berikut ini ke file ~ / .vimrc (pastikan Anda tidak memiliki pemetaan untuk n, m)

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

sekarang menekan ntombol akan memindahkan garis ke bawah dan makan memindahkan garis ke atas.


12

Dalam mode perintah, posisikan kursor pada baris yang Anda inginkan untuk bergerak ke bawah, dan kemudian

ddp

Penjelasan: dd menghapus baris saat ini ke buffer umum p mengembalikannya SETELAH posisi kursor, atau dalam kasus seluruh baris, satu baris di bawah ini.

Ada beberapa kebingungan tentang perintah p dan P di banyak dokumen. Pada kenyataannya, p pasta setelah kursor, dan kursor P AT.


8

Cukup tambahkan kode ini ke .vimrc (atau .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
Per vim.wikia.com/wiki/… lihat di sana untuk penjelasan yang komprehensif.
Serge Stroobandt

Pada Mac <A-sesuatu> tidak berfungsi, saya tidak tahu mengapa. Saya telah diganti dengan <Cj> <Ck>, dan berfungsi dengan baik menggunakan tombol Ctrl.
Cédric NICOLAS



3

Saya meletakkan yang berikut ini di akhir file .vimrc saya:

noremap H ddkkp
noremap N ddp

Jadi sekarang 'H' dan 'N' memindahkan garis saat ini ke atas dan ke bawah masing-masing.


H dan N sebenarnya adalah perintah yang berguna (H memindahkan kursor ke atas dan awal layar, N pindah ke hasil pencarian sebelumnya), jadi saya akan merekomendasikan menggunakan tombol yang berbeda
villapx

Saya melihat. Saya juga telah mengkonfigurasi ulang mereka. Untuk menuju ke bagian atas layar saya tekan a lalu ke atas. A selalu berarti sepenuhnya dalam buku-buku saya. Dan untuk mencari melalui hasil sebelumnya saya tekan f dan kemudian pergi. F kemudian adalah singkatan dari find. Tetapi bagi mereka yang tidak memilikinya seperti itu maka ya .. itu valid.
Fzs2

1

Berikut adalah versi yang disederhanakan, untuk MacVim, menggunakan contoh artikel Wikia (lih. Tautan dari komentar gun ).

" 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

Saya hanya menggunakan varian pemilihan blok, karena yang diperlukan hanyalah Shift-V untuk memilih garis saat ini, dan secara opsional kursor naik / turun untuk memilih beberapa garis lagi.

Menurut pintasan di atas, menekan Cmd-Shift-Atas / Bawah akan menggeser pemilihan blok ke atas / bawah. "D" adalah kunci Command di MacVim, untuk Windows coba "C" (Control), atau "A" (Alt) (mis. <CAf> akan menjadi Control Alt f).

Artikel Wikia menambahkan "= gv" pada ini, yang memiliki efek untuk menyesuaikan lekukan blok setelah pindah, berdasarkan teks di sekitarnya. Ini membingungkan jadi saya menghapusnya, dan menambahkan pintasan untuk dengan cepat membuat indentasi pemilihan.

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

Pikiran, hal yang sama dapat dilakukan dengan << dan >> tetapi pemilihan akan hilang, jadi pintasan di atas memungkinkan untuk indentasi beberapa kali dan masih memindahkan blok sekitar karena pemilihan dipertahankan.

MacVim saya dikonfigurasi untuk beralih Tab dengan Cmd-Shift-Kiri / Kanan jadi saya menggunakan Cmd-Alt-Kiri / Kanan.

Inilah Tab switching untuk MacVim (masukkan .gvimrc dengan sisanya di atas):

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

1

plugin vim unimpaired.vim [e and] e


2
Ini sepertinya berlebihan, saya tidak berpikir Anda benar-benar membutuhkan plugin lengkap untuk ini. 2 baris dalam vimrc melakukan persis seperti yang diinginkan OP
Daniel Gratzer

1

Ketika anda menekan perintah :help movedi vim, di sini adalah hasilnya:

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

Misalnya: Pindahkan baris saat ini satu baris ke bawah => :m+1 .

Misalnya: Pindahkan garis dengan angka 100 di bawah garis dengan angka 80 => :100 m 80 .

Misalnya: Pindahkan garis dengan angka 100 di bawah garis dengan angka 200 => :100 m 200 .

Misalnya: Pindahkan garis dengan angka dalam [100, 120] di bawah garis dengan angka 200 => :100,120 m 200 .


1

Berikut adalah solusi yang berfungsi pada komputer saya : MacBook Pro menjalankan VIM 8.1

Perintah-perintah ini tidak akan menghapus baris Anda di bagian atas atau bawah buffer Anda.

Menggunakan simbol aktual yang dihasilkan Alt-J dan Alt-K adalah solusi untuk kode-kunci mereka yang tidak memetakan dengan benar di lingkungan saya.

Lemparkan ini di .vimrc lama dan lihat apakah itu cocok untuk Anda.

" 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 atau: m.-2 akan dilakukan jika Anda memindahkan satu baris. Inilah skrip saya untuk memindahkan banyak baris. Dalam mode visual, Alt-up / Alt-down akan memindahkan garis yang berisi pemilihan visual naik / turun satu baris. Dalam mode insert atau mode normal, Alt-up / Alt-down akan memindahkan garis saat ini jika tidak ada awalan hitungan yang diberikan. Jika ada awalan hitungan, Alt-up / Alt-down akan memindahkan banyak baris mulai dari baris saat ini naik / turun dengan satu baris.

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

Jika Anda ingin melakukan ini pada beberapa baris yang cocok dengan pencarian tertentu:

  • Atas: :g/Your query/ normal ddpatau:g/Your query/ m -1
  • Turun :g/Your query/ normal ddpatau:g/Your query/ m +1
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.