Làm thế nào để thay thế các tab bằng dấu cách?


85

Có thể chuyển đổi các tab thành không gian, trong khi duy trì căn chỉnh văn bản?

Đơn giản chỉ cần thay thế hoạt động hữu ích khi không có nhân vật chính.


Nếu bạn đã cài đặt vim-faq , bạn có thể nhận được câu trả lời ngoại tuyến ở đó: :h vim-faqvà tìm kiếm /tab characters. Thẻ ghi nhớ khó là :h faq-14.16.
Hotschke

Câu trả lời:


98

Bạn có thể sử dụng :retablệnh. Từ :help :retab

Thay thế tất cả các chuỗi khoảng trắng chứa a <Tab>bằng các chuỗi khoảng trắng mới bằng cách sử dụng giá trị tabstop mới đã cho. Nếu bạn không chỉ định kích thước tabstop mới hoặc bằng 0, Vim sử dụng giá trị hiện tại là 'tabstop'. [...] Với 'expandtab'bật, Vim thay thế tất cả các tab bằng số lượng khoảng trống thích hợp.

Lưu ý rằng lệnh chấp nhận một phạm vi, vì vậy bạn có thể thực hiện lựa chọn trực quan và sau đó chỉ :retabcác dòng được chọn.


Mát mẻ! Hoạt động nhanh chóng và đơn giản!
DenisKolodin

2
làm thế nào về việc cung cấp một ví dụ?
Petr

23

:retabTuy nhiên, bạn có thể sử dụng , như đã nêu, điều này sẽ thay đổi tất cả các tab thành khoảng trắng, không chỉ các tab ở đầu dòng

Vì vậy, đây (nơi là một nhân vật tab):

if :; do
⇥echo "⇥hello"
end

được thay đổi thành ( ký tự không gian):

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

Điều này có thể tạo ra các tác dụng phụ không mong muốn trong một số trường hợp và nó thậm chí còn gây ra nhiều vấn đề hơn khi thay đổi không gian thành các tab!

Vì vậy, tôi đã viết một hàm nhỏ để chỉ thay đổi các tab / dấu cách ở đầu dòng:

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

Với phiên bản này, bạn phải chỉ định thủ công expandtabtrong lệnh gọi hàm (nghĩa là :call Retab(1)thay đổi tab thành khoảng trắng), nhưng bạn cũng có thể sửa đổi nó để lấy giá trị hiện tại của &expandtab(như đã làm với &tabstop) giống như :retabvậy. (Tôi tình cờ thích chỉ định nó bằng tay).


6
Ngoài ra còn có một câu trả lời về SO chỉ bao gồm việc thử lại ở đầu dòng. Đó là giá trị liên kết vì sự rõ ràng của lời giải thích đó.
jalanb

Ai đó có thể giải thích những gì hiện lá thư atrong if a:expandtabbình?
john cj

Ngoài ra, có vẻ như các điều kiện được đảo ngược (một trò đùa: D?). Nếu bạn có set expandtabtrong .vimrc của mình và sau đó autocmd BufWritePre * :call Retab(&expandtab)- thụt lề sẽ được thay đổi thành các tab, thay vì dấu cách.
john cj

11

Vim cung cấp !retablệnh sẽ thay thế tất cả các chuỗi <Tab>bằng các chuỗi khoảng trắng mới bằng cách sử dụng :set tabstop=2giá trị tabstop (ví dụ ) mới được cung cấp, nhưng tất cả các tab bên trong chuỗi có thể được sửa đổi (ví dụ: trong chương trình C, bạn nên sử dụng \tđể tránh điều này)!

Vì vậy, thay vào đó, bạn có thể thay đổi tất cả các tab thành khoảng trắng bằng lệnh sau:

:%s/\t/  /g

hoặc theo đề xuất của @Shahbaz :

:%s/^\t\+/ g

Vì vậy, chỉ các tab được sử dụng trong thụt lề được chuyển đổi.

Giải trình:

  • %đại diện cho toàn bộ bộ đệm / tệp ( :help :%)
  • slà viết tắt của thay thế ( :help sub-replace-special)
  • \thoặc ^Iviết tắt của tab
  • - sử dụng nhiều khoảng trống bạn cần cho mỗi tab
  • g - là viết tắt của toàn cầu và nó sẽ chuyển đổi nhiều lần xuất hiện của các tab trong cùng một dòng

Sau đó, để sửa lỗi thụt lề của toàn bộ tệp, bạn có thể thử : gg=G. Kiểm tra: Tái thụt mã thụt lề xấu để biết thêm chi tiết.

Để sử dụng khoảng trắng theo mặc định thay vì các tab, bạn cần thêm các cài đặt sau vào .vimrctệp của mình :

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

Giải pháp thay thế là sử dụng tidy


Liên quan:


1
Tôi ít nhất sẽ làm %s/^\t\+/ gnhư vậy để chỉ các tab được sử dụng trong thụt lề được chuyển đổi. Ngoài ra, gg=Gcó thể là thảm họa với các ngôn ngữ như python.
Shahbaz

3

Hãy thử sử dụng:

expand -t 4 input_filename output_filename

expandlà một công cụ dòng lệnh để chuyển đổi các tab thành khoảng trắng, mà bạn có thể chạy từ shell hoặc với :!expand.

Đó là trong POSIX vì vậy nó sẽ có sẵn trên hầu hết các hệ thống. unexpandNhân tiện, sẽ làm ngược lại.


2
expand
muru

Mở rộng là một lệnh đầu cuối sẵn có để sao chép ký tự tab vào khoảng trắng. Vui lòng tìm một bản mô tả chi tiết trong liên kết sau. computerhope.com/unix/uExand.htmlm
Ankit Shah

2
Nếu đây là các lệnh bên ngoài, bạn nên đề cập đến điều đó.
muru

Mô tả thêm. Vui lòng xem lại
Ankit Shah

5
Bạn cũng có thể làm :%!expand -t 4bên trong vim. Tốt hơn nữa, bạn cũng có thể sử dụng tùy chọn độ rộng ca hiện tại: :exe '%!expand -t ' . &shiftwidth
EvergreenTree

1

Để hoàn thiện, =cũng có thể được sử dụng để sửa các vết lõm, sau khi bạn đã chỉ định rằng các tab được thay thế bằng dấu cách. Trong chế độ bình thường, bạn có thể làm như vậy bằng cách gõ :set expandtab. Sau đó =có thể được sử dụng theo hai cách:

  • Trong chế độ Trực quan, một đơn =sẽ sửa các vết lõm của các khối mã được chọn.
  • Trong chế độ bình thường, gg=Gsẽ sửa toàn bộ tệp, trong đó ggdi chuyển con trỏ đến đầu tệp, sau đó =được áp dụng và Gdi chuyển con trỏ đến cuối tệp.

Tham khảo: liên kết


Giả định này vim có thể tính toán lại thụt lề hiện tại một cách chính xác (có thể không phải là trường hợp) - cũng cho các tệp không có cấu trúc hoặc mã được viết trong một trình soạn thảo khác với các quy tắc thụt lề hơi khác.
ideaman42

Cảm ơn @ ideaman42; Tôi đã thêm vào câu trả lời để hoàn thiện hơn.
Samuel Li
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.