Обновить

Emacs и правильная работа с чужим кодом: отступы

ПрограммированиеСовершенный кодEmacs
Так повелось, что во многих компаниях есть свой код-стандарт, регламентирующий, как оформлять отступы: пробелами или табуляцией, а также какой ширины они должны быть. Что делает новичок первым делом при работе над проектом, где код уже оформлен согласно стандарту? Правильно, он коммитит плоды своего труда и получает от тимлида по шапке за то, что не посмотрел как именно его редактор работает с отступами. Если вы начинающий(или не в меру удачливый) пользователь emacs и хотите избежать этого печального, но закономерного, если вы еще не сталкивались с этим, исхода, то добро пожаловать под кат.



С чем мы имеем дело?

Сперва неплохо узнать, что за код нам достался. Любопытно, но уже на этом этапе вы можете увидеть мешанину из отступов разной ширины, если редактор вашего предшественника ставил табы/пробелы в файле, где табуляция уже была представлена в виде пробелов/табов. Оговорюсь, что увидеть это вы сможете только если ширина отображения табов у вас не совпадает с шириной таба(в пробелах) в редакторе предшественника.
Если вы ничего не увидели, то не отчаивайтесь, чтобы увидеть, что происходит в файле на самом деле, можно использовать whitespace-mode. Он был добавлен в стандартную поставку emacs, начиная с версии 23, но в случае чего его можно всегда найти здесь: WhiteSpace.
Вот так выглядят 2 файла, на первый взгляд одинаковые, но использующие разные символы для формирования отступов, внешне:



И с использованием whitespace-mode:



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


Настройка отступов

Для того, чтобы выбрать, какой символ будет формировать отступы меняется значение переменной indent-tabs-mode.
Чтобы установить в качестве отступа пробелы она должная быть установлена в nil:
  (setq indent-tabs-mode nil) ; отступ делается пробелами

соответственно для табов значение должно быть t:
  (setq indent-tabs-mode t) ; отступ делается табами


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


С символами разобрались, теперь нужно установить ширину отступа. И тут есть некоторая хитрость. Большая часть наиболее распространенных языков вроде js, php, c++, java имеют режимы подсветки, идущие от c-mode, в котором есть переменная c-basic-offset. Она отвечает за то, какой будет ширина таба при индентации во всех этих режимах. Также есть переменная tab-width, она отвечает за ширину таба. Так уж исторически сложилось, что для того, чтобы все форматировалось корректно, значения этих переменных должны быть равны. Если вы поставите разные значения для каждой, то результат будет мало предсказуемым, вплоть до того что emacs будет использовать пробелы вперемешку с табами.
Итак, для режимов, основанных на c-mode нужно использовать следующую схему:
  ; устанавливаем ширину таба в 2 символа
  (setq tab-width 2)
  (setq c-basic-offset 2)


Если вы используете cperl-mode, то отступ устанавливается через переменную cperl-indent-level. Опять таки, очень важно, чтобы ее значение и значение tab-width совпадало.

  ; устанавливаем ширину таба в 4 символа
  (setq tab-width 4)
  (setq cperl-indent-level 4)

В заключение скажу, что для изменения индентации html нужно устанавливать переменную sgml-basic-offset(не забывая про tab-width).


Каждому языку — свои правила

Разные языки требуют разных правил, описанных в PEP, конфигурации perl-tidy, да даже в код-стандарте вашей фирмы. При это редактор для всего хочется использовать один. Самый простой способ реализовать это — использовать хуки. Вот пример конфигурационного файла для python и perl:

; ширина таба 4, индентация пробелами
(add-hook 'cperl-mode-hook
  (lambda()
    (setq tab-width 4)
	(setq indent-tabs-mode nil)
))

; ширина таба 4, индентация табами
(add-hook 'python-mode-hook
  (lambda()
    (setq tab-width 4)
	(setq indent-tabs-mode t)
))


Приведение к общему знаменателю

Если вы все-таки стали счастливым обладателем кода, где использованы и табы и пробелы одновременно, то вам помогут команды untabify и tabify(спасибо пользователю fader44 за напоминание). Первая команда переводит все отступы в пробелы, вторая, соответственно в табы. Независимо от того, чем была отформатирована каждая строка, индентация будет приведена к единому виду.
Теги:emacs
Хабы: Программирование Совершенный код Emacs
Рейтинг +21
Количество просмотров 10,5k Добавить в закладки 48
Комментарии
Комментарии 10

Похожие публикации

Junior Clojure Developer
от 70 000 до 150 000 ₽Health SamuraiСанкт-ПетербургМожно удаленно
.net core backend developer (IoT, IIoT) (Middle)
от 1 200 до 2 000 €BPS InternationalМожно удаленно
Backend Developer (Python/GO)
от 180 000 ₽AgentAppМожно удаленно
Reverse Engineer
от 3 500 до 4 000 $Hand2NoteМожно удаленно
Middle | High middle front-end разработчик (React + Typescript)
от 80 000 до 160 000 ₽CSSSRМожно удаленно

Лучшие публикации за сутки