2013-02-05 9 views
10

Tôi đang cố gắng để đạt được thụt đầu dòng sau đây trong emacs:emacs: thụt đầu dòng khác nhau cho các lớp học và 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 
}; 

Tuy nhiên với các tập tin cấu hình sau ...

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

... Tôi chỉ đạt được:

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

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

Tất nhiên đó là bởi vì:

012.
  • cho thụt đầu dòng rõ ràng không có sự khác biệt giữa "lớp" và "cấu trúc" (tất cả đều là "chữ"),
  • sự thụt đầu của công cụ "xếp" không phụ thuộc vào sự hiện diện của nhãn truy cập hay không .

Bất kỳ ý tưởng nào về cách tôi có thể làm cho thụt đầu dòng nội dung phụ thuộc vào lớp/cấu trúc hoặc khi có nhãn truy cập?

+0

Tôi nghĩ bạn chỉ muốn công khai: và riêng tư: để không thêm mức thụt lề. – djechlin

+0

Cảm ơn nhưng nếu bạn muốn nói "{" và "công khai:" trên cùng một cột, thì đó không phải là điều tôi muốn. – Aurelien

+1

Tôi có thể hiểu được mong muốn của bạn, và cho đủ tinh chỉnh nó sẽ là có thể. Mặt khác, nó cũng có thể là điều này không dễ dàng đạt được, bởi vì sự không phân biệt giữa các lớp và cấu trúc chạy khá sâu trong C++: bạn thậm chí có thể sử dụng các bộ định danh truy cập cho các cấu trúc. Tuy nhiên, vì việc sử dụng đó là rất hiếm, tôi sẽ +1 câu hỏi này và sẽ quan tâm để xem liệu có giải pháp nào bật lên hay không. – MvG

Trả lời

7

mới trả lời

Tôi chạy vào các yêu cầu chính xác mà bạn đã đề cập trong câu hỏi của bạn. Tôi đã phải thiết lập thụt lề theo phong cách mã hóa của dự án mới của tôi. Sau một chút nghiên cứu, tôi đã đạt được điều này bằng cách sử dụng Custom Line-up Functions.

Sửa my-cpp-mode của bạn trông như thế này:

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

Nếu câu trả lời này là chấp nhận được, tôi sẽ đi trước và loại bỏ các câu trả lời cũ.

Old trả lời

Dựa trên những gì bạn đang cố gắng để đạt được, tôi có thể đề nghị một cách tiếp cận khác nhau? Bạn dường như muốn nhãn truy cập ở mức thụt đầu dòng khác với lớp và các thành viên của lớp. Sử dụng sau đây để đạt được điều đó.

(access-label . /) 

Từ Emacs tài liệu:

Nếu OFFSET là một trong những biểu tượng +', - '++', -', *', or /' sau đó một bội số tích cực hay tiêu cực của `c-cơ bản-offset 'được thêm vào thụt lề cơ bản; Lần lượt là 1, -1, 2, -2, 0,5 và -0,5.

Đây là đoạn trích từ một trong các kiểu tùy chỉnh mà tôi đã xác định.

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

Với c-basic-offset bộ đến 4, (access-label . /) thêm một thụt đầu dòng tiêu cực của 2 không gian để các nhãn truy cập. Đây là kết quả thực sự của chế độ thụt đầu dòng trên mã mẫu của bạn.

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

Tôi khuyên bạn nên sử dụng chế độ này vì mức thụt lề của các biến thành viên/cấu trúc thành viên nhất quán. FWIW, Google C Style theo cùng cách tiếp cận.

Theo như tôi có thể biết, người ta không thể phân biệt giữa thành viên nhóm hoặc thành viên cấu trúc (inclass yếu tố sytax). Bạn có thể sử dụng M-x c-syntactic-information-on-region để thực hiện phân tích cú pháp trên một khu vực. Một phân tích như vậy về ví dụ của bạn mang lại những điều sau đây. Từ đầu ra, không có gì để phân biệt giữa nếu bạn đang ở trong một lớp hoặc một cấu trúc.

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

Vâng, cảm ơn, đây thực sự là sự thỏa hiệp mà tôi đã quyết định sử dụng, vì vậy tôi sẽ +1 câu trả lời của bạn vì nó có thể thu hút rất nhiều người dùng emacs. Nhưng như bạn nói nó không trả lời câu hỏi thực tế. – Aurelien

+1

OK trong chỉnh sửa cuối cùng của bạn, bạn cho thấy rằng nó không thể, mà bây giờ chắc chắn trả lời câu hỏi. Cảm ơn. – Aurelien

+0

Điều này giả định rằng 'struct' luôn không có nhãn truy cập. Tôi ước rằng có một giải pháp có thể nhận ra khi các nhãn truy cập có mặt ... – Arkadiy

0

Các tiêu chuẩn mã hóa trong dự án của tôi hiện yêu cầu loại thụt đầu dòng này. Giống như Arkadiy, tôi thích một giải pháp tôn trọng nhãn truy cập. Đây là những gì tôi đã đưa ra:

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

Như đã đề cập trước đó, biểu tượng indent-after-acess-label cần phải được thiết lập như là thụt đầu dòng cho inclass (thông qua c-set-offset hoặc c-offset-alist, vv).

Điều này hầu như không lý tưởng, do re-search-backward, nhưng nó hoạt động.

2

Dựa trên câu trả lời Praveen Kumar ở trên, tôi thực hiện một phiên bản hơi khác nhau của hàm line-up tùy chỉnh:

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

Mã gốc đã không làm việc trong trường hợp nẹp là trên dòng tiếp theo, tức là

struct foo 
{ 
     int bar; 
}; 

vẫn thụt vào "++".

Tuyên bố từ chối trách nhiệm: Tôi không biết bất kỳ Lisp nào. Tôi chỉ chơi xung quanh và điều này làm việc cho tôi. Tôi không biết, ví dụ: nếu có bất kỳ vấn đề hiệu suất nào liên quan đến vấn đề này.

+0

sử dụng '(c-start-of-defun)' không hoàn toàn chính xác, vì nó sẽ không hoạt động với các hàm nội tuyến được xác định trong cấu trúc/lớp ... –