2013-02-05 80 views
10

我想實現在Emacs以下縮進:emacs的:不同的縮進class和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 
}; 
與下面的配置文件

但是......

(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」),
  • 的「inclass」東西壓痕不依賴於訪問標籤或不存在。

任何想法如何我可以使依賴於類/結構或存在的訪問標籤inclass東西的縮進?

+0

我想你只想要public:和private:不添加縮進級別。 – djechlin

+0

謝謝,但如果你的意思是「{」和「public:」在同一列上,那不是我想要的。 – Aurelien

+1

我可以理解你的願望,並給予足夠的調整應該是可能的。另一方面,這很可能是不容易實現的,因爲類和結構之間的非區分在C++中運行得非常深入:甚至可以使用結構的訪問說明符。儘管這種用法很少見,但我會對此問題+1,並有興趣查看是否有解決方案出現。 – MvG

回答

7

新建答案

我遇到了你在你的問題中提到了確切的要求。 我必須根據我的新項目的編碼風格設置縮進。經過一些研究,我使用Custom Line-up Functions實現了這一點。

修改您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-基本偏移'被添加到 的基部縮進; 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 sytax元素)。您可以使用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)) 
+0

是的,謝謝,這確實是我決定使用的妥協,所以我會給你的答案+1,因爲它可能會讓很多emacs用戶感興趣。但正如你所說,它並不回答實際問題。 – Aurelien

+1

好的,在你上次編輯的時候,你會發現它不可能,現在肯定可以回答這個問題。謝謝。 – Aurelien

+0

這假定'struct'始終沒有訪問標籤。我希望有一個解決方案可以識別訪問標籤存在的時間... – Arkadiy

0

我的項目的編碼標準現在需要這種縮進。像Arkadiy一樣,我更喜歡一種尊重訪問標籤的解決方案。這是我想出了:

(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符號需要被設置爲(通過c-set-offsetc-offset-alist等)縮進inclass

由於re-search-backward,這並不理想,但它確實有效。

2

基於的Praveen Kumar的回答上面,我實現了一個稍微不同的版本定製陣容功能:

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

仍然會縮進到「++」。

聲明:我不知道任何Lisp。我只是玩過,這對我很有用。我不知道,例如,是否有任何與此相關的性能問題。

+0

'(c-defun-defun)'的使用不完全正確,因爲它不適用於struct/classes中定義的內聯函數。 –