我正在尝试在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
};
当然那是因为:
我知道如何根据类/结构或存在访问标签来缩进inclass内容吗?
答案 0 :(得分: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-basic-offset”的正或负倍数 基础压痕;分别为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
};
我推荐这种模式,因为成员变量/ struct成员的缩进级别是一致的。 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 :(得分: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。我刚玩过,这对我有用。我不知道,例如,是否存在任何与此相关的性能问题。
答案 2 :(得分: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
符号需要设置为inclass
的缩进(通过c-set-offset
或c-offset-alist
等)。
由于re-search-backward
,这并不理想,但确实有效。