20081125

Вставка Python-кода в Vim

Как известно, в пайтоне отступ слева («indentation») синтаксически важен. Есть две школы мысли, как набирать его в тексте: табуляциями (количество табуляций — уровень отступа) или пробелами (в этом случае редактор должен обеспечивать раскрытие табуляций до нужного числа пробелов). Главное, эти способы не смешивать.

С одной стороны, я сторонник табуляций, их ширину в редакторе всегда легко изменить, не трогая кода. С другой — Style Guide for Python Code рекомендует делать отбивку четырьмя пробелами. В новых программах я стал использовать четыре пробела, в старых использую табуляции.

Лирическое отступление

В целом, в Vim набирать код Python удобно: поддерживается как режим с табуляциями, так и режим с пробелами. В последнем случае нужно установить опцию expandtab. Автоматические отступы для Python поддерживаются.

Часто пригождается: чтобы сдвинуть блок текста влево или вправо: Shift-V, выделение блока, << или >> соответственно.

Задать желаемую ширину табуляции и ширину сдвига можно опциями tabstop и shiftwidth соответственно, например:
:set ts=4 sw=4
Настройки файла можно прописать в его modeline.
Проблемы начинаются при попытке вставить чужой код в свой проект. С высокой степенью вероятности, он или использует другой способ ввода отступов, или другую ширину отступа.

Собственно, проблемы здесь две. Первая неспецифична для пайтона, а проявляется всегда при вставке в Vim, запущенный в терминале. Vim попытается автоматически отбить вставляемый код ещё раз. Решение я уже описывал. :set paste.

Вторая проблема специфична для пайтона. Даже если код был вставлен правильно (с сохранением авторских отступов), но авторские отступы не совпадают с используемыми в программе, код либо не будет работать вообще, либо будет работать неправильно. Выравнивать код с помощью << и >> далеко не всегда удобно.

Выход здесь довольно прост:
  1. (опционально) временно отключить expandtab, если используется;
  2. преобразовать авторские пробелы в табуляции, для этого выделяем нужный блок и делаем :retab!5, где аргумент («5») — авторская ширина отступа;
  3. (опционально) при использовании expandtab, включить его обратно, а «авторские» табуляции заменить на нужное число пробелов (:s#\t#    #g).
Тот же самый приём применим и для других языков с синтаксическими отступами, например, YAML или Haskell.

P.S. Как легко заметить, пайтон не поощряет повторное использование в стиле copy-paste ;-)