Jak zamienić tabulatory na spacje?


85

Czy można konwertować tabulatory na spacje, zachowując wyrównanie tekstu?

Po prostu zamiana działa tylko wtedy, gdy nie ma wiodących postaci.


Jeśli zainstalowałeś vim-faq , możesz tam uzyskać odpowiedź offline: :h vim-faqi wyszukać /tab characters. Trudno zapamiętać tag :h faq-14.16.
Hotschke

Odpowiedzi:


98

Możesz użyć :retabpolecenia. Od :help :retab

Zastąp wszystkie sekwencje białych <Tab>znaków zawierających nowe ciągami białych znaków, używając nowej podanej wartości tabstop. Jeśli nie określisz nowego rozmiaru tabstop lub jest on zerowy, Vim użyje bieżącej wartości 'tabstop'. [...] Po 'expandtab'włączeniu Vim zastępuje wszystkie tabulatory odpowiednią liczbą spacji.

Zauważ, że polecenie akceptuje zakres, więc możesz dokonać wizualnego wyboru, a następnie tylko :retabwybranych linii.


Chłodny! Działa szybko i prosto!
DenisKolodin

2
co powiesz na podanie przykładu?
Petr

23

Można jednak użyć :retab, jak wspomniano, spowoduje to zmianę wszystkich tabulatorów na spacje, nie tylko tabulatory na początku wiersza

Więc to (gdzie jest znak tabulacji):

if :; do
⇥echo "⇥hello"
end

zmienia się na (gdzie jest spacja):

if :; do
␣␣echo "␣␣hello"
end

Może to powodować nieoczekiwane skutki uboczne w niektórych scenariuszach, a to jeszcze większy problem przy zmianie spacji na tabulatory!

Tak więc napisałem małą funkcję zmiany tylko tabulatorów / spacji na początku wiersza:

" :retab changes *everything*, not just start of lines
fun! Retab(expandtab)
    let l:spaces = repeat(' ', &tabstop)

    " Replace tabs with spaces
    if a:expandtab
        silent! execute '%substitute#^\%(' . l:spaces . '\)\+#\=repeat("\t", len(submatch(0)) / &tabstop)#e'
    " Replace spaces with tabs
    else
        silent! execute '%substitute#^\%(\t\)\+#\=repeat("' . l:spaces . '", len(submatch(0)))#e'
    endif
endfun

W tej wersji musisz ręcznie określić expandtabw wywołaniu funkcji (tj. :call Retab(1)Zmienić tabulatory na spacje), ale możesz również zmodyfikować ją, aby przyjmowała bieżącą wartość &expandtab(jak to już ma miejsce &tabstop), tak jak to :retabrobi. (Zdarza mi się to określać ręcznie).


6
Istnieje również odpowiedź na temat SO, która obejmuje tylko zmianę na początku linii. Warto połączyć ze względu na przejrzystość tego wyjaśnienia.
jalanb

Może ktoś wyjaśnić, co czyni nas aw if a:expandtabśredniej?
john cj

Wygląda też na to, że warunki są odwrócone (żart: D?). Jeśli masz set expandtabw .vimrc, a następnie autocmd BufWritePre * :call Retab(&expandtab)- wcięcie zostanie zmienione na tabulatory zamiast spacji.
John CJ

11

Vim udostępnia !retabpolecenie, które zastąpi wszystkie sekwencje <Tab>nowymi ciągami białych znaków za pomocą :set tabstop=2podanej nowej wartości tabstop (np. ), Ale wszystkie tabulacje wewnątrz ciągów można modyfikować (np. W programie C należy \ttego uniknąć)!

Alternatywnie możesz zmienić wszystkie tabulatory na spacje, używając następującego polecenia:

:%s/\t/  /g

lub zgodnie z sugestią @Shahbaz :

:%s/^\t\+/ g

Tak więc konwertowane są tylko tabulatory używane w wcięciach.

Wyjaśnienie:

  • %reprezentuje cały bufor / plik ( :help :%)
  • soznacza substytut ( :help sub-replace-special)
  • \tlub ^Ioznacza tab
  • - użyj tyle spacji, ile potrzebujesz na jedną kartę
  • g - oznacza globalny i przekształci wiele wystąpień kart w tym samym wierszu

Następnie skorygować wcięcia całego pliku, możesz spróbować: gg=G. Sprawdź: Ponowne wcięcie źle źle wciętego kodu, aby uzyskać więcej szczegółów.

Aby domyślnie używać spacji zamiast tabulatorów, musisz dodać do .vimrcpliku następujące ustawienia :

set tabstop=2     " (ts) width (in spaces) that a <tab> is displayed as
set expandtab     " (et) expand tabs to spaces (use :retab to redo entire file)
set shiftwidth=2  " (sw) width (in spaces) used in each step of autoindent (aswell as << and >>)

Alternatywnym rozwiązaniem jest użycie tidy


Związane z:


1
Zrobiłbym przynajmniej %s/^\t\+/ gtak, aby konwertowane były tylko tabulatory używane w wcięciach. Ponadto gg=Gmoże być katastrofalny w przypadku języków takich jak python.
Shahbaz

3

Spróbuj użyć:

expand -t 4 input_filename output_filename

expandto narzędzie wiersza polecenia do konwersji tabulatorów na spacje, które można uruchomić z powłoki lub za pomocą :!expand.

Jest w POSIX, więc powinien być dostępny na większości systemów. unexpandnawiasem mówiąc, zrobi odwrotnie.


2
Co to jest expand?
muru

Rozwiń to wbudowane polecenie terminala do kopiowania znaku tabulacji na spacje. Szczegółowy opis znajdziesz w poniższym linku. computerhope.com/unix/uexpand.htm
Ankit Shah

2
Jeśli są to polecenia zewnętrzne, powinieneś o tym wspomnieć.
muru

Dodano dalszy opis. Proszę przejrzeć
Ankit Shah

5
Możesz także zrobić to :%!expand -t 4w vimie. Jeszcze lepiej, możesz również użyć bieżącej opcji szerokości przesunięcia: :exe '%!expand -t ' . &shiftwidth
EvergreenTree

1

Dla kompletności =można go również użyć do naprawy wcięć, po określeniu, że tabulatory są zastępowane spacjami. W trybie normalnym możesz to zrobić, pisząc :set expandtab. Następnie =można go użyć na dwa sposoby:

  • W trybie wizualnym jeden =naprawiałby wcięcia wybranych bloków kodu.
  • W trybie normalnym gg=Gnaprawiałby cały plik, w którym ggprzesuwa kursor na początek pliku, a następnie =jest stosowany i Gprzesuwa kursor na koniec pliku.

Odniesienie: link


Zakłada się, że vim może poprawnie obliczyć bieżące wcięcie (może być inaczej) - także w przypadku plików nieustrukturyzowanych lub kodu napisanego w innym edytorze z nieco innymi regułami wcięcia.
ideasman42

Dzięki @ ideasman42; Dodałem do odpowiedzi, aby być bardziej kompletnym.
Samuel Li,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.