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

в 17:25, , рубрики: emacs, Программирование, Совершенный код, метки:

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

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

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

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

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

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

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

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

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

  (setq indent-tabs-mode nil) ; отступ делается пробелами

соответственно для табов значение должно быть t:

  (setq indent-tabs-mode nil) ; отступ делается табами

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

    С символами разобрались, теперь нужно установить ширину отступа. И тут есть некоторая хитрость. Большая часть наиболее распространенных языков вроде 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)
))

Автор: PerlPower

Поделиться

* - обязательные к заполнению поля