2013-02-05 21 views
10

Próbuję osiągnąć następujące wcięcia w emacs:Emacs: inna wcięcie dla klasy i struktury

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

Jednak z poniższym pliku konfiguracyjnego ...

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

... ja osiągnąć tylko:

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

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

oczywiście to dlatego, że:

  • do wgniecenie nie jest oczywiście nie ma różnicy między „klasa” i „struktury” (to wszystko „inclass”),
  • wcięcia „inclass” rzeczy nie zależy od obecności etykiet dostępu lub nie .

Każdy pomysł, w jaki sposób mogę wprowadzić wcięcie elementów compass zależne od klasy/struktury lub od obecności etykiet dostępu?

+0

Myślę, że po prostu chcesz public: and private: aby nie dodawać wcięć. – djechlin

+0

Dzięki, ale jeśli masz na myśli "{" i "public:" w tej samej kolumnie, nie, to nie jest to, czego chcę. – Aurelien

+1

Potrafię zrozumieć twoje pragnienie, i biorąc pod uwagę wystarczającą poprawę, powinno być możliwe. Z drugiej strony może się okazać, że nie jest to łatwe, ponieważ brak rozróżnienia między klasami i strukturami przebiega dość głęboko w C++: można nawet używać struktur specyfikacji dostępu. Ponieważ takie użycie jest rzadkie, udzielę +1 temu pytaniu i będę zainteresowany, czy pojawią się jakieś rozwiązania. – MvG

Odpowiedz

7

New Answer

wpadłem dokładnie wymogu, że wspominał w swoim pytaniu. Musiałem ustawić wcięcia zgodnie ze stylem kodowania mojego nowego projektu. Po kilku badaniach osiągnąłem to, używając Custom Line-up Functions.

zmodyfikować my-cpp-mode wyglądać tak:

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

Jeśli ta odpowiedź jest do zaakceptowania, pójdę do przodu i zdjąć starą odpowiedź.

Old Odpowiedź

W oparciu o to, co staramy się osiągnąć, może proponuję inne podejście? Wygląda na to, że chcesz uzyskać etykietę dostępu na innym poziomie wcięcia niż klasa i członkowie klasy. Aby to osiągnąć, wykonaj następujące czynności.

(access-label . /) 

Z dokumentacji Emacsa:

Jeśli przesunięcie jest jednym z symboli +', - '++', -', *', or /” wówczas dodatnia lub ujemna wielokrotność` przesunięcie c-basic- "dodaje się do wcięcie podstawowe; Odpowiednio 1, -1, 2, -2, 0,5 i -0,5.

Oto fragment z jednego z niestandardowych stylów, które zdefiniowałem.

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

Z c-basic-offset ustawiona na 4, (access-label . /) dodaje negatywny wcięcia 2 miejsca do etykiet dostępu. Oto rzeczywisty wynik mojego trybu wcięcia na przykładowym kodzie.

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

Polecam ten tryb, ponieważ poziom wcięcia zmiennych członkowskich/członków struktury jest spójny. FWIW, Google C Style postępuje zgodnie z tym samym podejściem.

Z tego co wiem, nie można rozróżnić między członkiem klasy lub członkiem struktury (element sytax inclass). Można użyć M-x c-syntactic-information-on-region, aby wykonać analizę składniową regionu. Jedna z takich analiz na przykładzie użytkownika daje następujące wyniki. Z danych wyjściowych nie ma nic do rozróżnienia, jeśli jesteś w klasie lub strukturze.

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

Tak, dziękuję, to jest rzeczywiście kompromis, z którego zdecydowałem się skorzystać, więc udzielę ci +1 Twojej odpowiedzi, ponieważ może zainteresować wielu użytkowników emacs. Ale jak powiedziałeś, nie odpowiada na faktyczne pytanie. – Aurelien

+1

OK w twojej ostatniej edycji pokazujesz, że nie jest to możliwe, co teraz zdecydowanie odpowiada na pytanie. Dzięki. – Aurelien

+0

Zakłada się, że 'struct' zawsze nie ma etykiet dostępu. Żałuję, że nie było rozwiązania, które rozpoznałoby, kiedy etykiety dostępu są obecne ... – Arkadiy

0

Standardy kodowania w moim projekcie wymagają obecnie tego rodzaju wcięcia. Podobnie jak Arkadiy, wolę rozwiązanie, które respektuje etykiety dostępu. To właśnie wymyśliłem:

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

Jak wspomniano wcześniej, indent-after-acess-label symbol musi być ustawiony jako wcięcia dla inclass (poprzez c-set-offset lub c-offset-alist, etc.).

To nie jest idealne ze względu na re-search-backward, ale działa.

2

podstawie odpowiedzi praveen Kumara powyżej, I wdrożone nieco inną wersję funkcji Line-up niestandardowe:

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

Oryginalny kod nie działa w przypadku klamra była w następnej linii, tj

struct foo 
{ 
     int bar; 
}; 

nadal będzie wcięty do "++".

Nota prawna: Nie znam żadnego Lispa. Po prostu bawiłem się i to działa dla mnie. Nie wiem, na przykład, czy są jakieś problemy z wydajnością związane z tym.

+0

użycie '(c-start-of-defun)' nie jest całkowicie poprawne, ponieważ nie będzie działać z wbudowanymi funkcjami zdefiniowanymi w struct/classes ... –

Powiązane problemy