Emacs: разные отступы для класса и структуры

Я пытаюсь добиться следующего отступа в Emacs:

class A
{
// I ALWAYS use access labels in classes

public: // access-label
int member; // inclass
};

struct B
{
// I NEVER use access labels in structs

int member; // inclass
};

Однако со следующим файлом конфигурации …

(defun my-cpp-mode ()
"My C++ mode"(c++-mode)
(c-set-style "K&R")
(setq c-basic-offset 4)
(c-set-offset 'access-label '-)
(c-set-offset 'inclass '++)
;; ...
(setq mode-name "My C++")
)
(add-to-list 'auto-mode-alist '("\\.[ch]p?p?\\'" . my-cpp-mode))

… Я достигаю только:

class A
{
public: // access-label
int member; // inclass
};

struct B
{
// this indentation is too long
int member; // inclass
};

Конечно это потому что:

  • для отступа, очевидно, нет никакой разницы между «классом» и «структурой» (все это «класс»),
  • Отступы «inclass» не зависят от наличия меток доступа или нет.

Любая идея, как я могу сделать отступ в классе вещи зависит от класса / структуры или от наличия меток доступа?

10

Решение

Новый ответ

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

Изменить ваш my-cpp-mode выглядеть так:

(defun my-c-lineup-inclass (langelem)
(let ((inclass (assoc 'inclass c-syntactic-context)))
(save-excursion
(goto-char (c-langelem-pos inclass))
(if (or (looking-at "struct")
(looking-at "typedef struct"))
'+
'++))))

(defun my-cpp-mode ()
"My C++ mode"(c++-mode)
(c-set-style "K&R")
(setq c-basic-offset 4)
(c-set-offset 'access-label '-)
(c-set-offset 'inclass 'my-c-lineup-inclass)
;; ...
(setq mode-name "My C++")
)

Если этот ответ приемлем, я уберу старый ответ.

Старый ответ

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

(access-label . /)

Из документации Emacs:

Если OFFSET является одним из символов +',-», ++',-», *', or
затем положительный или отрицательный кратный `c-basic-offset ‘добавляется к
отступ в основании; 1, -1, 2, -2, 0,5 и -0,5 соответственно.

Вот фрагмент из одного из определенных мной стилей.

(c-add-style
"xyz-style"'((indent-tabs-mode . nil)
(fill-column . 75)
(c-basic-offset . 4)
(c-offsets-alist . (
(access-label . /)
(inextern-lang . 0)
(innamespace . 0)
(member-init-intro . ++)
))))

С c-basic-offset установить на 4, (access-label . /) добавляет отрицательный отступ в 2 пробела к меткам доступа. Вот фактический результат моего режима отступа на вашем примере кода.

class A
{
// I ALWAYS use access labels in classes

public: // access-label
int member; // inclass
};

struct B
{
// I NEVER use access labels in structs

int member; // inclass
};

Я рекомендую этот режим, потому что уровень отступа переменных-членов / членов структуры является согласованным. FWIW, Google C Style следует тому же подходу.

Насколько я могу судить, нельзя различать члена класса или члена структуры (inclass элемент синтаксиса). Ты можешь использовать M-x c-syntactic-information-on-region провести синтаксический анализ региона. Один такой анализ на вашем примере дает следующее. Исходя из результатов, нечего различать, если вы находитесь в классе или структуре.

class A                                 // ((topmost-intro 1))
{                                       // ((class-open 1))
// ((inclass 64) (topmost-intro 64) (comment-intro))I ALWAYS use access labels in classes
// ((inclass 64) (topmost-intro 64))
public:                               // ((inclass 64) (access-label 64))access-label
int member;                         // ((inclass 64) (topmost-intro 64))inclass
};                                      // ((class-close 1))
// ((topmost-intro 503))
struct B                                // ((topmost-intro 503))
{                                       // ((class-open 629))
// ((inclass 694) (topmost-intro 694) (comment-intro))I NEVER use access labels in structs
// ((inclass 694) (topmost-intro 694))
int member;                         // ((inclass 694) (topmost-intro 694))inclass
};                                      // ((class-close 629))
7

Другие решения

Основываясь на ответе Правина Кумара выше, я реализовал немного другую версию пользовательской функции:

(defun my-c-lineup-inclass (langelem)
(let ((inclass (assoc 'inclass c-syntactic-context)))
(save-excursion
(c-beginning-of-defun) ; This sees the correct string.
(if (or (looking-at "struct")
(looking-at "typedef struct"))
'+
'++))))

; In particular, the following offsets need to be specified:
(c-set-offset 'access-label '-)
(c-set-offset 'inclass 'my-c-lineup-inclass)
; ...

Исходный код не работал в случае, если скобка была на следующей строке, т.е.

struct foo
{
int bar;
};

все равно отступ++».

Отказ от ответственности: я не знаю Лисп. Я просто играл, и это работает для меня. Я не знаю, например, есть ли какие-либо проблемы с производительностью, связанные с этим.

2

Стандарты кодирования в моем проекте теперь требуют такого отступа. Как и Аркадий, я предпочитаю решение, которое учитывает метки доступа. Вот что я придумал:

(defun indent-after-access-label (langelem)
"Return the appropriate indent for a class or a struct."(save-excursion
(save-match-data
;; Optimization to avoid at least a few calls to re-search-backward.
(if (assoc 'access-label c-syntactic-context)
'++
(if (re-search-backward "\\(?:p\\(?:ublic\\|r\\(?:otected\\|ivate\\)\\)\\)" c-langelem-pos langelem) t)
'++
'+)))))

Как упоминалось ранее, indent-after-acess-label Символ должен быть установлен в качестве отступа для inclass (с помощью c-set-offset или же c-offset-alist, так далее.).

Это вряд ли идеально, из-за re-search-backward, но это работает.

0
По вопросам рекламы [email protected]