Как заменить табуляцию пробелами?

85

Можно ли конвертировать вкладки в пробелы, сохраняя выравнивание текста?

Простая замена работает только тогда, когда нет ведущих символов.

ideasman42
источник
Если вы установили vim-faq , вы можете получить оффлайн ответ: :h vim-faqи искать /tab characters. Трудно запомнить тег :h faq-14.16.
Хотчке

Ответы:

98

Вы можете использовать :retabкоманду. Из :help :retab

Замените все последовательности пробелов, содержащих a, <Tab>новыми строками пробелов, используя новое заданное значение табуляции. Если вы не указали новый размер табуляции или он равен нулю, Vim использует текущее значение 'tabstop'. [...] При 'expandtab'включении Vim заменяет все вкладки соответствующим количеством пробелов.

Обратите внимание, что команда принимает диапазон, поэтому вы можете сделать визуальный выбор, а затем только :retabвыделенные строки.

Guillem
источник
Здорово! Работает быстро и просто!
ДенисКолодин
2
как насчет примера?
Петр
23

Вы можете использовать :retab, как указано, однако, это изменит все вкладки на пробелы, а не только вкладки в начале строки

Так вот (где находится символ табуляции):

if :; do
⇥echo "⇥hello"
end

изменяется на (где символ пробела):

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

Это может привести к неожиданным побочным эффектам в некоторых сценариях, и это еще больше проблема при переходе пробелов на вкладки!

Итак, я написал небольшую функцию для изменения только табуляции / пробелов в начале строки:

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

В этой версии вы должны вручную указывать expandtabв вызове функции (т. :call Retab(1)Е. Менять табуляцию на пробелы), но вы также можете изменить ее так, чтобы она принимала текущее значение &expandtab(как это уже было с &tabstop), как это :retabделается. (Я предпочитаю указать это вручную).

Мартин Турной
источник
6
Существует также ответ на SO, который охватывает повторное добавление только в начале строки. Это стоит связать из-за ясности этого объяснения.
Джаланб
Может кто - нибудь объяснить , что делает письмо aв if a:expandtabсреднем?
Джон CJ
Кроме того, кажется, что условия поменялись местами (шутка: D?). Если у вас есть set expandtab.vimrc, а затем autocmd BufWritePre * :call Retab(&expandtab)- отступ будет заменен на табуляцию, а не на пробел.
Джон CJ
11

Vim предоставляет !retabкоманду, которая заменит все последовательности <Tab>новыми строками пробела, используя новое заданное :set tabstop=2значение tabstop (например ), но все вкладки внутри строк могут быть изменены (например, в программе на C, вы должны использовать, \tчтобы избежать этого)!

Таким образом, в качестве альтернативы вы можете изменить все вкладки на пробелы, используя следующую команду:

:%s/\t/  /g

или как предложено @Shahbaz :

:%s/^\t\+/ g

Таким образом, конвертируются только вкладки, используемые в отступе.

Объяснение:

  • %представляет весь буфер / файл ( :help :%)
  • sобозначает замену ( :help sub-replace-special)
  • \tили ^Iобозначает вкладку
  • - используйте столько пробелов, сколько вам нужно на одной вкладке
  • g - обозначает глобальный, и он будет преобразовывать несколько вкладок в одной строке

Затем , чтобы исправить отступы весь файл, вы можете попробовать: gg=G. Проверьте: перезаписать плохо с отступом код для более подробной информации.

Чтобы использовать пробелы по умолчанию вместо вкладок, вам необходимо добавить следующие параметры в ваш .vimrcфайл:

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

Альтернативное решение заключается в использовании tidy


Связанный:

kenorb
источник
1
Я бы хотя бы сделал %s/^\t\+/ gтак, чтобы конвертировались только вкладки, используемые в отступе. Кроме того, gg=Gможет быть катастрофическим с такими языками, как Python.
Шахбаз
3

Попробуйте использовать:

expand -t 4 input_filename output_filename

expandэто инструмент командной строки для преобразования вкладок в пробелы, которые вы можете запустить из оболочки или с помощью :!expand.

Он находится в POSIX, поэтому он должен быть доступен на большинстве систем. unexpandсделаем наоборот, кстати.

Анкит Шах
источник
2
Что такое expand?
Муру
Expand - это встроенная команда терминала для копирования символа табуляции в пробелы. Подробное описание вы найдете по следующей ссылке. computerhope.com/unix/uexpand.htm
Анкит Шах,
2
Если это внешние команды, вы должны упомянуть об этом.
Муру
Добавлено дополнительное описание. Пожалуйста, просмотрите
Анкит Шах
5
Вы также можете просто сделать :%!expand -t 4внутри Vim. Более того, вы также можете использовать текущий параметр ширины смещения: :exe '%!expand -t ' . &shiftwidth
EvergreenTree
1

Для полноты =можно также использовать для исправления отступов после того, как вы указали, что вкладки заменяются пробелами. В обычном режиме вы можете сделать это, набрав :set expandtab. Тогда =может быть использовано двумя способами:

  • В визуальном режиме один =исправляет отступы выбранных блоков кода.
  • В обычном режиме gg=Gисправляет весь файл, где ggперемещает курсор в начало файла, затем =применяется и Gперемещает курсор в конец файла.

Ссылка: ссылка

Самуэль Ли
источник
Это предполагает, что vim может правильно пересчитать текущий отступ (может быть и не так) - также для неструктурированных файлов или кода, написанного в другом редакторе с немного отличающимися правилами отступа.
ideasman42
Спасибо @ ideasman42; Я добавил к ответу, чтобы быть более полным.
Самуэль Ли