【问题标题】:emacs: different indentation for class and structemacs:类和结构的不同缩进
【发布时间】:2013-02-05 19:48:26
【问题描述】:

我正在尝试在 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”),
  • “inclass”内容的缩进不取决于访问标签的存在与否。

知道如何根据类/结构或访问标签的存在来使 inclass 内容的缩进吗?

【问题讨论】:

  • 我想你只希望 public: 和 private: 不添加缩进级别。
  • 谢谢,但如果你的意思是“{”和“public:”在同一列上,那不是我想要的。
  • 我可以理解您的愿望,并且只要进行足够的调整,它应该是可能的。另一方面,这很可能不容易实现,因为类和结构之间的无区别在 C++ 中非常深入:您甚至可以对结构使用访问说明符。不过,由于这种用途很少见,我会为这个问题 +1,并有兴趣看看是否有任何解决方案出现。

标签: c++ emacs indentation


【解决方案1】:

新答案

我遇到了您在问题中提到的确切要求。 我必须根据我的新项目的编码风格设置缩进。经过一番研究,我使用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。

这是我定义的自定义样式之一的 sn-p。

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

【讨论】:

  • 是的,谢谢,这确实是我决定使用的妥协,所以我会 +1 你的答案,因为它可能会引起很多 emacs 用户的兴趣。但正如你所说,它没有回答实际问题。
  • OK 在您上次的编辑中,您表明这是不可能的,现在肯定回答了这个问题。谢谢。
  • 这假定struct 始终没有访问标签。我希望有一个解决方案可以识别何时存在访问标签...
  • 您的新答案对我不起作用。 goto-char 转到类的左大括号,而不是类/结构定义。这是 emacs 22.3.1(旧的,我知道,对此我无能为力)。
【解决方案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。我只是玩了一下,这对我有用。我不知道,例如,是否存在与此相关的任何性能问题。

【讨论】:

  • 使用(c-beginning-of-defun) 并不完全正确,因为它不适用于结构/类中定义的内联函数...
【解决方案3】:

我项目的编码标准现在需要这种缩进。像 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 符号需要设置为inclass 的缩进(通过c-set-offsetc-offset-alist 等)。

由于re-search-backward,这并不理想,但它确实有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-08
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    相关资源
    最近更新 更多