Emacs cc-mode проблема с отступом с классом переименования С++ 0x

Emacs cc-mode пока не распознает безопасный тип enum class, введенный в С++ 0x. В результате я получаю двойной отступ для второго, третьего и т.д. Перечислений:

enum class Color {
    Blue,
        Red,
        Orange,
        Green
        };

Я бы хотел:

enum class Color {
    Blue,
    Red,
    Orange,
    Green
};

Можете ли вы порекомендовать хорошую команду для добавления в .emacs, которая сделает cc-mode обработкой enum class так же, как она обрабатывает простой старый enum?

Ответ 1

В этом проблема:

cc-mode полагается несколько на предположение, что ключевые слова являются одиночными словами. Добавление поддержки enum_class вместо enum class было бы вопросом изменения нескольких регулярных выражений.

Вместо этого Emacs рассматривает это как класс. Правильный способ решения этого вопроса - обучать Emacs, что это перечисление. Но это выходит за рамки ответа.

Это хак:

Итак, мы изменим существующий отступ, чтобы вести себя по-другому в этом случае. (Код доступен для использования в gist.)

(defun inside-class-enum-p (pos)
  "Checks if POS is within the braces of a C++ \"enum class\"."
  (ignore-errors
    (save-excursion
      (goto-char pos)
      (up-list -1)
      (backward-sexp 1)
      (looking-back "enum[ \t]+class[ \t]+[^}]+"))))

(defun align-enum-class (langelem)
  (if (inside-class-enum-p (c-langelem-pos langelem))
      0
    (c-lineup-topmost-intro-cont langelem)))

(defun align-enum-class-closing-brace (langelem)
  (if (inside-class-enum-p (c-langelem-pos langelem))
      '-
    '+))

(defun fix-enum-class ()
  "Setup `c++-mode' to better handle \"class enum\"."
  (add-to-list 'c-offsets-alist '(topmost-intro-cont . align-enum-class))
  (add-to-list 'c-offsets-alist
               '(statement-cont . align-enum-class-closing-brace)))

(add-hook 'c++-mode-hook 'fix-enum-class)

Это не сильно проверено.;)

Как это работает:

c-offsets-alist определяет отступ для разных позиций в дереве синтаксиса. Ему могут быть назначены константы или функции.

Эти две функции определяют, находится ли текущая позиция внутри enum class {...}. В этом случае они возвращают 0 или '-, которые cc-mode интерпретирует как глубину углубления. Если это не так, они возвращают значение по умолчанию.

inside-class-enum-p просто перемещается к предыдущей фигурной скобке и проверяет, есть ли перед ним текст "enum class".