Sposta l'intera riga su e giù in Vim


311

In Notepad ++, posso usare Ctrl+ Shift+ Up/ Downper spostare la riga corrente su e giù. C'è un comando simile a questo in Vim? Ho guardato attraverso infinite guide, ma non ho trovato nulla.

In caso contrario, come potrei associare l'azione a quella combinazione di tasti?

Modifica: la risposta di Mykola funziona per tutte le righe, ad eccezione di quelle all'inizio e alla fine del buffer. Spostando la prima linea verso l'alto o la linea inferiore verso il basso si elimina la linea e quando si sposta la linea inferiore verso l'alto salta inizialmente due spazi, come una pedina! Qualcuno può offrire qualche raffinamento?


Non avevo altra scelta che implementare la soluzione di scripting. Spero sia pulito e adattabile alle tue esigenze.
Mykola Golubyev,

31

Non sono sicuro del motivo per cui hai bisogno di una sceneggiatura, gli esempi dell'articolo di Wikia funzionano. Ho pubblicato di seguito una versione semplificata, perché l'esempio di Wikia con 3 diverse modalità di mappatura può essere piuttosto scoraggiante (e non proprio necessario. Se usi solo i mapping di selezione dei blocchi, puoi semplicemente ricordare di bloccare select (Shift V) e usare queste scorciatoie (vedi la mia risposta di seguito).

Screencast sull'argomento: vimcasts.org/e/26
glts

Anche su vi SE
cfi il

Risposte:


81

Metti quanto segue sul tuo .vimrc per fare il lavoro

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

La scomparsa della linea sembra un bug di Vim. Ho messo un trucco per evitarlo. Probabilmente esiste una soluzione più accurata.

Aggiornare

Ci sono molte difficoltà inspiegabili con l'uso delle combinazioni di Vim. Questi mancano la linea e saltano la linea in più.

Ecco quindi la soluzione di scripting che può essere collocata all'interno di .vimrc o ~ / .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
Ho dovuto cambiare in <cj> e <ck> dato che sembra esserci uno scontro con la mia configurazione, ma una risposta fantastica! Grazie mille
user4812

1
Grazie, ottimo per git rebase - interattivo. Ho dovuto legare a <cj> e <ck>. cs-up / down non ha funzionato.
Lari Hotari,

2
Se qualcuno vuole una scorciatoia diversa: c è per controllo, A è per alt, io uso <A-up>come usato in eclissi.
gennaio

1
La linea che scompare non è un bug di Vim! È piuttosto dovuto all'esecuzione ddkPsull'ultima riga del documento. Provalo tu stesso su un file a 3 righe. Per evitare tali problemi, usa piuttosto le :mmappature molto più semplici fornite sul wiki di Vim .
Serge Stroobandt,

1
Ho cambiato le ultime righe in <A-up>e <A-down>ma quando provo quei tasti in vim in esecuzione visiva in tmux la selezione scompare e il cursore si sposta in linea; senza spostare le linee selezionate.
Konrad,

574

Se desidero scambiare una riga con la riga sopra, di solito faccio quanto segue

ddkP

Spiegazione

  • dd eliminerà la riga e la aggiungerà al registro predefinito.
  • k si sposta su una riga (j si sposta su una riga)
  • P incollerà sopra la riga corrente

5
Ed è sempre disponibile anche. :-)
Henno

71
E ddpper spostare una riga in basso (elimina la riga e incolla sotto la riga corrente)
bcoughlan

2
Per spostare un gruppo di righe, pronuncia 4, 4 ddquindi passa a, pronuncia 2 righe, quindi :2dove vuoi incollare e P.
Guru,

2
@Guru dovrebbe essere 4ddinvece di 4 dd?
Patrick McDonald,

3
E dd<number>jpper spostare la riga corrente <numero> +1 di righe verso il basso. E dd<number>kpper spostare la riga corrente <numero> di righe in alto.
egelev,

230

Supponendo che il cursore si trovi sulla linea che ti piace spostare.

Muoversi su e giù: :mper muoversi

:m +1 - si sposta in basso di 1 riga

:m -2 - sposta di 1 riga in alto

(Nota che puoi sostituire +1 con qualsiasi numero a seconda di quante linee vuoi spostarlo su o giù, cioè +2 lo sposterebbe di 2 righe, -3 lo sposterebbe di 2 righe)

Per passare a una linea specifica

:set number - mostra le linee numeriche (più facile vedere dove lo stai spostando)

:m 3 - sposta la riga dopo la 3a riga (sostituisci 3 con qualsiasi riga desideri)

Spostamento di più righe:

V(es. Shift- V) e sposta il cursore su e giù per selezionare più righe in VIM

una volta selezionato premi :ed esegui i comandi sopra, m +1ecc


14
per me: m -2 sale solo di una riga.
Fzs2,

2
ho inserito questo metodo nel mio vimrc ma non posso ripetere il comando usando '.'. qualcuno sa perché è così?
Fzs2,

Molto bella! Non comodo come la soluzione in Notepad ++, ma comunque - reale e funzionante.
Arturas M

Hermann, scusa, errore di battitura / errore da parte mia, hai ragione: m -2 lo sposterà di una riga. L'ho cambiato. Mi dispiace anche per la risposta molto tardi (non sono sicuro della parte .vimrc) Saluti
Serg

2
Spostandosi con il comando funziona, se si desidera utilizzarlo in associazioni come quelle di Notepad ++ come richiesto dall'OP, è necessario inserire quanto segue in .vimrc:noremap <c-s-up> :m -2<CR> noremap <c-s-down> :m +1<CR>
kap

74

Sposta una linea in alto: ddkP

Sposta una linea in basso: ddp


1
avere questo nel vimrc non consente di ripetere il comando usando '.'
Fzs2,

@HermannIngjaldsson, suppongo che potresti avvolgere il comando in una funzione se volessi essere in grado di usarlo .per ripetere.
jacobsimeon,

Sì, .. e se hai bisogno di spostare più linee, puoi usare V invece di dd.
sensorario,

15

Questo ha funzionato per me:

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

A proposito, se vuoi usare ALT + some_key e il tuo terminale (urxvt fa questo) rifiuta di conformarsi, dovresti inserire qualcosa del genere nel tuo .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

dove ^] è un singolo carattere che rappresenta il tasto ALT. Per inserire quel personaggio, usa C+v, Escin Vim ( C+q, Escsu Windows).


1
Questo va bene, usando il comando integrato di Vim per spostare una linea. È più probabile che si comporti bene di fronte all'annullamento o ad un errore.
Josh Lee,

1
Perché non inserisci Esc come <kbd>Cv<kbd/> <kbd> Esc </kbd> (linux). Windows sostituisce <kbd> Cv <kbd /> con <kbd> Cq <kbd /> su tutta la linea ma ha lo stesso modo per inserire qualsiasi chiave speciale in modalità inserimento / comando
vedi

@sehe: Grazie, non lo sapevo al momento. Ho aggiornato la risposta.
emil.p.stanchev,

1
@RafaelRinaldi, [niv]noremapsono rimappa per le normali modalità | insert | visual. <CR>è Carriage Return( Enterchiave).
vp_arth,

1
@vp_arth No there not
vedi il

13

aggiungi quanto segue al file ~ / .vimrc (assicurati di non avere alcun mapping per n, m)

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

ora premendo il ntasto si sposta una riga verso il basso e msi sposta una riga verso l'alto.


12

Nella modalità di comando posizionare il cursore sulla riga che si desidera spostare verso il basso, quindi

ddp

Spiegazione: dd cancella la riga corrente nel buffer generale p la riporta indietro DOPO la posizione del cursore o, nel caso di intere righe, una riga in basso.

C'è una certa confusione riguardo ai comandi pe P in molti documenti. In realtà, incolla il cursore DOPO e il cursore P AT.


8

Aggiungi questo codice a .vimrc (o .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
Come da vim.wikia.com/wiki/… vedere qui per una spiegazione completa.
Serge Stroobandt,

Su un Mac <A-something> non funziona, non so perché. Ho sostituito con <Cj> <Ck> e funziona bene usando il tasto Ctrl.
Cédric NICOLAS,



3

Ho inserito quanto segue alla fine del mio file .vimrc:

noremap H ddkkp
noremap N ddp

Quindi ora 'H' e 'N' spostano la linea corrente su e giù rispettivamente.


H e N sono in realtà comandi utili (H sposta il cursore in alto e all'inizio dello schermo, N si sposta sul risultato della ricerca precedente), quindi consiglierei di usare diversi tasti
villapx

Vedo. Li ho anche riconfigurati. Per andare nella parte superiore dello schermo premo a e poi su. A significa sempre tutto nei miei libri. E per cercare tra i risultati precedenti premo f e poi a sinistra. F quindi sta per trovare. Ma per quelli che non ce l'hanno così allora sì ... è valido.
Fzs2,

1

Ecco una versione semplificata, per MacVim, usando gli esempi di articoli di Wikia (vedi link dal commento di 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

Sto usando solo la variante di selezione del blocco, perché tutto ciò che serve è Maiusc-V per selezionare la linea corrente e, facoltativamente, il cursore su / giù per selezionare altre linee.

Secondo le scorciatoie sopra, premendo Cmd-Shift-Up / Down si sposta la selezione del blocco su / giù. "D" è il tasto Comando in MacVim, per Windows provare "C" (Control) o "A" (Alt) (es. <CAf> sarebbe Control Alt f).

L'articolo Wikia aggiunge "= gv" a questi, che ha l'effetto di regolare il rientro del blocco dopo lo spostamento, in base al testo circostante. Questo è confuso, quindi l'ho rimosso e ho aggiunto scorciatoie per rientrare rapidamente nella selezione.

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

Mente, lo stesso può essere fatto con << e >> ma la selezione andrebbe persa, quindi queste scorciatoie sopra consentono di rientrare più volte e spostare ancora il blocco perché la selezione viene mantenuta.

Il mio MacVim è configurato per cambiare scheda con Cmd-Maiusc-Sinistra / Destra, quindi ho usato Cmd-Alt-Sinistra / Destra.

Ecco la commutazione Tab per MacVim (inserisci .gvimrc con il resto sopra):

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

1

vim plugin unimpaired.vim [e and] e


2
Sembra eccessivo, non penso che tu abbia davvero bisogno di un plugin completo per questo. 2 righe in un vimrc fanno esattamente ciò che l'OP vuole
Daniel Gratzer il

1

Quando premi il comando :help movein vim, ecco il risultato:

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

Ad esempio: sposta la riga corrente di una riga in basso => :m+1 .

Ad esempio: spostare la riga con il numero 100 sotto la riga con il numero 80 => :100 m 80 .

Ad esempio: spostare la riga con il numero 100 sotto la riga con il numero 200 => :100 m 200 .

Ad esempio: sposta le linee con il numero entro [100, 120] sotto la linea con il numero 200 => :100,120 m 200 .


1

Ecco una soluzione che funziona sulla mia macchina : MacBook Pro con VIM 8.1

Questi comandi non elimineranno le righe nella parte superiore o inferiore del buffer.

L'uso dei simboli reali che Alt-J e Alt-K producono è una soluzione per i loro codici chiave che non vengono mappati correttamente nel mio ambiente.

Buttalo nel vecchio .vimrc e vedi se funziona per te.

" 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 o: m.-2 farebbe se si sposta una singola riga. Ecco il mio script per spostare più righe. In modalità visiva, Alt-su / Alt-giù sposta le linee contenenti la selezione visiva su / giù di una riga. Nella modalità di inserimento o normale, Alt-su / Alt-giù sposta la riga corrente se non viene fornito alcun prefisso di conteggio. Se esiste un prefisso di conteggio, Alt-su / Alt-giù sposta di molte righe quella linea che inizia su / giù dalla riga corrente di una riga.

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

Nel caso in cui si desideri eseguire ciò su più righe che corrispondono a una ricerca specifica:

  • Su: :g/Your query/ normal ddpo:g/Your query/ m -1
  • Giù :g/Your query/ normal ddpo:g/Your query/ m +1
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.