10

私はemacsで次のインデントを達成しようとしています:

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

もちろん、それは次の理由によるものです。

  • インデントについては、「class」と「struct」(すべて「inclass」)の間に明らかに違いはありません。
  • 「クラス内」のもののインデントは、アクセスラベルの存在に依存しません。

クラス内のもののインデントをクラス/構造体またはアクセスラベルの存在に依存させる方法はありますか?

4

3 に答える 3

8

新しい答え

私はあなたの質問で言及した正確な要件に遭遇しました. 新しいプロジェクトのコーディング スタイルに従ってインデントを設定する必要がありました。少し調査した後、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-basic-offset' の正または負の倍数がベース インデントに追加されます。それぞれ 1、-1、2、-2、0.5、および -0.5。

これは、私が定義したカスタム スタイルの 1 つからの抜粋です。

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

4にc-basic-offset設定する(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構文要素) を区別することはできません。M-x c-syntactic-information-on-region領域で構文解析を行うために使用できます。あなたの例に関するそのような分析の1つは、次の結果をもたらします。出力から、クラスまたは構造体にいるかどうかを区別するものは何もありません。

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))
于 2013-02-07T09:53:01.053 に答える
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 をまったく知りません。私はただ遊んだだけで、これは私にとってはうまくいきます。たとえば、これに関連するパフォーマンスの問題があるかどうかはわかりません。

于 2013-09-03T20:57:55.420 に答える
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のインデントとして設定する必要があります。inclassc-set-offsetc-offset-alist

のため、これはほとんど理想的ではre-search-backwardありませんが、機能します。

于 2013-07-24T18:28:11.670 に答える