Jak odwrócić kolejność wybranych linii w Vimie?

94

Na przykład, jeśli mam cztery następujące linie:

pierwsza linia
druga linia
trzecia linia
czwarta linia

Chcę je odwrócić

czwarta linia
trzecia linia
druga linia
pierwsza linia

Jak mogę to zrobić w Vimie?

Jichao
źródło
1
:command! -bar -range=% Reverse <line1>,<line2>global/^/m<line1>-1 vi.stackexchange.com/a/2107/10254
qeatzy

Odpowiedzi:

86

Aby odwrócić wszystkie linie w pliku,

:g/^/m0

Wyjaśnienie patrz

:help 12.4

który pokazuje również, jak odwrócić tylko zakres linii.

garyjohn
źródło
12
Świetna wskazówka na temat dokładnej sekcji pomocy! Podsumowując: 1. ustaw znacznik w ostatnim wierszu, który chcesz odwrócić (nazywam znacznik „a” za pomocą ma), 2. przesuń kursor do pierwszego wiersza bloku, 3. wpisz:'a,.g/^/m 'a
Brent Faust
68

Wybierz żądane linie, naciśnij !, a następnie w wyświetlonym monicie poprowadź linie przez tacla :'<,'>!tac. Zobacz man tacpo więcej szczegółów.

Rhys Ulerich
źródło
4
Aby wybrać linie, użyj, shift+vaby przejść do trybu linii wizualnej, a następnie jdodaj linie do zaznaczenia.
wisbucky
Mogę potwierdzić, że działa to również w systemie Windows gvim! W przeciwnym razie musisz użyć bezwzględnych liczb linii (być może możesz użyć względnego, ale musisz być ostrożny) z :g/^/m0(co również jest naprawdę trudne do zapamiętania) ... Tak więc, zasadniczo, tac powinien być z vimem bez względu na platformę jesteś włączony, ALE to nie jest 100% vimscript, ALE kogo to obchodzi: P
dylnmc
tac nie jest w pełni natywną obsługą vima, ale polecenie 'm'ove przyjmuje numer linii i nie zawsze jest to rozsądne. Często używam znaku jako części zakresu, więc :.,'a!tacdziała przy minimalnym wysiłku.
studog
Po użyciu shift+vmożesz użyć, }aby przejść do następnego akapitu lub pustej przestrzeni pionowej. Również man tac: concatenate and print files in reverse.
nilon
33

W systemie Mac OS X tacnie istnieje, ale można użyć tail -rtego samego efektu:

:%!tail -r

Działa to również ładnie w trybie wizualnym:

:'<,'>!tail -r

Fragment strony tail(1)man:

Opcja -r powoduje, że dane wejściowe są wyświetlane w odwrotnej kolejności, według linii. Dodatkowo ta opcja zmienia znaczenie opcji -b, -c i -n. Gdy podano opcję -r, opcje te określają liczbę bajtów, linii lub 512-bajtowych bloków do wyświetlenia, zamiast bajtów, linii lub bloków od początku lub końca wejścia, od którego należy rozpocząć wyświetlanie. Domyślną opcją -r jest wyświetlanie wszystkich danych wejściowych.

Thomas Perl
źródło
3
Doskonały! Aby podać „tac” w systemie OS X:alias tac='tail -r'
Brent Faust,
4
Możesz także brew install coreutilsi używać gtac.
Andrew Marshall,
1
Geniusz. Nigdy nie myślałem o użyciu! polecenia dla tego typu manipulacji wizualną linią.
Charlie Dalsass
3

Dla osób wygodniejszych w trybie wizualnym:
1. Zidentyfikuj numer linii powyżej zaznaczenia, którego chcesz obrócić :set nu.
2. Shift-Vaby podświetlić zaznaczenie, które chcesz przerzucić (tryb wizualny).
3 :g/^/m <Line number from step 1>.

Zauważ, że w trybie wizualnym automatycznie pokaże się tak, jak :'<,'>g/^/m <Line number>po wpisaniu polecenia z 3.

To polecenie działa poprzez przeniesienie zaznaczenia o jedną linię na raz na numer linii, który jej podałeś. Gdy drugi element zostanie wypchnięty do podanego numeru wiersza, przesuwa pierwszy w dół do numeru wiersza + 1. Następnie trzeci przesuwa pierwszy i drugi w dół i tak dalej, aż cała lista zostanie wypchnięta do pojedynczego numeru wiersza, w wyniku czego odwrócona lista uporządkowana.

horta
źródło
4
Możesz użyć '<zamiast ręcznie wpisywać numer linii. Po prostu rozpocznij zaznaczenie o jedną linię wcześniej i wykonaj :'<,'>g/^/m'<.
Palec
3

Polecenie :Rev[erse]i opcjonalne mapowania dla twojego vimrc, więc nie musisz pamiętać i wykonywać nieoczywistych kroków tego przepisu:

" Reverse the lines of the whole file or a visually highlighted block.
    " :Rev is a shorter prefix you can use.
    " Adapted from http://tech.groups.yahoo.com/group/vim/message/34305
command! -nargs=0 -bar -range=% Reverse
    \       let save_mark_t = getpos("'t")
    \<bar>      <line2>kt
    \<bar>      exe "<line1>,<line2>g/^/m't"
    \<bar>  call setpos("'t", save_mark_t)

nmap <Leader>r :Reverse<CR>
xmap <Leader>r :Reverse<CR>

( :xmapmapy dla trybu Visual, ale nie Select, zgodnie z :help mapmode-xzaleceniami dotyczącymi mapowania znaków do wydrukowania).

(Na podstawie: http://tech.groups.yahoo.com/group/vim/message/34305 )

Aaron Thoma
źródło
To powinna być zaakceptowana odpowiedź IMO. Najbardziej przydatne i nie muszę pamiętać :'<,'>g/^/m'<:)
Eliot
1
@Eliot, dzięki! :) (Dodałem trochę „dodatkowej zawartości”;;))
Aaron Thoma,
Jak mogę powiedzieć, że wybór zaczyna się od -1 w tym przypadku? Ponieważ ruch zaczyna się w tym momencie.
SergioAraujo
@SergioAraujo: Czy jest coś, :-1,+1Revczego szukasz? Wiedz, że możesz wizualnie wybrać zakres, który chcesz odwrócić, np V7j:Rev. : Jeśli to nie odpowiada na twoje pytanie, nie zrozumiałem go, więc musisz je dla mnie rozwinąć lub sformułować inaczej.
Aaron Thoma
1

Powiedzmy, że jesteś na linii 3, stąd mamy zakres od 3 do 6. Wystarczy wpisać.

:3,6g/^/m2
SergioAraujo
źródło
1
Możesz pozostawić domyślny numer bieżącej linii: Kursor na pierwszej linii zakresu możesz skrócić :,6g/^/m2; lub gdy na ostatniej linii poligonu: :3,g/^/m2; i :3,6g/^/m2działa z dowolnego miejsca w pliku.
Aaron Thoma