2013-02-05 2 views
10

Sto cercando di raggiungere i seguenti rientro in emacs:emacs: rientro diverso per la classe e struct

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 
}; 

Tuttavia, con il seguente file di configurazione ...

(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 solo raggiungere:

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

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

Naturalmente questo è perché:

012.
  • per il rientro non v'è ovviamente alcuna differenza tra "classe" e "struct" (è tutto "INCLASS"),
  • il rientro di roba "INCLASS" non dipende dalla presenza di etichette di accesso o non .

Qualche idea di come sia possibile rendere il rientro delle cose di inclass dipendente dalla classe/struttura o dalla presenza di etichette di accesso?

+0

Penso che vorresti solo pubblico: e privato: per non aggiungere un livello di indentazione. – djechlin

+0

Grazie, ma se intendi "{" e "public:" sulla stessa colonna, no non è quello che voglio. – Aurelien

+1

Posso capire il tuo desiderio, e dato abbastanza tweaking dovrebbe essere possibile. D'altra parte, potrebbe benissimo essere che questo non è facilmente raggiungibile, perché la non distinzione tra classi e strutture funziona piuttosto in profondità in C++: puoi persino usare gli specificatori di accesso per le strutture. Poiché tale uso è raro, tuttavia, aggiungerò questa domanda e sarei interessato a vedere se emergono delle soluzioni. – MvG

risposta

7

Nuova risposta

ho incontrato l'esigenza esatta che aveva citato nella sua interrogazione. Ho dovuto impostare il rientro in base allo stile di codifica del mio nuovo progetto. Dopo un po 'di ricerche, ho raggiunto questo obiettivo utilizzando Custom Line-up Functions.

Modificare la tua my-cpp-mode di simile a questa:

(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++") 
) 

Se questa risposta è accettabile, io vado avanti e rimuovere la vecchia risposta.

Vecchio risposta

In base a ciò che si sta cercando di ottenere, mi permetto di suggerire un approccio diverso? Sembra che tu voglia l'etichetta di accesso con un livello di indentazione diverso rispetto alla classe e ai membri della classe. Usa il seguente per farlo.

(access-label . /) 

Da Emacs documentazione:

Se offset è uno dei simboli +', - '++', -', *', or /' quindi un multiplo positivo o negativo del `c-base-offset 'è aggiunto a la rientranza di base; 1, -1, 2, -2, 0,5 e -0,5, rispettivamente.

Ecco uno snippet di uno degli stili personalizzati che ho definito.

(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 . ++) 
         )))) 

Con c-basic-offset impostato su 4, (access-label . /) aggiunge una rientranza negativo di 2 spazi verso le etichette di accesso. Ecco il risultato effettivo della mia modalità di indentazione sul tuo codice di esempio.

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 
}; 

Consiglio questo modo perché, il livello di rientro dei membri variabili terzi/struct è coerente. FWIW, Google C Style segue lo stesso approccio.

Per quanto posso dire, non è possibile distinguere tra un membro della classe o un membro della struttura (inclass elemento di sytax). È possibile utilizzare M-x c-syntactic-information-on-region per eseguire un'analisi sintattica su un'area. Una di queste analisi sul tuo esempio produce quanto segue. Dall'output, non c'è nulla da distinguere se sei in una classe o in una 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)) 
+0

Sì, grazie, questo è davvero il compromesso che ho deciso di utilizzare, quindi farò +1 sulla tua risposta in quanto potrebbe interessare molti utenti di emacs. Ma come hai detto non risponde alla domanda vera e propria. – Aurelien

+1

OK nel tuo ultimo montaggio, mostri che non è possibile, che ora sicuramente risponde alla domanda. Grazie. – Aurelien

+0

Ciò presuppone che 'struct' non abbia sempre etichette di accesso. Vorrei che esistesse una soluzione in grado di riconoscere quando sono presenti le etichette di accesso ... – Arkadiy

0

Gli standard di codifica del mio progetto richiedono ora questo tipo di rientranza. Come Arkadiy, preferisco una soluzione che rispetti le etichette di accesso. Questo è ciò che mi si avvicinò con:

(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) 
      '++ 
      '+))))) 

Come accennato in precedenza, il simbolo indent-after-acess-label deve essere impostato come il rientro per inclass (via c-set-offset o c-offset-alist, etc.).

Questo non è l'ideale, a causa del re-search-backward, ma funziona.

2

in base alla risposta del Praveen Kumar sopra, ho implementato una versione leggermente diversa della funzione di line-up personalizzato:

(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) 
; ... 

Il codice originale non ha funzionato nel caso in cui la coppia era sulla riga successiva, vale a dire

struct foo 
{ 
     int bar; 
}; 

farebbe ancora il rientro a "++".

Disclaimer: Non conosco alcun Lisp. Ho appena giocato e questo funziona per me. Non so, ad esempio, se ci sono problemi di prestazioni associati a questo.

+0

'(c-beginning-of-defun)' non è completamente corretto, in quanto non funzionerà con le funzioni inline definite nella struct/classes ... –