I'm trying to achieve the following indentation in 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
};
However with the following configuration file...
(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))
... I achieve only:
class A
{
public: // access-label
int member; // inclass
};
struct B
{
// this indentation is too long
int member; // inclass
};
Of course that's because:
Any idea how I can make the indentation of inclass stuff dependent on either class/struct or on the presence of access labels?
New Answer
I ran into the exact requirement that you had mentioned in your question. I had to setup indentation according to the coding style of my new project. After a bit of research, I achieved this using Custom Line-up Functions.
Modify your my-cpp-mode
to look like this:
(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++")
)
If this answer is acceptable, I'll go ahead and remove the old answer.
Old Answer
Based on what you are trying to achieve, may I suggest a different approach? You seem to want the access label at a different indentation level than the class and the class members. Use the following to achieve that.
(access-label . /)
From Emacs documentation:
If OFFSET is one of the symbols
+',
-',++',
--',*', or
/' then a positive or negative multiple of `c-basic-offset' is added to the base indentation; 1, -1, 2, -2, 0.5, and -0.5, respectively.
Here is a snippet from one of the custom styles that I have defined.
(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 . ++)
))))
With c-basic-offset
set to 4, (access-label . /)
adds a negative indentation of 2 spaces to the access labels. Here is the actual result of my indentation mode on your sample code.
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
};
I recommend this mode because, the indentation level of the member variables/struct members is consistent. FWIW, Google C Style follows the same approach.
As far as I can tell, one cannot differentiate between a class member or a struct member (inclass
sytax element). You can use M-x c-syntactic-information-on-region
to do a syntactic analysis on a region. One such analysis on you example yields the following. From the output, there is nothing to differentiate between if you are in a class or a struct.
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))
Based on Praveen Kumar's answer above, I implemented a slightly different version of the custom line-up function:
(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)
; ...
The original code did not work in case the brace was on the next line, i.e.
struct foo
{
int bar;
};
would still indent to "++
".
Disclaimer: I don't know any Lisp. I just played around and this works for me. I don't know, e.g., if there are any performance issues associated with this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With