433 votes

Déplacer une ligne entière de haut en bas dans Vim

Dans Notepad++, je peux utiliser Ctrl + Shift + Up / Down pour déplacer la ligne actuelle vers le haut et vers le bas. Existe-t-il une commande similaire à celle-ci dans Vim ? J'ai parcouru des guides interminables, mais je n'ai rien trouvé.

Si ce n'est pas le cas, comment puis-je lier l'action à cette combinaison de touches ?

Edit : La réponse de Mykola fonctionne pour toutes les lignes, à l'exception de celles qui se trouvent au début et à la fin du tampon. En déplaçant la première ligne vers le haut ou la ligne inférieure vers le bas, on supprime la ligne, et en déplaçant la ligne inférieure vers le haut, on fait un saut de deux espaces au départ, comme un pion ! Quelqu'un peut-il proposer des améliorations ?

1 votes

Je n'avais pas d'autre choix que de mettre en œuvre une solution de script. J'espère qu'elle est propre et qu'elle peut être adoptée pour vos besoins.

46 votes

0 votes

Je ne vois pas trop pourquoi vous avez besoin d'un script, les exemples de l'article de Wikia fonctionnent. J'ai posté ci-dessous une version simplifiée, car l'exemple de Wikia avec 3 modes de mappage différents peut être assez décourageant (et pas vraiment nécessaire. Si vous n'utilisez que les mappages de sélection de bloc, vous pouvez simplement vous rappeler de sélectionner le bloc (Shift V) et utiliser ces raccourcis (voir ma réponse ci-dessous).

798voto

JaredPar Points 333733

Si je veux échanger une ligne avec la ligne précédente, je fais généralement ce qui suit

ddkP

Explication

  • dd supprimera la ligne et l'ajoutera au registre par défaut.
  • k va monter d'une ligne (j descend d'une ligne)
  • P collera au-dessus de la ligne courante

6 votes

Et il est toujours disponible, aussi :-)

114 votes

Et ddp pour déplacer une ligne vers le bas (effacer la ligne et coller sous la ligne actuelle)

4 votes

Pour déplacer un groupe de lignes, disons 4, 4 dd et ensuite passer à, disons 2 lignes, puis :2 où vous voulez coller et P .

374voto

Serg Points 528

En supposant que le curseur se trouve sur la ligne que vous souhaitez déplacer.

On monte et on descend : :m pour le déménagement

:m +1 - descend d'une ligne

:m -2 - monter de 1 ligne

(Notez que vous pouvez remplacer +1 par n'importe quel chiffre en fonction du nombre de lignes que vous souhaitez déplacer vers le haut ou vers le bas, c'est-à-dire que +2 le déplacerait vers le bas de 2 lignes, -3 le déplacerait vers le haut de 2 lignes).

Pour passer à une ligne spécifique

:set number - afficher les lignes de chiffres (plus facile de voir où vous les déplacez)

:m 3 - déplacer la ligne après la 3ème ligne (remplacer 3 par la ligne de votre choix)

Déplacement de plusieurs lignes :

V (c'est-à-dire Shift - V ) et déplacez le curseur vers le haut et le bas pour sélectionner plusieurs lignes dans le VIM.

une fois sélectionné, appuyez sur : et exécutez les commandes ci-dessus, m +1 etc.

23 votes

Pour moi :m -2 ne fait que remonter d'une ligne.

2 votes

J'ai mis cette méthode dans mon vimrc mais je ne peux pas répéter la commande en utilisant '.'. quelqu'un sait-il pourquoi ?

0 votes

Très bien ! Pas aussi confortable que la solution dans Notepad++, mais quand même - réel et fonctionnel.

102voto

jacobsimeon Points 759

Déplacez une ligne vers le haut : ddkP

Déplacez une ligne vers le bas : ddp

1 votes

Le fait d'avoir ceci dans le vimrc empêche de répéter la commande en utilisant '.'.

0 votes

@HermannIngjaldsson, je suppose que vous pourriez envelopper la commande dans une fonction si vous vouliez pouvoir utiliser . à répéter.

0 votes

Oui, et si vous avez besoin de déplacer plus de lignes, vous pouvez utiliser V au lieu de dd.

97voto

Mykola Golubyev Points 21210

Mettez ce qui suit dans votre .vimrc pour faire le travail

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

La disparition de la ligne ressemble à un bug de Vim. J'ai mis un hack pour l'éviter. Il existe probablement une solution plus précise.

Mise à jour

Il y a beaucoup de difficultés inexpliquées avec la simple utilisation des combinaisons de Vim. Il s'agit de lignes manquantes et de sauts de lignes supplémentaires.

Voici donc la solution de script qui peut être placée soit dans .vimrc, soit dans ~/.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>

0 votes

Merci - C'est presque correct, mais il y a des problèmes avec le déplacement de la dernière ligne - je vais mettre à jour la question avec les détails.

0 votes

Je suis toujours en train de jouer. Veuillez patienter.

1 votes

J'ai dû changer pour <c-j> et <c-k> car il semble y avoir un clash avec ma configuration, mais réponse fantastique ! Merci beaucoup

16voto

slack3r Points 322

Cela a marché pour moi :

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

BTW, si vous voulez utiliser ALT+une touche et que votre terminal (urxvt le fait) refuse de s'y plier, vous devriez entrer quelque chose comme ceci dans votre .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

où ^] est un seul caractère qui représente la touche ALT. Pour saisir ce caractère, utilisez C+v, Esc dans Vim ( C+q, Esc sur Windows).

1 votes

C'est bien, en utilisant la commande intégrée de Vim pour déplacer une ligne. Il est plus probable qu'elle se comporte bien en cas d'annulation ou d'erreur.

1 votes

Why don't you enter Esc as C-v<kbd/>Esc (linux). Windows replaces C-v<kbd/> by C-q<kbd/> across the board but has the same way to enter any special key in insert/command mode

0 votes

@sehe : Merci, je ne le savais pas à l'époque. J'ai mis à jour la réponse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X