web-dev-qa-db-fra.com

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

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

S'il n'y en a pas, comment pourrais-je lier l'action à cette combinaison de touches?

Edit: La réponse de Mykola fonctionne pour toutes les lignes, à l'exception de celles situées au début et à la fin du tampon. Déplacer la première ligne vers le haut ou la ligne inférieure vers le bas supprime la ligne. Lorsque vous déplacez la ligne inférieure, elle saute initialement de deux espaces, comme un pion! Quelqu'un peut-il offrir des améliorations?

295
user4812

Mettez ce qui suit à 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 bogue de Vim. Je mets un bidouillage pour l'éviter. Il existe probablement une solution plus précise.

Mettre à jour

Il y a beaucoup de difficultés inexpliquées à utiliser simplement les combinaisons Vim. Ce sont des lignes manquantes et des sauts de ligne supplémentaires.

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

Si je veux échanger une ligne avec la ligne ci-dessus, je fais habituellement ce qui suit

ddkP

Explication

  • dd supprimera la ligne et l'ajoutera au registre par défaut.
  • k montera une ligne (j descendrais une ligne)
  • P va coller au dessus de la ligne courante
532
JaredPar

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

Déplacement de haut en bas: :m pour le déplacement

:m +1 - se déplace vers le bas d'une ligne

:m -2 - augmente de 1 ligne

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

Pour passer à une ligne spécifique

:set number - Affiche les lignes numériques (il est plus facile de voir où vous le déplacez)

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

Déplacement de plusieurs lignes:

V (i.e. Shift-V) et déplacez-vous de haut en bas pour sélectionner plusieurs lignes dans VIM

une fois sélectionné hit : et lancez les commandes ci-dessus, m +1 etc

211
Serg

Déplacer une ligne: ddkP

Déplacer une ligne vers le bas: ddp

70
jacobsimeon

Cela a fonctionné pour moi:

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

En passant, si vous voulez utiliser ALT + some_key et que votre terminal (ce que urxvt fait) refuse de se conformer, vous devez entrer quelque chose comme ceci dans votre fichier .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 à Vim (C+q, Esc sous Windows).

15
emil.p.stanchev

ajoutez ce qui suit au fichier ~/.vimrc (assurez-vous de ne pas avoir de mappage pour n, m)

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

appuyez maintenant sur la touche n pour déplacer une ligne vers le bas et m pour déplacer une ligne vers le haut.

12
Gajendra Jena

En mode commande, positionnez le curseur sur la ligne que vous souhaitez déplacer, puis

ddp

Explication: Dd supprime la ligne en cours dans le tampon général P la remet APRÈS la position du curseur ou, dans le cas de lignes complètes, une ligne en dessous.

Il existe une certaine confusion concernant les commandes p et P dans de nombreux documents . En réalité, p colle APRES le curseur et le curseur P AT.

11
szg

Ajoutez simplement ce code à .vimrc (ou .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
6
alexkv

Une solution simple est de mettre dans votre .vimrc ces lignes:

nmap <C-UP> :m-2<CR>  
nmap <C-DOWN> :m+1<CR>

Exactement ce que vous cherchez dans cet impressionnant plugin: https://github.com/vim-scripts/upAndDown

5
timoxley

Je mets ce qui suit à la fin de mon fichier .vimrc:

noremap H ddkkp
noremap N ddp

Alors maintenant, "H" et "N" déplacent la ligne actuelle de haut en bas, respectivement.

2
Hermann Ingjaldsson

Lorsque vous appuyez sur la commande :help move dans vim, voici le résultat:

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

E.g: Déplace la ligne en cours d’une ligne vers le bas =>:m+1.

E.g: Déplace la ligne avec le numéro 100 en dessous de la ligne avec le numéro 80 =>:100 m 80.

E.g: Déplace la ligne avec le numéro 100 en dessous de la ligne avec le numéro 200 =>:100 m 200.

E.g: Déplace les lignes dont le nombre est compris entre [100, 120] sous la ligne portant le nombre 200 =>:100,120 m 200.

1
ako

Pour moi, ddkkp l’a fait (au lieu de ddkP avec un P majuscule, ce qui fonctionnerait aussi). 

1

Voici une version simplifiée, pour MacVim, utilisant les exemples d’articles de Wikia (cf. lien depuis le commentaire de 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

J'utilise uniquement la variante de sélection de bloc, car il suffit de déplacer Shift-V pour sélectionner la ligne en cours, et éventuellement un curseur haut/bas pour sélectionner d'autres lignes.

Selon les raccourcis ci-dessus, une pression sur Cmd-Shift-Up/Down décale la sélection de bloc vers le haut ou le bas. "D" est la touche de commande de MacVim, pour Windows, essayez "C" (Contrôle) ou "A" (Alt) (par exemple, <C-A-f> correspondrait à Contrôle Alt f).

L'article de Wikia ajoute "= gv" à ceux-ci, ce qui a pour effet d'ajuster l'indentation du bloc après le déplacement, en fonction du texte environnant. C'est déroutant, alors je l'ai supprimé et ajouté des raccourcis pour indenter rapidement la sélection.

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

Bien sûr, on peut faire la même chose avec << et >>, mais la sélection serait perdue. Ces raccourcis permettent de mettre en retrait plusieurs fois tout en déplaçant le bloc car la sélection est conservée.

Mon MacVim est configuré pour permuter les onglets avec Cmd-Shift-Left/Right. J'ai donc utilisé Cmd-Alt-Left/Right.

Voici le changement d'onglet pour MacVim (mis en .gvimrc avec le reste ci-dessus):

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

vim plugin unimpaired.vim [e et] e

0
Baranina

Si vous souhaitez le faire sur plusieurs lignes correspondant à une recherche spécifique:

  • Up: :g/Your query/ normal ddp ou :g/Your query/ m -1
  • :g/Your query/ normal ddp ou :g/Your query/ m +1 en panne
0
Gleb Sabirzyanov

Voici une solution qui fonctionne sur ma machine : MacBook Pro sous VIM 8.1

Ces commandes ne supprimeront pas vos lignes en haut ou en bas de votre tampon.

L'utilisation des symboles réels générés par les sorties Alt-J et Alt-K constitue une solution de contournement car les codes-clés ne sont pas correctement mappés dans mon environnement. 

Jetez ceci dans l'ancien .vimrc et voyez si cela fonctionne pour vous.

" 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
Nick Sugar

: m + 1 ou: m.-2 suffiraient si vous ne déplacez qu'une seule ligne. Voici mon script pour déplacer plusieurs lignes. En mode visuel, Alt-haut/Alt-bas déplace les lignes contenant la sélection visuelle vers le haut/bas d'une ligne. En mode insertion ou en mode normal, Alt-up/Alt-down déplace la ligne en cours si aucun préfixe de comptage n'est indiqué. S'il y a un préfixe de nombre, Alt-up/Alt-down déplace ce nombre de lignes à partir de la ligne actuelle haut/bas d'une ligne.

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
Ji Han