Bagaimana cara mengganti tab dengan spasi?

85

Apakah mungkin untuk mengonversi tab menjadi spasi, sambil mempertahankan perataan teks?

Cukup mengganti hanya berfungsi bila tidak ada karakter utama.

gagasanman42
sumber
Jika Anda telah menginstal vim-faq , Anda bisa mendapatkan jawaban offline di sana: :h vim-faqdan cari /tab characters. Tag yang sulit diingat adalah :h faq-14.16.
Hotschke

Jawaban:

98

Anda bisa menggunakan :retabperintah. Dari :help :retab

Ganti semua urutan ruang putih yang berisi <Tab>string baru dengan ruang putih menggunakan nilai tabstop baru yang diberikan. Jika Anda tidak menentukan ukuran tabstop baru atau nol, Vim menggunakan nilai saat ini dari 'tabstop'. [...] Dengan 'expandtab'aktif, Vim mengganti semua tab dengan jumlah spasi yang sesuai.

Perhatikan bahwa perintah menerima rentang, sehingga Anda dapat membuat pemilihan visual dan kemudian hanya :retabgaris yang dipilih.

guillem
sumber
Keren! Bekerja cepat dan sederhana!
DenisKolodin
2
bagaimana kalau memberikan contoh?
Petr
23

Namun, Anda dapat menggunakan :retab, seperti yang dinyatakan, ini akan mengubah semua tab menjadi spasi, tidak hanya tab di awal baris

Jadi ini (di mana karakter tab):

if :; do
⇥echo "⇥hello"
end

diubah menjadi (di mana karakter spasi):

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

Ini dapat menghasilkan efek samping yang tidak terduga dalam beberapa skenario, dan itu bahkan lebih menjadi masalah ketika mengubah spasi menjadi tab!

Jadi, saya menulis sedikit fungsi untuk mengubah hanya tab / spasi di awal baris:

" :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

Dengan versi ini, Anda harus menentukan secara manual expandtabdalam panggilan fungsi (mis. :call Retab(1)Untuk mengubah tab menjadi spasi), tetapi Anda juga dapat memodifikasinya untuk mengambil nilai saat ini &expandtab(seperti yang sudah terjadi dengan &tabstop) sama seperti :retabhalnya. (Kebetulan saya lebih suka menentukannya secara manual).

Martin Tournoij
sumber
6
Ada juga jawaban pada SO yang mencakup retabbing pada awal baris saja. Layak dikaitkan karena kejelasan penjelasan itu.
jalanb
Bisa seseorang menjelaskan apa surat adi if a:expandtabberarti?
john cj
Juga, sepertinya kondisinya terbalik (lelucon: D?). Jika ada set expandtabdi .vimrc lalu autocmd BufWritePre * :call Retab(&expandtab)- indentasi akan diubah menjadi tab, alih-alih spasi.
john cj
11

Vim menyediakan !retabperintah yang akan mengganti semua urutan <Tab>dengan string white-space baru menggunakan nilai tabstop baru (misalnya :set tabstop=2) yang diberikan, tetapi semua tab di dalam string dapat dimodifikasi (misalnya dalam program C, Anda harus menggunakan \tuntuk menghindari ini)!

Jadi atau Anda dapat mengubah semua tab menjadi spasi menggunakan perintah berikut:

:%s/\t/  /g

atau seperti yang disarankan oleh @Shahbaz :

:%s/^\t\+/ g

Jadi hanya tab yang digunakan dalam indentasi yang dikonversi.

Penjelasan:

  • %mewakili seluruh buffer / file ( :help :%)
  • ssingkatan pengganti ( :help sub-replace-special)
  • \t, atau ^Ikependekan dari tab
  • - Gunakan ruang sebanyak yang Anda butuhkan per satu tab
  • g - singkatan global, dan itu akan mengonversi banyak kemunculan tab di baris yang sama

Kemudian untuk memperbaiki lekukan dari seluruh file, Anda dapat mencoba: gg=G. Periksa: Mengindeks ulang kode yang indentasi buruk untuk detail lebih lanjut.

Untuk menggunakan spasi secara default alih-alih tab, Anda perlu menambahkan pengaturan berikut ke .vimrcfile Anda :

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 >>)

Solusi alternatif adalah menggunakan tidy


Terkait:

kenorb
sumber
1
Saya setidaknya akan melakukannya %s/^\t\+/ gsehingga hanya tab yang digunakan dalam indentasi yang dikonversi. Juga, gg=Gbisa menjadi bencana besar dengan bahasa seperti python.
Shahbaz
3

Coba gunakan:

expand -t 4 input_filename output_filename

expandadalah alat baris perintah untuk mengonversi tab menjadi spasi, yang bisa Anda jalankan dari shell atau dengan :!expand.

Ada dalam POSIX sehingga harus tersedia di sebagian besar sistem. unexpandakan melakukan yang sebaliknya.

Ankit Shah
sumber
2
Apa expand?
muru
Expand adalah perintah terminal bawaan untuk menyalin karakter tab ke spasi. Silakan temukan keterangan rinci di tautan berikut. computerhope.com/unix/uexpand.htm
Ankit Shah
2
Jika ini adalah perintah eksternal, Anda harus menyebutkan itu.
muru
Penjelasan lebih lanjut ditambahkan. Harap tinjau
Ankit Shah
5
Anda juga bisa melakukannya :%!expand -t 4di dalam vim. Lebih baik lagi, Anda juga bisa menggunakan opsi lebar shift saat ini: :exe '%!expand -t ' . &shiftwidth
EvergreenTree
1

Untuk kelengkapan, =bisa juga digunakan untuk memperbaiki lekukan, setelah Anda menentukan bahwa tab diganti dengan spasi. Dalam mode normal, Anda dapat melakukannya dengan mengetik :set expandtab. Kemudian =dapat digunakan dalam dua cara:

  • Dalam mode Visual, satu =akan memperbaiki lekukan blok kode yang dipilih.
  • Dalam mode normal, gg=Gakan memperbaiki seluruh file, di mana ggmemindahkan kursor ke awal file, kemudian =diterapkan, dan Gmemindahkan kursor ke akhir file.

Referensi: tautan

Samuel Li
sumber
Ini mengasumsikan vim dapat menghitung ulang lekukan saat ini dengan benar (mungkin tidak demikian) - juga untuk file yang tidak terstruktur, atau kode yang ditulis dalam editor yang berbeda dengan aturan indentasi yang sedikit berbeda.
ideasman42
Terima kasih @ ideasman42; Saya sudah menambahkan jawaban untuk lebih lengkap.
Samuel Li