all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* C++ Indentation and access-labels
@ 2009-09-14 14:27 Marc Dürner
  2009-09-18 22:12 ` Alan Mackenzie
  0 siblings, 1 reply; 4+ messages in thread
From: Marc Dürner @ 2009-09-14 14:27 UTC (permalink / raw
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 728 bytes --]

Hello,

I am trying to set up semantic indentation for C++ and can't find a way to
configure the following indentation rule:

class A
{
    friend class X;

    int x;

    public:
        A();
        ~A();
};

struct B
{
    int n;
    bool b;
    char c;
};

I want to have class members and friend declarations indented by one level
is no access-label is present. If an acces-label is present it should be
indented and the class members that follow that access-label should be
indented further. It seems the is no way to handle class memers differently
if they are following an access-label. In the example above 'x' and 'A();'
are both classified as inclass/topmost-intro.

Is there a way to configure this?

regards,
Marc

[-- Attachment #2: Type: text/html, Size: 846 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* C++ Indentation and access-labels
@ 2009-09-18 10:32 Marc Dürner
  0 siblings, 0 replies; 4+ messages in thread
From: Marc Dürner @ 2009-09-18 10:32 UTC (permalink / raw
  To: help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 730 bytes --]

Hello,

I am trying to set up semantic indentation for C++ and can't find a way to
configure the following indentation scheme:

class A
{
    friend class X;

    int x;

    public:
        A();
        ~A();
};

struct B
{
    int n;
    bool b;
    char c;
};

I want to have class members and friend declarations indented by one level
is no access-label is present. If an acces-label is present it should be
indented and the class members that follow that access-label should be
indented further. It seems the is no way to handle class memers differently
if they are following an access-label. In the example above 'x' and 'A();'
are both classified as inclass/topmost-intro.

Is there a way to configure this?

regards,
Marc

[-- Attachment #2: Type: text/html, Size: 878 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: C++ Indentation and access-labels
  2009-09-14 14:27 Marc Dürner
@ 2009-09-18 22:12 ` Alan Mackenzie
       [not found]   ` <52a7da0f0909210708x21945b5ej557d4cd8b77a17cf@mail.gmail.com>
  0 siblings, 1 reply; 4+ messages in thread
From: Alan Mackenzie @ 2009-09-18 22:12 UTC (permalink / raw
  To: marc.duerner; +Cc: help-gnu-emacs

Hi, Marc!

On Mon, Sep 14, 2009 at 04:27:11PM +0200, Marc Dürner wrote:
> Hello,

> I am trying to set up semantic indentation for C++ and can't find a way
> to configure the following indentation rule:

> class A
> {
>     friend class X;

>     int x;

>     public:
>         A();    <===========
>         ~A();   <===========
> };

> I want to have class members and friend declarations indented by one level
> if no access-label is present. If an acces-label is present it should be
> indented and the class members that follow that access-label should be
> indented further. It seems the is no way to handle class memers differently
> if they are following an access-label. In the example above 'x' and 'A();'
> are both classified as inclass/topmost-intro.

> Is there a way to configure this?

No.  There should be, though.  The first member after "public:" ought to
get a special syntactical symbol, say "protection-clause-intro", somewhat
analagous to "statement-block-intro", the first statement inside a
compound statement (brace block).  Maybe I'll fix this sometime.

(If the previous paragraph doesn't make sense, either ignore it or look
it all up on page "Syntactic Symbols" in the CC Mode manual.)

However, CC Mode is flexible enough for workarounds to be possible.  So,
for the meantime, here's a workaround.  Put the file below somewhere
convenient (I've called it ~/duerner.el; you probably want to byte
compile it), and add this line to your .emacs:

   (eval-after-load "cc-mode" '(load-file "~/duerner.el))
[ or ................................................elc)) ]

# File ~/duerner.el:
#########################################################################
(defsubst md-at-inclass/topmost-intro (sintax)
  (and
   (eq (caar sintax) 'inclass)
   (eq (car (cadr sintax)) 'topmost-intro)))

(defun md-ind-prot-class ()
  "Give an extra level of indentation to class thingies under an access
specifier, e.g.:

    public
        A();        <========== extra level of indentation.

This should really be properly implemented in CC Mode, but it's not."
  (and
   (md-at-inclass/topmost-intro c-syntactic-context)
   (let (m-type)
     (when
	 (save-excursion
	   (back-to-indentation)
	   ;; Go back one "statement" at a time till we reach a label or something
	   ;; which isn't an inclass/topmost-intro
	   (while
	       (and (eq (setq m-type (c-beginning-of-statement-1)) 'previous)
		    (md-at-inclass/topmost-intro (c-guess-basic-syntax))))
	   ;; Have we found "private:", "public": or "protected"?
	   (and (eq m-type 'label)
		(looking-at
		 (eval-when-compile
		  (c-make-keywords-re nil (c-lang-const c-protection-kwds c++))))))
       (save-excursion
	(back-to-indentation)
	(c-shift-line-indentation c-basic-offset))))))

(defun md-add-hook ()
  (add-hook 'c-special-indent-hook 'md-ind-prot-class))
(add-hook 'c++-mode-hook 'md-add-hook)
#########################################################################

The above is a fairly rough and ready hack.  If it does something silly,
please get back to me with a description of the failure.


> regards,
> Marc

Sincerely,

-- 
Alan Mackenzie (Nürnberg).




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: C++ Indentation and access-labels
       [not found]     ` <20090925082833.GA2596@muc.de>
@ 2009-09-28 16:39       ` Marc Dürner
  0 siblings, 0 replies; 4+ messages in thread
From: Marc Dürner @ 2009-09-28 16:39 UTC (permalink / raw
  To: Alan Mackenzie, help-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 5460 bytes --]

Hello,

Thank you, Alan. This works much better now. Can you help me out with a few
remaining problems?

1) The inline-methods in a class or struct are not indented to the same
level as topmost-intro

Here is an example how it looks like:

class c
{
    friend class y;

    public:
        c()
        : _n(8)
    { } <=== here

        void meth()
    {} <=== here

    private:
        int _n;
};

2) when I type 'void meth()' after typing ')' eight spaces (two levels of
indentation) are added to the next line with the cursor positioned at the
beginning of the line:

class c
{
    public:
        void method()
X.......

where X is the cursor position and . are trailing whitespace. The same
happens when I close a inline-defun with '}'. When I continue it disappears,
but it is a bit uncomfortable if I would just add a method to a class. Also,
the trailing whitespace stays when I reindent a block with the tab key

3) Another problem is caused by macros before class names. This is something
which is very common:

class MY_API MyClass
{};

MY_API is some macro which expands to compiler specific attributes like
declspec (VC) or __attribute__ (GCC). Many libraries have macros like this.
Somehow it confuses the parser and indentation of access-labels is only two
spaces (half of what it should be, c-basic-offset is 4).Example:

class MY_API c
{
    friend class y;

  public:
    c()
        : _n(8)
    { }

    void meth()
    {}

  private:
    int _n;
};

Maybe there is another way to tell the parser to simply ignore "MY_API".

regards,
Marc

2009/9/25 Alan Mackenzie <acm@muc.de>

> Hi, Marc!
>
> On Mon, Sep 21, 2009 at 04:08:30PM +0200, Marc Dürner wrote:
>
> > > # File ~/duerner.el:
> > >
> #########################################################################
> > > (defsubst md-at-inclass/topmost-intro (sintax)
> > >  (and
> > >   (eq (caar sintax) 'inclass)
> > >   (eq (car (cadr sintax)) 'topmost-intro)))
>
> > > (defun md-ind-prot-class ()
> > >  "Give an extra level of indentation to class thingies under an access
> > > specifier, e.g.:
>
> > >    public
> > >        A();        <========== extra level of indentation.
>
> > > This should really be properly implemented in CC Mode, but it's not."
> > >  (and
> > >   (md-at-inclass/topmost-intro c-syntactic-context)
> > >   (let (m-type)
> > >     (when
> > >         (save-excursion
> > >           (back-to-indentation)
> > >           ;; Go back one "statement" at a time till we reach a label or
> > > something
> > >           ;; which isn't an inclass/topmost-intro
> > >           (while
> > >               (and (eq (setq m-type (c-beginning-of-statement-1))
> > > 'previous)
> > >                    (md-at-inclass/topmost-intro
> (c-guess-basic-syntax))))
> > >           ;; Have we found "private:", "public": or "protected"?
> > >           (and (eq m-type 'label)
> > >                (looking-at
> > >                 (eval-when-compile
> > >                  (c-make-keywords-re nil (c-lang-const
> c-protection-kwds
> > > c++))))))
> > >       (save-excursion
> > >        (back-to-indentation)
> > >        (c-shift-line-indentation c-basic-offset))))))
>
> > > (defun md-add-hook ()
> > >  (add-hook 'c-special-indent-hook 'md-ind-prot-class))
> > > (add-hook 'c++-mode-hook 'md-add-hook)
> > >
> #########################################################################
>
> > > The above is a fairly rough and ready hack.  If it does something
> silly,
> > > please get back to me with a description of the failure.
>
>
> > Thank you for you help!
>
> > The script you wrote seems to have no effect (yet):
>
> Sorry.  I hadn't tested things enough.  Here's what the problem is:
>
> > Here is what I added to my .emacs:
>
> > (require 'cc-mode)
> > (setq c-basic-offset 4)
> > (setq-default c-tab-always-indent nil)
>
> Just an aside: (setq c-basic-offset 4) will set the global value, but
> this will get overridden by the style system.  Either create your own
> style. or set this to c++-mode-hook (see below).  Yes, it's
> overcomplicated.  ;-(
>
> > (add-hook 'c++-mode-hook
> >           '(lambda ()
> >              (c-set-style "ellemtel")
> >              (c-set-offset 'access-label '0)))
>
> The form (c-set-style "ellemtel") in c++-mode-hook wipes clean the
> value of c-special-indent-hook.  :-(  So we need to arrange to do
> "ellemtel" before doing "special-indent".
>
> > (eval-after-load "cc-mode" '(load-file "~/duerner.el"))
>
> So, please change the following:
> (i) in ~/duerner.el, REMOVE the last line, "(add-hook 'c++-mode-hook
>  'md-add-hook)".
>
> (ii) in ~/duerner.el, insert at the top the line "(require 'cc-langs)",
>  to make sure it compiles properly.
>
> (ii) Change your .emacs bit to this:
>
>  (require 'cc-mode)
>  ;; (setq c-basic-offset 4)  ; <===== commented out
>   (setq-default c-tab-always-indent nil)
>
>  (add-hook 'c++-mode-hook
>            '(lambda ()
>               (c-set-style "ellemtel")
>                (add-hook 'c-special-indent-hook 'md-ind-prot-class) ;
> <======
>                (c-set-offset 'access-label '0)
>                (setq c-basic-offset 4)))
>
>  (eval-after-load "cc-mode" '(load-file "~/duerner.el"))
>
> Hope it works now!
>
> > regards,
> > Marc
>
> --
> Alan Mackenzie (Nürnberg).
>

[-- Attachment #2: Type: text/html, Size: 6884 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-09-28 16:39 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-09-18 10:32 C++ Indentation and access-labels Marc Dürner
  -- strict thread matches above, loose matches on Subject: below --
2009-09-14 14:27 Marc Dürner
2009-09-18 22:12 ` Alan Mackenzie
     [not found]   ` <52a7da0f0909210708x21945b5ej557d4cd8b77a17cf@mail.gmail.com>
     [not found]     ` <20090925082833.GA2596@muc.de>
2009-09-28 16:39       ` Marc Dürner

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.